extlibs/android/gradle/gradle-2.2.1
extlibs/android/ndk/android-ndk-r10d
extlibs/android/sdk/android-sdk_r24.2
+extlibs/android/sdk/android-sdk-linux
+extlibs/android/sdk/android-sdk-macosx
+extlibs/android/sdk/android-sdk-windows
extlibs/boost/boost_1_58_0
extlibs/tinycbor/tinycbor
*.tgz
Build release binaries:
$ scons
-(Note: C sdk requires tiny-cbor. Please follow the instruction in the build
-message to install tiny-cbor)
+(Note: C sdk requires tinycbor. Please follow the instruction in the build
+message to install tinycbor)
Build debug binaries:
$scons RELEASE=false
guide you to do that.)
Tizen:
-To build for tizen platform tiny-cbor library is needed.
-Please download tiny-cbor if it is not present in extlibs/tiny-cbor folder
+To build for tizen platform tinycbor library is needed.
+Please download tinycbor if it is not present in extlibs/tinycbor folder
by doing the following:
$ git clone https://github.com/01org/tinycbor.git extlibs/tinycbor/tinycbor
if target_os == 'arduino':
env.UploadHelp()
+# to install the generated pc file into custome prefix location
+env.UserInstallTargetPCFile('iotivity.pc', 'iotivity.pc')
+
'''
os.system(android_home + '/tools/android')
+def ensure_libs(target, source, env):
+ return target, [source, env.get('BUILD_DIR') + 'liboc.so', env.get('BUILD_DIR') + 'liboc_logger.so']
+
jdk_env = Environment(ENV=os.environ)
-jdk_env['BUILDERS']['Gradle'] = Builder(action = env.get('ANDROID_GRADLE') + ' build -b' + os.getcwd()+'/build.gradle -PTARGET_ARCH=%s -PRELEASE=%s' %(ANDROID_TARGET_ARCH, ANDROID_RELEASE))
+jdk_env['BUILDERS']['Gradle'] = Builder(action = env.get('ANDROID_GRADLE') + ' build -b' + os.getcwd()+'/build.gradle -PTARGET_ARCH=%s -PRELEASE=%s --stacktrace' %(ANDROID_TARGET_ARCH, ANDROID_RELEASE), emitter = ensure_libs)
+jdk_env['BUILD_DIR'] = env.get('BUILD_DIR')
jdk_env.Gradle(target="base/objs", source="base/src/main/java/org/iotivity/base/OcResource.java")
-
-/*
-* //******************************************************************
-* //
-* // Copyright 2015 Intel Corporation.
-* //
-* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-* //
-* // Licensed under the Apache License, Version 2.0 (the "License");
-* // you may not use this file except in compliance with the License.
-* // You may obtain a copy of the License at
-* //
-* // http://www.apache.org/licenses/LICENSE-2.0
-* //
-* // Unless required by applicable law or agreed to in writing, software
-* // distributed under the License is distributed on an "AS IS" BASIS,
-* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* // See the License for the specific language governing permissions and
-* // limitations under the License.
-* //
-* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-*/
+//******************************************************************
+//
+// Copyright 2015 Intel Corporation.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// 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 "JniEntityHandler.h"
#include "JniOcResourceRequest.h"
#include "JniOcResourceResponse.h"
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env)
+ {
+ return;
+ }
+
env->DeleteGlobalRef(m_jListener);
- if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ m_jListener = nullptr;
+
+ if (JNI_EDETACHED == ret)
+ {
+ g_jvm->DetachCurrentThread();
+ }
}
}
-OCEntityHandlerResult JniEntityHandler::handleEntity(const std::shared_ptr<OCResourceRequest> request)
+OCEntityHandlerResult JniEntityHandler::handleEntity(
+ const std::shared_ptr<OCResourceRequest> request)
{
LOGD("JniEntityHandler_handleEntity");
jint envRet;
JNIEnv *env = GetJNIEnv(envRet);
- if (NULL == env) return OC_EH_ERROR;
+ if (nullptr == env)
+ {
+ return OC_EH_ERROR;
+ }
JniOcResourceRequest* jniResReq = new JniOcResourceRequest(request);
jlong reqHandle = reinterpret_cast<jlong>(jniResReq);
- jobject jResourceRequest = env->NewObject(g_cls_OcResourceRequest, g_mid_OcResourceRequest_N_ctor,
- reqHandle);
+ jobject jResourceRequest =
+ env->NewObject(g_cls_OcResourceRequest,
+ g_mid_OcResourceRequest_N_ctor,
+ reqHandle);
if (!jResourceRequest)
{
LOGE("Failed to create OcResourceRequest");
delete jniResReq;
- if (JNI_EDETACHED == envRet) g_jvm->DetachCurrentThread();
+ if (JNI_EDETACHED == envRet)
+ {
+ g_jvm->DetachCurrentThread();
+ }
+
return OC_EH_ERROR;
}
jclass clsL = env->GetObjectClass(m_jListener);
if (!clsL)
{
- if (JNI_EDETACHED == envRet) g_jvm->DetachCurrentThread();
+ if (JNI_EDETACHED == envRet)
+ {
+ g_jvm->DetachCurrentThread();
+ }
+
return OC_EH_ERROR;
}
jmethodID midL = env->GetMethodID(clsL, "handleEntity",
"(Lorg/iotivity/base/OcResourceRequest;)Lorg/iotivity/base/EntityHandlerResult;");
if (!midL)
{
- if (JNI_EDETACHED == envRet) g_jvm->DetachCurrentThread();
+ if (JNI_EDETACHED == envRet)
+ {
+ g_jvm->DetachCurrentThread();
+ }
+
return OC_EH_ERROR;
}
jobject entityHandlerResult = env->CallObjectMethod(m_jListener, midL, jResourceRequest);
if (env->ExceptionCheck())
{
- if (JNI_EDETACHED == envRet) g_jvm->DetachCurrentThread();
+ if (JNI_EDETACHED == envRet)
+ {
+ g_jvm->DetachCurrentThread();
+ }
+
return OC_EH_ERROR;
}
if (!entityHandlerResult)
{
ThrowOcException(JNI_INVALID_VALUE, "EntityHandlerResult cannot be null");
- if (JNI_EDETACHED == envRet) g_jvm->DetachCurrentThread();
+ if (JNI_EDETACHED == envRet)
+ {
+ g_jvm->DetachCurrentThread();
+ }
+
return OC_EH_ERROR;
}
jclass clsResult = env->GetObjectClass(entityHandlerResult);
if (!clsResult)
{
- if (JNI_EDETACHED == envRet) g_jvm->DetachCurrentThread();
+ if (JNI_EDETACHED == envRet)
+ {
+ g_jvm->DetachCurrentThread();
+ }
+
return OC_EH_ERROR;
}
jmethodID getValue_ID = env->GetMethodID(clsResult, "getValue", "()I");
if (env->ExceptionCheck())
{
LOGE("Java exception is thrown");
- if (JNI_EDETACHED == envRet) g_jvm->DetachCurrentThread();
+ if (JNI_EDETACHED == envRet)
+ {
+ g_jvm->DetachCurrentThread();
+ }
+
return OC_EH_ERROR;
}
- if (JNI_EDETACHED == envRet) g_jvm->DetachCurrentThread();
+ if (JNI_EDETACHED == envRet)
+ {
+ g_jvm->DetachCurrentThread();
+ }
+
return JniUtils::getOCEntityHandlerResult(env, static_cast<int>(jResult));
-}
\ No newline at end of file
+}
+++ /dev/null
-///*
-//* //******************************************************************
-//* //
-//* // Copyright 2015 Intel Corporation.
-//* //
-//* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//* //
-//* // 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 "JniListenerManager.h"
-//
-//#include "JniOnGetListener.h"
-//
-//template<class T>
-//T* JniListenerManager<T>::addListener(JNIEnv* env, jobject jListener)
-//{
-// T *onEventListener = NULL;
-//
-// m_mapMutex.lock();
-//
-// for (auto it = m_listenerMap.begin(); it != m_listenerMap.end(); ++it)
-// {
-// if (env->IsSameObject(jListener, it->first))
-// {
-// auto refPair = it->second;
-// onEventListener = refPair.first;
-// refPair.second++;
-// it->second = refPair;
-// m_listenerMap.insert(*it);
-// LOGD("OnEventListener: ref. count is incremented");
-// break;
-// }
-// }
-//
-// if (!onEventListener)
-// {
-// onEventListener = new T(env, jListener, this);
-// jobject jgListener = env->NewGlobalRef(jListener);
-//
-// m_listenerMap.insert(std::pair<jobject, std::pair<T*, int>>(jgListener, std::pair<T*, int>(onEventListener, 1)));
-// LOGD("OnEventListener: new listener");
-// }
-//
-// m_mapMutex.unlock();
-//
-// return onEventListener;
-//}
-//
-//template<class T>
-//void JniListenerManager<T>::removeListener(JNIEnv* env, jobject jListener)
-//{
-// m_mapMutex.lock();
-//
-// bool isFound = false;
-//
-// for (auto it = m_listenerMap.begin(); it != m_listenerMap.end(); ++it)
-// {
-// if (env->IsSameObject(jListener, it->first))
-// {
-// auto refPair = it->second;
-// if (refPair.second > 1)
-// {
-// refPair.second--;
-// it->second = refPair;
-// m_listenerMap.insert(*it);
-// LOGI("OnEventListener: ref. count is decremented");
-// }
-// else
-// {
-// env->DeleteGlobalRef(it->first);
-// T* listener = refPair.first;
-// delete listener;
-// m_listenerMap.erase(it);
-//
-// LOGI("OnEventListener is removed");
-// }
-//
-// isFound = true;
-// break;
-// }
-// }
-//
-// if (!isFound)
-// {
-// ThrowOcException(JNI_EXCEPTION, "OnEventListener isn't found");
-// }
-//
-// m_mapMutex.unlock();
-//}
-//
public:
T* addListener(JNIEnv* env, jobject jListener, JniOcResource* owner)
{
- T *onEventListener = NULL;
+ T *onEventListener = nullptr;
m_mapMutex.lock();
-/*
-* //******************************************************************
-* //
-* // Copyright 2015 Intel Corporation.
-* //
-* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-* //
-* // Licensed under the Apache License, Version 2.0 (the "License");
-* // you may not use this file except in compliance with the License.
-* // You may obtain a copy of the License at
-* //
-* // http://www.apache.org/licenses/LICENSE-2.0
-* //
-* // Unless required by applicable law or agreed to in writing, software
-* // distributed under the License is distributed on an "AS IS" BASIS,
-* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* // See the License for the specific language governing permissions and
-* // limitations under the License.
-* //
-* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-*/
+//******************************************************************
+//
+// Copyright 2015 Intel Corporation.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// 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 "JniOcPlatform.h"
#include "OCPlatform.h"
#include "JniOcResource.h"
JniOnResourceFoundListener* AddOnResourceFoundListener(JNIEnv* env, jobject jListener)
{
- JniOnResourceFoundListener *onResourceFoundListener = NULL;
+ JniOnResourceFoundListener *onResourceFoundListener = nullptr;
resourceFoundMapLock.lock();
- for (auto it = onResourceFoundListenerMap.begin(); it != onResourceFoundListenerMap.end(); ++it)
+ for (auto it = onResourceFoundListenerMap.begin();
+ it != onResourceFoundListenerMap.end();
+ ++it)
{
if (env->IsSameObject(jListener, it->first))
{
if (!onResourceFoundListener)
{
- onResourceFoundListener = new JniOnResourceFoundListener(env, jListener, RemoveOnResourceFoundListener);
+ onResourceFoundListener =
+ new JniOnResourceFoundListener(env, jListener, RemoveOnResourceFoundListener);
jobject jgListener = env->NewGlobalRef(jListener);
- onResourceFoundListenerMap.insert(std::pair < jobject, std::pair < JniOnResourceFoundListener*,
- int >> (jgListener, std::pair<JniOnResourceFoundListener*, int>(onResourceFoundListener, 1)));
+ onResourceFoundListenerMap.insert(
+ std::pair<jobject,
+ std::pair<JniOnResourceFoundListener*, int >>(
+ jgListener,
+ std::pair<JniOnResourceFoundListener*, int>(onResourceFoundListener,
+ 1)));
LOGD("OnResourceFoundListener: new listener");
}
resourceFoundMapLock.unlock();
{
resourceFoundMapLock.lock();
- for (auto it = onResourceFoundListenerMap.begin(); it != onResourceFoundListenerMap.end(); ++it)
+ for (auto it = onResourceFoundListenerMap.begin();
+ it != onResourceFoundListenerMap.end();
+ ++it)
{
if (env->IsSameObject(jListener, it->first))
{
JniOnDeviceInfoListener* AddOnDeviceInfoListener(JNIEnv* env, jobject jListener)
{
- JniOnDeviceInfoListener *onDeviceInfoListener = NULL;
+ JniOnDeviceInfoListener *onDeviceInfoListener = nullptr;
deviceInfoMapLock.lock();
if (!onDeviceInfoListener)
{
- onDeviceInfoListener = new JniOnDeviceInfoListener(env, jListener, RemoveOnDeviceInfoListener);
+ onDeviceInfoListener =
+ new JniOnDeviceInfoListener(env, jListener, RemoveOnDeviceInfoListener);
jobject jgListener = env->NewGlobalRef(jListener);
- onDeviceInfoListenerMap.insert(std::pair < jobject, std::pair < JniOnDeviceInfoListener*,
- int >> (jgListener, std::pair<JniOnDeviceInfoListener*, int>(onDeviceInfoListener, 1)));
+ onDeviceInfoListenerMap.insert(
+ std::pair<jobject,
+ std::pair<JniOnDeviceInfoListener*, int>>(
+ jgListener,
+ std::pair<JniOnDeviceInfoListener*, int>(onDeviceInfoListener, 1)));
LOGI("OnDeviceInfoListener: new listener");
}
JniOnPlatformInfoListener* AddOnPlatformInfoListener(JNIEnv* env, jobject jListener)
{
- JniOnPlatformInfoListener *onPlatformInfoListener = NULL;
+ JniOnPlatformInfoListener *onPlatformInfoListener = nullptr;
platformInfoMapLock.lock();
if (!onPlatformInfoListener)
{
- onPlatformInfoListener = new JniOnPlatformInfoListener(env, jListener, RemoveOnPlatformInfoListener);
+ onPlatformInfoListener =
+ new JniOnPlatformInfoListener(env, jListener, RemoveOnPlatformInfoListener);
jobject jgListener = env->NewGlobalRef(jListener);
- onPlatformInfoListenerMap.insert(std::pair < jobject, std::pair < JniOnPlatformInfoListener*,
- int >> (jgListener, std::pair<JniOnPlatformInfoListener*, int>(onPlatformInfoListener, 1)));
+ onPlatformInfoListenerMap.insert(
+ std::pair<jobject, std::pair<JniOnPlatformInfoListener*, int>>(
+ jgListener,
+ std::pair<JniOnPlatformInfoListener*, int>(onPlatformInfoListener, 1)));
LOGI("OnPlatformInfoListener: new listener");
}
JniOnPresenceListener* AddOnPresenceListener(JNIEnv* env, jobject jListener)
{
- JniOnPresenceListener *onPresenceListener = NULL;
+ JniOnPresenceListener *onPresenceListener = nullptr;
presenceMapLock.lock();
{
onPresenceListener = new JniOnPresenceListener(env, jListener, RemoveOnPresenceListener);
jobject jgListener = env->NewGlobalRef(jListener);
- onPresenceListenerMap.insert(std::pair < jobject, std::pair < JniOnPresenceListener*,
- int >> (jgListener, std::pair<JniOnPresenceListener*, int>(onPresenceListener, 1)));
+ onPresenceListenerMap.insert(
+ std::pair<jobject, std::pair<JniOnPresenceListener*, int>>(
+ jgListener,
+ std::pair<JniOnPresenceListener*, int>(onPresenceListener, 1)));
LOGI("OnPresenceListener: new listener");
}
presenceMapLock.unlock();
std::string dbfile;
if (jIpAddress)
{
- ipAddress = env->GetStringUTFChars(jIpAddress, NULL);
+ ipAddress = env->GetStringUTFChars(jIpAddress, nullptr);
}
if (jDbPath)
{
try
{
- OCStackResult result = OCPlatform::notifyAllObservers(jniOcResourceHandle->getOCResourceHandle());
+ OCStackResult result =
+ OCPlatform::notifyAllObservers(jniOcResourceHandle->getOCResourceHandle());
if (OC_STACK_OK != result)
{
return;
}
- JniOcResourceHandle* jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceHandle);
- if (!jniOcResourceHandle) return;
+ JniOcResourceHandle* jniOcResourceHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle);
+ if (!jniOcResourceHandle)
+ {
+ return;
+ }
try{
OCStackResult result = OCPlatform::notifyAllObservers(
* Method: notifyListOfObservers2
* Signature: (Lorg/iotivity/base/OcResourceHandle;[Ljava/lang/Byte;Lorg/iotivity/base/OcResourceResponse;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_notifyListOfObservers2
-(JNIEnv *env, jclass clazz, jobject jResourceHandle, jbyteArray jObservationIdArr, jobject jResourceResponse)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_notifyListOfObservers2(
+ JNIEnv *env,
+ jclass clazz,
+ jobject jResourceHandle,
+ jbyteArray jObservationIdArr,
+ jobject jResourceResponse)
{
LOGD("OcPlatform_notifyListOfObservers2");
if (!jResourceHandle)
return;
}
- JniOcResourceHandle* jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceHandle);
- if (!jniOcResourceHandle) return;
+ JniOcResourceHandle* jniOcResourceHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle);
+ if (!jniOcResourceHandle)
+ {
+ return;
+ }
- JniOcResourceResponse* jniOcResourceResponse = JniOcResourceResponse::getJniOcResourceResponsePtr(
- env, jResourceResponse);
- if (!jniOcResourceResponse) return;
+ JniOcResourceResponse* jniOcResourceResponse =
+ JniOcResourceResponse::getJniOcResourceResponsePtr(env, jResourceResponse);
+ if (!jniOcResourceResponse)
+ {
+ return;
+ }
int len = env->GetArrayLength(jObservationIdArr);
uint8_t* bArr = (uint8_t*)env->GetByteArrayElements(jObservationIdArr, 0);
env->ReleaseByteArrayElements(jObservationIdArr, (jbyte*)bArr, 0);
- try{
+ try
+ {
OCStackResult result = OCPlatform::notifyListOfObservers(
jniOcResourceHandle->getOCResourceHandle(),
observationIds,
* Method: notifyListOfObservers3
* Signature: (Lorg/iotivity/base/OcResourceHandle;[Ljava/lang/Byte;Lorg/iotivity/base/OcResourceResponse;I)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_notifyListOfObservers3
-(JNIEnv *env, jclass clazz, jobject jResourceHandle, jbyteArray jObservationIdArr, jobject jResourceResponse, jint jQoS)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_notifyListOfObservers3(
+ JNIEnv *env,
+ jclass clazz,
+ jobject jResourceHandle,
+ jbyteArray jObservationIdArr,
+ jobject jResourceResponse,
+ jint jQoS)
{
LOGD("OcPlatform_notifyListOfObservers3");
if (!jResourceHandle)
return;
}
- JniOcResourceHandle* jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceHandle);
- if (!jniOcResourceHandle) return;
+ JniOcResourceHandle* jniOcResourceHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle);
+ if (!jniOcResourceHandle)
+ {
+ return;
+ }
- JniOcResourceResponse* jniOcResourceResponse = JniOcResourceResponse::getJniOcResourceResponsePtr(
- env, jResourceResponse);
- if (!jniOcResourceResponse) return;
+ JniOcResourceResponse* jniOcResourceResponse =
+ JniOcResourceResponse::getJniOcResourceResponsePtr(env, jResourceResponse);
+ if (!jniOcResourceResponse)
+ {
+ return;
+ }
int len = env->GetArrayLength(jObservationIdArr);
uint8_t* bArr = (uint8_t*)env->GetByteArrayElements(jObservationIdArr, 0);
env->ReleaseByteArrayElements(jObservationIdArr, (jbyte*)bArr, 0);
- try{
+ try
+ {
OCStackResult result = OCPlatform::notifyListOfObservers(
jniOcResourceHandle->getOCResourceHandle(),
observationIds,
* Method: findResource0
* Signature: (Ljava/lang/String;Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnResourceFoundListener;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_findResource0
-(JNIEnv *env, jclass clazz, jstring jHost, jstring jResourceUri, jint jConnectivityType, jobject jListener)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_findResource0(
+ JNIEnv *env,
+ jclass clazz,
+ jstring jHost,
+ jstring jResourceUri,
+ jint jConnectivityType,
+ jobject jListener)
{
LOGD("OcPlatform_findResource");
std::string host;
if (jHost)
{
- host = env->GetStringUTFChars(jHost, NULL);
+ host = env->GetStringUTFChars(jHost, nullptr);
}
std::string resourceUri;
if (jResourceUri)
{
- resourceUri = env->GetStringUTFChars(jResourceUri, NULL);
+ resourceUri = env->GetStringUTFChars(jResourceUri, nullptr);
}
if (!jListener)
{
* Method: findResource1
* Signature: (Ljava/lang/String;Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnResourceFoundListener;I)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_findResource1
-(JNIEnv *env, jclass clazz, jstring jHost, jstring jResourceUri, jint jConnectivityType, jobject jListener, jint jQoS)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_findResource1(
+ JNIEnv *env,
+ jclass clazz,
+ jstring jHost,
+ jstring jResourceUri,
+ jint jConnectivityType,
+ jobject jListener,
+ jint jQoS)
{
LOGD("OcPlatform_findResource");
std::string host;
if (jHost)
{
- host = env->GetStringUTFChars(jHost, NULL);
+ host = env->GetStringUTFChars(jHost, nullptr);
}
std::string resourceUri;
if (jResourceUri)
{
- resourceUri = env->GetStringUTFChars(jResourceUri, NULL);
+ resourceUri = env->GetStringUTFChars(jResourceUri, nullptr);
}
if (!jListener)
{
* Method: getDeviceInfo0
* Signature: (Ljava/lang/String;Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnDeviceFoundListener;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_getDeviceInfo0
-(JNIEnv *env, jclass clazz, jstring jHost, jstring jResourceUri, jint jConnectivityType, jobject jListener)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_getDeviceInfo0(
+ JNIEnv *env,
+ jclass clazz,
+ jstring jHost,
+ jstring jResourceUri,
+ jint jConnectivityType,
+ jobject jListener)
{
LOGD("OcPlatform_getDeviceInfo0");
std::string host;
if (jHost)
{
- host = env->GetStringUTFChars(jHost, NULL);
+ host = env->GetStringUTFChars(jHost, nullptr);
}
std::string resourceUri;
if (jResourceUri)
{
- resourceUri = env->GetStringUTFChars(jResourceUri, NULL);
+ resourceUri = env->GetStringUTFChars(jResourceUri, nullptr);
}
if (!jListener)
{
}
JniOnDeviceInfoListener *onDeviceInfoListener = AddOnDeviceInfoListener(env, jListener);
- FindDeviceCallback findDeviceCallback = [onDeviceInfoListener](const OCRepresentation& ocRepresentation)
- {
- onDeviceInfoListener->foundDeviceCallback(ocRepresentation);
- };
+ FindDeviceCallback findDeviceCallback =
+ [onDeviceInfoListener](const OCRepresentation& ocRepresentation)
+ {
+ onDeviceInfoListener->foundDeviceCallback(ocRepresentation);
+ };
try
{
* Method: getDeviceInfo1
* Signature: (Ljava/lang/String;Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnDeviceFoundListener;I)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_getDeviceInfo1
-(JNIEnv *env, jclass clazz, jstring jHost, jstring jResourceUri, jint jConnectivityType, jobject jListener, jint jQoS)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_getDeviceInfo1(
+ JNIEnv *env,
+ jclass clazz,
+ jstring jHost,
+ jstring jResourceUri,
+ jint jConnectivityType,
+ jobject jListener,
+ jint jQoS)
{
LOGD("OcPlatform_getDeviceInfo1");
std::string host;
if (jHost)
{
- host = env->GetStringUTFChars(jHost, NULL);
+ host = env->GetStringUTFChars(jHost, nullptr);
}
std::string resourceUri;
if (jResourceUri)
{
- resourceUri = env->GetStringUTFChars(jResourceUri, NULL);
+ resourceUri = env->GetStringUTFChars(jResourceUri, nullptr);
}
if (!jListener)
{
}
JniOnDeviceInfoListener *onDeviceInfoListener = AddOnDeviceInfoListener(env, jListener);
- FindDeviceCallback findDeviceCallback = [onDeviceInfoListener](const OCRepresentation& ocRepresentation)
- {
- onDeviceInfoListener->foundDeviceCallback(ocRepresentation);
- };
+ FindDeviceCallback findDeviceCallback =
+ [onDeviceInfoListener](const OCRepresentation& ocRepresentation)
+ {
+ onDeviceInfoListener->foundDeviceCallback(ocRepresentation);
+ };
try
{
* Method: getPlatformInfo0
* Signature: (Ljava/lang/String;Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnPlatformFoundListener;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_getPlatformInfo0
-(JNIEnv *env, jclass clazz, jstring jHost, jstring jResourceUri, jint jConnectivityType, jobject jListener)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_getPlatformInfo0(
+ JNIEnv *env,
+ jclass clazz,
+ jstring jHost,
+ jstring jResourceUri,
+ jint jConnectivityType,
+ jobject jListener)
{
LOGD("OcPlatform_getPlatformInfo0");
std::string host;
if (jHost)
{
- host = env->GetStringUTFChars(jHost, NULL);
+ host = env->GetStringUTFChars(jHost, nullptr);
}
std::string resourceUri;
if (jResourceUri)
{
- resourceUri = env->GetStringUTFChars(jResourceUri, NULL);
+ resourceUri = env->GetStringUTFChars(jResourceUri, nullptr);
}
if (!jListener)
{
}
JniOnPlatformInfoListener *onPlatformInfoListener = AddOnPlatformInfoListener(env, jListener);
- FindPlatformCallback findPlatformCallback = [onPlatformInfoListener](const OCRepresentation& ocRepresentation)
- {
- onPlatformInfoListener->foundPlatformCallback(ocRepresentation);
- };
+ FindPlatformCallback findPlatformCallback =
+ [onPlatformInfoListener](const OCRepresentation& ocRepresentation)
+ {
+ onPlatformInfoListener->foundPlatformCallback(ocRepresentation);
+ };
try
{
* Method: getPlatformInfo1
* Signature: (Ljava/lang/String;Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnPlatformFoundListener;I)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_getPlatformInfo1
-(JNIEnv *env, jclass clazz, jstring jHost, jstring jResourceUri, jint jConnectivityType, jobject jListener, jint jQoS)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_getPlatformInfo1(
+ JNIEnv *env,
+ jclass clazz,
+ jstring jHost,
+ jstring jResourceUri,
+ jint jConnectivityType,
+ jobject jListener,
+ jint jQoS)
{
LOGD("OcPlatform_getPlatformInfo1");
std::string host;
if (jHost)
{
- host = env->GetStringUTFChars(jHost, NULL);
+ host = env->GetStringUTFChars(jHost, nullptr);
}
std::string resourceUri;
if (jResourceUri)
{
- resourceUri = env->GetStringUTFChars(jResourceUri, NULL);
+ resourceUri = env->GetStringUTFChars(jResourceUri, nullptr);
}
if (!jListener)
{
}
JniOnDeviceInfoListener *onDeviceInfoListener = AddOnDeviceInfoListener(env, jListener);
- FindDeviceCallback findDeviceCallback = [onDeviceInfoListener](const OCRepresentation& ocRepresentation)
- {
- onDeviceInfoListener->foundDeviceCallback(ocRepresentation);
- };
+ FindDeviceCallback findDeviceCallback =
+ [onDeviceInfoListener](const OCRepresentation& ocRepresentation)
+ {
+ onDeviceInfoListener->foundDeviceCallback(ocRepresentation);
+ };
try
{
* Method: registerResource0
* Signature: (Lorg/iotivity/base/OcResource;)Lorg/iotivity/base/OcResourceHandle;
*/
-JNIEXPORT jobject JNICALL Java_org_iotivity_base_OcPlatform_registerResource0
-(JNIEnv *env, jclass clazz, jobject jResource)
+JNIEXPORT jobject JNICALL Java_org_iotivity_base_OcPlatform_registerResource0(
+ JNIEnv *env, jclass clazz, jobject jResource)
{
LOGD("OcPlatform_registerResource");
if (!jResource)
}
JniOcResourceHandle* jniHandle = new JniOcResourceHandle(resourceHandle);
jlong handle = reinterpret_cast<jlong>(jniHandle);
- jobject jResourceHandle = env->NewObject(g_cls_OcResourceHandle, g_mid_OcResourceHandle_N_ctor, handle);
+ jobject jResourceHandle =
+ env->NewObject(g_cls_OcResourceHandle, g_mid_OcResourceHandle_N_ctor, handle);
if (!jResourceHandle)
{
* Method: registerResource1
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/iotivity/base/OcPlatform/EntityHandler;I)Lorg/iotivity/base/OcResourceHandle;
*/
-JNIEXPORT jobject JNICALL Java_org_iotivity_base_OcPlatform_registerResource1
-(JNIEnv *env, jclass clazz, jstring jResourceUri, jstring jResourceTypeName, jstring jResourceInterface,
+JNIEXPORT jobject JNICALL Java_org_iotivity_base_OcPlatform_registerResource1(
+ JNIEnv *env,
+ jclass clazz,
+ jstring jResourceUri,
+ jstring jResourceTypeName,
+ jstring jResourceInterface,
jobject jListener, jint jResourceProperty)
{
LOGI("OcPlatform_registerResource1");
std::string resourceUri;
if (jResourceUri)
{
- resourceUri = env->GetStringUTFChars(jResourceUri, NULL);
+ resourceUri = env->GetStringUTFChars(jResourceUri, nullptr);
}
std::string resourceTypeName;
if (jResourceTypeName)
{
- resourceTypeName = env->GetStringUTFChars(jResourceTypeName, NULL);
+ resourceTypeName = env->GetStringUTFChars(jResourceTypeName, nullptr);
}
std::string resourceInterface;
if (jResourceInterface)
{
- resourceInterface = env->GetStringUTFChars(jResourceInterface, NULL);
+ resourceInterface = env->GetStringUTFChars(jResourceInterface, nullptr);
}
- if (!jListener)
+ JniEntityHandler* entityHandler = NULL;
+ EntityHandler handleEntityCallback = NULL;
+ if (jListener)
{
- ThrowOcException(OC_STACK_INVALID_PARAM, "entityHandler cannot be null");
- return nullptr;
+ entityHandler = new JniEntityHandler(env, jListener);
+ handleEntityCallback =
+ [entityHandler](const std::shared_ptr<OCResourceRequest> request) -> OCEntityHandlerResult
+ {
+ return entityHandler->handleEntity(request);
+ };
}
- JniEntityHandler* entityHandler = new JniEntityHandler(env, jListener);
- EntityHandler handleEntityCallback = [entityHandler](const std::shared_ptr<OCResourceRequest> request) ->
- OCEntityHandlerResult{
- return entityHandler->handleEntity(request);
- };
OCResourceHandle resourceHandle;
try
JniOcResourceHandle* jniHandle = new JniOcResourceHandle(resourceHandle);
jlong handle = reinterpret_cast<jlong>(jniHandle);
- jobject jResourceHandle = env->NewObject(g_cls_OcResourceHandle, g_mid_OcResourceHandle_N_ctor, handle);
+ jobject jResourceHandle =
+ env->NewObject(g_cls_OcResourceHandle, g_mid_OcResourceHandle_N_ctor, handle);
if (!jResourceHandle)
{
LOGE("Failed to create OcResourceHandle");
* Method: registerDeviceInfo0
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_registerDeviceInfo0
-(JNIEnv *env,
-jclass clazz,
-jstring jDeviceName)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_registerDeviceInfo0(
+ JNIEnv *env,
+ jclass clazz,
+ jstring jDeviceName)
{
LOGI("OcPlatform_registerDeviceInfo");
std::string deviceName;
if (jDeviceName)
{
- deviceName = env->GetStringUTFChars(jDeviceName, NULL);
+ deviceName = env->GetStringUTFChars(jDeviceName, nullptr);
}
OCDeviceInfo deviceInfo;
* Method: registerPlatformInfo0
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_registerPlatformInfo0
-(JNIEnv *env,
-jclass clazz,
-jstring jPlatformID,
-jstring jManufacturerName,
-jstring jManufacturerUrl,
-jstring jModelNumber,
-jstring jDateOfManufacture,
-jstring jPlatformVersion,
-jstring jOperatingSystemVersion,
-jstring jHardwareVersion,
-jstring jFirmwareVersion,
-jstring jSupportUrl,
-jstring jSystemTime)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_registerPlatformInfo0(
+ JNIEnv *env,
+ jclass clazz,
+ jstring jPlatformID,
+ jstring jManufacturerName,
+ jstring jManufacturerUrl,
+ jstring jModelNumber,
+ jstring jDateOfManufacture,
+ jstring jPlatformVersion,
+ jstring jOperatingSystemVersion,
+ jstring jHardwareVersion,
+ jstring jFirmwareVersion,
+ jstring jSupportUrl,
+ jstring jSystemTime)
{
LOGI("OcPlatform_registerPlatformInfo");
if (jPlatformID)
{
- platformID = env->GetStringUTFChars(jPlatformID, NULL);
+ platformID = env->GetStringUTFChars(jPlatformID, nullptr);
}
if (jManufacturerName)
{
- manufacturerName = env->GetStringUTFChars(jManufacturerName, NULL);
+ manufacturerName = env->GetStringUTFChars(jManufacturerName, nullptr);
}
if (jManufacturerUrl)
{
- manufacturerUrl = env->GetStringUTFChars(jManufacturerUrl, NULL);
+ manufacturerUrl = env->GetStringUTFChars(jManufacturerUrl, nullptr);
}
if (jModelNumber)
{
- modelNumber = env->GetStringUTFChars(jModelNumber, NULL);
+ modelNumber = env->GetStringUTFChars(jModelNumber, nullptr);
}
if (jDateOfManufacture)
{
- dateOfManufacture = env->GetStringUTFChars(jDateOfManufacture, NULL);
+ dateOfManufacture = env->GetStringUTFChars(jDateOfManufacture, nullptr);
}
if (jPlatformVersion)
{
- platformVersion = env->GetStringUTFChars(jPlatformVersion, NULL);
+ platformVersion = env->GetStringUTFChars(jPlatformVersion, nullptr);
}
if (jOperatingSystemVersion)
{
- operatingSystemVersion = env->GetStringUTFChars(jOperatingSystemVersion, NULL);
+ operatingSystemVersion = env->GetStringUTFChars(jOperatingSystemVersion, nullptr);
}
if (jHardwareVersion)
{
- hardwareVersion = env->GetStringUTFChars(jHardwareVersion, NULL);
+ hardwareVersion = env->GetStringUTFChars(jHardwareVersion, nullptr);
}
if (jFirmwareVersion)
{
- firmwareVersion = env->GetStringUTFChars(jFirmwareVersion, NULL);
+ firmwareVersion = env->GetStringUTFChars(jFirmwareVersion, nullptr);
}
if (jSupportUrl)
{
- supportUrl = env->GetStringUTFChars(jSupportUrl, NULL);
+ supportUrl = env->GetStringUTFChars(jSupportUrl, nullptr);
}
if (jSystemTime)
{
- systemTime = env->GetStringUTFChars(jSystemTime, NULL);
+ systemTime = env->GetStringUTFChars(jSystemTime, nullptr);
}
OCPlatformInfo platformInfo;
LOGE("Error is due to %s", e.reason().c_str());
ThrowOcException(OC_STACK_ERROR, e.reason().c_str());
}
-
-
-
}
/*
* Method: unregisterResource0
* Signature: (Lorg/iotivity/base/OcResourceHandle;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_unregisterResource0
-(JNIEnv *env, jclass clazz, jobject jResourceHandle)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_unregisterResource0(
+ JNIEnv *env, jclass clazz, jobject jResourceHandle)
{
LOGI("OcPlatform_unregisterResource");
if (!jResourceHandle)
}
JniOcResourceHandle* jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
env, jResourceHandle);
- if (!jniOcResourceHandle) return;
+ if (!jniOcResourceHandle)
+ {
+ return;
+ }
try
{
ThrowOcException(OC_STACK_INVALID_PARAM, "resourceHandle cannot be null");
return;
}
- JniOcResourceHandle* jniOcResourceCollectionHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceCollectionHandle);
+ JniOcResourceHandle* jniOcResourceCollectionHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceCollectionHandle);
if (!jniOcResourceCollectionHandle) return;
JniOcResourceHandle* jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
env, jResourceHandle);
- if (!jniOcResourceHandle) return;
+ if (!jniOcResourceHandle)
+ {
+ return;
+ }
try
{
* Method: bindResources0
* Signature: (Lorg/iotivity/base/OcResourceHandle;[Lorg/iotivity/base/OcResourceHandle;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindResources0
-(JNIEnv *env, jclass clazz, jobject jResourceCollectionHandle, jobjectArray jResourceHandleArray)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindResources0(
+ JNIEnv *env,
+ jclass clazz,
+ jobject jResourceCollectionHandle,
+ jobjectArray jResourceHandleArray)
{
LOGI("OcPlatform_bindResources");
return;
}
- JniOcResourceHandle* jniOcResourceCollectionHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceCollectionHandle);
- if (!jniOcResourceCollectionHandle) return;
+ JniOcResourceHandle* jniOcResourceCollectionHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceCollectionHandle);
+ if (!jniOcResourceCollectionHandle)
+ {
+ return;
+ }
std::vector<OCResourceHandle> resourceHandleList;
int len = env->GetArrayLength(jResourceHandleArray);
return;
}
- JniOcResourceHandle* jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceHandle);
- if (!jniOcResourceHandle) return;
+ JniOcResourceHandle* jniOcResourceHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle);
+ if (!jniOcResourceHandle)
+ {
+ return;
+ }
resourceHandleList.push_back(
jniOcResourceHandle->getOCResourceHandle());
* Method: unbindResource0
* Signature: (Lorg/iotivity/base/OcResourceHandle;Lorg/iotivity/base/OcResourceHandle;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_unbindResource0
-(JNIEnv *env, jclass clazz, jobject jResourceCollectionHandle, jobject jResourceHandle)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_unbindResource0(
+ JNIEnv *env,
+ jclass clazz,
+ jobject jResourceCollectionHandle,
+ jobject jResourceHandle)
{
LOGI("OcPlatform_unbindResource");
if (!jResourceCollectionHandle)
return;
}
- JniOcResourceHandle* jniOcResourceCollectionHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceCollectionHandle);
- if (!jniOcResourceCollectionHandle) return;
+ JniOcResourceHandle* jniOcResourceCollectionHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceCollectionHandle);
+ if (!jniOcResourceCollectionHandle)
+ {
+ return;
+ }
- JniOcResourceHandle* jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceHandle);
- if (!jniOcResourceHandle) return;
+ JniOcResourceHandle* jniOcResourceHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle);
+ if (!jniOcResourceHandle)
+ {
+ return;
+ }
try
{
OCStackResult result = OCPlatform::unbindResource(
jniOcResourceCollectionHandle->getOCResourceHandle(),
- jniOcResourceHandle->getOCResourceHandle()
- );
+ jniOcResourceHandle->getOCResourceHandle());
if (OC_STACK_OK != result)
{
* Method: unbindResources0
* Signature: (Lorg/iotivity/base/OcResourceHandle;[Lorg/iotivity/base/OcResourceHandle;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_unbindResources0
-(JNIEnv *env, jclass clazz, jobject jResourceCollectionHandle, jobjectArray jResourceHandleArray)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_unbindResources0(
+ JNIEnv *env,
+ jclass clazz,
+ jobject jResourceCollectionHandle,
+ jobjectArray jResourceHandleArray)
{
LOGI("OcPlatform_unbindResources");
if (!jResourceCollectionHandle)
return;
}
- JniOcResourceHandle* jniOcResourceCollectionHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceCollectionHandle);
- if (!jniOcResourceCollectionHandle) return;
+ JniOcResourceHandle* jniOcResourceCollectionHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceCollectionHandle);
+ if (!jniOcResourceCollectionHandle)
+ {
+ return;
+ }
std::vector<OCResourceHandle> resourceHandleList;
int len = env->GetArrayLength(jResourceHandleArray);
return;
}
- JniOcResourceHandle* jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceHandle);
- if (!jniOcResourceHandle) return;
+ JniOcResourceHandle* jniOcResourceHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle);
+ if (!jniOcResourceHandle)
+ {
+ return;
+ }
resourceHandleList.push_back(
jniOcResourceHandle->getOCResourceHandle());
* Method: bindTypeToResource0
* Signature: (Lorg/iotivity/base/OcResourceHandle;Ljava/lang/String;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindTypeToResource0
-(JNIEnv *env, jclass clazz, jobject jResourceHandle, jstring jResourceTypeName)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_bindTypeToResource0(
+ JNIEnv *env,
+ jclass clazz,
+ jobject jResourceHandle,
+ jstring jResourceTypeName)
{
LOGI("OcPlatform_bindTypeToResource");
if (!jResourceHandle)
std::string typeName;
if (jResourceTypeName)
{
- typeName = env->GetStringUTFChars(jResourceTypeName, NULL);
+ typeName = env->GetStringUTFChars(jResourceTypeName, nullptr);
}
- JniOcResourceHandle* jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceHandle);
+ JniOcResourceHandle* jniOcResourceHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle);
if (!jniOcResourceHandle) return;
try
std::string interfaceName;
if (jResourceInterfaceName)
{
- interfaceName = env->GetStringUTFChars(jResourceInterfaceName, NULL);
+ interfaceName = env->GetStringUTFChars(jResourceInterfaceName, nullptr);
}
- JniOcResourceHandle* jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceHandle);
- if (!jniOcResourceHandle) return;
+ JniOcResourceHandle* jniOcResourceHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle);
+ if (!jniOcResourceHandle)
+ {
+ return;
+ }
try
{
* Method: startPresence0
* Signature: (I)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_startPresence0
-(JNIEnv *env, jclass clazz, jint ttl)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_startPresence0(
+ JNIEnv *env, jclass clazz, jint ttl)
{
LOGI("OcPlatform_startPresence");
* Method: stopPresence0
* Signature: ()V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_stopPresence0
-(JNIEnv *env, jclass clazz)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_stopPresence0(
+ JNIEnv *env, jclass clazz)
{
LOGI("OcPlatform_stopPresence");
* Method: subscribePresence0
* Signature: (Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnPresenceListener;)Lorg/iotivity/base/OcPresenceHandle;
*/
-JNIEXPORT jobject JNICALL Java_org_iotivity_base_OcPlatform_subscribePresence0
-(JNIEnv *env, jclass clazz, jstring jHost, jint jConnectivityType, jobject jListener)
+JNIEXPORT jobject JNICALL Java_org_iotivity_base_OcPlatform_subscribePresence0(
+ JNIEnv *env,
+ jclass clazz,
+ jstring jHost,
+ jint jConnectivityType,
+ jobject jListener)
{
LOGD("OcPlatform_subscribePresence");
std::string host;
if (jHost)
{
- host = env->GetStringUTFChars(jHost, NULL);
+ host = env->GetStringUTFChars(jHost, nullptr);
}
if (!jListener)
{
JniOnPresenceListener *onPresenceListener = AddOnPresenceListener(env, jListener);
- SubscribeCallback subscribeCallback = [onPresenceListener](OCStackResult result, const unsigned int nonce,
- const std::string& hostAddress)
- {
- onPresenceListener->onPresenceCallback(result, nonce, hostAddress);
- };
+ SubscribeCallback subscribeCallback =
+ [onPresenceListener](OCStackResult result,
+ const unsigned int nonce,
+ const std::string& hostAddress)
+ {
+ onPresenceListener->onPresenceCallback(result, nonce, hostAddress);
+ };
OCPlatform::OCPresenceHandle presenceHandle;
try
return nullptr;
}
- JniOcPresenceHandle* jniPresenceHandle = new JniOcPresenceHandle(onPresenceListener, presenceHandle);
+ JniOcPresenceHandle* jniPresenceHandle =
+ new JniOcPresenceHandle(onPresenceListener, presenceHandle);
jlong jhandle = reinterpret_cast<jlong>(jniPresenceHandle);
- jobject jPresenceHandle = env->NewObject(g_cls_OcPresenceHandle, g_mid_OcPresenceHandle_N_ctor, jhandle);
+ jobject jPresenceHandle =
+ env->NewObject(g_cls_OcPresenceHandle, g_mid_OcPresenceHandle_N_ctor, jhandle);
if (!jPresenceHandle)
{
LOGE("Failed to create OcPresenceHandle");
* Signature: (Ljava/lang/String;Ljava/lang/String;I
Lorg/iotivity/base/OcPlatform/OnPresenceListener;)Lorg/iotivity/base/OcPresenceHandle;
*/
-JNIEXPORT jobject JNICALL Java_org_iotivity_base_OcPlatform_subscribePresence1
-(JNIEnv *env, jclass clazz, jstring jHost, jstring jResourceType, jint jConnectivityType, jobject jListener)
+JNIEXPORT jobject JNICALL Java_org_iotivity_base_OcPlatform_subscribePresence1(
+ JNIEnv *env,
+ jclass clazz,
+ jstring jHost,
+ jstring jResourceType,
+ jint jConnectivityType,
+ jobject jListener)
{
LOGD("OcPlatform_subscribePresence1");
std::string host;
if (jHost)
{
- host = env->GetStringUTFChars(jHost, NULL);
+ host = env->GetStringUTFChars(jHost, nullptr);
}
std::string resourceType;
if (jResourceType)
{
- resourceType = env->GetStringUTFChars(jResourceType, NULL);
+ resourceType = env->GetStringUTFChars(jResourceType, nullptr);
}
if (!jListener)
{
return nullptr;
}
- JniOcPresenceHandle* jniPresenceHandle = new JniOcPresenceHandle(onPresenceListener, presenceHandle);
+ JniOcPresenceHandle* jniPresenceHandle =
+ new JniOcPresenceHandle(onPresenceListener, presenceHandle);
jlong jhandle = reinterpret_cast<jlong>(jniPresenceHandle);
- jobject jPresenceHandle = env->NewObject(g_cls_OcPresenceHandle, g_mid_OcPresenceHandle_N_ctor, jhandle);
+ jobject jPresenceHandle =
+ env->NewObject(g_cls_OcPresenceHandle, g_mid_OcPresenceHandle_N_ctor, jhandle);
if (!jPresenceHandle)
{
LOGE("Failed to create OcPresenceHandle");
* Method: unsubscribePresence0
* Signature: (Lorg/iotivity/base/OcPresenceHandle;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_unsubscribePresence0
-(JNIEnv *env, jclass clazz, jobject jPresenceHandle)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_unsubscribePresence0(
+ JNIEnv *env, jclass clazz, jobject jPresenceHandle)
{
LOGD("OcPlatform_unsubscribePresence");
if (!jPresenceHandle)
ThrowOcException(OC_STACK_INVALID_PARAM, "presenceHandle cannot be null");
return;
}
- JniOcPresenceHandle* jniPresenceHandle = JniOcPresenceHandle::getJniOcPresenceHandlePtr(env, jPresenceHandle);
- if (!jniPresenceHandle) return;
+ JniOcPresenceHandle* jniPresenceHandle =
+ JniOcPresenceHandle::getJniOcPresenceHandlePtr(env, jPresenceHandle);
+ if (!jniPresenceHandle)
+ {
+ return;
+ }
OCPresenceHandle presenceHandle = jniPresenceHandle->getOCPresenceHandle();
ThrowOcException(result, "unsubscribe presence has failed");
return;
}
- jweak jwOnPresenceListener = jniPresenceHandle->getJniOnPresenceListener()->getJWListener();
+ jweak jwOnPresenceListener =
+ jniPresenceHandle->getJniOnPresenceListener()->getJWListener();
if (jwOnPresenceListener)
{
RemoveOnPresenceListener(env, jwOnPresenceListener);
* Signature: (Ljava/lang/String;Ljava/lang/String;IZ[Ljava/lang/String;[Ljava/lang/String;)
Lorg/iotivity/base/OcResource;
*/
-JNIEXPORT jobject JNICALL Java_org_iotivity_base_OcPlatform_constructResourceObject0
-(JNIEnv *env, jclass clazz, jstring jHost, jstring jUri, jint jConnectivityType,
-jboolean jIsObservable, jobjectArray jResourceTypeArray, jobjectArray jInterfaceArray)
+JNIEXPORT jobject JNICALL Java_org_iotivity_base_OcPlatform_constructResourceObject0(
+ JNIEnv *env,
+ jclass clazz,
+ jstring jHost,
+ jstring jUri,
+ jint jConnectivityType,
+ jboolean jIsObservable,
+ jobjectArray jResourceTypeArray,
+ jobjectArray jInterfaceArray)
{
LOGD("OcPlatform_constructResourceObject");
std::string host;
if (jHost)
{
- host = env->GetStringUTFChars(jHost, NULL);
+ host = env->GetStringUTFChars(jHost, nullptr);
}
std::string uri;
if (jUri)
{
- uri = env->GetStringUTFChars(jUri, NULL);
+ uri = env->GetStringUTFChars(jUri, nullptr);
}
if (!jResourceTypeArray)
{
* Method: sendResponse0
* Signature: (Lorg/iotivity/base/OcResourceResponse;)V
*/
-JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_sendResponse0
-(JNIEnv *env, jclass clazz, jobject jResourceResponse)
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_sendResponse0(
+ JNIEnv *env, jclass clazz, jobject jResourceResponse)
{
LOGD("OcPlatform_sendResponse");
if (!jResourceResponse)
return;
}
- JniOcResourceResponse *jniResponse = JniOcResourceResponse::getJniOcResourceResponsePtr(
- env, jResourceResponse);
+ JniOcResourceResponse *jniResponse =
+ JniOcResourceResponse::getJniOcResourceResponsePtr(env, jResourceResponse);
if (!jniResponse) return;
try
{
- OCStackResult result = OCPlatform::sendResponse(jniResponse->getOCResourceResponse());
+ OCStackResult result =
+ OCPlatform::sendResponse(jniResponse->getOCResourceResponse());
if (OC_STACK_OK != result)
{
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return nullptr;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
AttributeValue attrValue;
if (!rep->getAttributeValue(key.c_str(), attrValue))
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string str = env->GetStringUTFChars(jKey, NULL);
+ std::string str = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(str, static_cast<int>(jValue));
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string str = env->GetStringUTFChars(jKey, NULL);
+ std::string str = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(str, static_cast<double>(jValue));
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string str = env->GetStringUTFChars(jKey, NULL);
+ std::string str = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(str, static_cast<bool>(jValue));
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
- std::string value = env->GetStringUTFChars(jValue, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
+ std::string value = env->GetStringUTFChars(jValue, nullptr);
rep->setValue(key, value);
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
OCRepresentation *value = JniOcRepresentation::getOCRepresentationPtr(env, jValue);
if (!value) return;
}
const jsize len = env->GetArrayLength(jValue);
- jint* ints = env->GetIntArrayElements(jValue, NULL);
+ jint* ints = env->GetIntArrayElements(jValue, nullptr);
std::vector<int> value;
for (jsize i = 0; i < len; ++i)
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
for (jsize j = 0; j < lenOuter; ++j)
{
jintArray jInnerArray = static_cast<jintArray>(env->GetObjectArrayElement(jValue, j));
- jint* ints = env->GetIntArrayElements(jInnerArray, NULL);
+ jint* ints = env->GetIntArrayElements(jInnerArray, nullptr);
std::vector<int> innerVector;
const jsize lenInner = env->GetArrayLength(jInnerArray);
for (jsize i = 0; i < lenInner; ++i)
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
for (jsize j = 0; j < lenMiddle; ++j)
{
jintArray jInnerArray = static_cast<jintArray>(env->GetObjectArrayElement(jMiddleArray, j));
- jint* ints = env->GetIntArrayElements(jInnerArray, NULL);
+ jint* ints = env->GetIntArrayElements(jInnerArray, nullptr);
std::vector<int> innerVector;
const jsize lenInner = env->GetArrayLength(jInnerArray);
for (jsize i = 0; i < lenInner; ++i)
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
}
const jsize len = env->GetArrayLength(jValue);
- jdouble* doubles = env->GetDoubleArrayElements(jValue, NULL);
+ jdouble* doubles = env->GetDoubleArrayElements(jValue, nullptr);
std::vector<double> value;
for (jsize i = 0; i < len; ++i)
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
for (jsize j = 0; j < lenOuter; ++j)
{
jdoubleArray jInnerArray = static_cast<jdoubleArray>(env->GetObjectArrayElement(jValue, j));
- jdouble* doubles = env->GetDoubleArrayElements(jInnerArray, NULL);
+ jdouble* doubles = env->GetDoubleArrayElements(jInnerArray, nullptr);
std::vector<double> innerVector;
const jsize lenInner = env->GetArrayLength(jInnerArray);
for (jsize i = 0; i < lenInner; ++i)
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
for (jsize j = 0; j < lenMiddle; ++j)
{
jdoubleArray jInnerArray = static_cast<jdoubleArray>(env->GetObjectArrayElement(jMiddleArray, j));
- jdouble* doubles = env->GetDoubleArrayElements(jInnerArray, NULL);
+ jdouble* doubles = env->GetDoubleArrayElements(jInnerArray, nullptr);
std::vector<double> innerVector;
const jsize lenInner = env->GetArrayLength(jInnerArray);
for (jsize i = 0; i < lenInner; ++i)
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
}
const jsize len = env->GetArrayLength(jValue);
- jboolean* booleans = env->GetBooleanArrayElements(jValue, NULL);
+ jboolean* booleans = env->GetBooleanArrayElements(jValue, nullptr);
std::vector<bool> value;
for (jsize i = 0; i < len; ++i)
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
{
jbooleanArray jInnerArray = static_cast<jbooleanArray>(env->GetObjectArrayElement(jValue, j));
const jsize lenInner = env->GetArrayLength(jInnerArray);
- jboolean* booleans = env->GetBooleanArrayElements(jInnerArray, NULL);
+ jboolean* booleans = env->GetBooleanArrayElements(jInnerArray, nullptr);
std::vector<bool> innerVector;
for (jsize i = 0; i < lenInner; ++i)
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
{
jbooleanArray jInnerArray = static_cast<jbooleanArray>(env->GetObjectArrayElement(jMiddleArray, j));
const jsize lenInner = env->GetArrayLength(jInnerArray);
- jboolean* booleans = env->GetBooleanArrayElements(jInnerArray, NULL);
+ jboolean* booleans = env->GetBooleanArrayElements(jInnerArray, nullptr);
std::vector<bool> innerVector;
for (jsize i = 0; i < lenInner; ++i)
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string key = env->GetStringUTFChars(jKey, nullptr);
rep->setValue(key, value);
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- rep->setUri(env->GetStringUTFChars(jUri, NULL));
+ rep->setUri(env->GetStringUTFChars(jUri, nullptr));
}
JNIEXPORT jboolean JNICALL Java_org_iotivity_base_OcRepresentation_hasAttribute
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return false;
- std::string str = env->GetStringUTFChars(jstr, NULL);
+ std::string str = env->GetStringUTFChars(jstr, nullptr);
return rep->hasAttribute(str);
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return false;
- std::string attributeKey = env->GetStringUTFChars(jAttributeKey, NULL);
+ std::string attributeKey = env->GetStringUTFChars(jAttributeKey, nullptr);
return static_cast<jboolean>(rep->erase(attributeKey));
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return;
- std::string attributeKey = env->GetStringUTFChars(jAttributeKey, NULL);
+ std::string attributeKey = env->GetStringUTFChars(jAttributeKey, nullptr);
rep->setNULL(attributeKey);
}
OCRepresentation *rep = JniOcRepresentation::getOCRepresentationPtr(env, thiz);
if (!rep) return false;
- std::string attributeKey = env->GetStringUTFChars(jAttributeKey, NULL);
+ std::string attributeKey = env->GetStringUTFChars(jAttributeKey, nullptr);
return static_cast<jboolean>(rep->isNULL(attributeKey));
}
jobject operator()(const std::vector<std::string>& val) const
{
size_t len = val.size();
- jobjectArray strArr = env->NewObjectArray(len, g_cls_String, NULL);
+ jobjectArray strArr = env->NewObjectArray(len, g_cls_String, nullptr);
if (!strArr) return nullptr;
for (size_t i = 0; i < len; ++i)
{
jobject operator()(const std::vector<OC::OCRepresentation>& val) const
{
jsize len = static_cast<jsize>(val.size());
- jobjectArray repArr = env->NewObjectArray(len, g_cls_OcRepresentation, NULL);
+ jobjectArray repArr = env->NewObjectArray(len, g_cls_OcRepresentation, nullptr);
if (!repArr) return nullptr;
for (jsize i = 0; i < len; ++i)
{
jobject operator()(const std::vector<std::vector<int>>& val) const
{
jsize lenOuter = static_cast<jsize>(val.size());
- jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_int1DArray, NULL);
+ jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_int1DArray, nullptr);
if (!jOuterArr)
{
return nullptr;
jobject operator()(const std::vector<std::vector<std::vector<int>>>& val) const
{
jsize lenOuter = static_cast<jsize>(val.size());
- jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_int2DArray, NULL);
+ jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_int2DArray, nullptr);
if (!jOuterArr) return nullptr;
for (jsize k = 0; k < lenOuter; ++k)
{
jsize lenMiddle = static_cast<jsize>(val[k].size());
- jobjectArray jMiddleArr = env->NewObjectArray(lenMiddle, g_cls_int1DArray, NULL);
+ jobjectArray jMiddleArr = env->NewObjectArray(lenMiddle, g_cls_int1DArray, nullptr);
if (!jMiddleArr) return nullptr;
for (jsize i = 0; i < lenMiddle; ++i)
{
jobject operator()(const std::vector<std::vector<double>>& val) const
{
jsize lenOuter = static_cast<jsize>(val.size());
- jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_double1DArray, NULL);
+ jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_double1DArray, nullptr);
if (!jOuterArr) return nullptr;
for (jsize i = 0; i < lenOuter; ++i)
{
jobject operator()(const std::vector<std::vector<std::vector<double>>>& val) const
{
jsize lenOuter = static_cast<jsize>(val.size());
- jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_double2DArray, NULL);
+ jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_double2DArray, nullptr);
if (!jOuterArr) return nullptr;
for (jsize k = 0; k < lenOuter; ++k)
{
jsize lenMiddle = static_cast<jsize>(val[k].size());
- jobjectArray jMiddleArr = env->NewObjectArray(lenMiddle, g_cls_double1DArray, NULL);
+ jobjectArray jMiddleArr = env->NewObjectArray(lenMiddle, g_cls_double1DArray, nullptr);
if (!jMiddleArr) return nullptr;
for (jsize i = 0; i < lenMiddle; ++i)
{
jobject operator()(const std::vector<std::vector<std::vector<bool>>>& val) const
{
jsize lenOuter = static_cast<jsize>(val.size());
- jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_boolean2DArray, NULL);
+ jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_boolean2DArray, nullptr);
if (!jOuterArr) return nullptr;
for (jsize k = 0; k < lenOuter; ++k)
{
jsize lenMiddle = static_cast<jsize>(val[k].size());
- jobjectArray jMiddleArr = env->NewObjectArray(lenMiddle, g_cls_boolean1DArray, NULL);
+ jobjectArray jMiddleArr = env->NewObjectArray(lenMiddle, g_cls_boolean1DArray, nullptr);
if (!jMiddleArr) return nullptr;
for (jsize i = 0; i < lenMiddle; ++i)
{
jobject operator()(const std::vector<std::vector<std::string>>& val) const
{
jsize lenOuter = static_cast<jsize>(val.size());
- jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_String1DArray, NULL);
+ jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_String1DArray, nullptr);
if (!jOuterArr) return nullptr;
for (jsize i = 0; i < lenOuter; ++i)
{
jsize lenInner = static_cast<jsize>(val[i].size());
- jobjectArray strArr = env->NewObjectArray(lenInner, g_cls_String, NULL);
+ jobjectArray strArr = env->NewObjectArray(lenInner, g_cls_String, nullptr);
if (!strArr) return nullptr;
for (jsize j = 0; j < lenInner; ++j)
{
jobject operator()(const std::vector<std::vector<std::vector<std::string>>>& val) const
{
jsize lenOuter = static_cast<jsize>(val.size());
- jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_String2DArray, NULL);
+ jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_String2DArray, nullptr);
if (!jOuterArr) return nullptr;
for (jsize k = 0; k < lenOuter; ++k)
{
jsize lenMiddle = static_cast<jsize>(val[k].size());
- jobjectArray jMiddleArr = env->NewObjectArray(lenMiddle, g_cls_String1DArray, NULL);
+ jobjectArray jMiddleArr = env->NewObjectArray(lenMiddle, g_cls_String1DArray, nullptr);
if (!jMiddleArr) return nullptr;
for (jsize i = 0; i < lenMiddle; ++i)
{
jsize lenInner = static_cast<jsize>(val[k][i].size());
- jobjectArray strArr = env->NewObjectArray(lenInner, g_cls_String, NULL);
+ jobjectArray strArr = env->NewObjectArray(lenInner, g_cls_String, nullptr);
if (!strArr) return nullptr;
for (jsize j = 0; j < lenInner; ++j)
{
jobject operator()(const std::vector<std::vector<OC::OCRepresentation>>& val) const
{
jsize lenOuter = static_cast<jsize>(val.size());
- jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_OcRepresentation1DArray, NULL);
+ jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_OcRepresentation1DArray, nullptr);
if (!jOuterArr) return nullptr;
for (jsize i = 0; i < lenOuter; ++i)
{
jsize lenInner = static_cast<jsize>(val[i].size());
- jobjectArray repArr = env->NewObjectArray(lenInner, g_cls_OcRepresentation, NULL);
+ jobjectArray repArr = env->NewObjectArray(lenInner, g_cls_OcRepresentation, nullptr);
if (!repArr) return nullptr;
for (jsize j = 0; j < lenInner; ++j)
{
jobject operator()(const std::vector<std::vector<std::vector<OC::OCRepresentation>>>& val) const
{
jsize lenOuter = static_cast<jsize>(val.size());
- jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_OcRepresentation2DArray, NULL);
+ jobjectArray jOuterArr = env->NewObjectArray(lenOuter, g_cls_OcRepresentation2DArray, nullptr);
if (!jOuterArr) return nullptr;
for (jsize k = 0; k < lenOuter; ++k)
{
jsize lenMiddle = static_cast<jsize>(val[k].size());
- jobjectArray jMiddleArr = env->NewObjectArray(lenMiddle, g_cls_OcRepresentation1DArray, NULL);
+ jobjectArray jMiddleArr = env->NewObjectArray(lenMiddle, g_cls_OcRepresentation1DArray, nullptr);
if (!jMiddleArr) return nullptr;
for (jsize i = 0; i < lenMiddle; ++i)
{
jsize lenInner = static_cast<jsize>(val[k][i].size());
- jobjectArray repArr = env->NewObjectArray(lenInner, g_cls_OcRepresentation, NULL);
+ jobjectArray repArr = env->NewObjectArray(lenInner, g_cls_OcRepresentation, nullptr);
if (!repArr) return nullptr;
for (jsize j = 0; j < lenInner; ++j)
{
JniOcResource::~JniOcResource()
{
LOGD("~JniOcResource()");
- m_sharedResource = NULL;
+
+ m_sharedResource = nullptr;
jint envRet;
JNIEnv *env = GetJNIEnv(envRet);
- if (NULL == env) return;
+ if (nullptr == env) return;
m_onGetManager.removeAllListeners(env);
m_onPutManager.removeAllListeners(env);
std::string resourceType;
if (jResourceType)
{
- resourceType = env->GetStringUTFChars(jResourceType, NULL);
+ resourceType = env->GetStringUTFChars(jResourceType, nullptr);
}
std::string resourceInterface;
if (jResourceInterface)
{
- resourceInterface = env->GetStringUTFChars(jResourceInterface, NULL);
+ resourceInterface = env->GetStringUTFChars(jResourceInterface, nullptr);
}
if (!jQueryParamsMap)
{
std::string resourceType;
if (jResourceType)
{
- resourceType = env->GetStringUTFChars(jResourceType, NULL);
+ resourceType = env->GetStringUTFChars(jResourceType, nullptr);
}
std::string resourceInterface;
if (jResourceInterface)
{
- resourceInterface = env->GetStringUTFChars(jResourceInterface, NULL);
+ resourceInterface = env->GetStringUTFChars(jResourceInterface, nullptr);
}
JniOcResource *resource = JniOcResource::getJniOcResourcePtr(env, thiz);
if (!resource) return;
std::string resourceType;
if (jResourceType)
{
- resourceType = env->GetStringUTFChars(jResourceType, NULL);
+ resourceType = env->GetStringUTFChars(jResourceType, nullptr);
}
std::string resourceInterface;
if (jResourceInterface)
{
- resourceInterface = env->GetStringUTFChars(jResourceInterface, NULL);
+ resourceInterface = env->GetStringUTFChars(jResourceInterface, nullptr);
}
if (!jRepresentation)
{
std::string resourceType;
if (jResourceType)
{
- resourceType = env->GetStringUTFChars(jResourceType, NULL);
+ resourceType = env->GetStringUTFChars(jResourceType, nullptr);
}
std::string resourceInterface;
if (jResourceInterface)
{
- resourceInterface = env->GetStringUTFChars(jResourceInterface, NULL);
+ resourceInterface = env->GetStringUTFChars(jResourceInterface, nullptr);
}
JniOcResource *resource = JniOcResource::getJniOcResourcePtr(env, thiz);
std::string resourceType;
if (jResourceType)
{
- resourceType = env->GetStringUTFChars(jResourceType, NULL);
+ resourceType = env->GetStringUTFChars(jResourceType, nullptr);
}
std::string resourceInterface;
if (jResourceInterface)
{
- resourceInterface = env->GetStringUTFChars(jResourceInterface, NULL);
+ resourceInterface = env->GetStringUTFChars(jResourceInterface, nullptr);
}
JniOcResource *resource = JniOcResource::getJniOcResourcePtr(env, thiz);
std::string resourceType;
if (jResourceType)
{
- resourceType = env->GetStringUTFChars(jResourceType, NULL);
+ resourceType = env->GetStringUTFChars(jResourceType, nullptr);
}
std::string resourceInterface;
if (jResourceInterface)
{
- resourceInterface = env->GetStringUTFChars(jResourceInterface, NULL);
+ resourceInterface = env->GetStringUTFChars(jResourceInterface, nullptr);
}
JniOcResource *resource = JniOcResource::getJniOcResourcePtr(env, thiz);
#include "OCRepresentation.h"
#include "JniUtils.h"
-JavaVM* g_jvm = NULL;
-
-jclass g_cls_Integer = NULL;
-jclass g_cls_int1DArray = NULL;
-jclass g_cls_int2DArray = NULL;
-jclass g_cls_Double = NULL;
-jclass g_cls_double1DArray = NULL;
-jclass g_cls_double2DArray = NULL;
-jclass g_cls_Boolean = NULL;
-jclass g_cls_boolean1DArray = NULL;
-jclass g_cls_boolean2DArray = NULL;
-jclass g_cls_String = NULL;
-jclass g_cls_String1DArray = NULL;
-jclass g_cls_String2DArray = NULL;
-jclass g_cls_LinkedList = NULL;
-jclass g_cls_Map = NULL;
-jclass g_cls_MapEntry = NULL;
-jclass g_cls_Set = NULL;
-jclass g_cls_Iterator = NULL;
-jclass g_cls_HashMap = NULL;
-jclass g_cls_OcException = NULL;
-jclass g_cls_OcResource = NULL;
-jclass g_cls_OcRepresentation = NULL;
-jclass g_cls_OcRepresentation1DArray = NULL;
-jclass g_cls_OcRepresentation2DArray = NULL;
-jclass g_cls_OcResourceRequest = NULL;
-jclass g_cls_OcResourceResponse = NULL;
-jclass g_cls_OcResourceHandle = NULL;
-jclass g_cls_OcPresenceHandle = NULL;
-jclass g_cls_OcRequestHandle = NULL;
-jclass g_cls_OcPresenceStatus = NULL;
-jclass g_cls_OcHeaderOption = NULL;
-jclass g_cls_ObservationInfo = NULL;
-jclass g_cls_OcResourceIdentifier = NULL;
-
-jmethodID g_mid_Integer_ctor = NULL;
-jmethodID g_mid_Double_ctor = NULL;
-jmethodID g_mid_Boolean_ctor = NULL;
-jmethodID g_mid_LinkedList_ctor = NULL;
-jmethodID g_mid_LinkedList_add_object = NULL;
-jmethodID g_mid_Map_entrySet = NULL;
-jmethodID g_mid_MapEntry_getKey = NULL;
-jmethodID g_mid_MapEntry_getValue = NULL;
-jmethodID g_mid_Set_iterator = NULL;
-jmethodID g_mid_Iterator_hasNext = NULL;
-jmethodID g_mid_Iterator_next = NULL;
-jmethodID g_mid_HashMap_ctor = NULL;
-jmethodID g_mid_HashMap_put = NULL;
-jmethodID g_mid_OcException_ctor = NULL;
-jmethodID g_mid_OcException_setNativeExceptionLocation = NULL;
-jmethodID g_mid_OcResource_ctor = NULL;
-jmethodID g_mid_OcRepresentation_N_ctor = NULL;
-jmethodID g_mid_OcRepresentation_N_ctor_bool = NULL;
-jmethodID g_mid_OcResourceRequest_N_ctor = NULL;
-jmethodID g_mid_OcResourceResponse_N_ctor = NULL;
-jmethodID g_mid_OcResourceHandle_N_ctor = NULL;
-jmethodID g_mid_OcPresenceHandle_N_ctor = NULL;
-jmethodID g_mid_OcRequestHandle_N_ctor = NULL;
-jmethodID g_mid_OcHeaderOption_ctor = NULL;
-jmethodID g_mid_OcHeaderOption_get_id = NULL;
-jmethodID g_mid_OcHeaderOption_get_data = NULL;
-jmethodID g_mid_ObservationInfo_N_ctor = NULL;
-jmethodID g_mid_OcPresenceStatus_get = NULL;
-jmethodID g_mid_OcResourceIdentifier_N_ctor = NULL;
+JavaVM* g_jvm = nullptr;
+
+jclass g_cls_Integer = nullptr;
+jclass g_cls_int1DArray = nullptr;
+jclass g_cls_int2DArray = nullptr;
+jclass g_cls_Double = nullptr;
+jclass g_cls_double1DArray = nullptr;
+jclass g_cls_double2DArray = nullptr;
+jclass g_cls_Boolean = nullptr;
+jclass g_cls_boolean1DArray = nullptr;
+jclass g_cls_boolean2DArray = nullptr;
+jclass g_cls_String = nullptr;
+jclass g_cls_String1DArray = nullptr;
+jclass g_cls_String2DArray = nullptr;
+jclass g_cls_LinkedList = nullptr;
+jclass g_cls_Map = nullptr;
+jclass g_cls_MapEntry = nullptr;
+jclass g_cls_Set = nullptr;
+jclass g_cls_Iterator = nullptr;
+jclass g_cls_HashMap = nullptr;
+jclass g_cls_OcException = nullptr;
+jclass g_cls_OcResource = nullptr;
+jclass g_cls_OcRepresentation = nullptr;
+jclass g_cls_OcRepresentation1DArray = nullptr;
+jclass g_cls_OcRepresentation2DArray = nullptr;
+jclass g_cls_OcResourceRequest = nullptr;
+jclass g_cls_OcResourceResponse = nullptr;
+jclass g_cls_OcResourceHandle = nullptr;
+jclass g_cls_OcPresenceHandle = nullptr;
+jclass g_cls_OcRequestHandle = nullptr;
+jclass g_cls_OcPresenceStatus = nullptr;
+jclass g_cls_OcHeaderOption = nullptr;
+jclass g_cls_ObservationInfo = nullptr;
+jclass g_cls_OcResourceIdentifier = nullptr;
+
+jmethodID g_mid_Integer_ctor = nullptr;
+jmethodID g_mid_Double_ctor = nullptr;
+jmethodID g_mid_Boolean_ctor = nullptr;
+jmethodID g_mid_LinkedList_ctor = nullptr;
+jmethodID g_mid_LinkedList_add_object = nullptr;
+jmethodID g_mid_Map_entrySet = nullptr;
+jmethodID g_mid_MapEntry_getKey = nullptr;
+jmethodID g_mid_MapEntry_getValue = nullptr;
+jmethodID g_mid_Set_iterator = nullptr;
+jmethodID g_mid_Iterator_hasNext = nullptr;
+jmethodID g_mid_Iterator_next = nullptr;
+jmethodID g_mid_HashMap_ctor = nullptr;
+jmethodID g_mid_HashMap_put = nullptr;
+jmethodID g_mid_OcException_ctor = nullptr;
+jmethodID g_mid_OcException_setNativeExceptionLocation = nullptr;
+jmethodID g_mid_OcResource_ctor = nullptr;
+jmethodID g_mid_OcRepresentation_N_ctor = nullptr;
+jmethodID g_mid_OcRepresentation_N_ctor_bool = nullptr;
+jmethodID g_mid_OcResourceRequest_N_ctor = nullptr;
+jmethodID g_mid_OcResourceResponse_N_ctor = nullptr;
+jmethodID g_mid_OcResourceHandle_N_ctor = nullptr;
+jmethodID g_mid_OcPresenceHandle_N_ctor = nullptr;
+jmethodID g_mid_OcRequestHandle_N_ctor = nullptr;
+jmethodID g_mid_OcHeaderOption_ctor = nullptr;
+jmethodID g_mid_OcHeaderOption_get_id = nullptr;
+jmethodID g_mid_OcHeaderOption_get_data = nullptr;
+jmethodID g_mid_ObservationInfo_N_ctor = nullptr;
+jmethodID g_mid_OcPresenceStatus_get = nullptr;
+jmethodID g_mid_OcResourceIdentifier_N_ctor = nullptr;
jobject getOcException(JNIEnv* env, const char* file, const char* functionName,
const int line, const int code, const char* message)
LOGI("JNI_OnUnload");
JNIEnv* env;
- if (g_jvm->GetEnv((void **)&env, JNI_CURRENT_VERSION) != JNI_OK)
+ if (vm->GetEnv((void **)&env, JNI_CURRENT_VERSION) != JNI_OK)
{
LOGE("Failed to get the environment using GetEnv()");
return;
static JNIEnv* GetJNIEnv(jint& ret)
{
- JNIEnv *env = NULL;
+ JNIEnv *env = nullptr;
ret = g_jvm->GetEnv((void **)&env, JNI_CURRENT_VERSION);
switch (ret) {
case JNI_OK:
return env;
case JNI_EDETACHED:
- if (g_jvm->AttachCurrentThread(&env, NULL) < 0)
+ if (g_jvm->AttachCurrentThread(&env, nullptr) < 0)
{
LOGE("Failed to get the environment");
return nullptr;
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
+
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
+
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
}
{
jint envRet;
JNIEnv *env = GetJNIEnv(envRet);
- if (NULL == env) return;
+ if (nullptr == env) return;
jobject jListener = env->NewLocalRef(m_jwListener);
if (!jListener)
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
+
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
+
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
}
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
jobject jListener = env->NewLocalRef(m_jwListener);
if (!jListener)
JniOnGetListener::~JniOnGetListener()
{
+ LOGD("~JniOnGetListener");
if (m_jwListener)
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
{
jint envRet;
JNIEnv *env = GetJNIEnv(envRet);
- if (NULL == env) return;
+ if (nullptr == env) return;
jobject jListener = env->NewLocalRef(m_jwListener);
if (!jListener)
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
{
jint envRet;
JNIEnv *env = GetJNIEnv(envRet);
- if (NULL == env) return;
+ if (nullptr == env) return;
jobject jListener = env->NewLocalRef(m_jwListener);
if (!jListener)
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
+
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
+
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
}
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
jobject jListener = env->NewLocalRef(m_jwListener);
if (!jListener)
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
{
jint envRet;
JNIEnv *env = GetJNIEnv(envRet);
- if (NULL == env) return;
+ if (nullptr == env) return;
jobject jListener = env->NewLocalRef(m_jwListener);
if (!jListener)
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
+
env->DeleteWeakGlobalRef(m_jwListener);
m_jwListener = nullptr;
+
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
}
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
if (OC_STACK_OK != result && OC_STACK_PRESENCE_STOPPED != result &&
OC_STACK_PRESENCE_TIMEOUT != result && OC_STACK_PRESENCE_DO_NOT_HANDLE != result)
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
{
jint envRet;
JNIEnv *env = GetJNIEnv(envRet);
- if (NULL == env) return;
+ if (nullptr == env) return;
jobject jListener = env->NewLocalRef(m_jwListener);
if (!jListener)
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
}
{
jint ret;
JNIEnv *env = GetJNIEnv(ret);
- if (NULL == env) return;
+ if (nullptr == env) return;
jobject jListener = env->NewLocalRef(m_jwListener);
if (!jListener)
{
jstring jStr = (jstring)env->GetObjectArrayElement(jStrArr, i);
if (!jStr) return;
- vector.push_back(env->GetStringUTFChars(jStr, NULL));
+ vector.push_back(env->GetStringUTFChars(jStr, nullptr));
if (env->ExceptionCheck()) return;
env->DeleteLocalRef(jStr);
}
jstring jData = (jstring)env->CallObjectMethod(header, g_mid_OcHeaderOption_get_data);
OC::HeaderOption::OCHeaderOption hopt(
static_cast<int>(jId),
- env->GetStringUTFChars(jData, NULL));
+ env->GetStringUTFChars(jData, nullptr));
headerOptions.push_back(hopt);
jstring jValue = (jstring)env->CallObjectMethod(jEntry, g_mid_MapEntry_getValue);
if (!jValue) return;
- map.insert(std::make_pair(env->GetStringUTFChars(jKey, NULL),
- env->GetStringUTFChars(jValue, NULL)));
+ map.insert(std::make_pair(env->GetStringUTFChars(jKey, nullptr),
+ env->GetStringUTFChars(jValue, nullptr)));
if (env->ExceptionCheck()) return;
env->DeleteLocalRef(jEntry);
const std::vector<OC::OCRepresentation>& representationVector)
{
jsize len = static_cast<jsize>(representationVector.size());
- jobjectArray repArr = env->NewObjectArray(len, g_cls_OcRepresentation, NULL);
+ jobjectArray repArr = env->NewObjectArray(len, g_cls_OcRepresentation, nullptr);
if (!repArr) return nullptr;
for (jsize i = 0; i < len; ++i)
{
return OC::ModeType::Client;
case 2:
return OC::ModeType::Both;
+ case 3:
+ return OC::ModeType::Gateway;
default:
ThrowOcException(OC_STACK_INVALID_PARAM, "Unexpected mode type");
return OC::ModeType::Both;
assertTrue(false);
}
}
-// TODO - this test fails currently
-// public void testStartStopListenForPresence() throws InterruptedException {
-// final String resourceType = "unit.test.resource" +
-// new Date().getTime();
-// final CountDownLatch signal = new CountDownLatch(1);
-//
-// OcPlatform.EntityHandler entityHandler = new OcPlatform.EntityHandler() {
-// @Override
-// public EntityHandlerResult handleEntity(OcResourceRequest ocResourceRequest) {
-// return EntityHandlerResult.OK;
-// }
-// };
-//
-// final OcPlatform.OnPresenceListener presenceListener = new OcPlatform.OnPresenceListener() {
-// @Override
-// public void onPresence(OcPresenceStatus ocPresenceStatus, int nonce, String hostAddress) {
-// Log.i(TAG, "onPresence status " + ocPresenceStatus.toString() + " nonce " + nonce);
-// signal.countDown();
-// }
-// };
-//
-// OcPlatform.OnResourceFoundListener resourceFoundListener =
-// new OcPlatform.OnResourceFoundListener() {
-// @Override
-// public void onResourceFound(OcResource resource) {
-// try {
-// //client
-// OcPresenceHandle presenceHandle = OcPlatform.subscribePresence(
-// resource.getHost(),
-// EnumSet.of(OcConnectivityType.CT_DEFAULT),
-// presenceListener
-// );
-//
-// //wait for onPresence event
-// assertTrue(signal.await(60, TimeUnit.SECONDS));
-//
-// //client
-// OcPlatform.unsubscribePresence(presenceHandle);
-// } catch (OcException e) {
-// assertTrue(false);
-// } catch (InterruptedException e) {
-// assertTrue(false);
-// }
-// }
-// };
-//
-// try {
-// //server
-// OcResourceHandle resourceHandle = OcPlatform.registerResource(
-// "/a/unittest",
-// resourceType,
-// OcPlatform.DEFAULT_INTERFACE,
-// entityHandler,
-// EnumSet.of(ResourceProperty.DISCOVERABLE, ResourceProperty.OBSERVABLE)
-// );
-//
-// //client
-// OcPlatform.findResource("",
-// OcPlatform.WELL_KNOWN_QUERY + "?rt=" + resourceType,
-// EnumSet.of(OcConnectivityType.CT_DEFAULT),
-// resourceFoundListener);
-//
-// //server
-// OcPlatform.startPresence(OcPlatform.DEFAULT_PRESENCE_TTL);
-//
-// //wait for onPresence event
-// assertTrue(signal.await(60, TimeUnit.SECONDS));
-//
-// //server
-// OcPlatform.stopPresence();
-//
-// //client
-// OcPlatform.unregisterResource(resourceHandle);
-//
-// } catch (OcException e) {
-// Log.e(TAG, e.getMessage());
-// assertTrue(false);
-// }
-// }
+
+ public void testStartStopListenForPresence() throws InterruptedException {
+ final String resourceType = "unit.test.resource" +
+ new Date().getTime();
+ final CountDownLatch signal = new CountDownLatch(1);
+
+ OcPlatform.EntityHandler entityHandler = new OcPlatform.EntityHandler() {
+ @Override
+ public EntityHandlerResult handleEntity(OcResourceRequest ocResourceRequest) {
+ return EntityHandlerResult.OK;
+ }
+ };
+
+ final OcPlatform.OnPresenceListener presenceListener = new OcPlatform.OnPresenceListener() {
+ @Override
+ public void onPresence(OcPresenceStatus ocPresenceStatus, int nonce, String hostAddress) {
+ Log.i(TAG, "onPresence status " + ocPresenceStatus.toString() + " nonce " + nonce);
+ signal.countDown();
+ }
+ };
+
+ OcPlatform.OnResourceFoundListener resourceFoundListener =
+ new OcPlatform.OnResourceFoundListener() {
+ @Override
+ public void onResourceFound(OcResource resource) {
+ try {
+ //client
+ OcPresenceHandle presenceHandle = OcPlatform.subscribePresence(
+ resource.getHost(),
+ EnumSet.of(OcConnectivityType.CT_DEFAULT),
+ presenceListener
+ );
+
+ //wait for onPresence event
+ assertTrue(signal.await(60, TimeUnit.SECONDS));
+
+ //client
+ OcPlatform.unsubscribePresence(presenceHandle);
+ } catch (OcException e) {
+ assertTrue(false);
+ } catch (InterruptedException e) {
+ assertTrue(false);
+ }
+ }
+ };
+
+ try {
+ //server
+ OcResourceHandle resourceHandle = OcPlatform.registerResource(
+ "/a/unittest",
+ resourceType,
+ OcPlatform.DEFAULT_INTERFACE,
+ entityHandler,
+ EnumSet.of(ResourceProperty.DISCOVERABLE, ResourceProperty.OBSERVABLE)
+ );
+
+ //client
+ OcPlatform.findResource("",
+ OcPlatform.WELL_KNOWN_QUERY + "?rt=" + resourceType,
+ EnumSet.of(OcConnectivityType.CT_DEFAULT),
+ resourceFoundListener);
+
+ //server
+ OcPlatform.startPresence(OcPlatform.DEFAULT_PRESENCE_TTL);
+
+ //wait for onPresence event
+ assertTrue(signal.await(60, TimeUnit.SECONDS));
+
+ //server
+ OcPlatform.stopPresence();
+
+ //client
+ OcPlatform.unregisterResource(resourceHandle);
+
+ } catch (OcException e) {
+ Log.e(TAG, e.getMessage());
+ assertTrue(false);
+ }
+ }
public void testHandleGetRequest() throws InterruptedException {
final String someKey = "SomeKey";
ocResourceList.add(resource);
try {
resource.get(queryParamsMap, onGetListener);
- //TODO there is a bug in the stack that prevents the usage of the following APIs
+// TODO there is a bug in the stack that prevents the usage of the following APIs
// resource.get(resourceType, OcPlatform.DEFAULT_INTERFACE, queryParamsMap,
// onGetListener);
//
case GET:
Map<String, String> queryParams =
ocResourceRequest.getQueryParameters();
-//TODO after the merge with CA, the query params are missing
-// if (!(queryParams.containsKey(someKey) &&
-// someValue.equals(queryParams.get(someKey)))) {
-// assertTrue(false);
-// }
+
+ if (!(queryParams.containsKey(someKey) &&
+ someValue.equals(queryParams.get(someKey)))) {
+ assertTrue(false);
+ }
ocResourceResponse.setErrorCode(200);
ocResourceResponse.setResponseResult(EntityHandlerResult.OK);
public enum ModeType {
SERVER(0),
CLIENT(1),
- CLIENT_SERVER(2),;
+ CLIENT_SERVER(2),
+ GATEWAY(3),; /**< Client server mode along with Routing capabilities.*/
private int value;
*/
public static final String GROUP_INTERFACE = "oic.mi.grp";
- public static final String WELL_KNOWN_QUERY = "224.0.1.187:5683/oic/res";
+ public static final String WELL_KNOWN_QUERY = "/oic/res";
public static final String MULTICAST_PREFIX = "224.0.1.187:5683";
public static final String MULTICAST_IP = "224.0.1.187";
public static final int MULTICAST_PORT = 5683;
resProperty |= prop.getValue();
}
+ if(null == entityHandler){
+ entityHandler = new EntityHandler() {
+ @Override
+ public EntityHandlerResult handleEntity(OcResourceRequest ocResourceRequest) {
+ return EntityHandlerResult.OK;
+ }
+ };
+ }
+
return OcPlatform.registerResource1(resourceUri,
resourceTypeName,
resourceInterface,
-/******************************************************************
- *
- * 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.
- *
- ******************************************************************/
-
-package org.iotivity.ca;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.wifi.WifiManager;
-
-public class CaIpInterface {
- private static Context mContext;
-
- private CaIpInterface(Context context) {
- mContext = context;
- registerIpStateReceiver();
- }
-
- private void registerIpStateReceiver() {
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
- intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
-
- mContext.registerReceiver(mReceiver, intentFilter);
- }
-
- private static BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
- WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_DISABLED) {
- caIpStateDisabled();
- } else if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
- ConnectivityManager manager = (ConnectivityManager)
- mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo nwInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
-
- if(nwInfo.isConnected()) {
- caIpStateEnabled();
- }
- }
- }
- };
-
- private native static void caIpStateEnabled();
-
- private native static void caIpStateDisabled();
-}
+/******************************************************************\r
+ *\r
+ * Copyright 2014 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
+package org.iotivity.ca;\r
+\r
+import android.content.BroadcastReceiver;\r
+import android.content.Context;\r
+import android.content.Intent;\r
+import android.content.IntentFilter;\r
+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
+ }\r
+\r
+ private void 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
+\r
+ private static BroadcastReceiver mReceiver = new BroadcastReceiver() {\r
+ @Override\r
+ public void onReceive(Context context, Intent intent) {\r
+ if (intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,\r
+ WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_DISABLED) {\r
+ caIpStateDisabled();\r
+ } else if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {\r
+ ConnectivityManager manager = (ConnectivityManager)\r
+ mContext.getSystemService(Context.CONNECTIVITY_SERVICE);\r
+ NetworkInfo nwInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);\r
+\r
+ if(nwInfo.isConnected()) {\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
+ private native static void caIpStateEnabled();\r
+\r
+ private native static void caIpStateDisabled();\r
+}\r
private native static void caLeRegisterGattCallback(BluetoothGattCallback callback);
// BluetoothAdapter.LeScanCallback
- private native static void caLeScanCallback(BluetoothDevice device,
- int rssi, byte[] scanRecord);
+ private native static void caLeScanCallback(BluetoothDevice device);
// BluetoothGattCallback
private native static void caLeGattConnectionStateChangeCallback(
private native static void caLeGattServicesDiscoveredCallback(BluetoothGatt gatt, int status);
- private native static void caLeGattCharacteristicReadCallback(
- BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
- byte[] data, int status);
-
private native static void caLeGattCharacteristicWriteCallback(
- BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
- byte[] data, int status);
+ BluetoothGatt gatt, byte[] data, int status);
private native static void caLeGattCharacteristicChangedCallback(
- BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] data);
-
- private native static void caLeGattDescriptorReadCallback(BluetoothGatt gatt,
- BluetoothGattDescriptor descriptor,
- int status);
+ BluetoothGatt gatt, byte[] data);
- private native static void caLeGattDescriptorWriteCallback(BluetoothGatt gatt,
- BluetoothGattDescriptor descriptor,
- int status);
+ private native static void caLeGattDescriptorWriteCallback(BluetoothGatt gatt, int status);
private native static void caLeGattReliableWriteCompletedCallback(BluetoothGatt gatt,
int status);
Log.d(TAG, "UUID : " + uuid.toString());
if(uuid.toString().contains(SERVICE_UUID.toLowerCase())) {
Log.d(TAG, "we found that has the Device");
- caLeScanCallback(device, rssi, scanRecord);
+ caLeScanCallback(device);
}
}
} catch(UnsatisfiedLinkError e) {
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
-
- caLeGattCharacteristicReadCallback(gatt, characteristic,
- characteristic.getValue(), status);
}
@Override
BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
- caLeGattCharacteristicWriteCallback(gatt, characteristic,
- characteristic.getValue(), status);
+ caLeGattCharacteristicWriteCallback(gatt, characteristic.getValue(), status);
}
@Override
BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
- caLeGattCharacteristicChangedCallback(gatt, characteristic,
- characteristic.getValue());
+ caLeGattCharacteristicChangedCallback(gatt, characteristic.getValue());
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
int status) {
super.onDescriptorRead(gatt, descriptor, status);
-
- caLeGattDescriptorReadCallback(gatt, descriptor, status);
}
@Override
int status) {
super.onDescriptorWrite(gatt, descriptor, status);
- caLeGattDescriptorWriteCallback(gatt, descriptor, status);
+ caLeGattDescriptorWriteCallback(gatt, status);
}
@Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
super.onReliableWriteCompleted(gatt, status);
-
- caLeGattReliableWriteCompletedCallback(gatt, status);
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
super.onReadRemoteRssi(gatt, rssi, status);
-
- caLeGattReadRemoteRssiCallback(gatt, rssi, status);
}
};
};
}
+
BluetoothGattService service);
private native static void caLeGattServerCharacteristicReadRequestCallback(
- BluetoothDevice device,
- int requestId, int offset, BluetoothGattCharacteristic characteristic, byte[] data);
+ BluetoothDevice device, byte[] data);
private native static void caLeGattServerCharacteristicWriteRequestCallback(
- BluetoothDevice device, int requestId,
- BluetoothGattCharacteristic characteristic, byte[] data, boolean preparedWrite,
- boolean responseNeeded, int offset, byte[] value);
-
- private native static void caLeGattServerDescriptorReadRequestCallback(
- BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor);
-
- public native static void caLeGattServerDescriptorWriteRequestCallback(
- BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor,
- boolean preparedWrite, boolean responseNeeded, int offset, byte[] value);
-
- private native static void caLeGattServerExecuteWriteCallback(BluetoothDevice device,
- int requestId, boolean execute);
+ BluetoothDevice device, byte[] data);
private native static void caLeGattServerNotificationSentCallback(BluetoothDevice device,
int status);
BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
- caLeGattServerCharacteristicReadRequestCallback(device, requestId, offset,
- characteristic,
- characteristic.getValue());
+ caLeGattServerCharacteristicReadRequestCallback(device, characteristic.getValue());
}
@Override
super.onCharacteristicWriteRequest(device, requestId, characteristic,
preparedWrite, responseNeeded, offset, value);
- caLeGattServerCharacteristicWriteRequestCallback(device, requestId, characteristic,
- value, preparedWrite, responseNeeded,
- offset, value);
+ caLeGattServerCharacteristicWriteRequestCallback(device, value);
}
@Override
BluetoothDevice device,
int requestId, int offset, BluetoothGattDescriptor descriptor) {
super.onDescriptorReadRequest(device, requestId, offset, descriptor);
-
- caLeGattServerDescriptorReadRequestCallback(device, requestId, offset, descriptor);
}
@Override
byte[] value) {
super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite,
responseNeeded, offset, value);
-
- caLeGattServerDescriptorWriteRequestCallback(device, requestId, descriptor,
- preparedWrite, responseNeeded, offset,
- value);
}
@Override
public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
super.onExecuteWrite(device, requestId, execute);
-
- caLeGattServerExecuteWriteCallback(device, requestId, execute);
}
@Override
"doxm": {
"oxm": [0],
"oxmsel": 0,
+ "sct": 1,
"owned": true,
"deviceid": "MjIyMjIyMjIyMjIyMjIyMg==",
"ownr": "MjIyMjIyMjIyMjIyMjIyMg=="
"doxm": {
"oxm": [0],
"oxmsel": 0,
+ "sct": 1,
"owned": true,
"deviceid": "MTExMTExMTExMTExMTExMQ==",
"ownr": "MjIyMjIyMjIyMjIyMjIyMg=="
# Note: for android, as oic-resource uses C++11 feature stoi and to_string,
# it requires gcc-4.9, currently only android-ndk-r10(for linux)
# and windows android-ndk-r10(64bit target version) support these features.
- echo "*********** Build Boost for android ***********"
- # disable parallel build for android as gradle depends on scons to finish first
- export SCONSFLAGS="-Q"
+ build_android_x86 $1 $2
+ build_android_armeabi $1 $2
+}
+
+function build_android_x86()
+{
echo "*********** Build for android x86 *************"
scons TARGET_OS=android TARGET_ARCH=x86 RELEASE=$1 TARGET_TRANSPORT=IP $2
+ scons TARGET_OS=android TARGET_ARCH=x86 RELEASE=$1 TARGET_TRANSPORT=BT $2
+ scons TARGET_OS=android TARGET_ARCH=x86 RELEASE=$1 TARGET_TRANSPORT=BLE $2
+}
+function build_android_armeabi()
+{
echo "*********** Build for android armeabi *************"
scons TARGET_OS=android TARGET_ARCH=armeabi RELEASE=$1 TARGET_TRANSPORT=IP $2
-
- # enable parallel build
- export SCONSFLAGS="-Q -j 4"
+ scons TARGET_OS=android TARGET_ARCH=armeabi RELEASE=$1 TARGET_TRANSPORT=BT $2
+ scons TARGET_OS=android TARGET_ARCH=armeabi RELEASE=$1 TARGET_TRANSPORT=BLE $2
}
function build_arduino()
echo "*********** Build for arduino avr *************"
scons resource TARGET_OS=arduino UPLOAD=false BOARD=mega TARGET_ARCH=avr TARGET_TRANSPORT=IP SHIELD=ETH RELEASE=$1 $2
scons resource TARGET_OS=arduino UPLOAD=false BOARD=mega TARGET_ARCH=avr TARGET_TRANSPORT=IP SHIELD=WIFI RELEASE=$1 $2
+ scons resource TARGET_OS=arduino UPLOAD=false BOARD=mega TARGET_ARCH=avr TARGET_TRANSPORT=BLE SHIELD=RBL_NRF8001 RELEASE=$1 $2
echo "*********** Build for arduino arm *************"
scons resource TARGET_OS=arduino UPLOAD=false BOARD=arduino_due_x TARGET_ARCH=arm TARGET_TRANSPORT=IP SHIELD=ETH RELEASE=$1 $2
scons resource TARGET_OS=arduino UPLOAD=false BOARD=arduino_due_x TARGET_ARCH=arm TARGET_TRANSPORT=IP SHIELD=WIFI RELEASE=$1 $2
+ # BLE support for the Arduino Due is currently unavailable.
}
function build_tizen()
then
build_android true
build_android false
+ elif [ $1 = 'android_x86' ]
+ then
+ build_android_x86 true
+ build_android_x86 false
+ elif [ $1 = 'android_armeabi' ]
+ then
+ build_android_armeabi true
+ build_android_armeabi false
elif [ $1 = 'arduino' ]
then
build_arduino true
fi
echo "===================== done ====================="
-
-
if target_os in targets_disallow_multitransport:
help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'IP', ['BT', 'BLE', 'IP']))
else:
- help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'ALL', ['ALL', 'BT', 'BLE', 'IP']))
+ help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'ALL', ['ALL', 'BT', 'BLE', 'IP', 'TCP']))
help_vars.Add(EnumVariable('TARGET_ARCH', 'Target architecture', default_arch, os_arch_map[target_os]))
help_vars.Add(EnumVariable('SECURED', 'Build with DTLS', '0', allowed_values=('0', '1')))
help_vars.Add(EnumVariable('TEST', 'Run unit tests', '0', allowed_values=('0', '1')))
help_vars.Add(BoolVariable('LOGGING', 'Enable stack logging', logging_default))
help_vars.Add(BoolVariable('UPLOAD', 'Upload binary ? (For Arduino)', require_upload))
+help_vars.Add(EnumVariable('ROUTING', 'Enable routing', 'EP', allowed_values=('GW', 'EP')))
help_vars.Add(EnumVariable('BUILD_SAMPLE', 'Build with sample', 'ON', allowed_values=('ON', 'OFF')))
help_vars.AddVariables(('DEVICE_NAME', 'Network display name for device (For Arduino)', device_name, None, None),)
help_vars.Add(PathVariable('ANDROID_NDK', 'Android NDK path', None, PathVariable.PathAccept))
if target_os in ['android', 'arduino']: # Android/Arduino always uses GNU compiler regardless of the host
env = Environment(variables = help_vars,
- tools = ['gnulink', 'gcc', 'g++', 'ar', 'as']
+ tools = ['gnulink', 'gcc', 'g++', 'ar', 'as', 'textfile']
)
else:
- env = Environment(variables = help_vars, TARGET_ARCH = target_arch, TARGET_OS = target_os, PREFIX = GetOption('prefix'))
+ env = Environment(variables = help_vars, tools = ['default', 'textfile'], TARGET_ARCH = target_arch, TARGET_OS = target_os, PREFIX = GetOption('prefix'))
Help(help_vars.GenerateHelpText(env))
i_n = ienv.Install(env.get('BUILD_DIR'), targets)
ienv.Alias("install", i_n)
+def __installheader(ienv, targets, dir, name):
+ user_prefix = env.get('PREFIX')
+ if user_prefix:
+ i_n = ienv.Install(user_prefix + '/include/' + dir ,targets)
+ else:
+ i_n = ienv.Install(env.get('BUILD_DIR'), targets)
+ ienv.Alias("install", i_n)
+
+def __installpcfile(ienv, targets, name):
+ user_prefix = env.get('PREFIX')
+ if user_prefix:
+ i_n = ienv.Install(user_prefix + '/lib/pkgconfig', targets)
+ else:
+ i_n = ienv.Install(env.get('BUILD_DIR'), targets)
+ ienv.Alias("install", i_n)
+
def __append_target(ienv, name, targets = None):
if targets:
env.Alias(name, targets)
env.AddMethod(__install, 'InstallTarget')
env.AddMethod(__installlib, 'UserInstallTargetLib')
env.AddMethod(__installbin, 'UserInstallTargetBin')
+env.AddMethod(__installheader, 'UserInstallTargetHeader')
+env.AddMethod(__installpcfile, 'UserInstallTargetPCFile')
env.SetDir(env.GetLaunchDir())
env['ROOT_DIR']=env.GetLaunchDir()+'/..'
Export('env')
######################################################################
+# Scons to generate the iotivity.pc file from iotivity.pc.in file
+######################################################################
+pc_file = env.get('SRC_DIR') + '/iotivity.pc.in'
+
+user_prefix = env.get('PREFIX')
+
+if user_prefix:
+ pc_vars = {'\@PREFIX\@': user_prefix, '\@EXEC_PREFIX\@':user_prefix, '\@VERSION\@':'0.9.2'}
+else:
+ pc_vars = {'\@PREFIX\@': env.get('BUILD_DIR'), '\@EXEC_PREFIX\@': env.get('BUILD_DIR'), '\@VERSION\@':'0.9.2'}
+
+env.Substfile(pc_file, SUBST_DICT = pc_vars)
+
+######################################################################
# Link scons to Yocto cross-toolchain ONLY when target_os is yocto
######################################################################
if target_os == "yocto":
{
srand48(__s);
}
-
-/* from unistd.h */
-int getpagesize(void)
-{
- extern unsigned int __page_size;
- return __page_size;
-}
-
-int __getpageshift(void)
-{
- extern unsigned int __page_shift;
- return __page_shift;
-}
install_cmd = env.Command('install_cmd', None, upload_cmd)
env.Default('install_cmd')
elif target_arch == 'arm':
- protocol = __get_board_info(board, '.upload.protocol')
- speed = __get_board_info(board, '.upload.speed')
port = 'ttyACM0'
- uu = __get_board_info(board, '.upload.native_usb')
- os.system('stty -F /dev/' + port + ' speed 1200 cs8 -cstopb -parenb')
- os.system(arduino_home + '/hardware/tools/bossac -i --port=' + port + ' -U false -e -w -b ' + binary + ' -R')
+ upload_cmd = 'stty -F /dev/' + port + ' speed 1200 cs8 -cstopb -parenb \n' + arduino_home + '/hardware/tools/bossac -i --port=' + port + ' -U false -e -w -b ' + binary + ' -R'
+ print "Upload command: %s" %upload_cmd
+ install_cmd = env.Command('install_cmd', None, upload_cmd)
+ env.Default('install_cmd')
# Print the command line that to upload binary to the board
def __upload_help(env):
env.AppendUnique(CCFLAGS = ['-g'])
env.AppendUnique(LINKFLAGS = ['-g'])
+if env.get('LOGGING'):
+ env.AppendUnique(CPPDEFINES = ['-DTB_LOG'])
+
if target_os == 'darwin':
sys_root = tc_path + '/Platforms/MacOSX.platform/Developer/SDKs/MacOSX' + sys_version + '.sdk/'
else:
env.AddMethod(__download, "Download")
env.AddMethod(__install_head_file, "InstallHeadFile")
env.AddMethod(__install_lib, "InstallLib")
+
+if env.get('SECURED') == '1':
+ SConscript(os.path.join(env.get('SRC_DIR'), 'extlibs', 'sqlite3', 'SConscript'))
\ No newline at end of file
if not android_home:
print 'Creating ANDROID_HOME for Android SDK'
+ # older IoTivity versions expected the SDK at this position, this is left for backwards compatibility
androidlib_dir = src_dir + '/extlibs/android/sdk/android-sdk_r24.2'
if not os.path.exists(androidlib_dir):
if _platform == "linux" or _platform == "linux2":
androidlib_zip_file = src_dir + '/extlibs/android/android-sdk_r24.2-linux.tgz'
androidlib_url = 'http://dl.google.com/android/android-sdk_r24.2-linux.tgz'
+ androidlib_dir = src_dir + '/extlibs/android/sdk/android-sdk-linux'
elif _platform == "darwin":
androidlib_zip_file = src_dir + '/extlibs/android/android-sdk_r24.2-macosx.zip'
androidlib_url = 'http://dl.google.com/android/android-sdk_r24.2-macosx.zip'
+ androidlib_dir = src_dir + '/extlibs/android/sdk/android-sdk-macosx'
elif _platform == "win32":
androidlib_zip_file = src_dir + '/extlibs/android/android-sdk_r24.2-windows.zip'
androidlib_url = 'http://dl.google.com/android/android-sdk_r24.2-windows.zip'
+ androidlib_dir = src_dir + '/extlibs/android/sdk/android-sdk-windows'
+ if not os.path.exists(androidlib_dir):
# If the zip file is not already present, download it
if not os.path.exists(androidlib_zip_file):
androidlib_zip = env.Download(androidlib_zip_file, androidlib_url)
--- /dev/null
+##
+# Script to install (if they do not exist) the SQLite library
+##
+
+import os
+import shutil
+
+Import('env')
+sqlite_env = env.Clone()
+
+target_os = sqlite_env.get('TARGET_OS')
+src_dir = sqlite_env.get('SRC_DIR')
+
+targets_need_sqlite = ['linux', 'android']
+sqlite_dir = src_dir + '/extlibs/sqlite3/'
+sqlite_build_dir = src_dir + '/extlibs/sqlite3/sqlite-amalgamation-3081101/'
+sqlite_zip_file = src_dir + '/extlibs/sqlite3/sqlite-amalgamation-3081101.zip'
+sqlite_url = 'http://www.sqlite.org/2015/sqlite-amalgamation-3081101.zip'
+
+# Download
+if target_os in targets_need_sqlite:
+ print '*** Checking for installation of SQLite 3.8.11.1 ***'
+ if not os.path.exists(sqlite_dir + 'sqlite3.c') or not os.path.exists(sqlite_dir + 'sqlite3.h'):
+
+ # If the zip file is not already present, download it
+ if not os.path.exists(sqlite_zip_file):
+ sqlite_zip = sqlite_env.Download(sqlite_zip_file, sqlite_url)
+ else:
+ sqlite_zip = sqlite_zip_file
+
+ # Unzip the lib
+ print 'Unzipping SQLite amalgamation src...'
+ sqlite_env.UnpackAll(sqlite_build_dir, sqlite_zip)
+ print 'Unzipping SQLite amalgamation src complete'
+
+ # Move requried src and header
+ os.rename(sqlite_build_dir + 'sqlite3.c', sqlite_dir + 'sqlite3.c')
+ os.rename(sqlite_build_dir + 'sqlite3.h', sqlite_dir + 'sqlite3.h')
+ os.remove(sqlite_zip_file)
+ shutil.rmtree(sqlite_build_dir)
+
+# Build will be done with provisioning manager module.
\ No newline at end of file
--- /dev/null
+From 947179cd0d3646359272cc0645e5049e2426f9e0 Mon Sep 17 00:00:00 2001
+From: Sachin Agrawal <sachin.agrawal@intel.com>
+Date: Thu, 6 Aug 2015 15:13:29 -0700
+Subject: [PATCH 1/1] Add TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 cipher suite
+ in tinydtls
+
+[Patch #1] Initial upload
+[Patch #2] Add function to calculate the pre-master key of ECDHE_PSK cipher suite.
+[Patch #3] Update codes according to review comments
+[Patch #4] Modify code alignment.
+
+Change-Id: I70be3a8e9469cc1913373d820b4a3d4f4a6d6d0d
+Signed-off-by: leechul <chuls.lee@samsung.com>
+Signed-off-by: Sachin Agrawal <sachin.agrawal@intel.com>
+---
+ extlibs/tinydtls/crypto.c | 41 +++-
+ extlibs/tinydtls/crypto.h | 9 +
+ extlibs/tinydtls/dtls.c | 401 ++++++++++++++++++++++++++++++++--
+ extlibs/tinydtls/global.h | 1 +
+ extlibs/tinydtls/tests/dtls-client.c | 8 +-
+ 5 files changed, 444 insertions(+), 16 deletions(-)
+
+diff --git a/extlibs/tinydtls/crypto.c b/extlibs/tinydtls/crypto.c
+index 3fbb993..deaf581 100644
+--- a/extlibs/tinydtls/crypto.c
++++ b/extlibs/tinydtls/crypto.c
+@@ -641,6 +641,41 @@ dtls_ecdsa_verify_sig(const unsigned char *pub_key_x,
+ }
+ #endif /* DTLS_ECC */
+
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++int dtls_ecdhe_psk_pre_master_secret(unsigned char *psk, size_t psklen,
++ unsigned char *ecc_priv_key,
++ unsigned char *ecc_pub_key_x,
++ unsigned char *ecc_pub_key_y,
++ size_t ecc_key_size,
++ unsigned char *result,
++ size_t result_len)
++{
++ uint8_t eccPublicKey[64];
++ uint8_t eccPrivateKey[32];
++ unsigned char *p = result;
++
++ if (result_len < uECC_BYTES + psklen + (sizeof(uint16) * 2)) {
++ return -1;
++ }
++
++ dtls_int_to_uint16(p, uECC_BYTES);
++ p += sizeof(uint16);
++
++ memcpy(eccPublicKey, ecc_pub_key_x, 32);
++ memcpy(eccPublicKey + 32, ecc_pub_key_y, 32);
++ memcpy(eccPrivateKey, ecc_priv_key, 32);
++ uECC_shared_secret(eccPublicKey, eccPrivateKey, p);
++ p += uECC_BYTES;
++
++ dtls_int_to_uint16(p, psklen);
++ p += sizeof(uint16);
++
++ memcpy(p, psk, psklen);
++
++ return uECC_BYTES + psklen + (sizeof(uint16) * 2);
++}
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
++
+ int
+ dtls_encrypt(const unsigned char *src, size_t length,
+ unsigned char *buf,
+@@ -665,7 +700,8 @@ dtls_encrypt(const unsigned char *src, size_t length,
+ memmove(buf, src, length);
+ ret = dtls_ccm_encrypt(&ctx->data, src, length, buf, nounce, aad, la);
+ }
+- if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256) {
++ if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 ||
++ cipher == TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256) {
+ ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
+ if (ret < 0) {
+ /* cleanup everything in case the key has the wrong size */
+@@ -708,7 +744,8 @@ dtls_decrypt(const unsigned char *src, size_t length,
+ ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce, aad, la);
+ }
+
+- if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256) {
++ if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 ||
++ cipher == TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256) {
+ ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
+ if (ret < 0) {
+ /* cleanup everything in case the key has the wrong size */
+diff --git a/extlibs/tinydtls/crypto.h b/extlibs/tinydtls/crypto.h
+index a81d306..f4cfc66 100644
+--- a/extlibs/tinydtls/crypto.h
++++ b/extlibs/tinydtls/crypto.h
+@@ -39,6 +39,7 @@
+ #include "numeric.h"
+ #include "hmac.h"
+ #include "ccm.h"
++#include "ecc/ecc.h"
+
+ /* TLS_PSK_WITH_AES_128_CCM_8 */
+ #define DTLS_MAC_KEY_LENGTH 0
+@@ -129,6 +130,13 @@ typedef struct {
+ dtls_compression_t compression; /**< compression method */
+ dtls_cipher_t cipher; /**< cipher type */
+ unsigned int do_client_auth:1;
++
++#ifdef DTLS_ECC && DTLS_PSK
++ struct keyx_t {
++ dtls_handshake_parameters_ecc_t ecc;
++ dtls_handshake_parameters_psk_t psk;
++ } keyx;
++#else /* DTLS_ECC && DTLS_PSK */
+ union {
+ #ifdef DTLS_ECC
+ dtls_handshake_parameters_ecc_t ecc;
+@@ -137,6 +145,7 @@ typedef struct {
+ dtls_handshake_parameters_psk_t psk;
+ #endif /* DTLS_PSK */
+ } keyx;
++#endif /* DTLS_ECC && DTLS_PSK */
+ } dtls_handshake_parameters_t;
+
+ /* The following macros provide access to the components of the
+diff --git a/extlibs/tinydtls/dtls.c b/extlibs/tinydtls/dtls.c
+index b5b8fd1..6104a08 100644
+--- a/extlibs/tinydtls/dtls.c
++++ b/extlibs/tinydtls/dtls.c
+@@ -506,6 +506,17 @@ static inline int is_tls_ecdh_anon_with_aes_128_cbc_sha_256(dtls_cipher_t cipher
+ #endif
+ }
+
++/** returns true if the cipher matches TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 */
++static inline int is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(dtls_cipher_t cipher)
++{
++#if defined(DTLS_ECC) && defined(DTLS_PSK)
++ return cipher == TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256;
++#else
++ return 0;
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
++}
++
++
+
+ /** returns true if the application is configured for psk */
+ static inline int is_psk_supported(dtls_context_t *ctx)
+@@ -549,6 +560,17 @@ static inline int is_ecdh_anon_supported(dtls_context_t *ctx)
+ #endif
+ }
+
++/** returns true if ecdhe_psk_with_aes_128_cbc_sha_256 is supported */
++static inline int is_ecdhe_psk_supported(dtls_context_t *ctx)
++{
++#if defined(DTLS_ECC) && defined(DTLS_PSK)
++ return is_psk_supported(ctx);
++#else
++ return 0;
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
++}
++
++
+ /**
+ * Returns @c 1 if @p code is a cipher suite other than @c
+ * TLS_NULL_WITH_NULL_NULL that we recognize.
+@@ -563,14 +585,17 @@ known_cipher(dtls_context_t *ctx, dtls_cipher_t code, int is_client) {
+ int psk;
+ int ecdsa;
+ int ecdh_anon;
++ int ecdhe_psk;
+
+ psk = is_psk_supported(ctx);
+ ecdsa = is_ecdsa_supported(ctx, is_client);
+ ecdh_anon = is_ecdh_anon_supported(ctx);
++ ecdhe_psk = is_ecdhe_psk_supported(ctx);
+
+ return (psk && is_tls_psk_with_aes_128_ccm_8(code)) ||
+ (ecdsa && is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(code)) ||
+- (ecdh_anon && is_tls_ecdh_anon_with_aes_128_cbc_sha_256(code));
++ (ecdh_anon && is_tls_ecdh_anon_with_aes_128_cbc_sha_256(code)) ||
++ (ecdhe_psk && is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(code));
+ }
+
+ /**
+@@ -676,7 +701,11 @@ calculate_key_block(dtls_context_t *ctx,
+ dtls_peer_t *peer,
+ session_t *session,
+ dtls_peer_type role) {
+- unsigned char *pre_master_secret;
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++ unsigned char pre_master_secret[MAX_KEYBLOCK_LENGTH + uECC_BYTES];
++#else
++ unsigned char pre_master_secret[MAX_KEYBLOCK_LENGTH];
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+ int pre_master_len = 0;
+ dtls_security_parameters_t *security = dtls_security_params_next(peer);
+ uint8 master_secret[DTLS_MASTER_SECRET_LENGTH];
+@@ -685,8 +714,6 @@ calculate_key_block(dtls_context_t *ctx,
+ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+ }
+
+- pre_master_secret = security->key_block;
+-
+ switch (handshake->cipher) {
+ #ifdef DTLS_PSK
+ case TLS_PSK_WITH_AES_128_CCM_8: {
+@@ -733,6 +760,35 @@ calculate_key_block(dtls_context_t *ctx,
+ break;
+ }
+ #endif /* DTLS_ECC */
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++ case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256: {
++ unsigned char psk[DTLS_PSK_MAX_KEY_LEN];
++ int psklen;
++
++ psklen = CALL(ctx, get_psk_info, session, DTLS_PSK_KEY,
++ handshake->keyx.psk.identity,
++ handshake->keyx.psk.id_length,
++ psk, DTLS_PSK_MAX_KEY_LEN);
++ if (psklen < 0) {
++ dtls_crit("no psk key for session available\n");
++ return psklen;
++ }
++
++ pre_master_len = dtls_ecdhe_psk_pre_master_secret(psk, psklen,
++ handshake->keyx.ecc.own_eph_priv,
++ handshake->keyx.ecc.other_eph_pub_x,
++ handshake->keyx.ecc.other_eph_pub_y,
++ sizeof(handshake->keyx.ecc.own_eph_priv),
++ pre_master_secret,
++ MAX_KEYBLOCK_LENGTH + uECC_BYTES);
++
++ if (pre_master_len < 0) {
++ dtls_crit("the curve was too long, for the pre master secret\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
++ }
++ break;
++ }
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+ default:
+ dtls_crit("calculate_key_block: unknown cipher\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+@@ -1113,6 +1169,56 @@ check_client_keyexchange(dtls_context_t *ctx,
+ data += sizeof(handshake->keyx.ecc.other_eph_pub_y);
+ }
+ #endif /* DTLS_ECC */
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++ if (is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(handshake->cipher)) {
++ int id_length;
++
++ if (length < DTLS_HS_LENGTH + DTLS_CKXEC_LENGTH) {
++ dtls_debug("The client key exchange is too short\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++ }
++ data += DTLS_HS_LENGTH;
++
++ //PSK hint
++ id_length = dtls_uint16_to_int(data);
++ data += sizeof(uint16);
++
++ if (DTLS_HS_LENGTH + DTLS_CKXPSK_LENGTH_MIN + DTLS_CKXEC_LENGTH + id_length != length) {
++ dtls_debug("The identity has a wrong length\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++ }
++
++ if (id_length > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
++ dtls_warn("please use a smaller client identity\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
++ }
++
++ handshake->keyx.psk.id_length = id_length;
++ memcpy(handshake->keyx.psk.identity, data, id_length);
++ data += id_length;
++
++ //ECDH public
++ if (dtls_uint8_to_int(data) != 1 + 2 * DTLS_EC_KEY_SIZE) {
++ dtls_alert("expected 65 bytes long public point\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++ }
++ data += sizeof(uint8);
++
++ if (dtls_uint8_to_int(data) != 4) {
++ dtls_alert("expected uncompressed public point\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++ }
++ data += sizeof(uint8);
++
++ memcpy(handshake->keyx.ecc.other_eph_pub_x, data,
++ sizeof(handshake->keyx.ecc.other_eph_pub_x));
++ data += sizeof(handshake->keyx.ecc.other_eph_pub_x);
++
++ memcpy(handshake->keyx.ecc.other_eph_pub_y, data,
++ sizeof(handshake->keyx.ecc.other_eph_pub_y));
++ data += sizeof(handshake->keyx.ecc.other_eph_pub_y);
++ }
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+ #ifdef DTLS_PSK
+ if (is_tls_psk_with_aes_128_ccm_8(handshake->cipher)) {
+ int id_length;
+@@ -1286,7 +1392,8 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+ p += data_len_array[i];
+ res += data_len_array[i];
+ }
+- } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher)) {
++ } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher) ||
++ is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(security->cipher)) {
+
+ unsigned char nonce[DTLS_CBC_IV_LENGTH];
+
+@@ -2116,6 +2223,80 @@ dtls_send_server_key_exchange_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
+ }
+ #endif /* DTLS_ECC */
+
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++static int dtls_send_server_key_exchange_ecdhe_psk(dtls_context_t *ctx, dtls_peer_t *peer,
++ const unsigned char *psk_hint, size_t psk_hint_len)
++{
++ /* The ASN.1 Integer representation of an 32 byte unsigned int could be
++ * 33 bytes long add space for that */
++ uint8 buf[DTLS_SKEXEC_LENGTH + DTLS_SKEXECPSK_LENGTH_MAX + 2];
++ uint8 *p;
++ uint8 *ephemeral_pub_x;
++ uint8 *ephemeral_pub_y;
++ dtls_handshake_parameters_t *config = peer->handshake_params;
++
++ /* ServerKeyExchange
++ * Please see Session 2, RFC 5489.
++
++ struct {
++ select (KeyExchangeAlgorithm) {
++ //other cases for rsa, diffie_hellman, etc.
++ case ec_diffie_hellman_psk: // NEW
++ opaque psk_identity_hint<0..2^16-1>;
++ ServerECDHParams params;
++ };
++ } ServerKeyExchange; */
++ p = buf;
++
++ assert(psk_hint_len <= DTLS_PSK_MAX_CLIENT_IDENTITY_LEN);
++ if (psk_hint_len > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
++ // should never happen
++ dtls_warn("psk identity hint is too long\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
++ }
++
++ // psk_identity_hint
++ dtls_int_to_uint16(p, psk_hint_len);
++ p += sizeof(uint16);
++
++ memcpy(p, psk_hint, psk_hint_len);
++ p += psk_hint_len;
++
++ /* ServerECDHParams. */
++ /* ECCurveType curve_type: named_curve */
++ dtls_int_to_uint8(p, TLS_EC_CURVE_TYPE_NAMED_CURVE);
++ p += sizeof(uint8);
++
++ /* NamedCurve namedcurve: secp256r1 */
++ dtls_int_to_uint16(p, TLS_EXT_ELLIPTIC_CURVES_SECP256R1);
++ p += sizeof(uint16);
++
++ dtls_int_to_uint8(p, 1 + 2 * DTLS_EC_KEY_SIZE);
++ p += sizeof(uint8);
++
++ /* This should be an uncompressed point, but I do not have access to the spec. */
++ dtls_int_to_uint8(p, 4);
++ p += sizeof(uint8);
++
++ /* store the pointer to the x component of the pub key and make space */
++ ephemeral_pub_x = p;
++ p += DTLS_EC_KEY_SIZE;
++
++ /* store the pointer to the y component of the pub key and make space */
++ ephemeral_pub_y = p;
++ p += DTLS_EC_KEY_SIZE;
++
++ dtls_ecdsa_generate_key(config->keyx.ecc.own_eph_priv,
++ ephemeral_pub_x, ephemeral_pub_y,
++ DTLS_EC_KEY_SIZE);
++
++ assert(p - buf <= sizeof(buf));
++
++ return dtls_send_handshake_msg(ctx, peer, DTLS_HT_SERVER_KEY_EXCHANGE,
++ buf, p - buf);
++}
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
++
+ #ifdef DTLS_PSK
+ static int
+ dtls_send_server_key_exchange_psk(dtls_context_t *ctx, dtls_peer_t *peer,
+@@ -2207,6 +2388,7 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
+ int res;
+ int ecdsa;
+ int ecdh_anon;
++ int ecdhe_psk;
+
+ res = dtls_send_server_hello(ctx, peer);
+
+@@ -2217,6 +2399,7 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
+
+ ecdsa = is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher);
+ ecdh_anon = is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher);
++ ecdhe_psk = is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(peer->handshake_params->cipher);
+
+ #ifdef DTLS_ECC
+ if(ecdh_anon) {
+@@ -2261,7 +2444,31 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
+ }
+ }
+ #endif /* DTLS_ECC */
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++ else if(ecdhe_psk) {
++ unsigned char psk_hint[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
++ int psk_len;
++
++ /* The identity hint is optional, therefore we ignore the result
++ * and check psk only. */
++ psk_len = CALL(ctx, get_psk_info, &peer->session, DTLS_PSK_HINT,
++ NULL, 0, psk_hint, DTLS_PSK_MAX_CLIENT_IDENTITY_LEN);
+
++ if (psk_len < 0) {
++ dtls_debug("dtls_server_hello: cannot create ServerKeyExchange\n");
++ return psk_len;
++ }
++
++ if (psk_len > 0) {
++ res = dtls_send_server_key_exchange_ecdhe_psk(ctx, peer, psk_hint, (size_t)psk_len);
++
++ if (res < 0) {
++ dtls_debug("dtls_server_hello(with ECDHE): cannot prepare Server Key Exchange record\n");
++ return res;
++ }
++ }
++ }
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+ #ifdef DTLS_PSK
+ if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
+ unsigned char psk_hint[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
+@@ -2308,7 +2515,11 @@ dtls_send_ccs(dtls_context_t *ctx, dtls_peer_t *peer) {
+ static int
+ dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
+ {
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++ uint8 buf[DTLS_CKXEC_LENGTH + 2 + DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
++#else
+ uint8 buf[DTLS_CKXEC_LENGTH];
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+ uint8 client_id[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
+ uint8 *p;
+ dtls_handshake_parameters_t *handshake = peer->handshake_params;
+@@ -2368,6 +2579,60 @@ dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
+ break;
+ }
+ #endif /* DTLS_ECC */
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++ case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256: {
++ int psk_len;
++ uint8 *ephemeral_pub_x;
++ uint8 *ephemeral_pub_y;
++
++ /* Please see Session 2, RFC 5489.
++ struct {
++ select (KeyExchangeAlgorithm) {
++ // other cases for rsa, diffie_hellman, etc.
++ case ec_diffie_hellman_psk:
++ opaque psk_identity<0..2^16-1>;
++ ClientECDiffieHellmanPublic public;
++ } exchange_keys;
++ } ClientKeyExchange;
++ */
++
++ psk_len = CALL(ctx, get_psk_info, &peer->session, DTLS_PSK_IDENTITY,
++ NULL, 0,
++ client_id,
++ sizeof(client_id));
++ if (psk_len < 0) {
++ dtls_crit("no psk identity set in kx\n");
++ return psk_len;
++ }
++
++ if (psk_len + sizeof(uint16) > DTLS_CKXEC_LENGTH) {
++ dtls_warn("the psk identity is too long\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
++ }
++
++ dtls_int_to_uint16(p, psk_len);
++ p += sizeof(uint16);
++
++ memcpy(p, client_id, psk_len);
++ p += psk_len;
++
++ dtls_int_to_uint8(p, 1 + 2 * DTLS_EC_KEY_SIZE);
++ p += sizeof(uint8);
++
++ dtls_int_to_uint8(p, 4);
++ p += sizeof(uint8);
++
++ ephemeral_pub_x = p;
++ p += DTLS_EC_KEY_SIZE;
++ ephemeral_pub_y = p;
++ p += DTLS_EC_KEY_SIZE;
++
++ dtls_ecdsa_generate_key(peer->handshake_params->keyx.ecc.own_eph_priv,
++ ephemeral_pub_x, ephemeral_pub_y,
++ DTLS_EC_KEY_SIZE);
++ break;
++ }
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+ default:
+ dtls_crit("cipher not supported\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+@@ -2457,6 +2722,7 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
+ int psk = 0;
+ int ecdsa = 0;
+ int ecdh_anon = 0;
++ int ecdhe_psk = 0;
+ dtls_handshake_parameters_t *handshake = peer->handshake_params;
+ dtls_tick_t now;
+
+@@ -2471,14 +2737,18 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
+ case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256:
+ ecdh_anon = is_ecdh_anon_supported(ctx);
+ break;
++ case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256:
++ ecdhe_psk = is_ecdhe_psk_supported(ctx);
++ break;
+ default:
+ psk = is_psk_supported(ctx);
+ ecdsa = is_ecdsa_supported(ctx, 1);
+ ecdh_anon = is_ecdh_anon_supported(ctx);
++ ecdhe_psk = is_ecdhe_psk_supported(ctx);
+ break;
+ }
+
+- cipher_size = 2 + (ecdsa ? 2 : 0) + (psk ? 2 : 0) + (ecdh_anon ? 2 : 0);
++ cipher_size = 2 + (ecdsa ? 2 : 0) + (psk ? 2 : 0) + (ecdh_anon ? 2 : 0) + (ecdhe_psk ? 2 : 0);
+ extension_size = (ecdsa) ? (2 + 6 + 6 + 8 + 6) : 0;
+
+ if (cipher_size == 0) {
+@@ -2533,6 +2803,10 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
+ dtls_int_to_uint16(p, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+ p += sizeof(uint16);
+ }
++ if (ecdhe_psk) {
++ dtls_int_to_uint16(p, TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
++ p += sizeof(uint16);
++ }
+
+ /* compression method */
+ dtls_int_to_uint8(p, 1);
+@@ -2900,8 +3174,97 @@ check_server_key_exchange_ecdh(dtls_context_t *ctx,
+
+ return 0;
+ }
+-
+ #endif /* DTLS_ECC */
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++check_server_key_exchange_ecdhe_psk(dtls_context_t *ctx,
++ dtls_peer_t *peer,
++ uint8 *data, size_t data_length)
++{
++ dtls_handshake_parameters_t *config = peer->handshake_params;
++ uint16_t psk_len = 0;
++
++ /* ServerKeyExchange
++ * Please see Session 2, RFC 5489.
++
++ struct {
++ select (KeyExchangeAlgorithm) {
++ //other cases for rsa, diffie_hellman, etc.
++ case ec_diffie_hellman_psk: // NEW
++ opaque psk_identity_hint<0..2^16-1>;
++ ServerECDHParams params;
++ };
++ } ServerKeyExchange; */
++
++ update_hs_hash(peer, data, data_length);
++
++ assert(is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(config->cipher));
++
++ data += DTLS_HS_LENGTH;
++
++ psk_len = dtls_uint16_to_int(data);
++ data += sizeof(uint16);
++
++ if (psk_len != data_length - DTLS_HS_LENGTH - DTLS_SKEXEC_ECDH_ANON_LENGTH - sizeof(uint16)) {
++ dtls_warn("the length of the server identity hint is worng\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
++ }
++
++ if (psk_len > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
++ dtls_warn("please use a smaller server identity hint\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
++ }
++
++ // store the psk_identity_hint in config->keyx.psk for later use
++ config->keyx.psk.id_length = psk_len;
++ memcpy(config->keyx.psk.identity, data, psk_len);
++
++ data += psk_len;
++ data_length -= psk_len;
++
++ if (data_length < DTLS_HS_LENGTH + DTLS_SKEXEC_ECDH_ANON_LENGTH) {
++ dtls_alert("the packet length does not match the expected\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
++ }
++
++ if (dtls_uint8_to_int(data) != TLS_EC_CURVE_TYPE_NAMED_CURVE) {
++ dtls_alert("Only named curves supported\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++ }
++ data += sizeof(uint8);
++ data_length -= sizeof(uint8);
++
++ if (dtls_uint16_to_int(data) != TLS_EXT_ELLIPTIC_CURVES_SECP256R1) {
++ dtls_alert("secp256r1 supported\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++ }
++ data += sizeof(uint16);
++ data_length -= sizeof(uint16);
++
++ if (dtls_uint8_to_int(data) != 1 + 2 * DTLS_EC_KEY_SIZE) {
++ dtls_alert("expected 65 bytes long public point\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++ }
++ data += sizeof(uint8);
++ data_length -= sizeof(uint8);
++
++ if (dtls_uint8_to_int(data) != 4) {
++ dtls_alert("expected uncompressed public point\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
++ }
++ data += sizeof(uint8);
++ data_length -= sizeof(uint8);
++
++ memcpy(config->keyx.ecc.other_eph_pub_x, data, sizeof(config->keyx.ecc.other_eph_pub_x));
++ data += sizeof(config->keyx.ecc.other_eph_pub_x);
++ data_length -= sizeof(config->keyx.ecc.other_eph_pub_x);
++
++ memcpy(config->keyx.ecc.other_eph_pub_y, data, sizeof(config->keyx.ecc.other_eph_pub_y));
++ data += sizeof(config->keyx.ecc.other_eph_pub_y);
++ data_length -= sizeof(config->keyx.ecc.other_eph_pub_y);
++
++ return 0;
++}
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+
+ #ifdef DTLS_PSK
+ static int
+@@ -3113,7 +3476,8 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
+ if (security->cipher == TLS_NULL_WITH_NULL_NULL) {
+ /* no cipher suite selected */
+ return clen;
+- } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher)) {
++ } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher) ||
++ is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(security->cipher)) {
+
+ unsigned char nonce[DTLS_CBC_IV_LENGTH];
+
+@@ -3169,17 +3533,17 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
+ dtls_kb_remote_write_key(security, peer->role),
+ dtls_kb_key_size(security, peer->role),
+ A_DATA, A_DATA_LEN,
+- security->cipher);
++ security->cipher);
+ }
+
+ if (clen < 0)
+ dtls_warn("decryption failed\n");
+ else {
+ #ifndef NDEBUG
+- dtls_debug("decrypt_verify(): found %i bytes cleartext\n", clen);
++ dtls_debug("decrypt_verify(): found %i bytes cleartext\n", clen);
+ #endif
+- dtls_security_params_free_other(peer);
+- dtls_debug_dump("cleartext", *cleartext, clen);
++ dtls_security_params_free_other(peer);
++ dtls_debug_dump("cleartext", *cleartext, clen);
+ }
+
+ return clen;
+@@ -3282,7 +3646,8 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
+ }
+ if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher))
+ peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE; //ecdsa
+- else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher))
++ else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher) ||
++ is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(peer->handshake_params->cipher))
+ peer->state = DTLS_STATE_WAIT_SERVERKEYEXCHANGE; //ecdh
+ else
+ peer->state = DTLS_STATE_WAIT_SERVERHELLODONE; //psk
+@@ -3329,6 +3694,16 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
+ err = check_server_key_exchange_ecdh(ctx, peer, data, data_length);
+ }
+ #endif /* DTLS_ECC */
++
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++ if (is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(peer->handshake_params->cipher)) {
++ if (state != DTLS_STATE_WAIT_SERVERKEYEXCHANGE) {
++ return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
++ }
++ err = check_server_key_exchange_ecdhe_psk(ctx, peer, data, data_length);
++ }
++#endif defined(DTLS_PSK) && defined(DTLS_ECC)
++
+ #ifdef DTLS_PSK
+ if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
+ if (state != DTLS_STATE_WAIT_SERVERHELLODONE) {
+diff --git a/extlibs/tinydtls/global.h b/extlibs/tinydtls/global.h
+index 169c726..8b3c518 100644
+--- a/extlibs/tinydtls/global.h
++++ b/extlibs/tinydtls/global.h
+@@ -75,6 +75,7 @@ typedef enum {
+ TLS_NULL_WITH_NULL_NULL = 0x0000, /**< NULL cipher */
+ TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 = 0xC018, /**< see RFC 4492 */
+ TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8, /**< see RFC 6655 */
++ TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 = 0xC037, /**< see RFC 5489 */
+ TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE /**< see RFC 7251 */
+ } dtls_cipher_t;
+
+diff --git a/extlibs/tinydtls/tests/dtls-client.c b/extlibs/tinydtls/tests/dtls-client.c
+index dfc822a..dfd34c8 100644
+--- a/extlibs/tinydtls/tests/dtls-client.c
++++ b/extlibs/tinydtls/tests/dtls-client.c
+@@ -311,7 +311,8 @@ usage( const char *program, const char *version) {
+ "\t-c num\t\tcipher suite (default: 1)\n"
+ "\t\t\t1: TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 \n"
+ "\t\t\t2: TLS_PSK_WITH_AES_128_CCM_8\n"
+- "\t\t\t3: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n",
++ "\t\t\t3: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n"
++ "\t\t\t4: TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256\n",
+ program, version, program, DEFAULT_PORT);
+ }
+
+@@ -430,6 +431,11 @@ main(int argc, char **argv) {
+ selected_cipher = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ;
+ ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
+ }
++ else if( strcmp(optarg, "4") == 0)
++ {
++ selected_cipher = TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256;
++ ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
++ }
+ break;
+ default:
+ usage(argv[0], dtls_package_version());
+--
+1.7.9.5
+
--- /dev/null
+From 1ee27820ccad59423711c83fb01ff58939511f3b Mon Sep 17 00:00:00 2001
+From: Sachin Agrawal <sachin.agrawal@intel.com>
+Date: Mon, 29 Jun 2015 22:26:21 -0700
+Subject: [PATCH 1/1] Fix the wrong implementation about the anonymous cipher
+ suite of tinydtls. (NOTE : This patch has been modified
+ based on RFC 5246)
+
+1. IV for CBC block operation
+ - Apply the random IV for CBC block operations according to section 6.2.3.2 of RFC 5246.
+
+2. MAC calculation
+ - Apply HMAC for DTLS MAC calculation according to section 6.2.3.1 of RFC 5246.
+
+3. CBC padding
+ - Apply PKCS#5 padding for CBC block cipher accroding to section 6.2.3.2 of RFC 5246.
+
+4. Change the cipher suite name TLS_ECDH_anon_WITH_AES_128_CBC_SHA
+ to TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256.
+
+5. Fix the minor bug in dtls sample.
+
+Change-Id: I8783caa6ac04fe2d46e242efe56e3205646b1038
+Signed-off-by: leechul <chuls.lee@samsung.com>
+Signed-off-by: Sachin Agrawal <sachin.agrawal@intel.com>
+---
+ extlibs/tinydtls/crypto.c | 100 +++++++++++++-----
+ extlibs/tinydtls/crypto.h | 1 +
+ extlibs/tinydtls/dtls.c | 111 +++++++++++++++-----
+ extlibs/tinydtls/dtls.h | 6 +-
+ extlibs/tinydtls/global.h | 2 +-
+ extlibs/tinydtls/tests/dtls-client.c | 8 +-
+ extlibs/tinydtls/tests/dtls-server.c | 8 +-
+ resource/csdk/connectivity/api/cainterface.h | 4 +-
+ resource/csdk/connectivity/inc/caadapternetdtls.h | 2 +-
+ .../src/adapter_util/caadapternetdtls.c | 2 +-
+ .../provisioning/src/provisioningmanager.c | 2 +-
+ 11 files changed, 180 insertions(+), 66 deletions(-)
+
+diff --git a/extlibs/tinydtls/crypto.c b/extlibs/tinydtls/crypto.c
+index 5082535..3fbb993 100644
+--- a/extlibs/tinydtls/crypto.c
++++ b/extlibs/tinydtls/crypto.c
+@@ -58,6 +58,7 @@
+ #include "sha2/sha2.h"
+ #include "prng.h"
+ #include "netq.h"
++#include "hmac.h"
+
+ #ifndef WITH_CONTIKI
+ #include <pthread.h>
+@@ -329,6 +330,7 @@ dtls_ccm_decrypt(aes128_t *ccm_ctx, const unsigned char *src,
+
+ static size_t
+ dtls_cbc_encrypt(aes128_t *aes_ctx,
++ unsigned char *key, size_t keylen,
+ const unsigned char *iv,
+ const unsigned char *src, size_t srclen,
+ unsigned char *buf) {
+@@ -336,18 +338,35 @@ dtls_cbc_encrypt(aes128_t *aes_ctx,
+ unsigned char cbc[DTLS_BLK_LENGTH];
+ unsigned char tmp[DTLS_BLK_LENGTH];
+ unsigned char *pos;
+- dtls_hash_ctx shactx;
++ const unsigned char *dtls_hdr = NULL;
+ int i, j;
+ int blocks;
++ dtls_hmac_context_t* hmac_ctx = NULL;
++ int paddinglen = 0;
+
+ pos = buf;
+
+- dtls_hash_init(&shactx);
+- dtls_hash_update(&shactx, src, srclen);
+- dtls_hash_finalize(pos + srclen, &shactx);
++ dtls_hdr = src - DTLS_CBC_IV_LENGTH - sizeof(dtls_record_header_t);
++
++ //Calculate MAC : Append the MAC code to end of content
++ hmac_ctx = dtls_hmac_new(key, keylen);
++ dtls_mac(hmac_ctx,
++ dtls_hdr,
++ src, srclen,
++ buf + srclen);
++ dtls_hmac_free(hmac_ctx);
++
++ dtls_debug_dump("[MAC]",
++ buf + srclen,
++ DTLS_HMAC_DIGEST_SIZE);
++
++ paddinglen = DTLS_BLK_LENGTH - ((srclen + DTLS_HMAC_DIGEST_SIZE) % DTLS_BLK_LENGTH);
++
++ //TLS padding
++ memset(buf + (srclen + DTLS_HMAC_DIGEST_SIZE), paddinglen - 1, paddinglen);
+
+ memcpy(cbc, iv, DTLS_BLK_LENGTH);
+- blocks = (srclen + SHA256_DIGEST_LENGTH) / DTLS_BLK_LENGTH;
++ blocks = (srclen + DTLS_HMAC_DIGEST_SIZE + paddinglen) / DTLS_BLK_LENGTH;
+
+ for (i = 0; i < blocks; i++) {
+ for (j = 0; j < DTLS_BLK_LENGTH; j++) {
+@@ -360,14 +379,17 @@ dtls_cbc_encrypt(aes128_t *aes_ctx,
+ pos += DTLS_BLK_LENGTH;
+ }
+
+- dtls_debug_dump("Encrypted Data:", buf, srclen + SHA256_DIGEST_LENGTH);
+-
+- return srclen + SHA256_DIGEST_LENGTH;
++ dtls_debug_dump("[Encrypted Data]",
++ buf,
++ srclen + DTLS_HMAC_DIGEST_SIZE + paddinglen);
++
++ return srclen + DTLS_HMAC_DIGEST_SIZE + paddinglen;
+ }
+
+
+ static size_t
+ dtls_cbc_decrypt(aes128_t *aes_ctx,
++ unsigned char *key, size_t keylen,
+ const unsigned char *iv,
+ const unsigned char *src, size_t srclen,
+ unsigned char *buf) {
+@@ -375,14 +397,17 @@ dtls_cbc_decrypt(aes128_t *aes_ctx,
+ unsigned char cbc[DTLS_BLK_LENGTH];
+ unsigned char tmp[DTLS_BLK_LENGTH];
+ unsigned char tmp2[DTLS_BLK_LENGTH];
+- unsigned char msg_hash[SHA256_DIGEST_LENGTH];
++ unsigned char mac_buf[DTLS_HMAC_DIGEST_SIZE] = {0,};
++ const unsigned char *dtls_hdr = NULL;
+ unsigned char *pos;
+- dtls_hash_ctx shactx;
+ int i, j;
+ int blocks;
++ int depaddinglen = 0;
++ dtls_hmac_context_t* hmac_ctx = NULL;
+
+ pos = buf;
+- memcpy(pos, src, srclen);
++
++ dtls_hdr = src - DTLS_CBC_IV_LENGTH - sizeof(dtls_record_header_t);
+
+ memcpy(cbc, iv, DTLS_BLK_LENGTH);
+ blocks = srclen / DTLS_BLK_LENGTH;
+@@ -401,19 +426,46 @@ dtls_cbc_decrypt(aes128_t *aes_ctx,
+ pos += DTLS_BLK_LENGTH;
+ }
+
+- dtls_hash_init(&shactx);
+- dtls_hash_update(&shactx, buf, srclen - SHA256_DIGEST_LENGTH);
+- dtls_hash_finalize(msg_hash, &shactx);
+-
+- dtls_debug_dump("decrypted data:", buf, srclen);
++ //de-padding
++ depaddinglen = buf[srclen -1];
+
+- if(memcmp(msg_hash, buf + (srclen - SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH) != 0)
++ //Calculate MAC
++ hmac_ctx = dtls_hmac_new(key, keylen);
++ if(!hmac_ctx) {
++ return -1;
++ }
++ dtls_mac(hmac_ctx, dtls_hdr, buf,
++ srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1,
++ mac_buf);
++ dtls_hmac_free(hmac_ctx);
++
++ dtls_debug_dump("[MAC]",
++ mac_buf,
++ DTLS_HMAC_DIGEST_SIZE);
++ dtls_debug_dump("[Decrypted data]",
++ buf,
++ srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1);
++
++ //verify the MAC
++ if(memcmp(mac_buf,
++ buf + (srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1),
++ DTLS_HMAC_DIGEST_SIZE) != 0)
+ {
+- dtls_warn("message is broken\n");
++ dtls_crit("Failed to verification of MAC\n");
+ return -1;
+ }
+
+- return srclen - SHA256_DIGEST_LENGTH;
++ //verify the padding bytes
++ for (i =0; i < depaddinglen; i++)
++ {
++ if (buf[srclen - depaddinglen - 1 + i] != depaddinglen)
++ {
++ dtls_crit("Failed to verify padding bytes\n");
++ return -1;
++ }
++ }
++
++ return srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1;
+ }
+
+ #ifdef DTLS_PSK
+@@ -523,8 +575,6 @@ void
+ dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size,
+ const unsigned char *sign_hash, size_t sign_hash_size,
+ uint32_t point_r[9], uint32_t point_s[9]) {
+- int ret;
+-
+ uint8_t privateKey[32];
+ uint8_t hashValue[32];
+ uint8_t sign[64];
+@@ -615,7 +665,7 @@ dtls_encrypt(const unsigned char *src, size_t length,
+ memmove(buf, src, length);
+ ret = dtls_ccm_encrypt(&ctx->data, src, length, buf, nounce, aad, la);
+ }
+- if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA) {
++ if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256) {
+ ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
+ if (ret < 0) {
+ /* cleanup everything in case the key has the wrong size */
+@@ -625,7 +675,7 @@ dtls_encrypt(const unsigned char *src, size_t length,
+
+ if (src != buf)
+ memmove(buf, src, length);
+- ret = dtls_cbc_encrypt(&ctx->data, nounce, src, length, buf);
++ ret = dtls_cbc_encrypt(&ctx->data, key, keylen, nounce, src, length, buf);
+ }
+
+ error:
+@@ -658,7 +708,7 @@ dtls_decrypt(const unsigned char *src, size_t length,
+ ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce, aad, la);
+ }
+
+- if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA) {
++ if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256) {
+ ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
+ if (ret < 0) {
+ /* cleanup everything in case the key has the wrong size */
+@@ -668,7 +718,7 @@ dtls_decrypt(const unsigned char *src, size_t length,
+
+ if (src != buf)
+ memmove(buf, src, length);
+- ret = dtls_cbc_decrypt(&ctx->data, nounce, src, length, buf);
++ ret = dtls_cbc_decrypt(&ctx->data, key, keylen, nounce, src, length, buf);
+ }
+
+ error:
+diff --git a/extlibs/tinydtls/crypto.h b/extlibs/tinydtls/crypto.h
+index dd13ffa..a81d306 100644
+--- a/extlibs/tinydtls/crypto.h
++++ b/extlibs/tinydtls/crypto.h
+@@ -46,6 +46,7 @@
+ #define DTLS_BLK_LENGTH 16 /* AES-128 */
+ #define DTLS_MAC_LENGTH DTLS_HMAC_DIGEST_SIZE
+ #define DTLS_IV_LENGTH 4 /* length of nonce_explicit */
++#define DTLS_CBC_IV_LENGTH 16
+
+ /**
+ * Maximum size of the generated keyblock. Note that MAX_KEYBLOCK_LENGTH must
+diff --git a/extlibs/tinydtls/dtls.c b/extlibs/tinydtls/dtls.c
+index 41e68a5..b5b8fd1 100644
+--- a/extlibs/tinydtls/dtls.c
++++ b/extlibs/tinydtls/dtls.c
+@@ -496,11 +496,11 @@ static inline int is_tls_psk_with_aes_128_ccm_8(dtls_cipher_t cipher)
+ #endif /* DTLS_PSK */
+ }
+
+-/** returns true if the cipher matches TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
+-static inline int is_tls_ecdh_anon_with_aes_128_cbc_sha(dtls_cipher_t cipher)
++/** returns true if the cipher matches TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 */
++static inline int is_tls_ecdh_anon_with_aes_128_cbc_sha_256(dtls_cipher_t cipher)
+ {
+ #ifdef DTLS_ECC
+- return cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
++ return cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256;
+ #else
+ return 0;
+ #endif
+@@ -570,7 +570,7 @@ known_cipher(dtls_context_t *ctx, dtls_cipher_t code, int is_client) {
+
+ return (psk && is_tls_psk_with_aes_128_ccm_8(code)) ||
+ (ecdsa && is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(code)) ||
+- (ecdh_anon && is_tls_ecdh_anon_with_aes_128_cbc_sha(code));
++ (ecdh_anon && is_tls_ecdh_anon_with_aes_128_cbc_sha_256(code));
+ }
+
+ /**
+@@ -719,7 +719,7 @@ calculate_key_block(dtls_context_t *ctx,
+ #endif /* DTLS_PSK */
+ #ifdef DTLS_ECC
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+- case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: {
++ case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256: {
+ pre_master_len = dtls_ecdh_pre_master_secret(handshake->keyx.ecc.own_eph_priv,
+ handshake->keyx.ecc.other_eph_pub_x,
+ handshake->keyx.ecc.other_eph_pub_y,
+@@ -1084,7 +1084,7 @@ check_client_keyexchange(dtls_context_t *ctx,
+
+ #ifdef DTLS_ECC
+ if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher) ||
+- is_tls_ecdh_anon_with_aes_128_cbc_sha(handshake->cipher) ) {
++ is_tls_ecdh_anon_with_aes_128_cbc_sha_256(handshake->cipher) ) {
+
+ if (length < DTLS_HS_LENGTH + DTLS_CKXEC_LENGTH) {
+ dtls_debug("The client key exchange is too short\n");
+@@ -1286,6 +1286,51 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+ p += data_len_array[i];
+ res += data_len_array[i];
+ }
++ } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher)) {
++
++ unsigned char nonce[DTLS_CBC_IV_LENGTH];
++
++ /** Add IV into body of packet in case of AES CBC mode according to RFC 5246, Section 6.2.3.2
++ *
++ * opaque IV[SecurityParameters.record_iv_length];
++ * block-ciphered struct {
++ * opaque content[TLSCompressed.length];
++ * opaque MAC[SecurityParameters.mac_length];
++ * uint8 padding[GenericBlockCipher.padding_length];
++ * uint8 padding_length;
++ * };
++ *
++ */
++
++ res = 0;
++ dtls_prng(nonce, DTLS_CBC_IV_LENGTH);
++ memcpy(p , nonce, DTLS_CBC_IV_LENGTH);
++ p += DTLS_CBC_IV_LENGTH;
++ res += DTLS_CBC_IV_LENGTH;
++
++ for (i = 0; i < data_array_len; i++) {
++ /* check the minimum that we need for packets that are not encrypted */
++ if (*rlen < res + DTLS_RH_LENGTH + data_len_array[i]) {
++ dtls_debug("dtls_prepare_record: send buffer too small\n");
++ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
++ }
++
++ memcpy(p, data_array[i], data_len_array[i]);
++ p += data_len_array[i];
++ res += data_len_array[i];
++ }
++
++ res = dtls_encrypt(start + DTLS_CBC_IV_LENGTH, res - DTLS_CBC_IV_LENGTH,
++ start + DTLS_CBC_IV_LENGTH, nonce,
++ dtls_kb_local_write_key(security, peer->role),
++ dtls_kb_key_size(security, peer->role),
++ NULL, 0,
++ security->cipher);
++ if (res < 0)
++ return res;
++
++ res += DTLS_CBC_IV_LENGTH;
++
+ } else { /* TLS_PSK_WITH_AES_128_CCM_8 or TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */
+ /**
+ * length of additional_data for the AEAD cipher which consists of
+@@ -1299,8 +1344,6 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+ dtls_debug("dtls_prepare_record(): encrypt using TLS_PSK_WITH_AES_128_CCM_8\n");
+ } else if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(security->cipher)) {
+ dtls_debug("dtls_prepare_record(): encrypt using TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n");
+- } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha(security->cipher)) {
+- dtls_debug("dtls_prepare_record() : encrypt using TLS_ECDH_anon_WITH_AES_128_CBC_SHA\n");
+ } else {
+ dtls_debug("dtls_prepare_record(): encrypt using unknown cipher\n");
+ }
+@@ -1363,7 +1406,7 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+
+ memset(nonce, 0, DTLS_CCM_BLOCKSIZE);
+ memcpy(nonce, dtls_kb_local_iv(security, peer->role),
+- dtls_kb_iv_size(security, peer->role));
++ dtls_kb_iv_size(security, peer->role));
+ memcpy(nonce + dtls_kb_iv_size(security, peer->role), start, 8); /* epoch + seq_num */
+
+ dtls_debug_dump("nonce:", nonce, DTLS_CCM_BLOCKSIZE);
+@@ -1378,7 +1421,8 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+ memcpy(A_DATA, &DTLS_RECORD_HEADER(sendbuf)->epoch, 8); /* epoch and seq_num */
+ memcpy(A_DATA + 8, &DTLS_RECORD_HEADER(sendbuf)->content_type, 3); /* type and version */
+ dtls_int_to_uint16(A_DATA + 11, res - 8); /* length */
+-
++
++
+ res = dtls_encrypt(start + 8, res - 8, start + 8, nonce,
+ dtls_kb_local_write_key(security, peer->role),
+ dtls_kb_key_size(security, peer->role),
+@@ -1388,7 +1432,7 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+ if (res < 0)
+ return res;
+
+- res += 8; /* increment res by size of nonce_explicit */
++ res += 8; /* increment res by size of nonce_explicit */
+ dtls_debug_dump("message:", start, res);
+ }
+
+@@ -2172,7 +2216,7 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
+ }
+
+ ecdsa = is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher);
+- ecdh_anon = is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher);
++ ecdh_anon = is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher);
+
+ #ifdef DTLS_ECC
+ if(ecdh_anon) {
+@@ -2301,7 +2345,7 @@ dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
+ #endif /* DTLS_PSK */
+ #ifdef DTLS_ECC
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+- case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: {
++ case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256: {
+ uint8 *ephemeral_pub_x;
+ uint8 *ephemeral_pub_y;
+
+@@ -2424,7 +2468,7 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+ ecdsa = is_ecdsa_supported(ctx, 1);
+ break;
+- case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
++ case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256:
+ ecdh_anon = is_ecdh_anon_supported(ctx);
+ break;
+ default:
+@@ -2478,7 +2522,7 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
+ p += sizeof(uint16);
+
+ if (ecdh_anon) {
+- dtls_int_to_uint16(p, TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
++ dtls_int_to_uint16(p, TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256);
+ p += sizeof(uint16);
+ }
+ if (psk) {
+@@ -2809,7 +2853,7 @@ check_server_key_exchange_ecdh(dtls_context_t *ctx,
+
+ update_hs_hash(peer, data, data_length);
+
+- assert(is_tls_ecdh_anon_with_aes_128_cbc_sha(config->cipher));
++ assert(is_tls_ecdh_anon_with_aes_128_cbc_sha_256(config->cipher));
+
+ data += DTLS_HS_LENGTH;
+
+@@ -3069,6 +3113,23 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
+ if (security->cipher == TLS_NULL_WITH_NULL_NULL) {
+ /* no cipher suite selected */
+ return clen;
++ } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher)) {
++
++ unsigned char nonce[DTLS_CBC_IV_LENGTH];
++
++ if (clen < (DTLS_CBC_IV_LENGTH + DTLS_HMAC_DIGEST_SIZE)) /* need at least IV and MAC */
++ return -1;
++
++ memcpy(nonce, *cleartext , DTLS_CBC_IV_LENGTH);
++ clen -= DTLS_CBC_IV_LENGTH;
++ *cleartext += DTLS_CBC_IV_LENGTH ;
++
++ clen = dtls_decrypt(*cleartext, clen, *cleartext, nonce,
++ dtls_kb_remote_write_key(security, peer->role),
++ dtls_kb_key_size(security, peer->role),
++ NULL, 0,
++ security->cipher);
++
+ } else { /* TLS_PSK_WITH_AES_128_CCM_8 or TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */
+ /**
+ * length of additional_data for the AEAD cipher which consists of
+@@ -3083,7 +3144,7 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
+
+ memset(nonce, 0, DTLS_CCM_BLOCKSIZE);
+ memcpy(nonce, dtls_kb_remote_iv(security, peer->role),
+- dtls_kb_iv_size(security, peer->role));
++ dtls_kb_iv_size(security, peer->role));
+
+ /* read epoch and seq_num from message */
+ memcpy(nonce + dtls_kb_iv_size(security, peer->role), *cleartext, 8);
+@@ -3108,17 +3169,19 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
+ dtls_kb_remote_write_key(security, peer->role),
+ dtls_kb_key_size(security, peer->role),
+ A_DATA, A_DATA_LEN,
+- security->cipher);
+- if (clen < 0)
+- dtls_warn("decryption failed\n");
+- else {
++ security->cipher);
++ }
++
++ if (clen < 0)
++ dtls_warn("decryption failed\n");
++ else {
+ #ifndef NDEBUG
+ dtls_debug("decrypt_verify(): found %i bytes cleartext\n", clen);
+ #endif
+ dtls_security_params_free_other(peer);
+ dtls_debug_dump("cleartext", *cleartext, clen);
+- }
+ }
++
+ return clen;
+ }
+
+@@ -3219,7 +3282,7 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
+ }
+ if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher))
+ peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE; //ecdsa
+- else if (is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher))
++ else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher))
+ peer->state = DTLS_STATE_WAIT_SERVERKEYEXCHANGE; //ecdh
+ else
+ peer->state = DTLS_STATE_WAIT_SERVERHELLODONE; //psk
+@@ -3259,7 +3322,7 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
+ err = check_server_key_exchange_ecdsa(ctx, peer, data, data_length);
+ }
+
+- if (is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher)) {
++ if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher)) {
+ if (state != DTLS_STATE_WAIT_SERVERKEYEXCHANGE) {
+ return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
+ }
+diff --git a/extlibs/tinydtls/dtls.h b/extlibs/tinydtls/dtls.h
+index a2ab86e..7d2bc19 100644
+--- a/extlibs/tinydtls/dtls.h
++++ b/extlibs/tinydtls/dtls.h
+@@ -238,7 +238,7 @@ typedef struct dtls_context_t {
+
+ dtls_handler_t *h; /**< callback handlers */
+
+- dtls_cipher_enable_t is_anon_ecdh_eabled; /**< enable/disable the TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
++ dtls_cipher_enable_t is_anon_ecdh_eabled; /**< enable/disable the TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 */
+
+ dtls_cipher_t selected_cipher; /**< selected ciper suite for handshake */
+
+@@ -268,7 +268,7 @@ static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
+ }
+
+ /**
+- * @brief Enabling the TLS_ECDH_anon_WITH_AES_128_CBC_SHA
++ * @brief Enabling the TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256
+ *
+ * @param ctx The DTLS context to use.
+ * @param is_enable DTLS_CIPHER_ENABLE(1) or DTLS_CIPHER_DISABLE(0)
+@@ -279,7 +279,7 @@ void dtls_enables_anon_ecdh(dtls_context_t* ctx, dtls_cipher_enable_t is_enable)
+ * @brief Select the cipher suite for handshake
+ *
+ * @param ctx The DTLS context to use.
+- * @param cipher TLS_ECDH_anon_WITH_AES_128_CBC_SHA (0xC018)
++ * @param cipher TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 (0xC018)
+ * TLS_PSK_WITH_AES_128_CCM_8 (0xX0A8)
+ * TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 (0xC0AE)
+ */
+diff --git a/extlibs/tinydtls/global.h b/extlibs/tinydtls/global.h
+index 441710f..169c726 100644
+--- a/extlibs/tinydtls/global.h
++++ b/extlibs/tinydtls/global.h
+@@ -73,7 +73,7 @@ typedef unsigned char uint48[6];
+ /** Known cipher suites.*/
+ typedef enum {
+ TLS_NULL_WITH_NULL_NULL = 0x0000, /**< NULL cipher */
+- TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018, /**< see RFC 4492 */
++ TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 = 0xC018, /**< see RFC 4492 */
+ TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8, /**< see RFC 6655 */
+ TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE /**< see RFC 7251 */
+ } dtls_cipher_t;
+diff --git a/extlibs/tinydtls/tests/dtls-client.c b/extlibs/tinydtls/tests/dtls-client.c
+index 35521e9..dfc822a 100644
+--- a/extlibs/tinydtls/tests/dtls-client.c
++++ b/extlibs/tinydtls/tests/dtls-client.c
+@@ -309,7 +309,7 @@ usage( const char *program, const char *version) {
+ "\t-p port\t\tlisten on specified port (default is %d)\n"
+ "\t-v num\t\tverbosity level (default: 3)\n"
+ "\t-c num\t\tcipher suite (default: 1)\n"
+- "\t\t\t1: TLS_ECDH_anon_WITH_AES_128_CBC_SHA \n"
++ "\t\t\t1: TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 \n"
+ "\t\t\t2: TLS_PSK_WITH_AES_128_CCM_8\n"
+ "\t\t\t3: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n",
+ program, version, program, DEFAULT_PORT);
+@@ -347,7 +347,7 @@ main(int argc, char **argv) {
+ log_t log_level = DTLS_LOG_WARN;
+ int fd, result;
+ int on = 1;
+- dtls_cipher_t selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
++ dtls_cipher_t selected_cipher = TLS_NULL_WITH_NULL_NULL;
+ dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
+ int opt, res;
+ session_t dst;
+@@ -417,7 +417,7 @@ main(int argc, char **argv) {
+ case 'c':
+ if( strcmp(optarg, "1") == 0)
+ {
+- selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
++ selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256;
+ ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
+ }
+ else if( strcmp(optarg, "2") == 0)
+@@ -500,7 +500,7 @@ main(int argc, char **argv) {
+ /* select cipher suite */
+ dtls_select_cipher(dtls_context, selected_cipher);
+
+- /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha */
++ /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
+ dtls_enables_anon_ecdh(dtls_context, ecdh_anon_enalbe);
+
+ dtls_set_handler(dtls_context, &cb);
+diff --git a/extlibs/tinydtls/tests/dtls-server.c b/extlibs/tinydtls/tests/dtls-server.c
+index d3da1a7..5893084 100644
+--- a/extlibs/tinydtls/tests/dtls-server.c
++++ b/extlibs/tinydtls/tests/dtls-server.c
+@@ -254,8 +254,8 @@ usage(const char *program, const char *version) {
+ "\t-p port\t\tlisten on specified port (default is %d)\n"
+ "\t-v num\t\tverbosity level (default: 3)\n"
+ "\t-a enable|disable\t(default: disable)\n"
+- "\t\t\t\tenable:enable TLS_ECDH_anon_with_AES_128_CBC_SHA\n"
+- "\t\t\t\tdisable:disable TLS_ECDH_anon_with_AES_128_CBC_SHA\n",
++ "\t\t\t\tenable:enable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n"
++ "\t\t\t\tdisable:disable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n",
+ program, version, program, DEFAULT_PORT);
+ }
+
+@@ -280,7 +280,7 @@ main(int argc, char **argv) {
+ struct timeval timeout;
+ int fd, opt, result;
+ int on = 1;
+- int ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
++ dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
+ struct sockaddr_in6 listen_addr;
+
+ memset(&listen_addr, 0, sizeof(struct sockaddr_in6));
+@@ -356,7 +356,7 @@ main(int argc, char **argv) {
+
+ the_context = dtls_new_context(&fd);
+
+- /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha */
++ /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
+ dtls_enables_anon_ecdh(the_context, ecdh_anon_enalbe);
+
+ dtls_set_handler(the_context, &cb);
+diff --git a/resource/csdk/connectivity/api/cainterface.h b/resource/csdk/connectivity/api/cainterface.h
+index 760df09..2f10fd5 100644
+--- a/resource/csdk/connectivity/api/cainterface.h
++++ b/resource/csdk/connectivity/api/cainterface.h
+@@ -290,7 +290,7 @@ CAResult_t CAHandleRequestResponse();
+ * Select the cipher suite for dtls handshake
+ *
+ * @param[IN] cipher cipher suite (Note : Make sure endianness)
+- * 0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA
++ * 0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256
+ * 0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8
+ * 0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+ *
+@@ -301,7 +301,7 @@ CAResult_t CAHandleRequestResponse();
+ CAResult_t CASelectCipherSuite(const uint16_t cipher);
+
+ /**
+- * Enable TLS_ECDH_anon_WITH_AES_128_CBC_SHA cipher suite in dtls
++ * Enable TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 cipher suite in dtls
+ *
+ * @param[IN] enable TRUE/FALSE enables/disables anonymous cipher suite
+ *
+diff --git a/resource/csdk/connectivity/inc/caadapternetdtls.h b/resource/csdk/connectivity/inc/caadapternetdtls.h
+index f9f99d8..274321e 100644
+--- a/resource/csdk/connectivity/inc/caadapternetdtls.h
++++ b/resource/csdk/connectivity/inc/caadapternetdtls.h
+@@ -160,7 +160,7 @@ void CADTLSSetCredentialsCallback(CAGetDTLSCredentialsHandler credCallback);
+ * Select the cipher suite for dtls handshake
+ *
+ * @param[in] cipher cipher suite
+- * 0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA
++ * 0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256
+ * 0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8
+ * 0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+ *
+diff --git a/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c b/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c
+index 8f01c06..6fd83e8 100644
+--- a/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c
++++ b/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c
+@@ -598,7 +598,7 @@ CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable)
+ dtls_enables_anon_ecdh(g_caDtlsContext->dtlsContext,
+ enable == true ? DTLS_CIPHER_ENABLE : DTLS_CIPHER_DISABLE);
+ ca_mutex_unlock(g_dtlsContextMutex);
+- OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA is %s",
++ OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 is %s",
+ enable ? "enabled" : "disabled");
+
+ OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
+diff --git a/resource/csdk/security/provisioning/src/provisioningmanager.c b/resource/csdk/security/provisioning/src/provisioningmanager.c
+index defe4e6..301614d 100644
+--- a/resource/csdk/security/provisioning/src/provisioningmanager.c
++++ b/resource/csdk/security/provisioning/src/provisioningmanager.c
+@@ -1031,7 +1031,7 @@ static SPResult updateOperationMode(unsigned short timeout, SPTargetDeviceInfo_t
+ */
+ static SPResult initiateDtlsHandshake(const SPTargetDeviceInfo_t *deviceInfo)
+ {
+- CAResult_t caresult = CASelectCipherSuite(TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
++ CAResult_t caresult = CASelectCipherSuite(TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256);
+
+ if (CA_STATUS_OK != caresult)
+ {
+--
+1.7.9.5
+
#include "sha2/sha2.h"
#include "prng.h"
#include "netq.h"
+#include "hmac.h"
#ifndef WITH_CONTIKI
#include <pthread.h>
static size_t
dtls_cbc_encrypt(aes128_t *aes_ctx,
+ unsigned char *key, size_t keylen,
const unsigned char *iv,
const unsigned char *src, size_t srclen,
unsigned char *buf) {
unsigned char cbc[DTLS_BLK_LENGTH];
unsigned char tmp[DTLS_BLK_LENGTH];
unsigned char *pos;
- dtls_hash_ctx shactx;
+ const unsigned char *dtls_hdr = NULL;
int i, j;
int blocks;
+ dtls_hmac_context_t* hmac_ctx = NULL;
+ int paddinglen = 0;
pos = buf;
- dtls_hash_init(&shactx);
- dtls_hash_update(&shactx, src, srclen);
- dtls_hash_finalize(pos + srclen, &shactx);
+ dtls_hdr = src - DTLS_CBC_IV_LENGTH - sizeof(dtls_record_header_t);
+
+ //Calculate MAC : Append the MAC code to end of content
+ hmac_ctx = dtls_hmac_new(key, keylen);
+ dtls_mac(hmac_ctx,
+ dtls_hdr,
+ src, srclen,
+ buf + srclen);
+ dtls_hmac_free(hmac_ctx);
+
+ dtls_debug_dump("[MAC]",
+ buf + srclen,
+ DTLS_HMAC_DIGEST_SIZE);
+
+ paddinglen = DTLS_BLK_LENGTH - ((srclen + DTLS_HMAC_DIGEST_SIZE) % DTLS_BLK_LENGTH);
+
+ //TLS padding
+ memset(buf + (srclen + DTLS_HMAC_DIGEST_SIZE), paddinglen - 1, paddinglen);
memcpy(cbc, iv, DTLS_BLK_LENGTH);
- blocks = (srclen + SHA256_DIGEST_LENGTH) / DTLS_BLK_LENGTH;
+ blocks = (srclen + DTLS_HMAC_DIGEST_SIZE + paddinglen) / DTLS_BLK_LENGTH;
for (i = 0; i < blocks; i++) {
for (j = 0; j < DTLS_BLK_LENGTH; j++) {
pos += DTLS_BLK_LENGTH;
}
- dtls_debug_dump("Encrypted Data:", buf, srclen + SHA256_DIGEST_LENGTH);
-
- return srclen + SHA256_DIGEST_LENGTH;
+ dtls_debug_dump("[Encrypted Data]",
+ buf,
+ srclen + DTLS_HMAC_DIGEST_SIZE + paddinglen);
+
+ return srclen + DTLS_HMAC_DIGEST_SIZE + paddinglen;
}
static size_t
dtls_cbc_decrypt(aes128_t *aes_ctx,
+ unsigned char *key, size_t keylen,
const unsigned char *iv,
const unsigned char *src, size_t srclen,
unsigned char *buf) {
unsigned char cbc[DTLS_BLK_LENGTH];
unsigned char tmp[DTLS_BLK_LENGTH];
unsigned char tmp2[DTLS_BLK_LENGTH];
- unsigned char msg_hash[SHA256_DIGEST_LENGTH];
+ unsigned char mac_buf[DTLS_HMAC_DIGEST_SIZE] = {0,};
+ const unsigned char *dtls_hdr = NULL;
unsigned char *pos;
- dtls_hash_ctx shactx;
int i, j;
int blocks;
+ int depaddinglen = 0;
+ dtls_hmac_context_t* hmac_ctx = NULL;
pos = buf;
- memcpy(pos, src, srclen);
+
+ dtls_hdr = src - DTLS_CBC_IV_LENGTH - sizeof(dtls_record_header_t);
memcpy(cbc, iv, DTLS_BLK_LENGTH);
blocks = srclen / DTLS_BLK_LENGTH;
pos += DTLS_BLK_LENGTH;
}
- dtls_hash_init(&shactx);
- dtls_hash_update(&shactx, buf, srclen - SHA256_DIGEST_LENGTH);
- dtls_hash_finalize(msg_hash, &shactx);
-
- dtls_debug_dump("decrypted data:", buf, srclen);
+ //de-padding
+ depaddinglen = buf[srclen -1];
- if(memcmp(msg_hash, buf + (srclen - SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH) != 0)
+ //Calculate MAC
+ hmac_ctx = dtls_hmac_new(key, keylen);
+ if(!hmac_ctx) {
+ return -1;
+ }
+ dtls_mac(hmac_ctx, dtls_hdr, buf,
+ srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1,
+ mac_buf);
+ dtls_hmac_free(hmac_ctx);
+
+ dtls_debug_dump("[MAC]",
+ mac_buf,
+ DTLS_HMAC_DIGEST_SIZE);
+ dtls_debug_dump("[Decrypted data]",
+ buf,
+ srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1);
+
+ //verify the MAC
+ if(memcmp(mac_buf,
+ buf + (srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1),
+ DTLS_HMAC_DIGEST_SIZE) != 0)
{
- dtls_warn("message is broken\n");
+ dtls_crit("Failed to verification of MAC\n");
return -1;
}
- return srclen - SHA256_DIGEST_LENGTH;
+ //verify the padding bytes
+ for (i =0; i < depaddinglen; i++)
+ {
+ if (buf[srclen - depaddinglen - 1 + i] != depaddinglen)
+ {
+ dtls_crit("Failed to verify padding bytes\n");
+ return -1;
+ }
+ }
+
+ return srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1;
}
#ifdef DTLS_PSK
dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size,
const unsigned char *sign_hash, size_t sign_hash_size,
uint32_t point_r[9], uint32_t point_s[9]) {
- int ret;
-
uint8_t privateKey[32];
uint8_t hashValue[32];
uint8_t sign[64];
}
#endif /* DTLS_ECC */
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+int dtls_ecdhe_psk_pre_master_secret(unsigned char *psk, size_t psklen,
+ unsigned char *ecc_priv_key,
+ unsigned char *ecc_pub_key_x,
+ unsigned char *ecc_pub_key_y,
+ size_t ecc_key_size,
+ unsigned char *result,
+ size_t result_len)
+{
+ uint8_t eccPublicKey[64];
+ uint8_t eccPrivateKey[32];
+ unsigned char *p = result;
+
+ if (result_len < uECC_BYTES + psklen + (sizeof(uint16) * 2)) {
+ return -1;
+ }
+
+ dtls_int_to_uint16(p, uECC_BYTES);
+ p += sizeof(uint16);
+
+ memcpy(eccPublicKey, ecc_pub_key_x, 32);
+ memcpy(eccPublicKey + 32, ecc_pub_key_y, 32);
+ memcpy(eccPrivateKey, ecc_priv_key, 32);
+ uECC_shared_secret(eccPublicKey, eccPrivateKey, p);
+ p += uECC_BYTES;
+
+ dtls_int_to_uint16(p, psklen);
+ p += sizeof(uint16);
+
+ memcpy(p, psk, psklen);
+
+ return uECC_BYTES + psklen + (sizeof(uint16) * 2);
+}
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+
int
dtls_encrypt(const unsigned char *src, size_t length,
unsigned char *buf,
memmove(buf, src, length);
ret = dtls_ccm_encrypt(&ctx->data, src, length, buf, nounce, aad, la);
}
- if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA) {
+ if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 ||
+ cipher == TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256) {
ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
if (ret < 0) {
/* cleanup everything in case the key has the wrong size */
if (src != buf)
memmove(buf, src, length);
- ret = dtls_cbc_encrypt(&ctx->data, nounce, src, length, buf);
+ ret = dtls_cbc_encrypt(&ctx->data, key, keylen, nounce, src, length, buf);
}
error:
ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce, aad, la);
}
- if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA) {
+ if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 ||
+ cipher == TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256) {
ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
if (ret < 0) {
/* cleanup everything in case the key has the wrong size */
if (src != buf)
memmove(buf, src, length);
- ret = dtls_cbc_decrypt(&ctx->data, nounce, src, length, buf);
+ ret = dtls_cbc_decrypt(&ctx->data, key, keylen, nounce, src, length, buf);
}
error:
#include "numeric.h"
#include "hmac.h"
#include "ccm.h"
+#include "ecc/ecc.h"
/* TLS_PSK_WITH_AES_128_CCM_8 */
#define DTLS_MAC_KEY_LENGTH 0
#define DTLS_BLK_LENGTH 16 /* AES-128 */
#define DTLS_MAC_LENGTH DTLS_HMAC_DIGEST_SIZE
#define DTLS_IV_LENGTH 4 /* length of nonce_explicit */
+#define DTLS_CBC_IV_LENGTH 16
/**
* Maximum size of the generated keyblock. Note that MAX_KEYBLOCK_LENGTH must
dtls_compression_t compression; /**< compression method */
dtls_cipher_t cipher; /**< cipher type */
unsigned int do_client_auth:1;
+
+#ifdef DTLS_ECC && DTLS_PSK
+ struct keyx_t {
+ dtls_handshake_parameters_ecc_t ecc;
+ dtls_handshake_parameters_psk_t psk;
+ } keyx;
+#else /* DTLS_ECC && DTLS_PSK */
union {
#ifdef DTLS_ECC
dtls_handshake_parameters_ecc_t ecc;
dtls_handshake_parameters_psk_t psk;
#endif /* DTLS_PSK */
} keyx;
+#endif /* DTLS_ECC && DTLS_PSK */
} dtls_handshake_parameters_t;
/* The following macros provide access to the components of the
#endif /* DTLS_PSK */
}
-/** returns true if the cipher matches TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
-static inline int is_tls_ecdh_anon_with_aes_128_cbc_sha(dtls_cipher_t cipher)
+/** returns true if the cipher matches TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 */
+static inline int is_tls_ecdh_anon_with_aes_128_cbc_sha_256(dtls_cipher_t cipher)
{
#ifdef DTLS_ECC
- return cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
+ return cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256;
#else
return 0;
#endif
}
+/** returns true if the cipher matches TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 */
+static inline int is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(dtls_cipher_t cipher)
+{
+#if defined(DTLS_ECC) && defined(DTLS_PSK)
+ return cipher == TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256;
+#else
+ return 0;
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+}
+
+
/** returns true if the application is configured for psk */
static inline int is_psk_supported(dtls_context_t *ctx)
#endif
}
+/** returns true if ecdhe_psk_with_aes_128_cbc_sha_256 is supported */
+static inline int is_ecdhe_psk_supported(dtls_context_t *ctx)
+{
+#if defined(DTLS_ECC) && defined(DTLS_PSK)
+ return is_psk_supported(ctx);
+#else
+ return 0;
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+}
+
+
/**
* Returns @c 1 if @p code is a cipher suite other than @c
* TLS_NULL_WITH_NULL_NULL that we recognize.
int psk;
int ecdsa;
int ecdh_anon;
+ int ecdhe_psk;
psk = is_psk_supported(ctx);
ecdsa = is_ecdsa_supported(ctx, is_client);
ecdh_anon = is_ecdh_anon_supported(ctx);
+ ecdhe_psk = is_ecdhe_psk_supported(ctx);
return (psk && is_tls_psk_with_aes_128_ccm_8(code)) ||
(ecdsa && is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(code)) ||
- (ecdh_anon && is_tls_ecdh_anon_with_aes_128_cbc_sha(code));
+ (ecdh_anon && is_tls_ecdh_anon_with_aes_128_cbc_sha_256(code)) ||
+ (ecdhe_psk && is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(code));
}
/**
dtls_peer_t *peer,
session_t *session,
dtls_peer_type role) {
- unsigned char *pre_master_secret;
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+ unsigned char pre_master_secret[MAX_KEYBLOCK_LENGTH + uECC_BYTES];
+#else
+ unsigned char pre_master_secret[MAX_KEYBLOCK_LENGTH];
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
int pre_master_len = 0;
dtls_security_parameters_t *security = dtls_security_params_next(peer);
uint8 master_secret[DTLS_MASTER_SECRET_LENGTH];
return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
}
- pre_master_secret = security->key_block;
-
switch (handshake->cipher) {
#ifdef DTLS_PSK
case TLS_PSK_WITH_AES_128_CCM_8: {
#endif /* DTLS_PSK */
#ifdef DTLS_ECC
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
- case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: {
+ case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256: {
pre_master_len = dtls_ecdh_pre_master_secret(handshake->keyx.ecc.own_eph_priv,
handshake->keyx.ecc.other_eph_pub_x,
handshake->keyx.ecc.other_eph_pub_y,
break;
}
#endif /* DTLS_ECC */
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+ case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256: {
+ unsigned char psk[DTLS_PSK_MAX_KEY_LEN];
+ int psklen;
+
+ psklen = CALL(ctx, get_psk_info, session, DTLS_PSK_KEY,
+ handshake->keyx.psk.identity,
+ handshake->keyx.psk.id_length,
+ psk, DTLS_PSK_MAX_KEY_LEN);
+ if (psklen < 0) {
+ dtls_crit("no psk key for session available\n");
+ return psklen;
+ }
+
+ pre_master_len = dtls_ecdhe_psk_pre_master_secret(psk, psklen,
+ handshake->keyx.ecc.own_eph_priv,
+ handshake->keyx.ecc.other_eph_pub_x,
+ handshake->keyx.ecc.other_eph_pub_y,
+ sizeof(handshake->keyx.ecc.own_eph_priv),
+ pre_master_secret,
+ MAX_KEYBLOCK_LENGTH + uECC_BYTES);
+
+ if (pre_master_len < 0) {
+ dtls_crit("the curve was too long, for the pre master secret\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+ }
+ break;
+ }
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
default:
dtls_crit("calculate_key_block: unknown cipher\n");
return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
#ifdef DTLS_ECC
if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher) ||
- is_tls_ecdh_anon_with_aes_128_cbc_sha(handshake->cipher) ) {
+ is_tls_ecdh_anon_with_aes_128_cbc_sha_256(handshake->cipher) ) {
if (length < DTLS_HS_LENGTH + DTLS_CKXEC_LENGTH) {
dtls_debug("The client key exchange is too short\n");
data += sizeof(handshake->keyx.ecc.other_eph_pub_y);
}
#endif /* DTLS_ECC */
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+ if (is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(handshake->cipher)) {
+ int id_length;
+
+ if (length < DTLS_HS_LENGTH + DTLS_CKXEC_LENGTH) {
+ dtls_debug("The client key exchange is too short\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+ }
+ data += DTLS_HS_LENGTH;
+
+ //PSK hint
+ id_length = dtls_uint16_to_int(data);
+ data += sizeof(uint16);
+
+ if (DTLS_HS_LENGTH + DTLS_CKXPSK_LENGTH_MIN + DTLS_CKXEC_LENGTH + id_length != length) {
+ dtls_debug("The identity has a wrong length\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+ }
+
+ if (id_length > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
+ dtls_warn("please use a smaller client identity\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+ }
+
+ handshake->keyx.psk.id_length = id_length;
+ memcpy(handshake->keyx.psk.identity, data, id_length);
+ data += id_length;
+
+ //ECDH public
+ if (dtls_uint8_to_int(data) != 1 + 2 * DTLS_EC_KEY_SIZE) {
+ dtls_alert("expected 65 bytes long public point\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+ }
+ data += sizeof(uint8);
+
+ if (dtls_uint8_to_int(data) != 4) {
+ dtls_alert("expected uncompressed public point\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+ }
+ data += sizeof(uint8);
+
+ memcpy(handshake->keyx.ecc.other_eph_pub_x, data,
+ sizeof(handshake->keyx.ecc.other_eph_pub_x));
+ data += sizeof(handshake->keyx.ecc.other_eph_pub_x);
+
+ memcpy(handshake->keyx.ecc.other_eph_pub_y, data,
+ sizeof(handshake->keyx.ecc.other_eph_pub_y));
+ data += sizeof(handshake->keyx.ecc.other_eph_pub_y);
+ }
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
#ifdef DTLS_PSK
if (is_tls_psk_with_aes_128_ccm_8(handshake->cipher)) {
int id_length;
p += data_len_array[i];
res += data_len_array[i];
}
+ } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher) ||
+ is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(security->cipher)) {
+
+ unsigned char nonce[DTLS_CBC_IV_LENGTH];
+
+ /** Add IV into body of packet in case of AES CBC mode according to RFC 5246, Section 6.2.3.2
+ *
+ * opaque IV[SecurityParameters.record_iv_length];
+ * block-ciphered struct {
+ * opaque content[TLSCompressed.length];
+ * opaque MAC[SecurityParameters.mac_length];
+ * uint8 padding[GenericBlockCipher.padding_length];
+ * uint8 padding_length;
+ * };
+ *
+ */
+
+ res = 0;
+ dtls_prng(nonce, DTLS_CBC_IV_LENGTH);
+ memcpy(p , nonce, DTLS_CBC_IV_LENGTH);
+ p += DTLS_CBC_IV_LENGTH;
+ res += DTLS_CBC_IV_LENGTH;
+
+ for (i = 0; i < data_array_len; i++) {
+ /* check the minimum that we need for packets that are not encrypted */
+ if (*rlen < res + DTLS_RH_LENGTH + data_len_array[i]) {
+ dtls_debug("dtls_prepare_record: send buffer too small\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+ }
+
+ memcpy(p, data_array[i], data_len_array[i]);
+ p += data_len_array[i];
+ res += data_len_array[i];
+ }
+
+ res = dtls_encrypt(start + DTLS_CBC_IV_LENGTH, res - DTLS_CBC_IV_LENGTH,
+ start + DTLS_CBC_IV_LENGTH, nonce,
+ dtls_kb_local_write_key(security, peer->role),
+ dtls_kb_key_size(security, peer->role),
+ NULL, 0,
+ security->cipher);
+ if (res < 0)
+ return res;
+
+ res += DTLS_CBC_IV_LENGTH;
+
} else { /* TLS_PSK_WITH_AES_128_CCM_8 or TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */
/**
* length of additional_data for the AEAD cipher which consists of
dtls_debug("dtls_prepare_record(): encrypt using TLS_PSK_WITH_AES_128_CCM_8\n");
} else if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(security->cipher)) {
dtls_debug("dtls_prepare_record(): encrypt using TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n");
- } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha(security->cipher)) {
- dtls_debug("dtls_prepare_record() : encrypt using TLS_ECDH_anon_WITH_AES_128_CBC_SHA\n");
} else {
dtls_debug("dtls_prepare_record(): encrypt using unknown cipher\n");
}
memset(nonce, 0, DTLS_CCM_BLOCKSIZE);
memcpy(nonce, dtls_kb_local_iv(security, peer->role),
- dtls_kb_iv_size(security, peer->role));
+ dtls_kb_iv_size(security, peer->role));
memcpy(nonce + dtls_kb_iv_size(security, peer->role), start, 8); /* epoch + seq_num */
dtls_debug_dump("nonce:", nonce, DTLS_CCM_BLOCKSIZE);
memcpy(A_DATA, &DTLS_RECORD_HEADER(sendbuf)->epoch, 8); /* epoch and seq_num */
memcpy(A_DATA + 8, &DTLS_RECORD_HEADER(sendbuf)->content_type, 3); /* type and version */
dtls_int_to_uint16(A_DATA + 11, res - 8); /* length */
-
+
+
res = dtls_encrypt(start + 8, res - 8, start + 8, nonce,
dtls_kb_local_write_key(security, peer->role),
dtls_kb_key_size(security, peer->role),
if (res < 0)
return res;
- res += 8; /* increment res by size of nonce_explicit */
+ res += 8; /* increment res by size of nonce_explicit */
dtls_debug_dump("message:", start, res);
}
}
#ifdef DTLS_ECC
+#define DTLS_EC_SUBJECTPUBLICKEY_SIZE (2 * DTLS_EC_KEY_SIZE + sizeof(cert_asn1_header))
+
static int
dtls_send_certificate_ecdsa(dtls_context_t *ctx, dtls_peer_t *peer,
const dtls_ecc_key_t *key)
* Start message construction at beginning of buffer. */
p = buf;
- dtls_int_to_uint24(p, 94); /* certificates length */
+ /* length of this certificate */
+ dtls_int_to_uint24(p, DTLS_EC_SUBJECTPUBLICKEY_SIZE);
p += sizeof(uint24);
- dtls_int_to_uint24(p, 91); /* length of this certificate */
- p += sizeof(uint24);
-
memcpy(p, &cert_asn1_header, sizeof(cert_asn1_header));
p += sizeof(cert_asn1_header);
}
#endif /* DTLS_ECC */
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+static int dtls_send_server_key_exchange_ecdhe_psk(dtls_context_t *ctx, dtls_peer_t *peer,
+ const unsigned char *psk_hint, size_t psk_hint_len)
+{
+ /* The ASN.1 Integer representation of an 32 byte unsigned int could be
+ * 33 bytes long add space for that */
+ uint8 buf[DTLS_SKEXEC_LENGTH + DTLS_SKEXECPSK_LENGTH_MAX + 2];
+ uint8 *p;
+ uint8 *ephemeral_pub_x;
+ uint8 *ephemeral_pub_y;
+ dtls_handshake_parameters_t *config = peer->handshake_params;
+
+ /* ServerKeyExchange
+ * Please see Session 2, RFC 5489.
+
+ struct {
+ select (KeyExchangeAlgorithm) {
+ //other cases for rsa, diffie_hellman, etc.
+ case ec_diffie_hellman_psk: // NEW
+ opaque psk_identity_hint<0..2^16-1>;
+ ServerECDHParams params;
+ };
+ } ServerKeyExchange; */
+ p = buf;
+
+ assert(psk_hint_len <= DTLS_PSK_MAX_CLIENT_IDENTITY_LEN);
+ if (psk_hint_len > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
+ // should never happen
+ dtls_warn("psk identity hint is too long\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+ }
+
+ // psk_identity_hint
+ dtls_int_to_uint16(p, psk_hint_len);
+ p += sizeof(uint16);
+
+ memcpy(p, psk_hint, psk_hint_len);
+ p += psk_hint_len;
+
+ /* ServerECDHParams. */
+ /* ECCurveType curve_type: named_curve */
+ dtls_int_to_uint8(p, TLS_EC_CURVE_TYPE_NAMED_CURVE);
+ p += sizeof(uint8);
+
+ /* NamedCurve namedcurve: secp256r1 */
+ dtls_int_to_uint16(p, TLS_EXT_ELLIPTIC_CURVES_SECP256R1);
+ p += sizeof(uint16);
+
+ dtls_int_to_uint8(p, 1 + 2 * DTLS_EC_KEY_SIZE);
+ p += sizeof(uint8);
+
+ /* This should be an uncompressed point, but I do not have access to the spec. */
+ dtls_int_to_uint8(p, 4);
+ p += sizeof(uint8);
+
+ /* store the pointer to the x component of the pub key and make space */
+ ephemeral_pub_x = p;
+ p += DTLS_EC_KEY_SIZE;
+
+ /* store the pointer to the y component of the pub key and make space */
+ ephemeral_pub_y = p;
+ p += DTLS_EC_KEY_SIZE;
+
+ dtls_ecdsa_generate_key(config->keyx.ecc.own_eph_priv,
+ ephemeral_pub_x, ephemeral_pub_y,
+ DTLS_EC_KEY_SIZE);
+
+ assert(p - buf <= sizeof(buf));
+
+ return dtls_send_handshake_msg(ctx, peer, DTLS_HT_SERVER_KEY_EXCHANGE,
+ buf, p - buf);
+}
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+
#ifdef DTLS_PSK
static int
dtls_send_server_key_exchange_psk(dtls_context_t *ctx, dtls_peer_t *peer,
int res;
int ecdsa;
int ecdh_anon;
+ int ecdhe_psk;
res = dtls_send_server_hello(ctx, peer);
}
ecdsa = is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher);
- ecdh_anon = is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher);
+ ecdh_anon = is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher);
+ ecdhe_psk = is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(peer->handshake_params->cipher);
#ifdef DTLS_ECC
if(ecdh_anon) {
}
}
#endif /* DTLS_ECC */
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+ else if(ecdhe_psk) {
+ unsigned char psk_hint[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
+ int psk_len;
+ /* The identity hint is optional, therefore we ignore the result
+ * and check psk only. */
+ psk_len = CALL(ctx, get_psk_info, &peer->session, DTLS_PSK_HINT,
+ NULL, 0, psk_hint, DTLS_PSK_MAX_CLIENT_IDENTITY_LEN);
+
+ if (psk_len < 0) {
+ dtls_debug("dtls_server_hello: cannot create ServerKeyExchange\n");
+ return psk_len;
+ }
+
+ if (psk_len > 0) {
+ res = dtls_send_server_key_exchange_ecdhe_psk(ctx, peer, psk_hint, (size_t)psk_len);
+
+ if (res < 0) {
+ dtls_debug("dtls_server_hello(with ECDHE): cannot prepare Server Key Exchange record\n");
+ return res;
+ }
+ }
+ }
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
#ifdef DTLS_PSK
if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
unsigned char psk_hint[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
static int
dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
{
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+ uint8 buf[DTLS_CKXEC_LENGTH + 2 + DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
+#else
uint8 buf[DTLS_CKXEC_LENGTH];
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
uint8 client_id[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
uint8 *p;
dtls_handshake_parameters_t *handshake = peer->handshake_params;
#endif /* DTLS_PSK */
#ifdef DTLS_ECC
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
- case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: {
+ case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256: {
uint8 *ephemeral_pub_x;
uint8 *ephemeral_pub_y;
break;
}
#endif /* DTLS_ECC */
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+ case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256: {
+ int psk_len;
+ uint8 *ephemeral_pub_x;
+ uint8 *ephemeral_pub_y;
+
+ /* Please see Session 2, RFC 5489.
+ struct {
+ select (KeyExchangeAlgorithm) {
+ // other cases for rsa, diffie_hellman, etc.
+ case ec_diffie_hellman_psk:
+ opaque psk_identity<0..2^16-1>;
+ ClientECDiffieHellmanPublic public;
+ } exchange_keys;
+ } ClientKeyExchange;
+ */
+
+ psk_len = CALL(ctx, get_psk_info, &peer->session, DTLS_PSK_IDENTITY,
+ NULL, 0,
+ client_id,
+ sizeof(client_id));
+ if (psk_len < 0) {
+ dtls_crit("no psk identity set in kx\n");
+ return psk_len;
+ }
+
+ if (psk_len + sizeof(uint16) > DTLS_CKXEC_LENGTH) {
+ dtls_warn("the psk identity is too long\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+ }
+
+ dtls_int_to_uint16(p, psk_len);
+ p += sizeof(uint16);
+
+ memcpy(p, client_id, psk_len);
+ p += psk_len;
+
+ dtls_int_to_uint8(p, 1 + 2 * DTLS_EC_KEY_SIZE);
+ p += sizeof(uint8);
+
+ dtls_int_to_uint8(p, 4);
+ p += sizeof(uint8);
+
+ ephemeral_pub_x = p;
+ p += DTLS_EC_KEY_SIZE;
+ ephemeral_pub_y = p;
+ p += DTLS_EC_KEY_SIZE;
+
+ dtls_ecdsa_generate_key(peer->handshake_params->keyx.ecc.own_eph_priv,
+ ephemeral_pub_x, ephemeral_pub_y,
+ DTLS_EC_KEY_SIZE);
+ break;
+ }
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
default:
dtls_crit("cipher not supported\n");
return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
int psk = 0;
int ecdsa = 0;
int ecdh_anon = 0;
+ int ecdhe_psk = 0;
dtls_handshake_parameters_t *handshake = peer->handshake_params;
dtls_tick_t now;
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
ecdsa = is_ecdsa_supported(ctx, 1);
break;
- case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
+ case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256:
ecdh_anon = is_ecdh_anon_supported(ctx);
break;
+ case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256:
+ ecdhe_psk = is_ecdhe_psk_supported(ctx);
+ break;
default:
psk = is_psk_supported(ctx);
ecdsa = is_ecdsa_supported(ctx, 1);
ecdh_anon = is_ecdh_anon_supported(ctx);
+ ecdhe_psk = is_ecdhe_psk_supported(ctx);
break;
}
- cipher_size = 2 + (ecdsa ? 2 : 0) + (psk ? 2 : 0) + (ecdh_anon ? 2 : 0);
+ cipher_size = 2 + (ecdsa ? 2 : 0) + (psk ? 2 : 0) + (ecdh_anon ? 2 : 0) + (ecdhe_psk ? 2 : 0);
extension_size = (ecdsa) ? (2 + 6 + 6 + 8 + 6) : 0;
if (cipher_size == 0) {
p += sizeof(uint16);
if (ecdh_anon) {
- dtls_int_to_uint16(p, TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
+ dtls_int_to_uint16(p, TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256);
p += sizeof(uint16);
}
if (psk) {
dtls_int_to_uint16(p, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
p += sizeof(uint16);
}
+ if (ecdhe_psk) {
+ dtls_int_to_uint16(p, TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
+ p += sizeof(uint16);
+ }
/* compression method */
dtls_int_to_uint8(p, 1);
data += DTLS_HS_LENGTH;
- if (dtls_uint24_to_int(data) != 94) {
- dtls_alert("expect length of 94 bytes for server certificate message\n");
- return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
- }
- data += sizeof(uint24);
-
- if (dtls_uint24_to_int(data) != 91) {
- dtls_alert("expect length of 91 bytes for certificate\n");
+ if (dtls_uint24_to_int(data) != DTLS_EC_SUBJECTPUBLICKEY_SIZE) {
+ dtls_alert("expect length of %d bytes for certificate\n",
+ DTLS_EC_SUBJECTPUBLICKEY_SIZE);
return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
}
data += sizeof(uint24);
update_hs_hash(peer, data, data_length);
- assert(is_tls_ecdh_anon_with_aes_128_cbc_sha(config->cipher));
+ assert(is_tls_ecdh_anon_with_aes_128_cbc_sha_256(config->cipher));
data += DTLS_HS_LENGTH;
return 0;
}
-
#endif /* DTLS_ECC */
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+check_server_key_exchange_ecdhe_psk(dtls_context_t *ctx,
+ dtls_peer_t *peer,
+ uint8 *data, size_t data_length)
+{
+ dtls_handshake_parameters_t *config = peer->handshake_params;
+ uint16_t psk_len = 0;
+
+ /* ServerKeyExchange
+ * Please see Session 2, RFC 5489.
+
+ struct {
+ select (KeyExchangeAlgorithm) {
+ //other cases for rsa, diffie_hellman, etc.
+ case ec_diffie_hellman_psk: // NEW
+ opaque psk_identity_hint<0..2^16-1>;
+ ServerECDHParams params;
+ };
+ } ServerKeyExchange; */
+
+ update_hs_hash(peer, data, data_length);
+
+ assert(is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(config->cipher));
+
+ data += DTLS_HS_LENGTH;
+
+ psk_len = dtls_uint16_to_int(data);
+ data += sizeof(uint16);
+
+ if (psk_len != data_length - DTLS_HS_LENGTH - DTLS_SKEXEC_ECDH_ANON_LENGTH - sizeof(uint16)) {
+ dtls_warn("the length of the server identity hint is worng\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
+ }
+
+ if (psk_len > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
+ dtls_warn("please use a smaller server identity hint\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+ }
+
+ // store the psk_identity_hint in config->keyx.psk for later use
+ config->keyx.psk.id_length = psk_len;
+ memcpy(config->keyx.psk.identity, data, psk_len);
+
+ data += psk_len;
+ data_length -= psk_len;
+
+ if (data_length < DTLS_HS_LENGTH + DTLS_SKEXEC_ECDH_ANON_LENGTH) {
+ dtls_alert("the packet length does not match the expected\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
+ }
+
+ if (dtls_uint8_to_int(data) != TLS_EC_CURVE_TYPE_NAMED_CURVE) {
+ dtls_alert("Only named curves supported\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+ }
+ data += sizeof(uint8);
+ data_length -= sizeof(uint8);
+
+ if (dtls_uint16_to_int(data) != TLS_EXT_ELLIPTIC_CURVES_SECP256R1) {
+ dtls_alert("secp256r1 supported\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+ }
+ data += sizeof(uint16);
+ data_length -= sizeof(uint16);
+
+ if (dtls_uint8_to_int(data) != 1 + 2 * DTLS_EC_KEY_SIZE) {
+ dtls_alert("expected 65 bytes long public point\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+ }
+ data += sizeof(uint8);
+ data_length -= sizeof(uint8);
+
+ if (dtls_uint8_to_int(data) != 4) {
+ dtls_alert("expected uncompressed public point\n");
+ return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
+ }
+ data += sizeof(uint8);
+ data_length -= sizeof(uint8);
+
+ memcpy(config->keyx.ecc.other_eph_pub_x, data, sizeof(config->keyx.ecc.other_eph_pub_x));
+ data += sizeof(config->keyx.ecc.other_eph_pub_x);
+ data_length -= sizeof(config->keyx.ecc.other_eph_pub_x);
+
+ memcpy(config->keyx.ecc.other_eph_pub_y, data, sizeof(config->keyx.ecc.other_eph_pub_y));
+ data += sizeof(config->keyx.ecc.other_eph_pub_y);
+ data_length -= sizeof(config->keyx.ecc.other_eph_pub_y);
+
+ return 0;
+}
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
#ifdef DTLS_PSK
static int
if (security->cipher == TLS_NULL_WITH_NULL_NULL) {
/* no cipher suite selected */
return clen;
+ } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher) ||
+ is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(security->cipher)) {
+
+ unsigned char nonce[DTLS_CBC_IV_LENGTH];
+
+ if (clen < (DTLS_CBC_IV_LENGTH + DTLS_HMAC_DIGEST_SIZE)) /* need at least IV and MAC */
+ return -1;
+
+ memcpy(nonce, *cleartext , DTLS_CBC_IV_LENGTH);
+ clen -= DTLS_CBC_IV_LENGTH;
+ *cleartext += DTLS_CBC_IV_LENGTH ;
+
+ clen = dtls_decrypt(*cleartext, clen, *cleartext, nonce,
+ dtls_kb_remote_write_key(security, peer->role),
+ dtls_kb_key_size(security, peer->role),
+ NULL, 0,
+ security->cipher);
+
} else { /* TLS_PSK_WITH_AES_128_CCM_8 or TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */
/**
* length of additional_data for the AEAD cipher which consists of
memset(nonce, 0, DTLS_CCM_BLOCKSIZE);
memcpy(nonce, dtls_kb_remote_iv(security, peer->role),
- dtls_kb_iv_size(security, peer->role));
+ dtls_kb_iv_size(security, peer->role));
/* read epoch and seq_num from message */
memcpy(nonce + dtls_kb_iv_size(security, peer->role), *cleartext, 8);
dtls_kb_remote_write_key(security, peer->role),
dtls_kb_key_size(security, peer->role),
A_DATA, A_DATA_LEN,
- security->cipher);
- if (clen < 0)
- dtls_warn("decryption failed\n");
- else {
+ security->cipher);
+ }
+
+ if (clen < 0)
+ dtls_warn("decryption failed\n");
+ else {
#ifndef NDEBUG
- dtls_debug("decrypt_verify(): found %i bytes cleartext\n", clen);
+ dtls_debug("decrypt_verify(): found %i bytes cleartext\n", clen);
#endif
- dtls_security_params_free_other(peer);
- dtls_debug_dump("cleartext", *cleartext, clen);
- }
+ dtls_security_params_free_other(peer);
+ dtls_debug_dump("cleartext", *cleartext, clen);
}
+
return clen;
}
}
if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher))
peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE; //ecdsa
- else if (is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher))
+ else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher) ||
+ is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(peer->handshake_params->cipher))
peer->state = DTLS_STATE_WAIT_SERVERKEYEXCHANGE; //ecdh
else
peer->state = DTLS_STATE_WAIT_SERVERHELLODONE; //psk
err = check_server_key_exchange_ecdsa(ctx, peer, data, data_length);
}
- if (is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher)) {
+ if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher)) {
if (state != DTLS_STATE_WAIT_SERVERKEYEXCHANGE) {
return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
}
err = check_server_key_exchange_ecdh(ctx, peer, data, data_length);
}
#endif /* DTLS_ECC */
+
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+ if (is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(peer->handshake_params->cipher)) {
+ if (state != DTLS_STATE_WAIT_SERVERKEYEXCHANGE) {
+ return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
+ }
+ err = check_server_key_exchange_ecdhe_psk(ctx, peer, data, data_length);
+ }
+#endif defined(DTLS_PSK) && defined(DTLS_ECC)
+
#ifdef DTLS_PSK
if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
if (state != DTLS_STATE_WAIT_SERVERHELLODONE) {
dtls_handler_t *h; /**< callback handlers */
- dtls_cipher_enable_t is_anon_ecdh_eabled; /**< enable/disable the TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
+ dtls_cipher_enable_t is_anon_ecdh_eabled; /**< enable/disable the TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 */
dtls_cipher_t selected_cipher; /**< selected ciper suite for handshake */
}
/**
- * @brief Enabling the TLS_ECDH_anon_WITH_AES_128_CBC_SHA
+ * @brief Enabling the TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256
*
* @param ctx The DTLS context to use.
* @param is_enable DTLS_CIPHER_ENABLE(1) or DTLS_CIPHER_DISABLE(0)
* @brief Select the cipher suite for handshake
*
* @param ctx The DTLS context to use.
- * @param cipher TLS_ECDH_anon_WITH_AES_128_CBC_SHA (0xC018)
+ * @param cipher TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 (0xC018)
* TLS_PSK_WITH_AES_128_CCM_8 (0xX0A8)
* TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 (0xC0AE)
*/
/** Known cipher suites.*/
typedef enum {
TLS_NULL_WITH_NULL_NULL = 0x0000, /**< NULL cipher */
- TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018, /**< see RFC 4492 */
+ TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 = 0xC018, /**< see RFC 4492 */
TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8, /**< see RFC 6655 */
+ TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 = 0xC037, /**< see RFC 5489 */
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE /**< see RFC 7251 */
} dtls_cipher_t;
"\t-p port\t\tlisten on specified port (default is %d)\n"
"\t-v num\t\tverbosity level (default: 3)\n"
"\t-c num\t\tcipher suite (default: 1)\n"
- "\t\t\t1: TLS_ECDH_anon_WITH_AES_128_CBC_SHA \n"
+ "\t\t\t1: TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 \n"
"\t\t\t2: TLS_PSK_WITH_AES_128_CCM_8\n"
- "\t\t\t3: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n",
+ "\t\t\t3: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n"
+ "\t\t\t4: TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256\n",
program, version, program, DEFAULT_PORT);
}
log_t log_level = DTLS_LOG_WARN;
int fd, result;
int on = 1;
- dtls_cipher_t selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
+ dtls_cipher_t selected_cipher = TLS_NULL_WITH_NULL_NULL;
dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
int opt, res;
session_t dst;
case 'c':
if( strcmp(optarg, "1") == 0)
{
- selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
+ selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256;
ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
}
else if( strcmp(optarg, "2") == 0)
selected_cipher = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ;
ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
}
+ else if( strcmp(optarg, "4") == 0)
+ {
+ selected_cipher = TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256;
+ ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
+ }
break;
default:
usage(argv[0], dtls_package_version());
/* select cipher suite */
dtls_select_cipher(dtls_context, selected_cipher);
- /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha */
+ /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
dtls_enables_anon_ecdh(dtls_context, ecdh_anon_enalbe);
dtls_set_handler(dtls_context, &cb);
"\t-p port\t\tlisten on specified port (default is %d)\n"
"\t-v num\t\tverbosity level (default: 3)\n"
"\t-a enable|disable\t(default: disable)\n"
- "\t\t\t\tenable:enable TLS_ECDH_anon_with_AES_128_CBC_SHA\n"
- "\t\t\t\tdisable:disable TLS_ECDH_anon_with_AES_128_CBC_SHA\n",
+ "\t\t\t\tenable:enable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n"
+ "\t\t\t\tdisable:disable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n",
program, version, program, DEFAULT_PORT);
}
struct timeval timeout;
int fd, opt, result;
int on = 1;
- int ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
+ dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
struct sockaddr_in6 listen_addr;
memset(&listen_addr, 0, sizeof(struct sockaddr_in6));
the_context = dtls_new_context(&fd);
- /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha */
+ /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
dtls_enables_anon_ecdh(the_context, ecdh_anon_enalbe);
dtls_set_handler(the_context, &cb);
cp ./SConstruct ./tmp
cp ./tools/tizen/*.rpm ./tmp
cp ./tools/tizen/.gbs.conf ./tmp
+
+cp -R $sourcedir/iotivity.pc.in $sourcedir/tmp
+
cd $sourcedir/tmp
echo `pwd`
--- /dev/null
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=${prefix}
+libdir=${prefix}/lib
+includedir=${prefix}/include/
+
+Name: iotivity
+Description: IoTivity is an open source reference implementation of the OIC standard specifications.
+Version: @VERSION@
+URL: https://www.iotivity.org
+Requires:
+Libs: -L${libdir} -lBMISensor -lc_common -loctbstack -lcoap -lpmimpl -lconnectivity_abstraction -lppm -lcpluff -lDiscomfortIndexSensor -lrcs_client -lmosquitto -lmosquittopp -lSSMCore -loc_logger_core -lSSMSDK -loc_logger -loc -lTGMSDKLibrary -locsrm
+Cflags: -I${includedir}
# Build connectivity
SConscript('csdk/connectivity/SConscript')
+if env.get('ROUTING') in ['GW', 'EP']:
+ # Build Routing
+ SConscript('csdk/routing/SConscript')
+
# Build libocsrm
SConscript('csdk/security/SConscript')
# Build liboc
SConscript('src/SConscript')
-if target_os not in ['arduino','darwin','ios','android','tizen']:
+if target_os not in ['arduino','darwin','ios','android']:
# Build examples
SConscript('examples/SConscript')
#ifdef ENABLE_MALLOC_DEBUG
void *ptr = malloc(size);
- count++;
+ if (ptr)
+ {
+ count++;
+ }
OIC_LOG_V(INFO, TAG, "malloc: ptr=%p, size=%u, count=%u", ptr, size, count);
return ptr;
#else
#ifdef ENABLE_MALLOC_DEBUG
void *ptr = calloc(num, size);
- OIC_LOG_V(INFO, TAG, "calloc: ptr=%p, num=%u, size=%u", ptr, num, size);
+ if (ptr)
+ {
+ count++;
+ }
+ OIC_LOG_V(INFO, TAG, "calloc: ptr=%p, num=%u, size=%u, count=%u", ptr, num, size, count);
return ptr;
#else
return calloc(num, size);
#define SUPPORTS_DEFAULT_CTOR
#endif
+#if (__STDC_VERSION__ >= 201112L)
+ #include <stdassert.h>
+ #define OC_STATIC_ASSERT(condition, msg) static_assert(condition, msg)
+#else
+ #define OC_STATIC_ASSERT(condition, msg) ((void)sizeof(char[2*!!(condition) - 1]))
+#endif
+
#endif
liboctbstack_env.AppendUnique(CPPDEFINES = ['WITH_POSIX'])
liboctbstack_env.AppendUnique(CFLAGS = ['-std=c99'])
+if liboctbstack_env.get('ROUTING') == 'GW':
+ liboctbstack_env.AppendUnique(CPPDEFINES = ['ROUTING_GATEWAY'])
+elif liboctbstack_env.get('ROUTING') == 'EP':
+ liboctbstack_env.AppendUnique(CPPDEFINES = ['ROUTING_EP'])
+
if target_os not in ['windows', 'winrt']:
liboctbstack_env.AppendUnique(CFLAGS = ['-Wall'])
liboctbstack_env.Append(LIBS = ['c_common'])
+if liboctbstack_env.get('ROUTING') in ['GW', 'EP']:
+ liboctbstack_env.Prepend(LIBS = ['routingmanager'])
+
######################################################################
# Source files and Targets
######################################################################
static_liboctbstack = liboctbstack_env.StaticLibrary('octbstack', liboctbstack_src)
liboctbstack_env.InstallTarget(static_liboctbstack, 'liboctbstack')
liboctbstack_env.UserInstallTargetLib(static_liboctbstack, 'liboctbstack')
+ liboctbstack_env.UserInstallTargetHeader('stack/include/ocstackconfig.h', 'resource', 'ocstackconfig.h')
+ liboctbstack_env.UserInstallTargetHeader('stack/include/octypes.h', 'resource', 'octypes.h')
else:
static_liboctbstack = liboctbstack_env.StaticLibrary('octbstack', liboctbstack_src)
shared_liboctbstack = liboctbstack_env.SharedLibrary('octbstack', liboctbstack_src)
liboctbstack_env.InstallTarget([static_liboctbstack, shared_liboctbstack], 'liboctbstack')
liboctbstack_env.UserInstallTargetLib([static_liboctbstack, shared_liboctbstack], 'liboctbstack')
+ liboctbstack_env.UserInstallTargetHeader('stack/include/ocstackconfig.h', 'resource', 'ocstackconfig.h')
+ liboctbstack_env.UserInstallTargetHeader('stack/include/octypes.h', 'resource', 'octypes.h')
+ liboctbstack_env.UserInstallTargetHeader('stack/include/ocstack.h', 'resource', 'ocstack.h')
if with_ra == True:
env.AppendUnique(CPPDEFINES = ['RA_ADAPTER'])
if target_os == 'linux':
- env.AppendUnique(CPPDEFINES = ['IP_ADAPTER','NO_EDR_ADAPTER','LE_ADAPTER'])
+ env.AppendUnique(CPPDEFINES = ['IP_ADAPTER','NO_EDR_ADAPTER','LE_ADAPTER', 'TCP_ADAPTER'])
elif target_os == 'tizen':
env.AppendUnique(CPPDEFINES = ['IP_ADAPTER','EDR_ADAPTER','LE_ADAPTER'])
elif target_os in['darwin','ios']:
else:
env.AppendUnique(CPPDEFINES = ['NO_IP_ADAPTER'])
+ if 'TCP' in transport:
+ if target_os in['linux']:
+ env.AppendUnique(CPPDEFINES = ['TCP_ADAPTER'])
+ print "CA Transport is TCP"
+ else:
+ print "CA Transport TCP is not supported "
+ Exit(1)
+ else:
+ env.AppendUnique(CPPDEFINES = ['NO_TCP_ADAPTER'])
+
env.SConscript('./src/SConscript')
if build_sample == 'ON':
/**
* Max header options data length
*/
-#define CA_MAX_HEADER_OPTION_DATA_LENGTH 16
+#define CA_MAX_HEADER_OPTION_DATA_LENGTH 20
/**
* Max token length
CA_ADAPTER_GATT_BTLE = (1 << 1), // GATT over Bluetooth LE
CA_ADAPTER_RFCOMM_BTEDR = (1 << 2), // RFCOMM over Bluetooth EDR
- #ifdef RA_ADAPTER
+#ifdef RA_ADAPTER
CA_ADAPTER_REMOTE_ACCESS = (1 << 3), // Remote Access over XMPP.
- #endif
+#endif
+ CA_ADAPTER_TCP = (1 << 4), // CoAP over TCP
CA_ALL_ADAPTERS = 0xffffffff
} CATransportAdapter_t;
{
CATransportAdapter_t adapter; // adapter type
CATransportFlags_t flags; // transport modifiers
+ uint16_t port; // for IP
char addr[MAX_ADDR_STR_SIZE_CA]; // address for all
uint32_t interface; // usually zero for default interface
- uint16_t port; // for IP
- CARemoteId_t identity; // endpoint identity
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+ char routeData[MAX_ADDR_STR_SIZE_CA]; /**< GatewayId:ClientId of
+ destination. **/
+#endif
} CAEndpoint_t;
/**
+ * Endpoint information for secure messages
+ */
+typedef struct
+{
+ CAEndpoint_t endpoint; /**< endpoint */
+ CARemoteId_t identity; /**< endpoint identity */
+} CASecureEndpoint_t;
+
+/**
* @enum CAResult_t
* Enums for CA return values
*/
{
/* Response status code - START HERE */
CA_EMPTY = 0, /**< Empty */
- CA_SUCCESS = 200, /**< Success */
CA_CREATED = 201, /**< Created */
CA_DELETED = 202, /**< Deleted */
CA_VALID = 203, /**< Valid */
CA_BAD_OPT = 402, /**< Bad Option */
CA_FORBIDDEN_REQ = 403, /**< Forbidden Request */
CA_NOT_FOUND = 404, /**< Not found */
+ CA_NOT_ACCEPTABLE = 406, /**< Not Acceptable */
CA_REQUEST_ENTITY_INCOMPLETE = 408, /**< Request Entity Incomplete */
CA_REQUEST_ENTITY_TOO_LARGE = 413, /**< Request Entity Too Large */
CA_INTERNAL_SERVER_ERROR = 500, /**< Internal Server Error */
} CAAdapterState_t;
/**
+ * Format indicating which encoding has been used on the payload.
+ */
+typedef enum
+{
+ CA_FORMAT_UNDEFINED = 0, /**< Undefined enoding format */
+ CA_FORMAT_TEXT_PLAIN,
+ CA_FORMAT_APPLICATION_LINK_FORMAT,
+ CA_FORMAT_APPLICATION_XML,
+ CA_FORMAT_APPLICATION_OCTET_STREAM,
+ CA_FORMAT_APPLICATION_RDF_XML,
+ CA_FORMAT_APPLICATION_EXI,
+ CA_FORMAT_APPLICATION_JSON,
+ CA_FORMAT_APPLICATION_CBOR,
+ CA_FORMAT_UNSUPPORTED
+} CAPayloadFormat_t;
+
+/**
* Header options structure to be filled
*
* This structure is used to hold header information.
{
CAMessageType_t type; /**< Qos for the request */
+#ifdef ROUTING_GATEWAY
+ bool skipRetransmission; /**< Will not attempt retransmission even if type is CONFIRM.
+ Required for packet forwarding */
+#endif
uint16_t messageId; /**< Message id.
* if message id is zero, it will generated by CA inside.
* otherwise, you can use it */
uint8_t numOptions; /**< Number of Header options */
CAPayload_t payload; /**< payload of the request */
size_t payloadSize; /**< size in bytes of the payload */
+ CAPayloadFormat_t payloadFormat; /**< encoding format of the request payload */
+ CAPayloadFormat_t acceptFormat; /**< accept format for the response payload */
CAURI_t resourceUri; /**< Resource URI information **/
+ CARemoteId_t identity; /**< endpoint identity */
} CAInfo_t;
/**
{
CAResponseResult_t result; /**< Result for response by resource model */
CAInfo_t info; /**< Information of the response */
+ bool isMulticast;
} CAResponseInfo_t;
/**
*/
typedef struct
{
- int fd;
- uint16_t port;
+ int fd; /**< socket fd */
+ uint16_t port; /**< socket port */
} CASocket_t;
+#define HISTORYSIZE (4)
+
+typedef struct
+{
+ CATransportFlags_t flags;
+ uint16_t messageId;
+ char token[CA_MAX_TOKEN_LEN];
+ uint8_t tokenLength;
+} CAHistoryItem_t;
+
typedef struct
{
- CATransportFlags_t clientFlags;
- CATransportFlags_t serverFlags;
- bool client;
- bool server;
+ int nextIndex;
+ CAHistoryItem_t items[HISTORYSIZE];
+} CAHistory_t;
+
+/**
+ * Hold interface index for keeping track of comings and goings
+ */
+typedef struct
+{
+ int32_t ifIndex; /**< network interface index */
+} CAIfItem_t;
+
+typedef struct
+{
+ CATransportFlags_t clientFlags; /**< flag for client */
+ CATransportFlags_t serverFlags; /**< flag for server */
+ bool client; /**< client mode */
+ bool server; /**< server mode */
struct sockets
{
int shutdownFds[2]; /**< shutdown pipe */
int selectTimeout; /**< in seconds */
int maxfd; /**< highest fd (for select) */
- int numInterfaces; /**< number of active interfaces */
bool started; /**< the IP adapter has started */
bool terminate; /**< the IP adapter needs to stop */
bool ipv6enabled; /**< IPv6 enabled by OCInit flags */
bool ipv4enabled; /**< IPv4 enabled by OCInit flags */
+ bool dualstack; /**< IPv6 and IPv4 enabled */
+
+ struct networkmonitors
+ {
+ CAIfItem_t *ifItems; /**< current network interface index list */
+ size_t sizeIfItems; /**< size of network interface index array */
+ size_t numIfItems; /**< number of valid network interfaces */
+ } nm;
} ip;
struct calayer
{
- CATransportFlags_t previousRequestFlags; /**< address family filtering */
- uint16_t previousRequestMessageId; /**< address family filtering */
+ CAHistory_t requestHistory; /**< filter IP family in requests */
+ CAHistory_t responseHistory; /**< filter IP family in responses */
+ CATransportFlags_t previousRequestFlags;/**< address family filtering */
+ uint16_t previousRequestMessageId; /**< address family filtering */
} ca;
+
+#ifdef TCP_ADAPTER
+ /**
+ * Hold global variables for TCP Adapter.
+ */
+ struct tcpsockets
+ {
+ void *threadpool; /**< threadpool between Initialize and Start */
+ void *svrlist; /**< unicast IPv4 TCP server information*/
+ int selectTimeout; /**< in seconds */
+ int listenBacklog; /**< backlog counts*/
+ int maxfd; /**< highest fd (for select) */
+ bool started; /**< the TCP adapter has started */
+ bool terminate; /**< the TCP adapter needs to stop */
+ bool ipv4tcpenabled; /**< IPv4 TCP enabled by OCInit flags */
+ } tcp;
+#endif
} CAGlobals_t;
extern CAGlobals_t caglobals;
#endif
/**
- * @brief Callback function type for request delivery.
- * @param object [OUT] Endpoint object from which the request is received. It contains
- * endpoint address based on the connectivity type.
- * @param requestInfo [OUT] Info for resource model to understand about the request.
- * @return NONE
+ * Callback function type for request delivery.
+ * @param[out] object Endpoint object from which the request is received.
+ * It contains endpoint address based on the connectivity type.
+ * @param[out] requestInfo Info for resource model to understand about the request.
*/
typedef void (*CARequestCallback)(const CAEndpoint_t *object,
const CARequestInfo_t *requestInfo);
/**
- * @brief Callback function type for response delivery.
- * @param object [OUT] Endpoint object from which the response is received.
- * @param responseInfo [OUT] Identifier which needs to be mapped with response.
- * @return NONE
+ * Callback function type for response delivery.
+ * @param[out] object Endpoint object from which the response is received.
+ * @param[out] responseInfo Identifier which needs to be mapped with response.
*/
typedef void (*CAResponseCallback)(const CAEndpoint_t *object,
const CAResponseInfo_t *responseInfo);
/**
- * @brief Callback function type for error
- * @param object [OUT] remote device information
- * @param errorInfo [OUT] CA Error information
- * @return NONE
+ * Callback function type for error.
+ * @param[out] object remote device information.
+ * @param[out] errorInfo CA Error information.
*/
typedef void (*CAErrorCallback)(const CAEndpoint_t *object,
const CAErrorInfo_t *errorInfo);
*/
typedef struct
{
- unsigned char identity[DTLS_PSK_ID_LEN]; /** identity of self */
- uint32_t num; /** number of credentials in this blob */
+ unsigned char identity[DTLS_PSK_ID_LEN]; /** identity of self. */
+ uint32_t num; /** number of credentials in this blob. */
OCDtlsPskCreds *creds; /** list of credentials. Size of this
array is determined by 'num' variable. */
} CADtlsPskCredsBlob_t;
/**
- * @brief Callback function type for getting DTLS credentials.
- * @param credInfo [OUT] DTLS credentials info. Handler has to allocate new memory for
- * both credInfo and credInfo->creds which is then freed by CA
- * @return NONE
+ * Callback function type for getting DTLS credentials.
+ * @param[out] credInfo DTLS credentials info. Handler has to allocate new memory for.
+ * both credInfo and credInfo->creds which is then freed by CA.
*/
typedef void (*CAGetDTLSCredentialsHandler)(CADtlsPskCredsBlob_t **credInfo);
#endif //__WITH_DTLS__
/**
- * @brief Initialize the connectivity abstraction module.
- * It will initialize adapters, thread pool and other modules based on the platform
- * compilation options.
+ * Initialize the connectivity abstraction module.
+ * It will initialize adapters, thread pool and other modules based on the platform
+ * compilation options.
*
- * @return #CA_STATUS_OK or #CA_STATUS_FAILED or #CA_MEMORY_ALLOC_FAILED
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED or ::CA_MEMORY_ALLOC_FAILED
*/
CAResult_t CAInitialize();
/**
- * @brief Terminate the connectivity abstraction module.
- * All threads, data structures are destroyed for next initializations.
- * @return NONE
+ * Terminate the connectivity abstraction module.
+ * All threads, data structures are destroyed for next initializations.
*/
void CATerminate();
/**
- * @brief Starts listening servers.
- * This API is used by resource hosting server for listening multicast requests.
- * Based on the adapters configurations, different kinds of servers are started.
- * @return #CA_STATUS_OK or #CA_STATUS_FAILED
+ * Starts listening servers.
+ * This API is used by resource hosting server for listening multicast requests.
+ * Based on the adapters configurations, different kinds of servers are started.
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED
*/
CAResult_t CAStartListeningServer();
/**
- * @brief Starts discovery servers.
- * This API is used by resource required clients for listening multicast requests.
- * Based on the adapters configurations, different kinds of servers are started.
- * @return #CA_STATUS_OK or #CA_STATUS_FAILED
+ * Starts discovery servers.
+ * This API is used by resource required clients for listening multicast requests.
+ * Based on the adapters configurations, different kinds of servers are started.
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED
*/
CAResult_t CAStartDiscoveryServer();
/**
- * @brief Register request callbacks and response callbacks.
- * Requests and responses are delivered these callbacks .
- * @param ReqHandler [IN] Request callback ( for GET,PUT ..etc)
- * @param RespHandler [IN] Response Handler Callback
+ * Register request callbacks and response callbacks.
+ * Requests and responses are delivered these callbacks.
+ * @param[in] ReqHandler Request callback ( for GET,PUT ..etc).
+ * @param[in] RespHandler Response Handler Callback.
* @see CARequestCallback
* @see CAResponseCallback
* @see CAErrorCallback
- * @return NONE
*/
void CARegisterHandler(CARequestCallback ReqHandler, CAResponseCallback RespHandler,
CAErrorCallback ErrorHandler);
#ifdef __WITH_DTLS__
/**
- * @brief Register callback to get DTLS PSK credentials.
- * @param GetDTLSCredentials [IN] GetDTLS Credetials callback
- * @return #CA_STATUS_OK
+ * Register callback to get DTLS PSK credentials.
+ * @param[in] GetDTLSCredentials GetDTLS Credetials callback.
+ * @return ::CA_STATUS_OK
*/
CAResult_t CARegisterDTLSCredentialsHandler(CAGetDTLSCredentialsHandler GetDTLSCredentials);
#endif //__WITH_DTLS__
/**
- * @brief Create an endpoint description
- * @param flags [IN] how the adapter should be used
- * @param adapter [IN] which adapter to use
- * @param addr [IN] string representation of address
- * @param port [IN] port (for IP_ADAPTER)
- * @param endpoint [OUT] Endpoint which contains the above
- * @return #CA_STATUS_OK or #CA_STATUS_FAILED
+ * Create an endpoint description.
+ * @param[in] flags how the adapter should be used.
+ * @param[in] adapter which adapter to use.
+ * @param[in] addr string representation of address.
+ * @param[in] port port (for IP_ADAPTER).
+ * @param[in] endpoint Endpoint which contains the above.
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED
* @remark The created Remote endpoint can be freed using CADestroyEndpoint().
* @see CADestroyEndpoint
*/
CAEndpoint_t **object);
/**
- * @brief Destroy the remote endpoint created
- * @param object [IN] Remote Endpoint object created with CACreateEndpoint
- * @return NONE
+ * Destroy the remote endpoint created.
+ * @param[in] object Remote Endpoint object created with CACreateEndpoint.
*/
void CADestroyEndpoint(CAEndpoint_t *object);
/**
- * @brief Generating the token for matching the request and response.
- * @param token [OUT] Token for the request
- * @param tokenLength [IN] length of the token
- * @return #CA_STATUS_OK or #CA_STATUS_FAILED or #CA_MEMORY_ALLOC_FAILED
- * or #CA_STATUS_NOT_INITIALIZED
+ * Generating the token for matching the request and response.
+ * @param[in] token Token for the request.
+ * @param[in] tokenLength length of the token.
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED or
+ * ::CA_MEMORY_ALLOC_FAILED or ::CA_STATUS_NOT_INITIALIZED
* @remark Token memory is destroyed by the caller using CADestroyToken().
* @see CADestroyToken
*/
CAResult_t CAGenerateToken(CAToken_t *token, uint8_t tokenLength);
/**
- * @brief Destroy the token generated by CAGenerateToken
- * @param token [IN] token to be freed
- * @return NONE
+ * Destroy the token generated by CAGenerateToken.
+ * @param[in] token token to be freed.
*/
void CADestroyToken(CAToken_t token);
/**
- * @brief Send control Request on a resource
- * @param object [IN] Endpoint where the payload need to be sent.
+ * Send control Request on a resource.
+ * @param[in] object Endpoint where the payload need to be sent.
* This endpoint is delivered with Request or response callback.
- * @param requestInfo [IN] Information for the request.
- * @return #CA_STATUS_OK #CA_STATUS_FAILED #CA_MEMORY_ALLOC_FAILED
+ * @param[in] requestInfo Information for the request.
+ * @return ::CA_STATUS_OK ::CA_STATUS_FAILED ::CA_MEMORY_ALLOC_FAILED
*/
CAResult_t CASendRequest(const CAEndpoint_t *object, const CARequestInfo_t *requestInfo);
/**
- * @brief Send the response
- * @param object [IN] Endpoint where the payload need to be sent.
- * This endpoint is delivered with Request or response callback
- * @param responseInfo [IN] Information for the response
- * @return #CA_STATUS_OK or #CA_STATUS_FAILED or #CA_MEMORY_ALLOC_FAILED
+ * Send the response.
+ * @param[in] object Endpoint where the payload need to be sent.
+ * This endpoint is delivered with Request or response callback.
+ * @param[in] responseInfo Information for the response.
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED or ::CA_MEMORY_ALLOC_FAILED
*/
CAResult_t CASendResponse(const CAEndpoint_t *object, const CAResponseInfo_t *responseInfo);
/**
- * @brief Send notification to the remote object
- * @param object [IN] Endpoint where the payload need to be sent.
+ * Send notification to the remote object.
+ * @param[in] object Endpoint where the payload need to be sent.
* This endpoint is delivered with Request or response callback.
- * @param responseInfo [IN] Information for the response.
- * @return #CA_STATUS_OK or #CA_STATUS_FAILED or #CA_MEMORY_ALLOC_FAILED
+ * @param[in] responseInfo Information for the response.
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED or ::CA_MEMORY_ALLOC_FAILED
*/
CAResult_t CASendNotification(const CAEndpoint_t *object,
const CAResponseInfo_t *responseInfo);
/**
- * @brief Select network to use
- * @param interestedNetwork [IN] Connectivity Type enum
- * @return #CA_STATUS_OK or #CA_NOT_SUPPORTED or #CA_STATUS_FAILED or #CA_NOT_SUPPORTED
+ * Select network to use.
+ * @param[in] interestedNetwork Connectivity Type enum.
+ * @return ::CA_STATUS_OK or ::CA_NOT_SUPPORTED or
+ * ::CA_STATUS_FAILED or ::CA_NOT_SUPPORTED
*/
CAResult_t CASelectNetwork(CATransportAdapter_t interestedNetwork);
/**
- * @brief Select network to unuse
- * @param nonInterestedNetwork [IN] Connectivity Type enum
- * @return #CA_STATUS_OK or #CA_NOT_SUPPORTED or #CA_STATUS_FAILED
+ * Select network to unuse.
+ * @param[in] nonInterestedNetwork Connectivity Type enum.
+ * @return ::CA_STATUS_OK or ::CA_NOT_SUPPORTED or ::CA_STATUS_FAILED
*/
CAResult_t CAUnSelectNetwork(CATransportAdapter_t nonInterestedNetwork);
/**
- * @brief Get network information
- * It should be destroyed by the caller as it Get Information.
- * @param info [OUT] LocalConnectivity objects
- * @param size [OUT] No Of Array objects
- * @return #CA_STATUS_OK or #CA_STATUS_FAILED or #CA_STATUS_INVALID_PARAM or
-* #CA_MEMORY_ALLOC_FAILED
+ * Get network information.
+ * It should be destroyed by the caller as it Get Information.
+ * @param[out] info LocalConnectivity objects
+ * @param[out] size No Of Array objects
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED or
+ * ::CA_STATUS_INVALID_PARAM or ::CA_MEMORY_ALLOC_FAILED
*/
CAResult_t CAGetNetworkInformation(CAEndpoint_t **info, uint32_t *size);
/**
- * @brief To Handle the Request or Response
- * @return #CA_STATUS_OK
+ * To Handle the Request or Response.
+ * @return ::CA_STATUS_OK
*/
CAResult_t CAHandleRequestResponse();
#ifdef RA_ADAPTER
/**
- * @brief Set Remote Access information for XMPP Client.
- * @param caraInfo [IN] remote access info.
+ * Set Remote Access information for XMPP Client.
+ * @param[in] caraInfo remote access info.
*
- * @return #CA_STATUS_OK
+ * @return ::CA_STATUS_OK
*/
CAResult_t CASetRAInfo(const CARAInfo_t *caraInfo);
#endif
#ifdef __WITH_DTLS__
/**
- * Select the cipher suite for dtls handshake
+ * Select the cipher suite for dtls handshake.
*
- * @param[IN] cipher cipher suite (Note : Make sure endianness)
- * 0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA
- * 0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8
- * 0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+ * @param[in] cipher cipher suite (Note : Make sure endianness).
+ * 0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA
+ * 0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8
+ * 0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
*
- * @retval CA_STATUS_OK Successful
- * @retval CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval CA_STATUS_FAILED Operation failed
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
+ * @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CASelectCipherSuite(const uint16_t cipher);
/**
- * Enable TLS_ECDH_anon_WITH_AES_128_CBC_SHA cipher suite in dtls
+ * Enable TLS_ECDH_anon_WITH_AES_128_CBC_SHA cipher suite in dtls.
*
- * @param[IN] enable TRUE/FALSE enables/disables anonymous cipher suite
+ * @param[in] enable TRUE/FALSE enables/disables anonymous cipher suite.
*
- * @retval CA_STATUS_OK Successful
- * @retval CA_STATUS_FAILED Operation failed
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_FAILED Operation failed.
*
* @note anonymous cipher suite should only be enabled for 'JustWorks' provisioning.
*/
/**
- * Generate ownerPSK using PRF
+ * Generate ownerPSK using PRF.
* OwnerPSK = TLS-PRF('master key' , 'oic.sec.doxm.jw',
- * 'ID of new device(Resource Server)',
- * 'ID of owner smart-phone(Provisioning Server)')
+ * 'ID of new device(Resource Server)',
+ * 'ID of owner smart-phone(Provisioning Server)')
*
- * @param[IN] endpoint information of network address
- * @param[IN] label Ownership transfer method e.g)"oic.sec.doxm.jw"
- * @param[IN] labelLen Byte length of label
- * @param[IN] rsrcServerDeviceID ID of new device(Resource Server)
- * @param[IN] rsrcServerDeviceIDLen Byte length of rsrcServerDeviceID
- * @param[IN] provServerDeviceID label of previous owner
- * @param[IN] provServerDeviceIDLen byte length of provServerDeviceID
- * @param[IN,OUT] ownerPSK Output buffer for owner PSK
- * @param[IN] ownerPSKSize Byte length of the ownerPSK to be generated
+ * @param[in] endpoint information of network address.
+ * @param[in] label Ownership transfer method e.g)"oic.sec.doxm.jw".
+ * @param[in] labelLen Byte length of label.
+ * @param[in] rsrcServerDeviceID ID of new device(Resource Server).
+ * @param[in] rsrcServerDeviceIDLen Byte length of rsrcServerDeviceID.
+ * @param[in] provServerDeviceID label of previous owner.
+ * @param[in] provServerDeviceIDLen byte length of provServerDeviceID.
+ * @param[in,out] ownerPSK Output buffer for owner PSK.
+ * @param[in] ownerPSKSize Byte length of the ownerPSK to be generated.
*
- * @retval CA_STATUS_OK Successful
- * @retval CA_STATUS_FAILED Operation failed
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CAGenerateOwnerPSK(const CAEndpoint_t *endpoint,
const uint8_t* label, const size_t labelLen,
uint8_t* ownerPSK, const size_t ownerPSKSize);
/**
- * Initiate DTLS handshake with selected cipher suite
+ * Initiate DTLS handshake with selected cipher suite.
*
- * @param[IN] endpoint information of network address
+ * @param[in] endpoint information of network address.
*
- * @retval CA_STATUS_OK Successful
- * @retval CA_STATUS_FAILED Operation failed
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CAInitiateHandshake(const CAEndpoint_t *endpoint);
/**
- * Close the DTLS session
+ * Close the DTLS session.
*
- * @param[IN] endpoint information of network address
+ * @param[in] endpoint information of network address.
*
- * @retval CA_STATUS_OK Successful
- * @retval CA_STATUS_FAILED Operation failed
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CACloseDtlsSession(const CAEndpoint_t *endpoint);
help_vars.Add(BoolVariable('RELEASE', 'Build for release?', True)) # set to 'no', 'false' or 0 for debug
help_vars.Add(BoolVariable('LOGGING', 'Enable stack logging', False))
help_vars.Add(EnumVariable('TARGET_OS', 'Target platform', host, host_target_map[host]))
-help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'ALL', ['ALL', 'BT', 'BLE', 'IP']))
+help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'ALL', ['ALL', 'BT', 'BLE', 'IP', 'TCP']))
help_vars.Add(EnumVariable('TARGET_ARCH', 'Target architecture', default_arch, os_arch_map[target_os]))
help_vars.Add(EnumVariable('SECURED', 'Build with DTLS', '0', allowed_values=('0', '1')))
help_vars.Add(BoolVariable('UPLOAD', 'Upload binary ? (For Arduino)', require_upload))
+help_vars.Add(EnumVariable('ROUTING', 'Enable routing', 'EP', allowed_values=('GW', 'EP')))
help_vars.Add(EnumVariable('BUILD_SAMPLE', 'Build with sample', 'ON', allowed_values=('ON', 'OFF')))
help_vars.AddVariables(('DEVICE_NAME', 'Network display name for device', 'OIC-DEVICE', None, None),)
cp -R ./iotivityconfig/* $sourcedir/tmp/iotivityconfig/
cp -R ./SConscript $sourcedir/tmp/
+cp -R $sourcedir/iotivity.pc.in $sourcedir/tmp/
+
cd $sourcedir/tmp
echo `pwd`
######################################################################
ca_common_src = [
ca_common_src_path + 'uarraylist.c',
+ ca_common_src_path + 'ulinklist.c',
ca_common_src_path + 'uqueue.c',
ca_common_src_path + 'caremotehandler.c'
]
#define MAX_LOG_V_BUFFER_SIZE (256)
// Log levels
-#ifndef __TIZEN__
+#ifdef __TIZEN__
+typedef enum {
+ DEBUG = DLOG_DEBUG,
+ INFO = DLOG_INFO,
+ WARNING = DLOG_WARN,
+ ERROR = DLOG_ERROR,
+ FATAL = DLOG_ERROR
+} LogLevel;
+#else
typedef enum
{
DEBUG = 0, INFO, WARNING, ERROR, FATAL
} LogLevel;
-#else
-#define DEBUG DLOG_DEBUG
-#define INFO DLOG_INFO
-#define WARNING DLOG_WARN
-#define ERROR DLOG_ERROR
-#define FATAL DLOG_ERROR
+#endif
+
+#ifdef __TIZEN__
+#define OC_LOG(level,tag,mes) LOG_(LOG_ID_MAIN, level, tag, mes)
+#define OC_LOG_V(level,tag,fmt,args...) LOG_(LOG_ID_MAIN, level, tag, fmt,##args)
+#define OC_LOG_BUFFER(level, tag, buffer, bufferSize)
#endif
#ifdef __TIZEN__
#define U_ARRAYLIST_H_
#include <stdint.h>
-#include "cacommon.h"
+#include <stdbool.h>
#ifdef __cplusplus
extern "C"
/**
* array list structure.
+ *
+ * @note
+ * Members should be treated as private and not accessed directly. Instead
+ * all access should be through the defined u_arraylist_*() functions.
*/
typedef struct u_arraylist_t
{
void **data;
uint32_t length;
- uint32_t size;
+ uint32_t capacity;
} u_arraylist_t;
/**
* Arraylist elements are deleted. Calling function must take care of free
* dynamic memory allocated before freeing the arraylist.
* @param[in] list u_arraylist pointer
- * @return ::CAResult_t.
- * ::CA_STATUS_OK if Success, ::CA_STATUS_INVALID_PARAM if pointer to list is NULL.
*/
-CAResult_t u_arraylist_free(u_arraylist_t **list);
+void u_arraylist_free(u_arraylist_t **list);
+
+/**
+ * Request that the list prepare room for the specified number of entries.
+ * If count is greater than the current internal storage size then an
+ * an attempt will be made to reallocate room for at least count items.
+ *
+ * In other cases there will be no effect.
+ *
+ * This call will not affect the length used and cannot be used to remove
+ * entries.
+ * @param list the list to operate on.
+ * @param count the size to attempt to reserve room for.
+ */
+void u_arraylist_reserve(u_arraylist_t *list, size_t count);
+
+/**
+ * Request that the storage in the list be reduced to fit its current length.
+ *
+ * The request is non-binding, and may not affect the entries in the list.
+ * @param list the list to operate on.
+ */
+void u_arraylist_shrink_to_fit(u_arraylist_t *list);
/**
* Returns the data of the index from the array list.
* Add data in the array list.
* @param[in] list pointer of array list.
* @param[in] data pointer of data.
- * @return CAResult_t.
- * ::CA_STATUS_OK if Success, ::CA_MEMORY_ALLOC_FAILED if memory allocation fails.
+ * @return true if success, false otherwise.
*/
-CAResult_t u_arraylist_add(u_arraylist_t *list, void *data);
+bool u_arraylist_add(u_arraylist_t *list, void *data);
/**
* Remove the data of the index from the array list.
--- /dev/null
+/* ****************************************************************
+ *
+ * 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 U_LINKLIST_H_
+#define U_LINKLIST_H_
+
+/**
+ * @todo Do performance comparision with array list.
+ */
+
+#include <stdint.h>
+#include "cacommon.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#ifndef OICDEFINE
+#include <stdbool.h>
+
+#endif
+
+/**
+ * link list structure
+ */
+typedef struct linked_list_data u_linklist_data_t;
+
+typedef struct linked_list_data u_linklist_iterator_t;
+
+typedef struct u_linklist
+{
+ u_linklist_data_t *list;
+ int size;
+}u_linklist_t;
+
+struct linked_list_data
+{
+ void *data;
+ u_linklist_data_t *next;
+};
+
+/**
+ * API to create link list and initializes the elements.
+ * @return u_linklist_t if Success, NULL otherwise.
+ */
+u_linklist_t *u_linklist_create();
+
+/**
+ * Resets and deletes the link list
+ * Linklist elements are deleted, Calling function must take care of freeing
+ * dynamic memory allocated before freeing the linklist.
+ * @param[in,out] list u_linklist pointer.
+ * @return ::CA_STATUS_OK if Success, ::CA_STATUS_INVALID_PARAM if pointer to list is NULL.
+ */
+CAResult_t u_linklist_free(u_linklist_t **list);
+
+/**
+ * Add data to the head of the link list.
+ * @param[in/out] list pointer of link list.
+ * @param[in] data pointer of data.
+ * @return ::CA_STATUS_OK if Success, ::CA_MEMORY_ALLOC_FAILED if memory allocation fails.
+ */
+CAResult_t u_linklist_add_head(u_linklist_t *list, void *data);
+
+/**
+ * Add data to the tail of the link list.
+ * @param[in/out] list pointer of link list.
+ * @param[in] data pointer of data.
+ * @return ::CA_STATUS_OK if Success, ::CA_MEMORY_ALLOC_FAILED if memory allocation fails.
+ */
+CAResult_t u_linklist_add(u_linklist_t *list, void *data);
+
+
+/**
+ * This api deletes node pointed by iterator.
+ * Advances iterator to next node in the list.
+ * @param[in/out] list pointer of link list.
+ * @param[in/out] iter pointer of iterator pointing to previous node.
+ * @return ::CA_STATUS_OK if Success, ::CA_STATUS_INVALID_PARAM if iterator is NULL.
+ */
+CAResult_t u_linklist_remove(u_linklist_t *list, u_linklist_iterator_t **iter);
+
+
+/**
+ * Returns the length of the link list.
+ * @param[in] list pointer of link list.
+ * @return length of the link list.
+ */
+uint32_t u_linklist_length(const u_linklist_t *list);
+
+/**
+ * Initializes the iterator, need to be called before calling u_linklist_get_next.
+ * @param[in] list pointer of link list.
+ * @param[in,out] iter iterator of link list.
+ * @return NONE
+ */
+void u_linklist_init_iterator(const u_linklist_t *list, u_linklist_iterator_t **iter);
+
+/**
+ * Returns the data of the node iterator points to from the link list.
+ * @param[in] iter iterator of link list.
+ * @return the data of node to which iterator is pointing.
+ */
+void *u_linklist_get_data(const u_linklist_iterator_t *iter);
+
+/**
+ * Returns the data of the next node iterator points to from the link list
+ * Advances iterator to next node in the list.
+ * @param[in,out] iter iterator of link list.
+ * @return the data of next node.
+ */
+void *u_linklist_get_next(u_linklist_iterator_t **iter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* U_LINKLIST_H_ */
+
return NULL;
}
- *clone = *rep;
-
- if (rep->info.token)
+ CAResult_t result = CACloneInfo(&rep->info, &clone->info);
+ if(CA_STATUS_OK != result)
{
- char *temp = NULL;
-
- // allocate token field
- uint8_t len = rep->info.tokenLength;
-
- if (len)
- {
- temp = (char *) OICCalloc(len, sizeof(char));
- if (!temp)
- {
- OIC_LOG(ERROR, TAG, "CACloneRequestInfo Out of memory");
-
- CADestroyRequestInfoInternal(clone);
-
- return NULL;
- }
- memcpy(temp, rep->info.token, len);
- }
-
- // save the token
- clone->info.token = temp;
- clone->info.tokenLength = len;
- }
-
- if (NULL != rep->info.options && 0 < rep->info.numOptions)
- {
- // save the options
- clone->info.options =
- (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) * rep->info.numOptions);
- if (NULL == clone->info.options)
- {
- OIC_LOG(ERROR, TAG, "CACloneRequestInfo Out of memory");
- OICFree(clone->info.token);
- OICFree(clone);
- return NULL;
- }
- memcpy(clone->info.options, rep->info.options,
- sizeof(CAHeaderOption_t) * rep->info.numOptions);
- }
- else
- {
- clone->info.options = NULL;
- clone->info.numOptions = 0;
- }
-
- if (NULL != rep->info.payload && 0 < rep->info.payloadSize)
- {
- // allocate payload field
- uint8_t *temp = OICMalloc(rep->info.payloadSize);
- if (NULL == temp)
- {
- OIC_LOG(ERROR, TAG, "CACloneRequestInfo Out of memory");
-
- CADestroyRequestInfoInternal(clone);
-
- return NULL;
- }
- memcpy(temp, rep->info.payload, rep->info.payloadSize);
-
- // save the payload
- clone->info.payload = temp;
- }
- else
- {
- clone->info.payload = NULL;
- clone->info.payloadSize = 0;
+ OIC_LOG(ERROR, TAG, "CACloneRequestInfo error in CACloneInfo");
+ CADestroyRequestInfoInternal(clone);
+ return NULL;
}
- if (NULL != rep->info.resourceUri)
- {
- // allocate payload field
- char *temp = OICStrdup(rep->info.resourceUri);
- if (NULL == temp)
- {
- OIC_LOG(ERROR, TAG, "CACloneRequestInfo Out of memory");
-
- CADestroyRequestInfoInternal(clone);
-
- return NULL;
- }
-
- // save the resourceUri
- clone->info.resourceUri = temp;
- }
+ clone->method = rep->method;
+ clone->isMulticast = rep->isMulticast;
return clone;
}
switch (rep->result)
{
case CA_EMPTY:
- case CA_SUCCESS:
case CA_CREATED:
case CA_DELETED:
case CA_VALID:
case CA_BAD_OPT:
case CA_FORBIDDEN_REQ:
case CA_NOT_FOUND:
+ case CA_NOT_ACCEPTABLE:
case CA_REQUEST_ENTITY_INCOMPLETE:
case CA_REQUEST_ENTITY_TOO_LARGE:
case CA_INTERNAL_SERVER_ERROR:
case CA_RETRANSMIT_TIMEOUT:
break;
-
default:
OIC_LOG_V(ERROR, TAG, "Response code %u is invalid", rep->result);
return NULL;
OIC_LOG(ERROR, TAG, "CACloneResponseInfo Out of memory");
return NULL;
}
- *clone = *rep;
- if (rep->info.token)
+ CAResult_t result = CACloneInfo(&rep->info, &clone->info);
+ if(CA_STATUS_OK != result)
{
- char *temp = NULL;
-
- // allocate token field
- uint8_t len = rep->info.tokenLength;
-
- if (len)
- {
- temp = (char *) OICCalloc(len, sizeof(char));
- if (!temp)
- {
- OIC_LOG(ERROR, TAG, "CACloneResponseInfo Out of memory");
-
- CADestroyResponseInfoInternal(clone);
-
- return NULL;
- }
- memcpy(temp, rep->info.token, len);
- }
- // save the token
- clone->info.token = temp;
- clone->info.tokenLength = len;
- }
-
- if (NULL != rep->info.options && rep->info.numOptions)
- {
- // save the options
- clone->info.options =
- (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) * rep->info.numOptions);
-
- if (NULL == clone->info.options)
- {
- OIC_LOG(ERROR, TAG, "CACloneResponseInfo Out of memory");
-
- OICFree(clone->info.token);
- OICFree(clone);
- return NULL;
- }
- memcpy(clone->info.options, rep->info.options,
- sizeof(CAHeaderOption_t) * rep->info.numOptions);
- }
- else
- {
- clone->info.options = NULL;
- clone->info.numOptions = 0;
- }
-
- if (NULL != rep->info.payload && 0 < rep->info.payloadSize)
- {
- // allocate payload field
- uint8_t *temp = (uint8_t *) OICMalloc(rep->info.payloadSize);
- if (NULL == temp)
- {
- OIC_LOG(ERROR, TAG, "CACloneResponseInfo Out of memory");
-
- CADestroyResponseInfoInternal(clone);
-
- return NULL;
- }
- memcpy(temp, rep->info.payload, rep->info.payloadSize);
-
- // save the payload
- clone->info.payload = temp;
- }
- else
- {
- clone->info.payload = NULL;
- clone->info.payloadSize = 0;
- }
-
- if (NULL != rep->info.resourceUri)
- {
- // allocate payload field
- char *temp = OICStrdup(rep->info.resourceUri);
- if (NULL == temp)
- {
- OIC_LOG(ERROR, TAG, "CACloneResponseInfo Out of memory");
-
- CADestroyResponseInfoInternal(clone);
-
- return NULL;
- }
-
- // save the resourceUri
- clone->info.resourceUri = temp;
+ OIC_LOG(ERROR, TAG, "CACloneResponseInfo error in CACloneInfo");
+ CADestroyResponseInfoInternal(clone);
+ return NULL;
}
+ clone->isMulticast = rep->isMulticast;
+ clone->result = rep->result;
return clone;
}
return CA_STATUS_INVALID_PARAM;
}
+ memset(clone, 0 , sizeof(CAInfo_t));
+
//Do not free clone. we cannot declare it const, as the content is modified
if ((info->token) && (0 < info->tokenLength))
{
temp = (char *) OICMalloc(len * sizeof(char));
if (!temp)
{
- OIC_LOG(ERROR, TAG, "CAClonePayloadInfo Out of memory");
+ OIC_LOG(ERROR, TAG, "CACloneInfo Out of memory");
return CA_MEMORY_ALLOC_FAILED;
}
if (!clone->options)
{
- OIC_LOG(ERROR, TAG, "CAClonePayloadInfo Out of memory");
+ OIC_LOG(ERROR, TAG, "CACloneInfo Out of memory");
CADestroyInfoInternal(clone);
return CA_MEMORY_ALLOC_FAILED;
}
memcpy(clone->options, info->options, sizeof(CAHeaderOption_t) * info->numOptions);
+ clone->numOptions = info->numOptions;
}
- if (info->payload && 0 < info->payloadSize)
+ if ((info->payload) && (0 < info->payloadSize))
{
// allocate payload field
uint8_t *temp = OICMalloc(info->payloadSize);
if (!temp)
{
- OIC_LOG(ERROR, TAG, "CAClonePayloadInfo Out of memory");
+ OIC_LOG(ERROR, TAG, "CACloneInfo Out of memory");
CADestroyInfoInternal(clone);
return CA_MEMORY_ALLOC_FAILED;
}
// save the payload
clone->payload = temp;
+ clone->payloadSize = info->payloadSize;
}
- else
- {
- clone->payload = NULL;
- clone->payloadSize = 0;
- }
+ clone->payloadFormat = info->payloadFormat;
+ clone->acceptFormat = info->acceptFormat;
if (info->resourceUri)
{
char *temp = OICStrdup(info->resourceUri);
if (!temp)
{
- OIC_LOG(ERROR, TAG, "CAClonePayloadInfo Out of memory");
+ OIC_LOG(ERROR, TAG, "CACloneInfo Out of memory");
CADestroyInfoInternal(clone);
return CA_MEMORY_ALLOC_FAILED;
}
clone->resourceUri = temp;
}
+#ifdef ROUTING_GATEWAY
+ clone->skipRetransmission = info->skipRetransmission;
+#endif
+
+ clone->messageId = info->messageId;
+ clone->type = info->type;
+
return CA_STATUS_OK;
}
}
ca_mutex_lock(thread_pool->details->list_lock);
- CAResult_t addResult = u_arraylist_add(thread_pool->details->threads_list, (void*)threadHandle);
+ bool addResult = u_arraylist_add(thread_pool->details->threads_list, (void*)threadHandle);
ca_mutex_unlock(thread_pool->details->list_lock);
- if(addResult != CA_STATUS_OK)
+ if(!addResult)
{
OIC_LOG_V(ERROR, TAG, "Arraylist Add failed, may not be properly joined: %d", addResult);
- return addResult;
+ return CA_STATUS_FAILED;
}
OIC_LOG(DEBUG, TAG, "OUT");
}
}
- CAResult_t freeres = u_arraylist_free(&(thread_pool->details->threads_list));
- if(CA_STATUS_OK != freeres)
- {
- OIC_LOG_V(ERROR, TAG, "Failed to free array list, error was: %d", freeres);
- }
+ u_arraylist_free(&(thread_pool->details->threads_list));
ca_mutex_unlock(thread_pool->details->list_lock);
ca_mutex_free(thread_pool->details->list_lock);
static android_LogPriority LEVEL[] =
{ ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
#endif
-#elif defined __linux__
+#elif defined (__linux__) || defined (__APPLE__)
static const char *LEVEL[] __attribute__ ((unused)) =
{ "DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
#elif defined ARDUINO
void OICLogShutdown()
{
-#ifdef __linux__
+#if defined(__linux__) || defined(__APPLE__)
if (logCtx && logCtx->destroy)
{
logCtx->destroy(logCtx);
__android_log_write(LEVEL[level], tag, logStr);
#endif
-#elif defined __linux__
+#elif defined __linux__ || defined __APPLE__
if (logCtx && logCtx->write_level)
{
logCtx->write_level(logCtx, LEVEL_XTABLE[level], logStr);
int min = 0;
int sec = 0;
int ms = 0;
-#ifdef _POSIX_TIMERS
+#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
struct timespec when = { 0, 0 };
clockid_t clk = CLOCK_REALTIME;
#ifdef CLOCK_REALTIME_COARSE
va_end(ap);
}
-#endif //ARDUINO
+#endif //ARDUINO
\ No newline at end of file
#define TAG "UARRAYLIST"
/**
- * Use this default size when initialized
+ * Use this default capacity when initialized
*/
-#define U_ARRAYLIST_DEFAULT_SIZE 1
+#define U_ARRAYLIST_DEFAULT_CAPACITY 1
u_arraylist_t *u_arraylist_create()
{
- u_arraylist_t *list = NULL;
-
- list = (u_arraylist_t *) OICMalloc(sizeof(u_arraylist_t));
+ u_arraylist_t *list = (u_arraylist_t *) OICCalloc(1, sizeof(u_arraylist_t));
if (!list)
{
+ OIC_LOG(DEBUG, TAG, "Out of memory");
return NULL;
}
- list->size = U_ARRAYLIST_DEFAULT_SIZE;
+ list->capacity = U_ARRAYLIST_DEFAULT_CAPACITY;
list->length = 0;
- list->data = (void *) OICMalloc(list->size * sizeof(void *));
+ list->data = (void **) OICMalloc(list->capacity * sizeof(list->data[0]));
if (!list->data)
{
OIC_LOG(DEBUG, TAG, "Out of memory");
return list;
}
-CAResult_t u_arraylist_free(u_arraylist_t **list)
+void u_arraylist_free(u_arraylist_t **list)
{
if (!list || !(*list))
{
- return CA_STATUS_INVALID_PARAM;
+ return;
}
OICFree((*list)->data);
OICFree(*list);
*list = NULL;
+}
- return CA_STATUS_OK;
+void u_arraylist_reserve(u_arraylist_t *list, size_t count)
+{
+ if (list && (count > list->capacity))
+ {
+ void *tmp = OICRealloc(list->data, count * sizeof(list->data[0]));
+ if (!tmp)
+ {
+ OIC_LOG(DEBUG, TAG, "Memory reallocation failed.");
+ // Note that this is considered non-fatal.
+ }
+ else
+ {
+ list->data = (void **) tmp;
+ list->capacity = count;
+ }
+ }
+}
+
+void u_arraylist_shrink_to_fit(u_arraylist_t *list)
+{
+ if (!list)
+ {
+ return;
+ }
+
+ if ((list->capacity > list->length)
+ && (list->length >= U_ARRAYLIST_DEFAULT_CAPACITY))
+ {
+ void *tmp = OICRealloc(list->data,
+ list->length * sizeof(list->data[0]));
+ if (!tmp)
+ {
+ OIC_LOG(DEBUG, TAG, "Memory reallocation failed.");
+ // Considered non-fatal as this call is non-binding.
+ }
+ else
+ {
+ list->data = (void **) tmp;
+ list->capacity = list->length;
+ }
+ }
}
void *u_arraylist_get(const u_arraylist_t *list, uint32_t index)
return NULL;
}
-CAResult_t u_arraylist_add(u_arraylist_t *list, void *data)
+bool u_arraylist_add(u_arraylist_t *list, void *data)
{
if (!list)
{
- return CA_STATUS_INVALID_PARAM;
+ return false;
}
- if (list->size <= list->length)
+ if (list->capacity <= list->length)
{
+ // Does a non-FP calcuation of the 1.5 growth factor. Helpful for
+ // certain limited platforms.
+ size_t new_capacity = ((list->capacity * 3) + 1) / 2;
- uint32_t new_size = list->size + 1;
- if (!(list->data = (void **) realloc(list->data, new_size * sizeof(void *))))
+ // In case the re-alloc returns null, use a local variable to avoid
+ // losing the current block of memory.
+ void *tmp = OICRealloc(list->data,
+ new_capacity * sizeof(list->data[0]));
+ if (!tmp)
{
- return CA_MEMORY_ALLOC_FAILED;
+ OIC_LOG(DEBUG, TAG, "Memory reallocation failed.");
+ return false;
}
-
- memset(list->data + list->size, 0, (new_size - list->size) * sizeof(void *));
- list->size = new_size;
+ list->data = (void **) tmp;
+ memset(list->data + list->capacity, 0,
+ (new_capacity - list->capacity) * sizeof(list->data[0]));
+ list->capacity = (uint32_t)new_capacity;
}
list->data[list->length] = data;
list->length++;
- return CA_STATUS_OK;
+ return true;
}
void *u_arraylist_remove(u_arraylist_t *list, uint32_t index)
{
void *removed = NULL;
- if (!list)
- {
- return NULL;
- }
-
- if (index >= list->length)
+ if (!list || (index >= list->length))
{
return NULL;
}
if (index < list->length - 1)
{
- memmove(&list->data[index], &list->data[index + 1],
- (list->length - index - 1) * sizeof(void *));
+ memmove(&list->data[index],
+ &list->data[index + 1],
+ (list->length - index - 1) * sizeof(list->data[0]));
}
- list->size--;
list->length--;
- // check minimum size.
- list->size = (list->size <= U_ARRAYLIST_DEFAULT_SIZE) ? U_ARRAYLIST_DEFAULT_SIZE : list->size;
-
- if (!(list->data = (void **) realloc(list->data, list->size * sizeof(void *))))
- {
- return NULL;
- }
-
return removed;
}
return list->length;
}
-bool u_arraylist_contains(const u_arraylist_t *list,const void *data)
+bool u_arraylist_contains(const u_arraylist_t *list, const void *data)
{
- uint32_t i = 0;
-
if (!list)
{
return false;
}
- uint32_t length = u_arraylist_length(list);
-
- for (i = 0; i < length; i++)
+ for (uint32_t i = 0; i < list->length; i++)
{
- if (data == u_arraylist_get(list, i))
+ if (data == list->data[i])
{
return true;
}
{
return;
}
- uint32_t len = u_arraylist_length(list);
- for (uint32_t i = 0; i < len; i++)
+ for (uint32_t i = 0; i < list->length; i++)
{
- OICFree(u_arraylist_get(list, i));
+ OICFree(list->data[i]);
}
(void)u_arraylist_free(&list);
}
--- /dev/null
+/* ****************************************************************
+ *
+ * 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 "ulinklist.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "caadapterutils.h"
+
+/**
+ * Logging tag for module name.
+ */
+#define TAG "ULINKLIST"
+
+u_linklist_t *u_linklist_create()
+{
+ u_linklist_t *header = (u_linklist_t *)OICMalloc(sizeof(u_linklist_t));
+ if (!header)
+ {
+ OIC_LOG(ERROR, TAG, "Out of memory");
+ return NULL;
+ }
+ header->list=NULL;
+ header->size=0;
+ return header;
+}
+
+CAResult_t u_linklist_add_head(u_linklist_t *linklist, void *data)
+{
+ VERIFY_NON_NULL(linklist, TAG, "list is null");
+ VERIFY_NON_NULL(data, TAG, "data is null");
+
+ u_linklist_data_t *add_node = NULL;
+ add_node = (u_linklist_data_t *) OICMalloc(sizeof(u_linklist_data_t));
+ if (NULL == add_node)
+ {
+ OIC_LOG(DEBUG, TAG, "LinklistAdd FAIL, memory allocation failed");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ add_node->data = data;
+ add_node->next = linklist->list;
+ linklist->list = add_node;
+ linklist->size += 1;
+ return CA_STATUS_OK;
+}
+
+CAResult_t u_linklist_add(u_linklist_t *linklist, void *data)
+{
+ VERIFY_NON_NULL(linklist, TAG, "list is null");
+ VERIFY_NON_NULL(data, TAG, "data is null");
+
+ u_linklist_data_t *add_node = NULL;
+ u_linklist_data_t *node = linklist->list;
+ add_node = (u_linklist_data_t *) OICMalloc(sizeof(u_linklist_data_t));
+ if (NULL == add_node)
+ {
+ OIC_LOG(DEBUG, TAG, "LinklistAdd FAIL, memory allocation failed");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ add_node->data = data;
+ add_node->next = NULL;
+
+ if (NULL == node)
+ {
+ linklist->list = add_node;
+ linklist->size += 1;
+ }
+ else
+ {
+ //else loop through the list and find the last node, insert next to it
+ while (true)
+ {
+ if(node->next == NULL)
+ {
+ node->next = add_node;
+ linklist->size += 1;
+ break;
+ }
+ node = node->next;
+ };
+ }
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t u_linklist_free(u_linklist_t **linklist)
+{
+ VERIFY_NON_NULL(linklist, TAG, "linklist is null");
+ if (!(*linklist))
+ {
+ OIC_LOG(DEBUG, TAG, "List is already Empty");
+ return CA_STATUS_OK;
+ }
+
+ u_linklist_data_t *free_node=NULL;
+ while((*linklist)->size)
+ {
+ free_node = (*linklist)->list;
+ (*linklist)->list = (*linklist)->list->next;
+
+ if(free_node != NULL)
+ {
+ OICFree(free_node);
+ free_node=NULL;
+ }
+
+ (*linklist)->size -= 1;
+ }
+ *linklist=NULL;
+
+ return CA_STATUS_OK;
+}
+
+CAResult_t u_linklist_remove(u_linklist_t *linklist, u_linklist_iterator_t **iter)
+{
+ VERIFY_NON_NULL(linklist, TAG, "list is null");
+ VERIFY_NON_NULL(iter, TAG, "iterator is null");
+
+ if (NULL == *iter)
+ {
+ return CA_STATUS_INVALID_PARAM;
+ }
+
+ // When node to be deleted is head node
+ if (linklist->list == *iter)
+ {
+ // store address of next node
+ linklist->list = linklist->list->next;
+
+ // free memory
+ linklist->size -=1;
+ OICFree(*iter);
+
+ *iter = linklist->list;
+
+ return CA_STATUS_OK;
+ }
+
+
+ // When not first node, follow the normal deletion process find the previous node
+ u_linklist_data_t *prev = linklist->list;
+ while(NULL != prev->next && prev->next != *iter)
+ {
+ prev = prev->next;
+ }
+
+ // Check if node really exists in Linked List
+ if (NULL == prev->next)
+ {
+ OIC_LOG(ERROR, TAG, " Given node is not present in Linked List\n");
+ return CA_STATUS_FAILED;
+ }
+
+ // Remove node from Linked List
+ prev->next = prev->next->next;
+ linklist->size -=1;
+ OICFree(*iter);
+ *iter = prev->next;
+
+ return CA_STATUS_OK;
+}
+
+
+uint32_t u_linklist_length(const u_linklist_t *linklist)
+{
+ VERIFY_NON_NULL(linklist, TAG, "list is null");
+
+ return linklist->size;
+}
+
+void u_linklist_init_iterator(const u_linklist_t *linklist, u_linklist_iterator_t **iter)
+{
+ VERIFY_NON_NULL_VOID(linklist, TAG, "list is null");
+ VERIFY_NON_NULL_VOID(iter, TAG, "iterator is null");
+
+ *iter = linklist->list;
+}
+
+void *u_linklist_get_data(const u_linklist_iterator_t *iter)
+{
+ VERIFY_NON_NULL_RET(iter, TAG, "iterator is null", NULL);
+
+ return iter->data;
+}
+
+void *u_linklist_get_next(u_linklist_iterator_t **iter)
+{
+ VERIFY_NON_NULL_RET(iter, TAG, "iterator is null", NULL);
+ *iter = (*iter)->next;
+
+ if (NULL != *iter)
+ {
+ return (*iter)->data;
+ }
+ else
+ {
+ return NULL;
+ }
+}
* This will be used during the receive of network requests and response.
* @see SendUnicastData(), SendMulticastData()
*/
-typedef void (*CANetworkPacketReceivedCallback)(const CAEndpoint_t *endPoint,
+typedef void (*CANetworkPacketReceivedCallback)(const CASecureEndpoint_t *sep,
const void *data, uint32_t dataLen);
/**
*/
extern void OCGetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo);
-typedef void (*CAPacketReceivedCallback)(const CAEndpoint_t *endpoint,
+typedef void (*CAPacketReceivedCallback)(const CASecureEndpoint_t *sep,
const void *data, uint32_t dataLength);
typedef void (*CAPacketSendCallback)(CAEndpoint_t *endpoint,
* Select the cipher suite for dtls handshake
*
* @param[in] cipher cipher suite
- * 0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA
+ * 0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256
* 0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8
* 0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
*
* @retval ::CA_STATUS_FAILED Operation failed.
*
*/
-CAResult_t CAAdapterNetDtlsDecrypt(const CAEndpoint_t *endpoint,
+CAResult_t CAAdapterNetDtlsDecrypt(const CASecureEndpoint_t *sep,
uint8_t *data,
uint32_t dataLen);
} CAServerInfo_t;
/**
- * To log the PDU data.
- */
-void CALogPDUData(coap_pdu_t *pdu);
-
-/**
* To parse the IP address and port from "ipaddress:port".
* @param[in] ipAddrStr IP address to be parsed.
* @param[out] ipAddr Parsed IP address.
* @param[in] endpoint port of transport.
* @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
-CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t info,
+CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info,
const CAEndpoint_t *endpoint);
/**
* @param[in] blockID ID set of CABlockData.
* @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
-CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t info, size_t dataLength,
+CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t *info, size_t dataLength,
const CABlockDataID_t *blockID);
/**
* @param[in] blockID ID set of CABlockData.
* @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
-CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t info, size_t dataLength,
+CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t *info, size_t dataLength,
const CABlockDataID_t *blockID);
/**
typedef struct
{
CAEndpoint_t *remoteEndpoint; /**< Remote Endpoint. */
- void *data; /**< Data to be sent. */
+ uint8_t *data; /**< Data to be sent. */
uint32_t dataLen; /**< Length of the data to be sent. */
} CAEDRData;
* @param[out] sentLength Length of the sent data.
* @pre Callback must be registered using CAEDRSetPacketReceivedCallback().
*/
-typedef void (*CAEDRDataReceivedCallback)(const char *remoteAddress, const void *data,
+typedef void (*CAEDRDataReceivedCallback)(const char *remoteAddress, const uint8_t *data,
uint32_t dataLength, uint32_t *sentLength);
/**
* @param[in] result error code as defined in ::CAResult_t.
* @pre Callback must be registered using CAEDRSetPacketReceivedCallback().
*/
-typedef void (*CAEDRErrorHandleCallback)(const char *remoteAddress, const void *data,
- uint32_t dataLength, CAResult_t result);
+typedef void (*CAEDRErrorHandleCallback)(const char *remoteAddress,
+ const uint8_t *data,
+ uint32_t dataLength,
+ CAResult_t result);
/**
* Initialize the network monitor module
* @param[in] dataLength Length of the data to be sent.
* @return ::CA_STATUS_OK or Appropriate error code.
*/
-CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const void *data,
+CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress,
+ const uint8_t *data,
uint32_t dataLength);
/**
* @param[in] dataLength Length of the data to be sent.
* @return ::CA_STATUS_OK or Appropriate error code.
*/
-CAResult_t CAEDRClientSendMulticastData(const void *data, uint32_t dataLength);
+CAResult_t CAEDRClientSendMulticastData(const uint8_t *data,
+ uint32_t dataLength);
/**
* This function gets bonded bluetooth device list
/**
* This function is used to generate the CA specific header to
- * maintain the fragmentation logic. The header structure
- * explained above will be formed and returned to the caller.
+ * maintain the fragmentation logic. The header structure explained
+ * above will be formed and returned to the caller.
*
- * @param[in,out] header Pointer to the octet array that will contain
- * the generated header.
- * @param[in] length The total length of the data. The length will
- * be embedded in bits 5-16 of the header,
- * meaning the maximum overall length of the
- * data to be fragmented can be no more than 4096
- * (2^12).
+ * @param[in,out] header Pointer to the octet array that will
+ * contain the generated header.
+ * @param[in] headerLength Length of the @a header octet array.
+ * @param[in] dataLength The total length of the data. The
+ * length will be embedded in bits 5-16 of
+ * the header, meaning the maximum overall
+ * length of the data to be fragmented can
+ * be no more than 4096 (2^12).
*
- * @return ::CA_STATUS_OK on success. One of the ::CA_STATUS_FAILED or
- * other error values on error.
- * @retval ::CA_STATUS_OK Successful
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments
- * @retval ::CA_STATUS_FAILED Operation failed
-*/
-CAResult_t CAGenerateHeader(char *header, uint32_t length);
-
-/**
- * This function is used to parse the header in the receiver
- * end. This function will provide the information of the total
- * length of the data which has been fragmented.
+ * @return @c CA_STATUS_OK on success. One of the @c CA_STATUS_FAILED
+ * or other error values on error.
+ * @retval @c CA_STATUS_OK Successful
+ * @retval @c CA_STATUS_INVALID_PARAM Invalid input arguments
+ * @retval @c CA_STATUS_FAILED Operation failed
+ */
+CAResult_t CAGenerateHeader(uint8_t *header,
+ size_t headerLength,
+ size_t datalength);
+
+/**
+ * This function is used to parse the header in the receiver end. This
+ * function will provide the information of the total length of the
+ * data which has been fragmented.
*
- * @param[in] header Pointer to the octet array data which contains the
- * header information. Note that pointer should
+ * @param[in] header Pointer to the octet array data which contains
+ * the header information. Note that pointer should
* point to two bytes of data header which needs to
* be parsed.
+ * @param[in] length Length of the @a octet array containing the
+ * header.
*
* @return Overall length of the data to be reassembled, or 0 on
* failure.
*/
-uint32_t CAParseHeader(const char *header);
+uint32_t CAParseHeader(const uint8_t *header, size_t length);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* CA_FRAGMENTATION_H_ */
-
/**
* Callback to be notified on reception of any data from remote OIC devices.
*
- * @param[in] endpoint network endpoint description.
+ * @param[in] sep network endpoint description.
* @param[in] data Data received from remote OIC device.
* @param[in] dataLength Length of data in bytes.
* @pre Callback must be registered using CAIPSetPacketReceiveCallback().
*/
-typedef void (*CAIPPacketReceivedCallback)(const CAEndpoint_t *endpoint,
+typedef void (*CAIPPacketReceivedCallback)(const CASecureEndpoint_t *sep,
const void *data,
uint32_t dataLength);
u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex);
/**
- * Set callback for error handling.
+ * @brief Find a new network interface.
+ *
+ * @return Description of interface (or NULL if no change)
+ */
+CAInterface_t *CAFindInterfaceChange();
+
+/**
+ * @brief Let the network monitor update the polling interval.
+ * @param [in] current polling interval
+ *
+ * @return desired polling interval
+ */
+int CAGetPollingInterval(int interval);
+
+/**
+ * @brief Tell the IP server an interface has been added.
+ */
+void CAWakeUpForChange();
+
+/**
+ * Start network monitor.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAIPStartNetworkMonitor();
+
+/**
+ * Stops network monitor.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAIPStopNetworkMonitor();
+
+/**
+ * @brief Set callback for error handling.
*
* @param[in] ipErrorCallback callback to notify error to the ipadapter.
*/
******************************************************************/
/**
+ * @file
+ *
* This file provides APIs for BLE modules.
*/
* @retval ::CA_STATUS_FAILED Operation failed.
*/
typedef CAResult_t (*CABLEDataReceivedCallback)(const char *remoteAddress,
- const void *data,
+ const uint8_t *data,
uint32_t dataLength,
uint32_t *sentLength);
* Update characteristics(Read/Write) value that we want to send to
* particular client.
*
- * @param[in] address BD address of Gatt client
- * @param[in] charValue Data that we want to send to client(unicast)
- * @param[in] charValueLen Length of the data.
+ * @param[in] address BD address of Gatt client
+ * @param[in] value Data that we want to send to client(unicast)
+ * @param[in] valueLen Length of the data.
*
* @return ::CA_STATUS_OK or Appropriate error code
* @retval ::CA_STATUS_OK Successful
* @retval ::CA_STATUS_FAILED Operation failed
*/
CAResult_t CAUpdateCharacteristicsToGattClient(const char *address,
- const char *charValue,
- uint32_t charValueLen);
+ const uint8_t *value,
+ uint32_t valueLen);
/**
* Update characteristics(Read/Write) value that we want to multicast
* to all clients.
*
- * @param[in] charValue Data that we want to send to clients(multicast)
- * @param[in] charValueLen Length of the data.
+ * @param[in] value Data that we want to send to clients(multicast)
+ * @param[in] valueLen Length of the data.
*
* @return ::CA_STATUS_OK or Appropriate error code
* @retval ::CA_STATUS_OK Successful
* @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments
* @retval ::CA_STATUS_FAILED Operation failed
*/
-CAResult_t CAUpdateCharacteristicsToAllGattClients(const char *charValue,
- uint32_t charValueLen);
+CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *value,
+ uint32_t valueLen);
/**
* Start @c CAStartBleGattClientThread for initializing Gatt Client.
* @retval ::CA_STATUS_FAILED Operation failed
*/
CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress,
- const char *data,
+ const uint8_t *data,
uint32_t dataLen,
CALETransferType_t type,
int32_t position);
* @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments
* @retval ::CA_STATUS_FAILED Operation failed
*/
-CAResult_t CAUpdateCharacteristicsToAllGattServers(const char *data,
+CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data,
uint32_t dataLen);
/**
* @param[in] result error code as per CAResult_t
*/
typedef void (*CABLEErrorHandleCallback)(const char *remoteAddress,
- const void *data,
+ const uint8_t *data,
uint32_t dataLength,
CAResult_t result);
/**
CARequestInfo_t *requestInfo;
CAResponseInfo_t *responseInfo;
CAErrorInfo_t *errorInfo;
- CAHeaderOption_t *options;
CADataType_t dataType;
- uint8_t numOptions;
} CAData_t;
#ifdef __cplusplus
/**
* To log the PDU data.
* @param[in] pdu pdu data.
+ * @param[in] endpoint endpoint
*/
-void CALogPDUInfo(coap_pdu_t *pdu);
+void CALogPDUInfo(coap_pdu_t *pdu, const CAEndpoint_t *endpoint);
#ifdef WITH_BWT
/**
#include "cacommon.h"
#include "config.h"
#include "coap.h"
-#include "debug.h"
#ifdef __cplusplus
extern "C"
/**
* extracts request information from received pdu.
* @param[in] pdu received pdu.
+ * @param[in] endpoint endpoint information.
* @param[out] outReqInfo request info structure made from received pdu.
* @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
*/
-CAResult_t CAGetRequestInfoFromPDU(const coap_pdu_t *pdu, CARequestInfo_t *outReqInfo);
+CAResult_t CAGetRequestInfoFromPDU(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
+ CARequestInfo_t *outReqInfo);
/**
* extracts response information from received pdu.
* @param[in] pdu received pdu.
* @param[out] outResInfo response info structure made from received pdu.
+ * @param[in] endpoint endpoint information.
* @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
*/
-CAResult_t CAGetResponseInfoFromPDU(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo);
+CAResult_t CAGetResponseInfoFromPDU(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo,
+ const CAEndpoint_t *endpoint);
/**
* extracts error information from received pdu.
* @param[in] pdu received pdu.
+ * @param[in] endpoint endpoint information.
* @param[out] errorInfo error info structure made from received pdu.
* @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
*/
-CAResult_t CAGetErrorInfoFromPDU(const coap_pdu_t *pdu, CAErrorInfo_t *errorInfo);
+CAResult_t CAGetErrorInfoFromPDU(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
+ CAErrorInfo_t *errorInfo);
/**
* creates pdu from the request information.
* @param[in] code request or response code.
- * @param[out] options options for the request and response.
* @param[in] info information to create pdu.
* @param[in] endpoint endpoint information.
+ * @param[out] options options for the request and response.
* @return generated pdu.
*/
-coap_pdu_t *CAGeneratePDUImpl(code_t code, coap_list_t *options, const CAInfo_t *info,
- const CAEndpoint_t *endpoint);
+coap_pdu_t *CAGeneratePDUImpl(code_t code, const CAInfo_t *info,
+ const CAEndpoint_t *endpoint, coap_list_t *options);
/**
* parse the URI and creates the options.
/**
* gets option data.
+ * @param[in] key ID of the option
* @param[in] data data that is received.
* @param[in] length length of the data.
* @param[out] option result of the operation.
* @param[in] buflen buffer length of the result.
* @return option count.
*/
-uint32_t CAGetOptionData(const uint8_t *data, uint32_t len, uint8_t *option, uint32_t buflen);
+uint32_t CAGetOptionData(uint16_t key, const uint8_t *data, uint32_t len,
+ uint8_t *option, uint32_t buflen);
/**
* extracts request information from received pdu.
* @param[in] pdu received pdu.
+ * @param[in] endpoint endpoint information.
* @param[out] outCode code of the received pdu.
* @param[out] outInfo request info structure made from received pdu.
* @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
*/
-CAResult_t CAGetInfoFromPDU(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *outInfo);
+CAResult_t CAGetInfoFromPDU(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
+ uint32_t *outCode, CAInfo_t *outInfo);
/**
* create pdu from received data.
* @param[in] data received data.
* @param[in] length length of the data received.
* @param[out] outCode code received.
+ * @param[in] endpoint endpoint information.
* @return coap_pdu_t value.
*/
-coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode);
+coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode,
+ const CAEndpoint_t *endpoint);
/**
* get Token from received data(pdu).
* @param[in] pdu_hdr header of received pdu.
* @param[out] outInfo information with token received.
+ * @param[in] endpoint endpoint information.
* @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
*/
-CAResult_t CAGetTokenFromPDU(const coap_hdr_t *pdu_hdr, CAInfo_t *outInfo);
+CAResult_t CAGetTokenFromPDU(const coap_hdr_t *pdu_hdr, CAInfo_t *outInfo,
+ const CAEndpoint_t *endpoint);
/**
* generates the token.
*/
CAResponseResult_t CAGetCodeFromPduBinaryData(const void *pdu, uint32_t size);
+/**
+ * convert format from CoAP media type encoding to CAPayloadFormat_t.
+ * @param[in] format coap format code.
+ * @return format.
+ */
+CAPayloadFormat_t CAConvertFormat(uint8_t format);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
--- /dev/null
+/* ****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the APIs for TCP Adapter.
+ */
+#ifndef CA_TCP_ADAPTER_H_
+#define CA_TCP_ADAPTER_H_
+
+#include "cacommon.h"
+#include "caadapterinterface.h"
+#include "cathreadpool.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * TCP Server Information for IPv4 TCP transport
+ */
+typedef struct
+{
+ char addr[MAX_ADDR_STR_SIZE_CA]; /**< TCP Server address */
+ CASocket_t u4tcp; /**< TCP Server port */
+} CATCPServerInfo_t;
+
+/**
+ * API to initialize TCP Interface.
+ * @param[in] registerCallback Callback to register TCP interfaces to
+ * Connectivity Abstraction Layer.
+ * @param[in] networkPacketCallback Callback to notify request and
+ * response messages from server(s)
+ * started at Connectivity Abstraction Layer.
+ * @param[in] netCallback Callback to notify the network additions
+ * to Connectivity Abstraction Layer.
+ * @param[in] errorCallback Callback to notify the network errors to
+ * Connectivity Abstraction Layer.
+ * @param[in] handle Threadpool Handle.
+ * @return ::CA_STATUS_OK or Appropriate error code
+ */
+CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
+ CANetworkPacketReceivedCallback networkPacketCallback,
+ CANetworkChangeCallback netCallback,
+ CAErrorHandleCallback errorCallback, ca_thread_pool_t handle);
+
+/**
+ * Start TCP Interface adapter.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAStartTCP();
+
+/**
+ * Start listening server for receiving connect requests.
+ * Transport Specific Behavior:
+ * TCP Starts Listening Server on a particular interface and prefixed port
+ * number and as per OIC Specification.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAStartTCPListeningServer();
+
+/**
+ * Start discovery servers for receiving advertisements.
+ * Transport Specific Behavior:
+ * TCP Starts Discovery server on a particular interface and prefixed port
+ * number as per OIC Specification.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAStartTCPDiscoveryServer();
+
+/**
+ * Sends data to the endpoint using the adapter connectivity.
+ * @param[in] endpoint Remote Endpoint information (like ipaddress,
+ * port, reference uri and transport type) to
+ * which the unicast data has to be sent.
+ * @param[in] data Data which is required to be sent.
+ * @param[in] dataLen Size of data to be sent.
+ * @note dataLen must be > 0.
+ * @return The number of bytes sent on the network, or -1 upon error.
+ */
+int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
+ const void *data, uint32_t dataLen);
+
+/**
+ * Send Multicast data to the endpoint using the TCP connectivity.
+ * @param[in] endpoint Remote Endpoint information (like ipaddress,
+ * port)
+ * @param[in] data Data which is required to be sent.
+ * @param[in] dataLen Size of data to be sent.
+ * @note dataLen must be > 0.
+ * @return The number of bytes sent on the network, or -1 upon error.
+ */
+int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
+ const void *data, uint32_t dataLen);
+
+/**
+ * Get TCP Connectivity network information.
+ * @param[out] info Local connectivity information structures.
+ * @note info is allocated in this API and should be freed by the caller.
+ * @param[out] size Number of local connectivity structures.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAGetTCPInterfaceInformation(CAEndpoint_t **info, uint32_t *size);
+
+/**
+ * Read Synchronous API callback.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAReadTCPData();
+
+/**
+ * Stops Unicast, servers and close the sockets.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CAStopTCP();
+
+/**
+ * Terminate the TCP connectivity adapter.
+ * Configuration information will be deleted from further use.
+ */
+void CATerminateTCP();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif // CA_TCP_ADAPTER_H_
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file provides APIs TCP client/server/network monitor modules.
+ */
+
+#ifndef CA_TCP_INTERFACE_H_
+#define CA_TCP_INTERFACE_H_
+
+#include <stdbool.h>
+
+#include "cacommon.h"
+#include "catcpadapter.h"
+#include "cathreadpool.h"
+#include "uarraylist.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Callback to be notified on reception of any data from remote OIC devices.
+ *
+ * @param[in] endpoint network endpoint description.
+ * @param[in] data Data received from remote OIC device.
+ * @param[in] dataLength Length of data in bytes.
+ * @pre Callback must be registered using CAIPSetPacketReceiveCallback().
+ */
+typedef void (*CATCPPacketReceivedCallback)(const CAEndpoint_t *endpoint,
+ const void *data,
+ uint32_t dataLength);
+
+/**
+ * Callback to notify error in the TCP adapter.
+ *
+ * @param[in] endpoint network endpoint description.
+ * @param[in] data Data sent/received.
+ * @param[in] dataLength Length of data in bytes.
+ * @param[in] result result of request from R.I.
+ * @pre Callback must be registered using CAIPSetPacketReceiveCallback().
+ */
+typedef void (*CATCPErrorHandleCallback)(const CAEndpoint_t *endpoint, const void *data,
+ uint32_t dataLength, CAResult_t result);
+
+/**
+ * set error callback to notify error in TCP adapter.
+ *
+ * @param[in] errorHandleCallback Callback function to notify the error
+ * in the TCP adapter.
+ */
+void CATCPSetErrorHandler(CATCPErrorHandleCallback errorHandleCallback);
+
+/**
+ * Start TCP server.
+ *
+ * @param threadPool Thread pool for managing Unicast server threads.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input data.
+ * @retval ::CA_STATUS_FAILED Initialization failed.
+ */
+CAResult_t CATCPStartServer(const ca_thread_pool_t threadPool);
+
+/**
+ * Stop TCP server.
+ */
+void CATCPStopServer();
+
+/**
+ * Set this callback for receiving data packets from peer devices.
+ *
+ * @param[in] callback Callback to be notified on reception of unicast data packets.
+ */
+void CATCPSetPacketReceiveCallback(CATCPPacketReceivedCallback callback);
+
+/**
+ * API to send unicast TCP data.
+ *
+ * @param[in] endpoint complete network address to send to.
+ * @param[in] data Data to be send.
+ * @param[in] dataLength Length of data in bytes.
+ * @param[in] isMulticast Whether data needs to be sent to multicast ip.
+ */
+void CATCPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t dataLength,
+ bool isMulticast);
+
+/**
+ * Get a list of CAInterface_t items.
+ *
+ * @return List of CAInterface_t items.
+ */
+u_arraylist_t *CATCPGetInterfaceInformation(int desiredIndex);
+
+/**
+ * Connect to TCP Server.
+ * @param[in] TCPServerInfo TCP Server information.
+ * @return TCP Server Information structure.
+ */
+CATCPServerInfo_t *CAConnectToTCPServer(const CAEndpoint_t *TCPServerInfo);
+
+/**
+ * Disconnect from TCP Server.
+ * @param[in] TCPServerInfo TCP Server information.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+CAResult_t CADisconnectFromTCPServer(const CAEndpoint_t *TCPServerInfo);
+
+/**
+ * Get TCP Connection Information from list.
+ * @param[in] addr TCP Server address.
+ * @param[in] port TCP Server port.
+ * @param[out] index index of array list.
+ * @return TCP Server Information structure.
+ */
+CATCPServerInfo_t *CAGetTCPServerInfoFromList(const char *addr, const uint16_t port,
+ uint32_t *index);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CA_TCP_INTERFACE_H_ */
+++ /dev/null
-/*
- * Copyright (c) 1995, 1999
- * Berkeley Software Design, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
- */
-
-#ifndef _IFADDRS_H_
-#define _IFADDRS_H_
-
-struct ifaddrs {
- struct ifaddrs *ifa_next;
- char *ifa_name;
- unsigned int ifa_flags;
- struct sockaddr *ifa_addr;
- struct sockaddr *ifa_netmask;
- union {
- struct sockaddr *ifu_broadaddr; /* Broadcast address of interface */
- struct sockaddr *ifu_dstaddr; /* Point-to-point destination address */
- } ifa_ifu;
- void *ifa_data;
-};
-#define ifa_broadaddr ifa_ifu.ifu_broadaddr
-#define ifa_dstaddr ifa_ifu.ifu_dstaddr
-
-/*
- * This may have been defined in <net/if.h>. Note that if <net/if.h> is
- * to be included it must be included before this header file.
- */
-#ifndef ifa_broadaddr
-#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
-#endif
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-extern int getifaddrs(struct ifaddrs **ifap);
-extern void freeifaddrs(struct ifaddrs *ifa);
-__END_DECLS
-
-#endif
libcoap_env = env.Clone()
target_os = env.get('TARGET_OS')
+ca_transport = env.get('TARGET_TRANSPORT')
# As in the source code(C) includes arduino Time library head file(C++)
# It requires compile the .c with g++
if target_os == 'arduino':
libcoap_env.AppendUnique(CFLAGS = ['-Wall', '-ffunction-sections',
'-fdata-sections', '-fno-exceptions'])
+if target_os == 'linux':
+ if (('TCP' in ca_transport) or ('ALL' in ca_transport)):
+ libcoap_env.AppendUnique(CPPDEFINES = ['WITH_TCP'])
+
if target_os == 'android':
libcoap_env.AppendUnique(LIBS = ['log'])
libcoap = libcoap_env.StaticLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap_')
libcoap_env.InstallTarget([libcoap], 'libcoap')
-libcoap_env.UserInstallTargetLib([libcoap], 'libcoap')
+libcoap_env.UserInstallTargetLib([libcoap], 'libcoap')
\ No newline at end of file
/* store information for handling the asynchronous task */
s = (coap_async_state_t *) coap_malloc(sizeof(coap_async_state_t) +
- request->hdr->token_length);
+ request->hdr->coap_hdr_udp_t.token_length);
if (!s)
{
coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n");
return NULL;
}
- memset(s, 0, sizeof(coap_async_state_t) + request->hdr->token_length);
+ memset(s, 0, sizeof(coap_async_state_t) + request->hdr->coap_hdr_udp_t.token_length);
/* set COAP_ASYNC_CONFIRM according to request's type */
s->flags = flags & ~COAP_ASYNC_CONFIRM;
- if (request->hdr->type == COAP_MESSAGE_CON)
+ if (request->hdr->coap_hdr_udp_t.type == COAP_MESSAGE_CON)
s->flags |= COAP_ASYNC_CONFIRM;
s->appdata = data;
memcpy(&s->peer, peer, sizeof(coap_address_t));
- if (request->hdr->token_length)
+ if (request->hdr->coap_hdr_udp_t.token_length)
{
- s->tokenlen = request->hdr->token_length;
- memcpy(s->token, request->hdr->token, request->hdr->token_length);
+ s->tokenlen = request->hdr->coap_hdr_udp_t.token_length;
+ memcpy(s->token, request->hdr->coap_hdr_udp_t.token, request->hdr->coap_hdr_udp_t.token_length);
}
memcpy(&s->id, &id, sizeof(coap_tid_t));
/* to re-encode the block option */
coap_add_option(pdu, type,
- coap_encode_var_bytes(buf, ((block->num << 4) | (block->m << 3) | block->szx)), buf);
+ coap_encode_var_bytes(buf, ((block->num << 4) | (block->m << 3) | block->szx)), buf,
+ coap_udp);
return 1;
}
#ifndef WITH_CONTIKI
void coap_show_pdu(const coap_pdu_t *pdu)
{
+#ifndef WITH_TCP
unsigned char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */
+#else
+ unsigned char buf[COAP_TCP_LENGTH_LIMIT_32_BIT]; /* need some space for output creation */
+#endif
int encode = 0, have_options = 0;
coap_opt_iterator_t opt_iter;
coap_opt_t *option;
- fprintf(COAP_DEBUG_FD, "v:%d t:%d tkl:%d c:%d id:%u", pdu->hdr->version, pdu->hdr->type,
- pdu->hdr->token_length, pdu->hdr->code, ntohs(pdu->hdr->id));
+ fprintf(COAP_DEBUG_FD, "v:%d t:%d tkl:%d c:%d id:%u", pdu->hdr->coap_hdr_udp_t.version,
+ pdu->hdr->coap_hdr_udp_t.type, pdu->hdr->coap_hdr_udp_t.token_length,
+ pdu->hdr->coap_hdr_udp_t.code, ntohs(pdu->hdr->coap_hdr_udp_t.id));
/* show options, if any */
- coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL);
+ coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL, coap_udp);
while ((option = coap_option_next(&opt_iter)))
{
unsigned char buf[80]; /* need some space for output creation */
PRINTF("v:%d t:%d oc:%d c:%d id:%u",
- pdu->hdr->version, pdu->hdr->type,
- pdu->hdr->optcnt, pdu->hdr->code, uip_ntohs(pdu->hdr->id));
+ pdu->hdr->coap_hdr_udp_t.version, pdu->hdr->coap_hdr_udp_t.type,
+ pdu->hdr->coap_hdr_udp_t.optcnt, pdu->hdr->coap_hdr_udp_t.code,
+ uip_ntohs(pdu->hdr->coap_hdr_udp_t.id));
/* show options, if any */
- if (pdu->hdr->optcnt)
+ if (pdu->hdr->coap_hdr_udp_t.optcnt)
{
coap_opt_iterator_t opt_iter;
coap_opt_t *option;
- coap_option_iterator_init((coap_pdu_t *)pdu, &opt_iter, COAP_OPT_ALL);
+ coap_option_iterator_init((coap_pdu_t *)pdu, &opt_iter, COAP_OPT_ALL, coap_udp);
PRINTF(" o:");
while ((option = coap_option_next(&opt_iter)))
* README for terms of use.
*/
+#include "config.h"
+
+#if defined(HAVE_ASSERT_H) && !defined(assert)
+# include <assert.h>
+#endif
+
#ifndef NDEBUG
# include <stdio.h>
#endif
#include "config.h"
#include "encode.h"
+#include "option.h"
/* Carsten suggested this when fls() is not available: */
int coap_fls(unsigned int i)
return n;
}
+bool coap_is_var_bytes(coap_option_def_t* def)
+{
+ assert (def);
+
+ if('u' == def->type)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
#endif
#endif
+#include "option.h"
+
#define Nn 8 /* duplicate definition of N if built on sky motes */
#define E 4
#define HIBIT (1 << (Nn - 1))
*/
unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val);
+/**
+ * Tests whether the option definition has a type that allows variable byte encoding.
+ * Returns true when supported, false when not supported.
+ */
+bool coap_is_var_bytes(coap_option_def_t* def);
+
#endif /* _COAP_ENCODE_H_ */
coap_opt_iterator_t opt_iter;
int ok = 1;
- coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL);
+ coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL, coap_udp);
while (coap_option_next(&opt_iter))
{
coap_hash((const unsigned char *)&peer->addr, sizeof(peer->addr), h);
#endif /* WITH_LWIP || WITH_CONTIKI */
- coap_hash((const unsigned char *)&pdu->hdr->id, sizeof(unsigned short), h);
+ coap_hash((const unsigned char *)&pdu->hdr->coap_hdr_udp_t.id, sizeof(unsigned short), h);
*id = ((h[0] << 8) | h[1]) ^ ((h[2] << 8) | h[3]);
}
coap_pdu_t *response;
coap_tid_t result = COAP_INVALID_TID;
- if (request && request->hdr->type == COAP_MESSAGE_CON)
+ if (request && request->hdr->coap_hdr_udp_t.type == COAP_MESSAGE_CON)
{
- response = coap_pdu_init(COAP_MESSAGE_ACK, 0, request->hdr->id, sizeof(coap_pdu_t));
+ response = coap_pdu_init(COAP_MESSAGE_ACK, 0, request->hdr->coap_hdr_udp_t.id,
+ sizeof(coap_pdu_t), coap_udp);
if (response)
{
result = coap_send(context, dst, response);
if (request)
{
- response = coap_pdu_init(type, 0, request->hdr->id, sizeof(coap_pdu_t));
+ response = coap_pdu_init(type, 0, request->hdr->coap_hdr_udp_t.id,
+ sizeof(coap_pdu_t), coap_udp);
if (response)
{
result = coap_send(context, dst, response);
node->t = node->timeout << node->retransmit_cnt;
coap_insert_node(&context->sendqueue, node);
#ifdef WITH_LWIP
- if (node == context->sendqueue) /* don't bother with timer stuff if there are earlier retransmits */
+ /* don't bother with timer stuff if there are earlier retransmits */
+ if (node == context->sendqueue)
coap_retransmittimer_restart(context);
#endif
debug(
- "** retransmission #%d of transaction %d\n", node->retransmit_cnt, ntohs(node->pdu->hdr->id));
+ "** retransmission #%d of transaction %d\n", node->retransmit_cnt,
+ ntohs(node->pdu->hdr->coap_hdr_udp_t.id));
node->id = coap_send_impl(context, &node->remote, node->pdu);
return node->id;
#ifndef WITHOUT_OBSERVE
/* Check if subscriptions exist that should be canceled after
COAP_MAX_NOTIFY_FAILURES */
- if (node->pdu->hdr->code >= 64)
+ if (node->pdu->hdr->coap_hdr_udp_t.code >= 64)
{
str token =
{ 0, NULL };
- token.length = node->pdu->hdr->token_length;
- token.s = node->pdu->hdr->token;
+ token.length = node->pdu->hdr->coap_hdr_udp_t.token_length;
+ token.s = node->pdu->hdr->coap_hdr_udp_t.token;
coap_handle_failed_notify(context, &node->remote, &token);
}
goto error_early;
}
- if (pdu->version != COAP_DEFAULT_VERSION)
+ if (pdu->coap_hdr_udp_t.version != COAP_DEFAULT_VERSION)
{
debug("coap_read: unknown protocol version\n");
goto error_early;
node->pdu = coap_pdu_from_pbuf(ctx->pending_package);
ctx->pending_package = NULL;
#else
- node->pdu = coap_pdu_init(0, 0, 0, bytes_read);
+ node->pdu = coap_pdu_init(0, 0, 0, bytes_read, coap_udp);
#endif
if (!node->pdu)
goto error;
memcpy(&node->local, &dst, sizeof(coap_address_t));
memcpy(&node->remote, &src, sizeof(coap_address_t));
- if (!coap_pdu_parse((unsigned char *) buf, bytes_read, node->pdu))
+ if (!coap_pdu_parse((unsigned char *) buf, bytes_read, node->pdu, coap_udp))
{
warn("discard malformed PDU");
goto error;
debug("cancel_all_messages\n");
while (context->sendqueue && coap_address_equals(dst, &context->sendqueue->remote)
- && token_match(token, token_length, context->sendqueue->pdu->hdr->token,
- context->sendqueue->pdu->hdr->token_length))
+ && token_match(token, token_length, context->sendqueue->pdu->hdr->coap_hdr_udp_t.token,
+ context->sendqueue->pdu->hdr->coap_hdr_udp_t.token_length))
{
q = context->sendqueue;
context->sendqueue = q->next;
- debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id));
+ debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->coap_hdr_udp_t.id));
coap_delete_node(q);
}
while (q)
{
if (coap_address_equals(dst, &q->remote)
- && token_match(token, token_length, q->pdu->hdr->token, q->pdu->hdr->token_length))
+ && token_match(token, token_length, q->pdu->hdr->coap_hdr_udp_t.token,
+ q->pdu->hdr->coap_hdr_udp_t.token_length))
{
p->next = q->next;
- debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id));
+ debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->coap_hdr_udp_t.id));
coap_delete_node(q);
q = p->next;
}
{
coap_opt_iterator_t opt_iter;
coap_pdu_t *response;
- size_t size = sizeof(coap_hdr_t) + request->hdr->token_length;
+ size_t size = sizeof(coap_hdr_t) + request->hdr->coap_hdr_udp_t.token_length;
int type;
coap_opt_t *option;
unsigned short opt_type = 0; /* used for calculating delta-storage */
assert(request);
/* cannot send ACK if original request was not confirmable */
- type = request->hdr->type == COAP_MESSAGE_CON ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON;
+ type = request->hdr->coap_hdr_udp_t.type == COAP_MESSAGE_CON ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON;
/* Estimate how much space we need for options to copy from
* request. We always need the Token, for 4.02 the unknown critical
* options must be included as well. */
coap_option_clrb(opts, COAP_OPTION_CONTENT_TYPE); /* we do not want this */
- coap_option_iterator_init(request, &opt_iter, opts);
+ coap_option_iterator_init(request, &opt_iter, opts, coap_udp);
/* Add size of each unknown critical option. As known critical
options as well as elective options are not copied, the delta
}
/* Now create the response and fill with options and payload data. */
- response = coap_pdu_init(type, code, request->hdr->id, size);
+ response = coap_pdu_init(type, code, request->hdr->coap_hdr_udp_t.id, size, coap_udp);
if (response)
{
/* copy token */
- if (!coap_add_token(response, request->hdr->token_length, request->hdr->token))
+ if (!coap_add_token(response, request->hdr->coap_hdr_udp_t.token_length,
+ request->hdr->coap_hdr_udp_t.token, coap_udp))
{
debug("cannot add token to error response\n");
coap_delete_pdu(response);
}
/* copy all options */
- coap_option_iterator_init(request, &opt_iter, opts);
+ coap_option_iterator_init(request, &opt_iter, opts, coap_udp);
while ((option = coap_option_next(&opt_iter)))
coap_add_option(response, opt_iter.type, COAP_OPT_LENGTH(option),
- COAP_OPT_VALUE(option));
+ COAP_OPT_VALUE(option), coap_udp);
#if COAP_ERROR_PHRASE_LENGTH > 0
/* note that diagnostic messages do not need a Content-Format option. */
size_t offset = 0;
resp = coap_pdu_init(
- request->hdr->type == COAP_MESSAGE_CON ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
+ request->hdr->coap_hdr_udp_t.type == COAP_MESSAGE_CON ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
COAP_RESPONSE_CODE(205),
- request->hdr->id, COAP_MAX_PDU_SIZE);
+ request->hdr->coap_hdr_udp_t.id, COAP_MAX_PDU_SIZE, coap_udp);
if (!resp)
{
debug("wellknown_response: cannot create PDU\n");
return NULL;
}
- if (!coap_add_token(resp, request->hdr->token_length, request->hdr->token))
+ if (!coap_add_token(resp, request->hdr->coap_hdr_udp_t.token_length,
+ request->hdr->coap_hdr_udp_t.token, coap_udp))
{
debug("wellknown_response: cannot add token\n");
goto error;
offset = block.num << (block.szx + 4);
if (block.szx > 6)
{ /* invalid, MUST lead to 4.00 Bad Request */
- resp->hdr->code = COAP_RESPONSE_CODE(400);
+ resp->hdr->coap_hdr_udp_t.code = COAP_RESPONSE_CODE(400);
return resp;
}
else if (block.szx > COAP_MAX_BLOCK_SZX)
* nothing should go wrong here. */
assert(coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT) == 1);
coap_add_option(resp, COAP_OPTION_CONTENT_FORMAT,
- coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf);
+ coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf, coap_udp);
/* check if Block2 option is required even if not requested */
if (!need_block2 && (resp->max_size - (size_t) resp->length < wkc_len))
error:
/* set error code 5.03 and remove all options and data from response */
- resp->hdr->code = COAP_RESPONSE_CODE(503);
- resp->length = sizeof(coap_hdr_t) + resp->hdr->token_length;
+ resp->hdr->coap_hdr_udp_t.code = COAP_RESPONSE_CODE(503);
+ resp->length = sizeof(coap_hdr_t) + resp->hdr->coap_hdr_udp_t.token_length;
return resp;
}
#define WANT_WKC(Pdu,Key) \
- (((Pdu)->hdr->code == COAP_REQUEST_GET) && is_wkc(Key))
+ (((Pdu)->hdr->coap_hdr_udp_t.code == COAP_REQUEST_GET) && is_wkc(Key))
void handle_request(coap_context_t *context, coap_queue_t *node, const char* responseData)
{
* be the well-known URI. In that case, we generate a default
* response, otherwise, we return 4.04 */
- switch (node->pdu->hdr->code)
+ switch (node->pdu->hdr->coap_hdr_udp_t.code)
{
case COAP_REQUEST_GET:
}
/* the resource was found, check if there is a registered handler */
- if ((size_t) node->pdu->hdr->code - 1
+ if ((size_t) node->pdu->hdr->coap_hdr_udp_t.code - 1
< sizeof(resource->handler) / sizeof(coap_method_handler_t))
- h = resource->handler[node->pdu->hdr->code - 1];
+ h = resource->handler[node->pdu->hdr->coap_hdr_udp_t.code - 1];
if (h)
{
debug(
"call custom handler for resource 0x%02x%02x%02x%02x\n", key[0], key[1], key[2], key[3]);
response = coap_pdu_init(
- node->pdu->hdr->type == COAP_MESSAGE_CON ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
- 0, node->pdu->hdr->id, COAP_MAX_PDU_SIZE);
+ node->pdu->hdr->coap_hdr_udp_t.type ==
+ COAP_MESSAGE_CON ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
+ 0, node->pdu->hdr->coap_hdr_udp_t.id, COAP_MAX_PDU_SIZE, coap_udp);
/* Implementation detail: coap_add_token() immediately returns 0
if response == NULL */
- if (coap_add_token(response, node->pdu->hdr->token_length, node->pdu->hdr->token))
+ if (coap_add_token(response, node->pdu->hdr->coap_hdr_udp_t.token_length,
+ node->pdu->hdr->coap_hdr_udp_t.token, coap_udp))
{
str token =
- { node->pdu->hdr->token_length, node->pdu->hdr->token };
+ { node->pdu->hdr->coap_hdr_udp_t.token_length, node->pdu->hdr->coap_hdr_udp_t.token };
h(context, resource, &node->remote, node->pdu, &token, response);
unsigned char buf[3];
- response->hdr->code = COAP_RESPONSE_CODE(205);
+ response->hdr->coap_hdr_udp_t.code = COAP_RESPONSE_CODE(205);
coap_add_option(response, COAP_OPTION_CONTENT_TYPE,
- coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf);
- coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x2ffff), buf);
+ coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf, coap_udp);
+ coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, 0x2ffff), buf, coap_udp);
coap_add_data(response, strlen(responseData), (unsigned char *) responseData);
- if (response->hdr->type != COAP_MESSAGE_NON
- || (response->hdr->code >= 64 && !coap_is_mcast(&node->local)))
+ if (response->hdr->coap_hdr_udp_t.type != COAP_MESSAGE_NON
+ || (response->hdr->coap_hdr_udp_t.code >= 64 && !coap_is_mcast(&node->local)))
{
if (coap_send(context, &node->remote, response) == COAP_INVALID_TID)
{
- debug("cannot send response for message %d\n", node->pdu->hdr->id);
+ debug("cannot send response for message %d\n", node->pdu->hdr->coap_hdr_udp_t.id);
}
}
* get token from sent and try to find a matching resource. Uh!
*/
- COAP_SET_STR(&token, sent->pdu->hdr->token_length, sent->pdu->hdr->token);
+ COAP_SET_STR(&token, sent->pdu->hdr->coap_hdr_udp_t.token_length,
+ sent->pdu->hdr->coap_hdr_udp_t.token);
#ifndef WITH_CONTIKI
#ifdef COAP_RESOURCES_NOHASH
context->recvqueue = context->recvqueue->next;
rcvd->next = NULL;
- if (rcvd->pdu->hdr->version != COAP_DEFAULT_VERSION)
+ if (rcvd->pdu->hdr->coap_hdr_udp_t.version != COAP_DEFAULT_VERSION)
{
- debug("dropped packet with unknown version %u\n", rcvd->pdu->hdr->version);
+ debug("dropped packet with unknown version %u\n", rcvd->pdu->hdr->coap_hdr_udp_t.version);
goto cleanup;
}
- switch (rcvd->pdu->hdr->type)
+ switch (rcvd->pdu->hdr->coap_hdr_udp_t.type)
{
case COAP_MESSAGE_ACK:
/* find transaction in sendqueue to stop retransmission */
coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent);
- if (rcvd->pdu->hdr->code == 0)
+ if (rcvd->pdu->hdr->coap_hdr_udp_t.code == 0)
goto cleanup;
/* FIXME: if sent code was >= 64 the message might have been a
* notification. Then, we must flag the observer to be alive
* by setting obs->fail_cnt = 0. */
- if (sent && COAP_RESPONSE_CLASS(sent->pdu->hdr->code) == 2)
+ if (sent && COAP_RESPONSE_CLASS(sent->pdu->hdr->coap_hdr_udp_t.code) == 2)
{
const str token =
- { sent->pdu->hdr->token_length, sent->pdu->hdr->token };
+ { sent->pdu->hdr->coap_hdr_udp_t.token_length,
+ sent->pdu->hdr->coap_hdr_udp_t.token };
+
coap_touch_observer(context, &sent->remote, &token);
}
break;
* not only the transaction but also the subscriptions we might
* have. */
- coap_log(LOG_ALERT, "got RST for message %u\n", ntohs(rcvd->pdu->hdr->id));
+ coap_log(LOG_ALERT, "got RST for message %u\n",
+ ntohs(rcvd->pdu->hdr->coap_hdr_udp_t.id));
/* find transaction in sendqueue to stop retransmission */
coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent);
* registered for a request that should be handled locally. */
if (handle_locally(context, rcvd))
{
- if (COAP_MESSAGE_IS_REQUEST(rcvd->pdu->hdr))
+ if (COAP_MESSAGE_IS_REQUEST(rcvd->pdu->hdr->coap_hdr_udp_t))
handle_request(context, rcvd, responseData);
- else if (COAP_MESSAGE_IS_RESPONSE(rcvd->pdu->hdr))
+ else if (COAP_MESSAGE_IS_RESPONSE(rcvd->pdu->hdr->coap_hdr_udp_t))
handle_response(context, sent, rcvd);
else
{
#include "option.h"
#include "debug.h"
+#include "pdu.h"
coap_opt_t *
-options_start(coap_pdu_t *pdu)
+options_start(coap_pdu_t *pdu, coap_transport_type transport)
{
-
- if (pdu && pdu->hdr
- && (pdu->hdr->token + pdu->hdr->token_length < (unsigned char *) pdu->hdr + pdu->length))
+ if (pdu && pdu->hdr)
{
-
- coap_opt_t *opt = pdu->hdr->token + pdu->hdr->token_length;
- return (*opt == COAP_PAYLOAD_START) ? NULL : opt;
-
+ if (coap_udp == transport && (pdu->hdr->coap_hdr_udp_t.token +
+ pdu->hdr->coap_hdr_udp_t.token_length
+ < (unsigned char *) pdu->hdr + pdu->length))
+ {
+ coap_opt_t *opt = pdu->hdr->coap_hdr_udp_t.token +
+ pdu->hdr->coap_hdr_udp_t.token_length;
+ return (*opt == COAP_PAYLOAD_START) ? NULL : opt;
+ }
+#ifdef WITH_TCP
+ else if(coap_tcp == transport && (pdu->hdr->coap_hdr_tcp_t.token +
+ pdu->hdr->coap_hdr_tcp_t.token_length
+ < (unsigned char *) pdu->hdr + pdu->length))
+ {
+ coap_opt_t *opt = pdu->hdr->coap_hdr_tcp_t.token +
+ pdu->hdr->coap_hdr_tcp_t.token_length;
+ return (*opt == COAP_PAYLOAD_START) ? NULL : opt;
+ }
+#endif
+ return NULL;
}
else
return NULL;
}
coap_opt_iterator_t *
-coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi, const coap_opt_filter_t filter)
+coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi,
+ const coap_opt_filter_t filter, coap_transport_type transport)
{
assert(pdu);
assert(pdu->hdr);
memset(oi, 0, sizeof(coap_opt_iterator_t));
- oi->next_option = (unsigned char *) pdu->hdr + sizeof(coap_hdr_t) + pdu->hdr->token_length;
- if ((unsigned char *) pdu->hdr + pdu->length <= oi->next_option)
+ unsigned int token_length;
+ unsigned int headerSize;
+
+ switch(transport)
{
- oi->bad = 1;
- return NULL;
+#ifdef WITH_TCP
+ case coap_tcp:
+ token_length = pdu->hdr->coap_hdr_tcp_t.token_length;
+ headerSize = COAP_TCP_HEADER_NO_FIELD;
+ break;
+ case coap_tcp_8bit:
+ token_length = pdu->hdr->coap_hdr_tcp_t.token_length;
+ headerSize = COAP_TCP_HEADER_8_BIT;
+ break;
+ case coap_tcp_16bit:
+ token_length = pdu->hdr->coap_hdr_tcp_t.token_length;
+ headerSize = COAP_TCP_HEADER_16_BIT;
+ break;
+ case coap_tcp_32bit:
+ token_length = pdu->hdr->coap_hdr_tcp_32bit_t.header_data[0] & 0x0f;
+ headerSize = COAP_TCP_HEADER_32_BIT;
+ break;
+#endif
+ default:
+ token_length = pdu->hdr->coap_hdr_udp_t.token_length;
+ headerSize = sizeof(pdu->hdr->coap_hdr_udp_t);
+ break;
}
- assert((sizeof(coap_hdr_t) + pdu->hdr->token_length) <= pdu->length);
+ oi->next_option = (unsigned char *) pdu->hdr + headerSize + token_length;
- oi->length = pdu->length - (sizeof(coap_hdr_t) + pdu->hdr->token_length);
+ if (coap_udp == transport)
+ {
+ if ((unsigned char *) &(pdu->hdr->coap_hdr_udp_t) + pdu->length <= oi->next_option)
+ {
+ oi->bad = 1;
+ return NULL;
+ }
+ }
+#ifdef WITH_TCP
+ else
+ {
+ if ((unsigned char *) &(pdu->hdr->coap_hdr_tcp_t) + pdu->length <= oi->next_option)
+ {
+ oi->bad = 1;
+ return NULL;
+ }
+ }
+#endif
+
+ assert((headerSize + token_length) <= pdu->length);
+
+ oi->length = pdu->length - (headerSize + token_length);
if (filter)
{
coap_option_filter_clear(f);
coap_option_setb(f, type);
- coap_option_iterator_init(pdu, oi, f);
+ coap_option_iterator_init(pdu, oi, f, coap_udp);
return coap_option_next(oi);
}
return l + length;
}
+static coap_option_def_t coap_option_def[] = {
+ { COAP_OPTION_IF_MATCH, 'o', 0, 8 },
+ { COAP_OPTION_URI_HOST, 's', 1, 255 },
+ { COAP_OPTION_ETAG, 'o', 1, 8 },
+ { COAP_OPTION_IF_NONE_MATCH, 'e', 0, 0 },
+ { COAP_OPTION_URI_PORT, 'u', 0, 2 },
+ { COAP_OPTION_LOCATION_PATH, 's', 0, 255 },
+ { COAP_OPTION_URI_PATH, 's', 0, 255 },
+ { COAP_OPTION_CONTENT_TYPE, 'u', 0, 2 },
+ { COAP_OPTION_MAXAGE, 'u', 0, 4 },
+ { COAP_OPTION_URI_QUERY, 's', 1, 255 },
+ { COAP_OPTION_ACCEPT, 'u', 0, 2 },
+ { COAP_OPTION_LOCATION_QUERY, 's', 0, 255 },
+ { COAP_OPTION_PROXY_URI, 's', 1,1034 },
+ { COAP_OPTION_PROXY_SCHEME, 's', 1, 255 },
+ { COAP_OPTION_SIZE1, 'u', 0, 4 },
+ { COAP_OPTION_SIZE2, 'u', 0, 4 },
+ { COAP_OPTION_OBSERVE, 'u', 0, 3 },
+ { COAP_OPTION_BLOCK2, 'u', 0, 3 },
+ { COAP_OPTION_BLOCK1, 'u', 0, 3 },
+};
+
+
+coap_option_def_t* coap_opt_def(unsigned short key)
+{
+ int i;
+
+ if (COAP_MAX_OPT < key)
+ {
+ return NULL;
+ }
+ for (i = 0; i < (int)(sizeof(coap_option_def)/sizeof(coap_option_def_t)); i++)
+ {
+ if (key == coap_option_def[i].key)
+ return &(coap_option_def[i]);
+ }
+ debug("coap_opt_def: add key:[%d] to coap_is_var_bytes", key);
+ return NULL;
+}
unsigned char *value;
} coap_option_t;
+
+/** Representation of the association between a CoAP option key and its
+ * data type and valid data length ranges.
+ */
+typedef struct
+{
+ unsigned short key; /**< The ID of the option the following values apply to. */
+ unsigned char type; /**< The type of the option: u=uint, s=string, o=opaque. */
+ unsigned int min; /**< The minimum number of bytes allowed for the option data */
+ unsigned int max; /**< The maximum number of bytes allowed for the option data */
+} coap_option_def_t;
+
/**
* Parses the option pointed to by @p opt into @p result. This
* function returns the number of bytes that have been parsed, or @c 0
* @param pdu The PDU containing the options.
* @return A pointer to the first option if available, or @c NULL otherwise.
*/
-coap_opt_t *options_start(coap_pdu_t *pdu);
+coap_opt_t *options_start(coap_pdu_t *pdu, coap_transport_type transport);
/**
* Interprets @p opt as pointer to a CoAP option and advances to
* @return The iterator object @p oi on success, @c NULL otherwise.
*/
coap_opt_iterator_t *coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi,
- const coap_opt_filter_t filter);
+ const coap_opt_filter_t filter, coap_transport_type transport);
/**
* Updates the iterator @p oi to point to the next option. This
#define COAP_OPT_DELTA(opt) coap_opt_delta(opt)
/** @deprecated { Use coap_opt_encode() instead. } */
+#ifndef WITH_TCP
#define COAP_OPT_SETDELTA(opt,val) \
coap_opt_encode((opt), COAP_MAX_PDU_SIZE, (val), NULL, 0)
-
+#endif
/**
* Returns the length of the given option. @p opt must point to an
* option jump or the beginning of the option. This function returns
*/
unsigned char *coap_opt_value(coap_opt_t *opt);
+/**
+ * Returns a pointer to the coap option range definitions. @key
+ * must be a valid option ID. This function returns @c NULL if
+ * @p key is not a valid option ID.
+ *
+ * @param key The option ID whose definition should be returned.
+ * @return A pointer to the option definition.
+ */
+coap_option_def_t* coap_opt_def(unsigned short key);
+
/** @deprecated { Use coap_opt_value() instead. } */
#define COAP_OPT_VALUE(opt) coap_opt_value((coap_opt_t *)opt)
#ifdef WITH_CONTIKI
#include "memb.h"
+#ifndef WITH_TCP
typedef unsigned char _pdu[sizeof(coap_pdu_t) + COAP_MAX_PDU_SIZE];
MEMB(pdu_storage, _pdu, COAP_PDU_MAXCNT);
+#endif
void
coap_pdu_resources_init()
#include "mem.h"
#endif /* WITH_CONTIKI */
-void coap_pdu_clear(coap_pdu_t *pdu, size_t size)
+void coap_pdu_clear(coap_pdu_t *pdu, size_t size, coap_transport_type transport, unsigned int length)
{
assert(pdu);
memset(pdu, 0, sizeof(coap_pdu_t) + size);
pdu->max_size = size;
pdu->hdr = (coap_hdr_t *) ((unsigned char *) pdu + sizeof(coap_pdu_t));
- pdu->hdr->version = COAP_DEFAULT_VERSION;
- /* data is NULL unless explicitly set by coap_add_data() */
- pdu->length = sizeof(coap_hdr_t);
+ if (coap_udp == transport)
+ {
+ pdu->hdr->coap_hdr_udp_t.version = COAP_DEFAULT_VERSION;
+ /* data is NULL unless explicitly set by coap_add_data() */
+ pdu->length = sizeof(pdu->hdr->coap_hdr_udp_t);
+ }
+#ifdef WITH_TCP
+ else
+ {
+ /* data is NULL unless explicitly set by coap_add_data() */
+ pdu->length = length;
+ }
+#endif
}
#ifdef WITH_LWIP
#endif
coap_pdu_t *
-coap_pdu_init(unsigned char type, unsigned char code, unsigned short id, size_t size)
+coap_pdu_init(unsigned char type, unsigned char code, unsigned short id,
+ size_t size, coap_transport_type transport)
{
coap_pdu_t *pdu;
#ifdef WITH_LWIP
struct pbuf *p;
#endif
+ unsigned int length = 0;
+ switch(transport)
+ {
+ case coap_udp:
+ length = sizeof(pdu->hdr->coap_hdr_udp_t);
+ break;
+#ifdef WITH_TCP
+ case coap_tcp:
+ length = COAP_TCP_HEADER_NO_FIELD;
+ break;
+ case coap_tcp_8bit:
+ length = COAP_TCP_HEADER_8_BIT;
+ break;
+ case coap_tcp_16bit:
+ length = COAP_TCP_HEADER_16_BIT;
+ break;
+ case coap_tcp_32bit:
+ length = COAP_TCP_HEADER_32_BIT;
+ break;
+#endif
+ default:
+ debug("it has wrong type\n");
+ }
+
+#ifndef WITH_TCP
assert(size <= COAP_MAX_PDU_SIZE);
/* Size must be large enough to fit the header. */
- if (size < sizeof(coap_hdr_t) || size > COAP_MAX_PDU_SIZE)
+ if (size < length || size > COAP_MAX_PDU_SIZE)
return NULL;
+#endif
/* size must be large enough for hdr */
#if defined(WITH_POSIX) || defined(WITH_ARDUINO)
#endif
if (pdu)
{
- coap_pdu_clear(pdu, size);
- pdu->hdr->id = id;
- pdu->hdr->type = type;
- pdu->hdr->code = code;
+ coap_pdu_clear(pdu, size, transport, length);
+
+ switch(transport)
+ {
+ case coap_udp:
+ pdu->hdr->coap_hdr_udp_t.id = id;
+ pdu->hdr->coap_hdr_udp_t.type = type;
+ pdu->hdr->coap_hdr_udp_t.code = code;
+ break;
+#ifdef WITH_TCP
+ case coap_tcp:
+ pdu->hdr->coap_hdr_tcp_t.message_length = 0;
+ pdu->hdr->coap_hdr_tcp_t.code = code;
+ break;
+ case coap_tcp_8bit:
+ pdu->hdr->coap_hdr_tcp_8bit_t.message_length = COAP_TCP_LENGTH_FIELD_NUM_8_BIT;
+ pdu->hdr->coap_hdr_tcp_8bit_t.length_byte = 0;
+ pdu->hdr->coap_hdr_tcp_8bit_t.code = code;
+ break;
+ case coap_tcp_16bit:
+ pdu->hdr->coap_hdr_tcp_16bit_t.header_data[0] = COAP_TCP_LENGTH_FIELD_NUM_16_BIT << 4;
+ pdu->hdr->coap_hdr_tcp_16bit_t.header_data[3] = code;
+ break;
+ case coap_tcp_32bit:
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[0] = COAP_TCP_LENGTH_FIELD_NUM_32_BIT << 4;
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[5] = code;
+ break;
+#endif
+ default:
+ debug("it has wrong type\n");
+ }
+
#ifdef WITH_LWIP
pdu->pbuf = p;
#endif
}
coap_pdu_t *
-coap_new_pdu()
+coap_new_pdu(coap_transport_type transport, unsigned int size)
{
coap_pdu_t *pdu;
#ifndef WITH_CONTIKI
- pdu = coap_pdu_init(0, 0, ntohs(COAP_INVALID_TID), COAP_MAX_PDU_SIZE);
+ pdu = coap_pdu_init(0, 0,
+ ntohs(COAP_INVALID_TID),
+#ifndef WITH_TCP
+ COAP_MAX_PDU_SIZE,
+#else
+ size,
+#endif
+ transport);
#else /* WITH_CONTIKI */
- pdu = coap_pdu_init(0, 0, uip_ntohs(COAP_INVALID_TID), COAP_MAX_PDU_SIZE);
+ pdu = coap_pdu_init(0, 0, uip_ntohs(COAP_INVALID_TID),
+#ifndef WITH_TCP
+ COAP_MAX_PDU_SIZE,
+#else
+ size,
+#endif
+ transport);
#endif /* WITH_CONTIKI */
#ifndef NDEBUG
#endif
}
-int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data)
+#ifdef WITH_TCP
+coap_transport_type coap_get_tcp_header_type_from_size(unsigned int size)
+{
+ if (COAP_TCP_LENGTH_LIMIT_8_BIT < size && COAP_TCP_LENGTH_LIMIT_16_BIT >= size)
+ {
+ return coap_tcp_8bit;
+ }
+ else if (COAP_TCP_LENGTH_LIMIT_16_BIT < size && COAP_TCP_LENGTH_LIMIT_32_BIT >= size)
+ {
+ return coap_tcp_16bit;
+ }
+ else if (COAP_TCP_LENGTH_LIMIT_32_BIT < size)
+ {
+ return coap_tcp_32bit;
+ }
+ else
+ {
+ return coap_tcp;
+ }
+}
+
+coap_transport_type coap_get_tcp_header_type_from_initbyte(unsigned int length)
+{
+ coap_transport_type type;
+ switch(length)
+ {
+ case COAP_TCP_LENGTH_FIELD_NUM_8_BIT:
+ type = coap_tcp_8bit;
+ break;
+ case COAP_TCP_LENGTH_FIELD_NUM_16_BIT:
+ type = coap_tcp_16bit;
+ break;
+ case COAP_TCP_LENGTH_FIELD_NUM_32_BIT:
+ type = coap_tcp_32bit;
+ break;
+ default:
+ type = coap_tcp;
+ }
+ return type;
+}
+
+void coap_add_length(const coap_pdu_t *pdu, coap_transport_type transport, unsigned int length)
+{
+ assert(pdu);
+
+ switch(transport)
+ {
+ case coap_tcp:
+ pdu->hdr->coap_hdr_tcp_t.message_length = length;
+ break;
+ case coap_tcp_8bit:
+ if (length > COAP_TCP_LENGTH_FIELD_8_BIT)
+ {
+ pdu->hdr->coap_hdr_tcp_8bit_t.length_byte =
+ length - COAP_TCP_LENGTH_FIELD_8_BIT;
+ }
+ break;
+ case coap_tcp_16bit:
+ if (length > COAP_TCP_LENGTH_FIELD_16_BIT)
+ {
+ unsigned int total_length = length - COAP_TCP_LENGTH_FIELD_16_BIT;
+ pdu->hdr->coap_hdr_tcp_16bit_t.header_data[1] = (total_length >> 8) & 0x0000ff;
+ pdu->hdr->coap_hdr_tcp_16bit_t.header_data[2] = total_length & 0x000000ff;
+ }
+ break;
+ case coap_tcp_32bit:
+ if (length > COAP_TCP_LENGTH_FIELD_32_BIT)
+ {
+ unsigned int total_length = length - COAP_TCP_LENGTH_FIELD_32_BIT;
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[1] = total_length >> 24;
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[2] = (total_length >> 16) & 0x00ff;
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[3] = (total_length >> 8) & 0x0000ff;
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[4] = total_length & 0x000000ff;
+ }
+ break;
+ default:
+ debug("it has wrong type\n");
+ }
+}
+
+unsigned int coap_get_length_from_header(const unsigned char *header, coap_transport_type transport)
+{
+ assert(header);
+
+ unsigned int length = 0;
+ unsigned int length_field_data = 0;
+ switch(transport)
+ {
+ case coap_tcp_8bit:
+ length = header[1] + COAP_TCP_LENGTH_FIELD_8_BIT;
+ break;
+ case coap_tcp_16bit:
+ length_field_data = (header[1] << 8 | header[2]);
+ length = length_field_data + COAP_TCP_LENGTH_FIELD_16_BIT;
+ break;
+ case coap_tcp_32bit:
+ length_field_data = header[1] << 24 | header[2] << 16 | header[3] << 8 | header[4];
+ length = length_field_data + COAP_TCP_LENGTH_FIELD_32_BIT;
+ break;
+ default:
+ debug("it has wrong type\n");
+ }
+
+ return length;
+}
+
+unsigned int coap_get_length(const coap_pdu_t *pdu, coap_transport_type transport)
+{
+ assert(pdu);
+
+ unsigned int length = 0;
+ unsigned int length_field_data = 0;
+ switch(transport)
+ {
+ case coap_tcp:
+ length = pdu->hdr->coap_hdr_tcp_t.message_length;
+ break;
+ case coap_tcp_8bit:
+ length = pdu->hdr->coap_hdr_tcp_8bit_t.length_byte + COAP_TCP_LENGTH_FIELD_8_BIT;
+ break;
+ case coap_tcp_16bit:
+ length_field_data =
+ pdu->hdr->coap_hdr_tcp_16bit_t.header_data[1] << 8 |
+ pdu->hdr->coap_hdr_tcp_16bit_t.header_data[2];
+ length = length_field_data + COAP_TCP_LENGTH_FIELD_16_BIT;
+ break;
+ case coap_tcp_32bit:
+ length_field_data =
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[1] << 24 |
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[2] << 16 |
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[3] << 8 |
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[4];
+ length = length_field_data + COAP_TCP_LENGTH_FIELD_32_BIT;
+ break;
+ default:
+ debug("it has wrong type\n");
+ }
+
+ return length;
+}
+
+unsigned int coap_get_tcp_header_length(unsigned char *data)
+{
+ assert(data);
+
+ unsigned int tokenLength = data[0] & 0x0f;
+ coap_transport_type transport =
+ coap_get_tcp_header_type_from_initbyte(data[0] >> 4);
+ unsigned int length = 0;
+
+ length = coap_get_tcp_header_length_for_transport(transport) + tokenLength;
+ return length;
+}
+
+unsigned int coap_get_tcp_header_length_for_transport(coap_transport_type transport)
+{
+ unsigned int length = 0;
+ switch(transport)
+ {
+ case coap_tcp:
+ length = COAP_TCP_HEADER_NO_FIELD;
+ break;
+ case coap_tcp_8bit:
+ length = COAP_TCP_HEADER_8_BIT;
+ break;
+ case coap_tcp_16bit:
+ length = COAP_TCP_HEADER_16_BIT;
+ break;
+ case coap_tcp_32bit:
+ length = COAP_TCP_HEADER_32_BIT;
+ break;
+ default:
+ debug("it has wrong type\n");
+ }
+
+ return length;
+}
+
+#endif
+
+void coap_add_code(const coap_pdu_t *pdu, coap_transport_type transport, unsigned int code)
+{
+ assert(pdu);
+
+ switch(transport)
+ {
+ case coap_udp:
+ pdu->hdr->coap_hdr_udp_t.code = COAP_RESPONSE_CODE(code);
+ break;
+#ifdef WITH_TCP
+ case coap_tcp:
+ pdu->hdr->coap_hdr_tcp_t.code = COAP_RESPONSE_CODE(code);
+ break;
+ case coap_tcp_8bit:
+ pdu->hdr->coap_hdr_tcp_8bit_t.code = COAP_RESPONSE_CODE(code);
+ break;
+ case coap_tcp_16bit:
+ pdu->hdr->coap_hdr_tcp_16bit_t.header_data[3] = COAP_RESPONSE_CODE(code);
+ break;
+ case coap_tcp_32bit:
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[5] = COAP_RESPONSE_CODE(code);
+ break;
+#endif
+ default:
+ debug("it has wrong type\n");
+ }
+}
+
+unsigned int coap_get_code(const coap_pdu_t *pdu, coap_transport_type transport)
+{
+ assert(pdu);
+
+ unsigned int code = 0;
+ switch(transport)
+ {
+ case coap_udp:
+ code = pdu->hdr->coap_hdr_udp_t.code;
+ break;
+#ifdef WITH_TCP
+ case coap_tcp:
+ code = pdu->hdr->coap_hdr_tcp_t.code;
+ break;
+ case coap_tcp_8bit:
+ code = pdu->hdr->coap_hdr_tcp_8bit_t.code;
+ break;
+ case coap_tcp_16bit:
+ code = pdu->hdr->coap_hdr_tcp_16bit_t.header_data[3];
+ break;
+ case coap_tcp_32bit:
+ code = pdu->hdr->coap_hdr_tcp_32bit_t.header_data[5];
+ break;
+#endif
+ default:
+ debug("it has wrong type\n");
+ }
+ return code;
+}
+
+int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data,
+ coap_transport_type transport)
{
const size_t HEADERLENGTH = len + 4;
/* must allow for pdu == NULL as callers may rely on this */
if (!pdu || len > 8 || pdu->max_size < HEADERLENGTH)
return 0;
- pdu->hdr->token_length = len;
+ unsigned char* token = NULL;
+ switch(transport)
+ {
+ case coap_udp:
+ pdu->hdr->coap_hdr_udp_t.token_length = len;
+ token = pdu->hdr->coap_hdr_udp_t.token;
+ pdu->length = HEADERLENGTH;
+ break;
+#ifdef WITH_TCP
+ case coap_tcp:
+ pdu->hdr->coap_hdr_tcp_t.token_length = len;
+ token = pdu->hdr->coap_hdr_tcp_t.token;
+ pdu->length = len + COAP_TCP_HEADER_NO_FIELD;
+ break;
+ case coap_tcp_8bit:
+ pdu->hdr->coap_hdr_tcp_8bit_t.token_length = len;
+ token = pdu->hdr->coap_hdr_tcp_8bit_t.token;
+ pdu->length = len + COAP_TCP_HEADER_8_BIT;
+ break;
+ case coap_tcp_16bit:
+ pdu->hdr->coap_hdr_tcp_16bit_t.header_data[0] =
+ pdu->hdr->coap_hdr_tcp_16bit_t.header_data[0] | len;
+ token = pdu->hdr->coap_hdr_tcp_16bit_t.token;
+ pdu->length = len + COAP_TCP_HEADER_16_BIT;
+ break;
+ case coap_tcp_32bit:
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[0] =
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[0] | len;
+ token = pdu->hdr->coap_hdr_tcp_32bit_t.token;
+ pdu->length = len + COAP_TCP_HEADER_32_BIT;
+ break;
+#endif
+ default:
+ debug("it has wrong type\n");
+ }
+
if (len)
- memcpy(pdu->hdr->token, data, len);
+ {
+ memcpy(token, data, len);
+ }
+
pdu->max_delta = 0;
- pdu->length = HEADERLENGTH;
pdu->data = NULL;
return 1;
}
+void coap_get_token(const coap_hdr_t *pdu_hdr, coap_transport_type transport,
+ unsigned char **token, unsigned int *token_length)
+{
+ assert(pdu_hdr);
+ assert(token);
+ assert(token_length);
+
+ switch(transport)
+ {
+ case coap_udp:
+ *token_length = pdu_hdr->coap_hdr_udp_t.token_length;
+ *token = (unsigned char *)pdu_hdr->coap_hdr_udp_t.token;
+ break;
+#ifdef WITH_TCP
+ case coap_tcp:
+ *token_length = pdu_hdr->coap_hdr_tcp_t.token_length;
+ *token = (unsigned char *)pdu_hdr->coap_hdr_tcp_t.token;
+ break;
+ case coap_tcp_8bit:
+ *token_length = pdu_hdr->coap_hdr_tcp_8bit_t.token_length;
+ *token = (unsigned char *)pdu_hdr->coap_hdr_tcp_8bit_t.token;
+ break;
+ case coap_tcp_16bit:
+ *token_length = (pdu_hdr->coap_hdr_tcp_16bit_t.header_data[0]) & 0x0f;
+ *token = (unsigned char *)pdu_hdr->coap_hdr_tcp_16bit_t.token;
+ break;
+ case coap_tcp_32bit:
+ *token_length = (pdu_hdr->coap_hdr_tcp_32bit_t.header_data[0]) & 0x0f;
+ *token = (unsigned char *)pdu_hdr->coap_hdr_tcp_32bit_t.token;
+ break;
+#endif
+ default:
+ debug("it has wrong type\n");
+ }
+}
+
/** @FIXME de-duplicate code with coap_add_option_later */
size_t coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len,
- const unsigned char *data)
+ const unsigned char *data, coap_transport_type transport)
{
size_t optsize;
coap_opt_t *opt;
return 0;
}
- opt = (unsigned char *) pdu->hdr + pdu->length;
+ switch(transport)
+ {
+#ifdef WITH_TCP
+ case coap_tcp:
+ opt = (unsigned char *) &(pdu->hdr->coap_hdr_tcp_t) + pdu->length;
+ break;
+ case coap_tcp_8bit:
+ opt = (unsigned char *) &(pdu->hdr->coap_hdr_tcp_8bit_t) + pdu->length;
+ break;
+ case coap_tcp_16bit:
+ opt = (unsigned char *) &(pdu->hdr->coap_hdr_tcp_16bit_t) + pdu->length;
+ break;
+ case coap_tcp_32bit:
+ opt = (unsigned char *) &(pdu->hdr->coap_hdr_tcp_32bit_t) + pdu->length;
+ break;
+#endif
+ default:
+ opt = (unsigned char *) &(pdu->hdr->coap_hdr_udp_t) + pdu->length;
+ break;
+ }
/* encode option and check length */
optsize = coap_opt_encode(opt, pdu->max_size - pdu->length, type - pdu->max_delta, data, len);
return optsize;
}
-int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *pdu)
+int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *pdu,
+ coap_transport_type transport)
{
- coap_opt_t *opt;
-
assert(data);
assert(pdu);
{
debug("insufficient space to store parsed PDU\n");
printf("[COAP] insufficient space to store parsed PDU\n");
- return 0;
+ return -1;
}
- if (length < sizeof(coap_hdr_t))
+ unsigned int headerSize = 0;
+
+ if (coap_udp == transport)
+ {
+ headerSize = sizeof(pdu->hdr->coap_hdr_udp_t);
+ }
+#ifdef WITH_TCP
+ else
+ {
+ headerSize = coap_get_tcp_header_length_for_transport(transport);
+ }
+#endif
+
+ if (length < headerSize)
{
debug("discarded invalid PDU\n");
}
- pdu->hdr->version = data[0] >> 6;
- pdu->hdr->type = (data[0] >> 4) & 0x03;
- pdu->hdr->token_length = data[0] & 0x0f;
- pdu->hdr->code = data[1];
- /*
- printf("[COAP] pdu - version : %d\n", pdu->hdr->version);
- printf("[COAP] pdu - type : %d\n", pdu->hdr->type);
- printf("[COAP] pdu - token_length : %d\n", pdu->hdr->token_length);
- printf("[COAP] pdu - code : %d\n", pdu->hdr->code);
- */
- pdu->data = NULL;
+ coap_opt_t *opt = NULL;
+ unsigned int tokenLength = 0;
+#ifdef WITH_TCP
+ switch(transport)
+ {
+ case coap_udp:
+ break;
+ case coap_tcp:
+ pdu->hdr->coap_hdr_tcp_t.message_length = data[0] >> 4;
+ pdu->hdr->coap_hdr_tcp_t.token_length = data[0] & 0x0f;
+ pdu->hdr->coap_hdr_tcp_t.code = data[1];
+ tokenLength = pdu->hdr->coap_hdr_tcp_t.token_length;
+ opt = (unsigned char *) (&(pdu->hdr->coap_hdr_tcp_t) + 1) + tokenLength;
+ break;
+ case coap_tcp_8bit:
+ pdu->hdr->coap_hdr_tcp_8bit_t.message_length = data[0] >> 4;
+ pdu->hdr->coap_hdr_tcp_8bit_t.token_length = data[0] & 0x0f;
+ pdu->hdr->coap_hdr_tcp_8bit_t.length_byte = data[1];
+ pdu->hdr->coap_hdr_tcp_8bit_t.code = data[2];
+ tokenLength = pdu->hdr->coap_hdr_tcp_8bit_t.token_length;
+ opt = (unsigned char *) (&(pdu->hdr->coap_hdr_tcp_8bit_t))
+ + tokenLength + COAP_TCP_HEADER_8_BIT;
+ break;
+ case coap_tcp_16bit:
+ for (size_t i = 0 ; i < headerSize ; i++)
+ {
+ pdu->hdr->coap_hdr_tcp_16bit_t.header_data[i] = data[i];
+ }
+
+ tokenLength = data[0] & 0x0f;
+ opt = (unsigned char *) (&(pdu->hdr->coap_hdr_tcp_16bit_t) + 1) + tokenLength;
+ break;
+ case coap_tcp_32bit:
+ for (size_t i = 0 ; i < headerSize ; i++)
+ {
+ pdu->hdr->coap_hdr_tcp_32bit_t.header_data[i] = data[i];
+ }
+
+ tokenLength = data[0] & 0x0f;
+ opt = ((unsigned char *) &(pdu->hdr->coap_hdr_tcp_32bit_t)) +
+ headerSize + tokenLength;
+ break;
+ default:
+ printf("it has wrong type\n");
+ }
+#endif
+ pdu->length = length;
- /* sanity checks */
- if (pdu->hdr->code == 0)
+ if (coap_udp == transport)
{
- if (length != sizeof(coap_hdr_t) || pdu->hdr->token_length)
+ pdu->hdr->coap_hdr_udp_t.version = data[0] >> 6;
+ pdu->hdr->coap_hdr_udp_t.type = (data[0] >> 4) & 0x03;
+ pdu->hdr->coap_hdr_udp_t.token_length = data[0] & 0x0f;
+ pdu->hdr->coap_hdr_udp_t.code = data[1];
+ pdu->data = NULL;
+
+ tokenLength = pdu->hdr->coap_hdr_udp_t.token_length;
+
+ /* sanity checks */
+ if (pdu->hdr->coap_hdr_udp_t.code == 0)
+ {
+ if (length != headerSize || tokenLength)
+ {
+ debug("coap_pdu_parse: empty message is not empty\n");
+ goto discard;
+ }
+ }
+
+ if (length < headerSize + tokenLength || tokenLength > 8)
{
- debug("coap_pdu_parse: empty message is not empty\n");
+ debug("coap_pdu_parse: invalid Token\n");
goto discard;
}
- }
- if (length < sizeof(coap_hdr_t) + pdu->hdr->token_length || pdu->hdr->token_length > 8)
- {
- debug("coap_pdu_parse: invalid Token\n");
- goto discard;
- }
+ memcpy(&pdu->hdr->coap_hdr_udp_t.id, data + 2, 2);
- /* Copy message id in network byte order, so we can easily write the
- * response back to the network. */
- memcpy(&pdu->hdr->id, data + 2, 2);
+ /* Finally calculate beginning of data block and thereby check integrity
+ * of the PDU structure. */
- //printf("[COAP] pdu - id : %d\n", pdu->hdr->id);
+ /* append data (including the Token) to pdu structure */
+ memcpy(&(pdu->hdr->coap_hdr_udp_t) + 1, data + headerSize, length - headerSize);
- /* append data (including the Token) to pdu structure */
- memcpy(pdu->hdr + 1, data + sizeof(coap_hdr_t), length - sizeof(coap_hdr_t));
- pdu->length = length;
+ /* skip header + token */
+ length -= (tokenLength + headerSize);
+ opt = (unsigned char *) (&(pdu->hdr->coap_hdr_udp_t) + 1) + tokenLength;
+ }
+#ifdef WITH_TCP
+ else // common for tcp header setting
+ {
+ pdu->data = NULL;
+
+ if (length < headerSize + tokenLength || tokenLength > 8)
+ {
+ debug("coap_pdu_parse: invalid Token\n");
+ goto discard;
+ }
+ /* Finally calculate beginning of data block and thereby check integrity
+ * of the PDU structure. */
- /* Finally calculate beginning of data block and thereby check integrity
- * of the PDU structure. */
+ /* append data (including the Token) to pdu structure */
+ memcpy(((unsigned char *) pdu->hdr) + headerSize,
+ data + headerSize, length - headerSize);
- /* skip header + token */
- length -= (pdu->hdr->token_length + sizeof(coap_hdr_t));
- opt = (unsigned char *) (pdu->hdr + 1) + pdu->hdr->token_length;
+ /* skip header + token */
+ length -= (tokenLength + headerSize);
+ }
+#endif
while (length && *opt != COAP_PAYLOAD_START)
{
}
debug(
- "set data to %p (pdu ends at %p)\n", (unsigned char *)opt, (unsigned char *)pdu->hdr + pdu->length);
+ "set data to %p (pdu ends at %p)\n", (unsigned char *)opt,
+ (unsigned char *)pdu->hdr + pdu->length);
pdu->data = (unsigned char *) opt;
//printf("[COAP] pdu - data : %s\n", pdu->data);
}
#define COAP_MEDIATYPE_APPLICATION_RDF_XML 43 /* application/rdf+xml */
#define COAP_MEDIATYPE_APPLICATION_EXI 47 /* application/exi */
#define COAP_MEDIATYPE_APPLICATION_JSON 50 /* application/json */
+#define COAP_MEDIATYPE_APPLICATION_CBOR 60 /* application/cbor */
/* Note that identifiers for registered media types are in the range 0-65535. We
* use an unallocated type here and hope for the best. */
typedef int coap_tid_t;
#define COAP_INVALID_TID -1
+#define COAP_TCP_HEADER_NO_FIELD 2
+#define COAP_TCP_HEADER_8_BIT 3
+#define COAP_TCP_HEADER_16_BIT 4
+#define COAP_TCP_HEADER_32_BIT 6
+
+#define COAP_TCP_LENGTH_FIELD_8_BIT 13
+#define COAP_TCP_LENGTH_FIELD_16_BIT 269
+#define COAP_TCP_LENGTH_FIELD_32_BIT 65805
+
+#define COAP_TCP_LENGTH_LIMIT_8_BIT 13
+#define COAP_TCP_LENGTH_LIMIT_16_BIT 256
+#define COAP_TCP_LENGTH_LIMIT_32_BIT 65536
+
+#define COAP_TCP_LENGTH_FIELD_NUM_8_BIT 13
+#define COAP_TCP_LENGTH_FIELD_NUM_16_BIT 14
+#define COAP_TCP_LENGTH_FIELD_NUM_32_BIT 15
+
+typedef enum
+{
+ coap_udp = 0,
+ coap_tcp,
+ coap_tcp_8bit,
+ coap_tcp_16bit,
+ coap_tcp_32bit
+} coap_transport_type;
+
#ifdef WORDS_BIGENDIAN
-typedef struct
+typedef union
{
- unsigned int version:2; /* protocol version */
- unsigned int type:2; /* type flag */
- unsigned int token_length:4; /* length of Token */
- unsigned int code:8; /* request method (value 1--10) or response code (value 40-255) */
- unsigned short id; /* message id */
- unsigned char token[]; /* the actual token, if any */
-}coap_hdr_t;
+ typedef struct
+ {
+ unsigned int version:2; /* protocol version */
+ unsigned int type:2; /* type flag */
+ unsigned int token_length:4; /* length of Token */
+ unsigned int code:8; /* request method (value 1--10) or response code (value 40-255) */
+ unsigned short id; /* message id */
+ unsigned char token[]; /* the actual token, if any */
+ } coap_hdr_udp_t;
+
+
+ struct
+ {
+ unsigned int message_length :4; /* length of message */
+ unsigned int token_length :4; /* length of Token */
+ unsigned int code :8; /* request method (value 1--10) or response code (value 40-255) */
+ unsigned char token[]; /* the actual token, if any */
+ } coap_hdr_tcp_t;
+
+ struct
+ {
+ unsigned int message_length :4; /* length of message */
+ unsigned int token_length :4; /* length of Token */
+ unsigned int length_byte :8; /* extend length of message */
+ unsigned int code :8; /* request method (value 1--10) or response code (value 40-255) */
+ unsigned char token[]; /* the actual token, if any */
+ } coap_hdr_tcp_8bit_t;
+
+ struct
+ {
+ unsigned int message_length :4; /* length of message */
+ unsigned int token_length :4; /* length of Token */
+ unsigned short length_byte :16; /* extend length of message */
+ unsigned int code :8; /* request method (value 1--10) or response code (value 40-255) */
+ unsigned char token[]; /* the actual token, if any */
+ } coap_hdr_tcp_16bit_t;
+
+ struct
+ {
+ unsigned char header_data[6];
+ unsigned char token[]; /* the actual token, if any */
+ } coap_hdr_tcp_32bit_t;
+
+} coap_hdr_t;
#else
-typedef struct
+typedef union
{
- unsigned int token_length :4; /* length of Token */
- unsigned int type :2; /* type flag */
- unsigned int version :2; /* protocol version */
- unsigned int code :8; /* request method (value 1--10) or response code (value 40-255) */
- unsigned short id; /* transaction id (network byte order!) */
- unsigned char token[]; /* the actual token, if any */
+ struct
+ {
+ unsigned int token_length :4; /* length of Token */
+ unsigned int type :2; /* type flag */
+ unsigned int version :2; /* protocol version */
+ unsigned int code :8; /* request method (value 1--10) or response code (value 40-255) */
+ unsigned short id; /* transaction id (network byte order!) */
+ unsigned char token[]; /* the actual token, if any */
+ } coap_hdr_udp_t;
+
+ struct
+ {
+ unsigned int token_length :4; /* length of Token */
+ unsigned int message_length :4; /* length of message */
+ unsigned int code :8; /* request method (value 1--10) or response code (value 40-255) */
+ unsigned char token[]; /* the actual token, if any */
+ } coap_hdr_tcp_t;
+
+ struct
+ {
+ unsigned int token_length :4; /* length of Token */
+ unsigned int message_length :4; /* length of message */
+ unsigned int length_byte :8; /* extend length of message */
+ unsigned int code :8; /* request method (value 1--10) or response code (value 40-255) */
+ unsigned char token[]; /* the actual token, if any */
+ } coap_hdr_tcp_8bit_t;
+
+ struct
+ {
+ unsigned char header_data[COAP_TCP_HEADER_16_BIT];
+ unsigned char token[]; /* the actual token, if any */
+ } coap_hdr_tcp_16bit_t;
+
+ struct
+ {
+ unsigned char header_data[COAP_TCP_HEADER_32_BIT];
+ unsigned char token[]; /* the actual token, if any */
+ } coap_hdr_tcp_32bit_t;
+
} coap_hdr_t;
#endif
-#define COAP_MESSAGE_IS_EMPTY(MSG) ((MSG)->code == 0)
+#define COAP_MESSAGE_IS_EMPTY(MSG) ((MSG).code == 0)
#define COAP_MESSAGE_IS_REQUEST(MSG) (!COAP_MESSAGE_IS_EMPTY(MSG) \
- && ((MSG)->code < 32))
-#define COAP_MESSAGE_IS_RESPONSE(MSG) ((MSG)->code >= 64 && (MSG)->code <= 191)
+ && ((MSG).code < 32))
+#define COAP_MESSAGE_IS_RESPONSE(MSG) ((MSG).code >= 64 && (MSG).code <= 191)
#define COAP_OPT_LONG 0x0F /* OC == 0b1111 indicates that the option list in a
* CoAP message is limited by 0b11110000 marker */
coap_hdr_t *hdr;
unsigned short max_delta; /**< highest option number */
- unsigned short length; /**< PDU length (including header, options, data) */
+ unsigned int length; /**< PDU length (including header, options, data) */
unsigned char *data; /**< payload */
#ifdef WITH_LWIP
* @param code The message code.
* @param id The message id to set or COAP_INVALID_TID if unknown.
* @param size The number of bytes to allocate for the actual message.
+ * @param transport The transport type.
*
* @return A pointer to the new PDU object or @c NULL on error.
*/
coap_pdu_t *
-coap_pdu_init(unsigned char type, unsigned char code, unsigned short id, size_t size);
+coap_pdu_init(unsigned char type, unsigned char code, unsigned short id,
+ size_t size, coap_transport_type transport);
/**
* Clears any contents from @p pdu and resets @c version field, @c
* other field is set to @c 0. Note that @p pdu must be a valid
* pointer to a coap_pdu_t object created e.g. by coap_pdu_init().
*/
-void coap_pdu_clear(coap_pdu_t *pdu, size_t size);
+void coap_pdu_clear(coap_pdu_t *pdu, size_t size, coap_transport_type transport,
+ unsigned int length);
/**
* Creates a new CoAP PDU. The object is created on the heap and must be released
* @deprecated This function allocates the maximum storage for each
* PDU. Use coap_pdu_init() instead.
*/
-coap_pdu_t *coap_new_pdu();
+coap_pdu_t *coap_new_pdu(coap_transport_type transport, unsigned int size);
void coap_delete_pdu(coap_pdu_t *);
* @param result The PDU structure to fill. Note that the structure must
* provide space for at least @p length bytes to hold the
* entire CoAP PDU.
+ * @param transport The transport type.
* @return A value greater than zero on success or @c 0 on error.
*/
-int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *result);
+int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *pdu,
+ coap_transport_type transport);
+
+#ifdef WITH_TCP
+/**
+ * Get transport type of coap header for coap over tcp through payload size.
+ *
+ * @param size payload size of pdu.
+ * @return The transport type.
+ */
+coap_transport_type coap_get_tcp_header_type_from_size(unsigned int size);
+
+/**
+ * Get transport type of coap header for coap over tcp through init-byte.
+ *
+ * @param legnth length value of init byte.
+* @return The transport type.
+ */
+coap_transport_type coap_get_tcp_header_type_from_initbyte(unsigned int length);
+
+/**
+ * Add length value in field of coap header for coap over tcp.
+ *
+ * @param pdu The pdu pointer.
+ * @param transport The transport type.
+ * @param length length value of init byte.
+ */
+void coap_add_length(const coap_pdu_t *pdu, coap_transport_type transport,
+ unsigned int length);
+
+/**
+ * Get the value of length field of coap header for coap over tcp.
+ *
+ * @param pdu The pdu pointer.
+ * @param transport The transport type.
+ * @return length value of init byte.
+ */
+unsigned int coap_get_length(const coap_pdu_t *pdu, coap_transport_type transport);
+
+/**
+ * Get pdu length from header of coap over tcp.
+ *
+ * @param header The header to parse.
+ * @return transport The transport type.
+ */
+unsigned int coap_get_length_from_header(const unsigned char *header, coap_transport_type transport);
+
+/**
+ * Get length of header for coap over tcp.
+ *
+ * @param data The raw data to parse as CoAP PDU
+ * @return header length + token length
+ */
+unsigned int coap_get_tcp_header_length(unsigned char *data);
+
+/**
+ * Get length of header without token length for coap over tcp.
+ *
+ * @param transport The transport type.
+ * @return header length.
+ */
+unsigned int coap_get_tcp_header_length_for_transport(coap_transport_type transport);
+#endif
/**
+ * Add code in coap header.
+ *
+ * @param pdu The pdu pointer.
+ * @param transport The transport type.
+ * @param code The message code.
+ */
+void coap_add_code(const coap_pdu_t *pdu, coap_transport_type transport,
+ unsigned int code);
+
+/**
+ * Get message code from coap header
+ *
+ * @param pdu The pdu pointer.
+ * @param transport The transport type.
+ * @return The message code.
+ */
+unsigned int coap_get_code(const coap_pdu_t *pdu, coap_transport_type transport);
+/**
* Adds token of length @p len to @p pdu. Adding the token destroys
* any following contents of the pdu. Hence options and data must be
* added after coap_add_token() has been called. In @p pdu, length is
* set to @p len + @c 4, and max_delta is set to @c 0. This funtion
* returns @c 0 on error or a value greater than zero on success.
*
- * @param pdu The PDU where the token is to be added.
+ * @param pdu The pdu pointer.
* @param len The length of the new token.
* @param data The token to add.
+ * @param transport The transport type.
* @return A value greater than zero on success, or @c 0 on error.
*/
-int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data);
+int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data,
+ coap_transport_type transport);
+
+/**
+ * Get token from coap header base on transport type
+ *
+ * @param pdu_hdr The header pointer of PDU.
+ * @param transport The transport type.
+ * @param token out parameter to get token.
+ * @param token_length out parameter to get token length.
+ */
+void coap_get_token(const coap_hdr_t *pdu_hdr, coap_transport_type transport,
+ unsigned char **token, unsigned int *token_length);
/**
* Adds option of given type to pdu that is passed as first
* This function returns the number of bytes written or @c 0 on error.
*/
size_t coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len,
- const unsigned char *data);
+ const unsigned char *data, coap_transport_type transport);
/**
* Adds option of given type to pdu that is passed as first
- * parameter, but does not write a value. It works like coap_add_option with
+ * parameter, but does not write a val13ue. It works like coap_add_option with
* respect to calling sequence (i.e. after token and before data).
* This function returns a memory address to which the option data has to be
* written before the PDU can be sent, or @c NULL on error.
coap_option_filter_clear(filter);
coap_option_setb(filter, COAP_OPTION_URI_PATH);
- coap_option_iterator_init((coap_pdu_t *) request, &opt_iter, filter);
+ coap_option_iterator_init((coap_pdu_t *) request, &opt_iter, filter, coap_udp);
while ((option = coap_option_next(&opt_iter)))
coap_hash(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option), key);
}
obs; obs = (coap_subscription_t *) list_item_next((void *) obs))
{
if (r->dirty == 0 && obs->dirty == 0)
- /* running this resource due to partiallydirty, but this observation's notification was already enqueued */
+ /* running this resource due to partiallydirty,
+ * but this observation's notification was already enqueued */
continue;
coap_tid_t tid = COAP_INVALID_TID;
obs->dirty = 0;
/* initialize response */
- response = coap_pdu_init(COAP_MESSAGE_CON, 0, 0, COAP_MAX_PDU_SIZE);
+ response = coap_pdu_init(COAP_MESSAGE_CON, 0, 0, COAP_MAX_PDU_SIZE, coap_udp);
if (!response)
{
obs->dirty = 1;
continue;
}
- if (!coap_add_token(response, obs->token_length, obs->token))
+ if (!coap_add_token(response, obs->token_length, obs->token, coap_udp))
{
obs->dirty = 1;
r->partiallydirty = 1;
token.length = obs->token_length;
token.s = obs->token;
- response->hdr->id = coap_new_message_id(context);
+ response->hdr->coap_hdr_udp_t.id = coap_new_message_id(context);
if (obs->non && obs->non_cnt < COAP_OBS_MAX_NON)
{
- response->hdr->type = COAP_MESSAGE_NON;
+ response->hdr->coap_hdr_udp_t.type = COAP_MESSAGE_NON;
}
else
{
- response->hdr->type = COAP_MESSAGE_CON;
+ response->hdr->coap_hdr_udp_t.type = COAP_MESSAGE_CON;
}
/* fill with observer-specific data */
h(context, r, &obs->subscriber, NULL, &token, response);
- if (response->hdr->type == COAP_MESSAGE_CON)
+ if (response->hdr->coap_hdr_udp_t.type == COAP_MESSAGE_CON)
{
tid = coap_send_confirmed(context, &obs->subscriber, response);
obs->non_cnt = 0;
obs->non_cnt++;
}
- if (COAP_INVALID_TID == tid || response->hdr->type != COAP_MESSAGE_CON)
+ if (COAP_INVALID_TID == tid || response->hdr->coap_hdr_udp_t.type != COAP_MESSAGE_CON)
coap_delete_pdu(response);
if (COAP_INVALID_TID == tid)
{
if ( !context || !res || !sub || !(pdu = coap_new_pdu()) )
return;
- pdu->hdr->type = COAP_MESSAGE_CON;
- pdu->hdr->id = rand(); /* use a random transaction id */
- pdu->hdr->code = code;
+ pdu->hdr->coap_hdr_udp_t.type = COAP_MESSAGE_CON;
+ pdu->hdr->coap_hdr_udp_t.id = rand(); /* use a random transaction id */
+ pdu->hdr->coap_hdr_udp_t.code = code;
/* FIXME: content-type and data (how about block?) */
if (res->uri->host.length)
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
-
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
-
--- /dev/null
+package org.iotivity.ca.service;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.os.Environment;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager.LayoutParams;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Arrays;
+
+public class FileChooser {
+ private static final String PARENT_DIR = "..";
+
+ private final Activity activity;
+ private ListView list;
+ private Dialog dialog;
+ private File currentPath;
+
+ // filter on file extension
+ private String extension = null;
+ public void setExtension(String extension) {
+ this.extension = (extension == null) ? null :
+ extension.toLowerCase();
+ }
+
+ // file selection event handling
+ public interface FileSelectedListener {
+ void fileSelected(File file);
+ }
+ public FileChooser setFileListener(FileSelectedListener fileListener) {
+ this.fileListener = fileListener;
+ return this;
+ }
+ private FileSelectedListener fileListener;
+
+ public FileChooser(Activity activity) {
+ this.activity = activity;
+ dialog = new Dialog(activity);
+ list = new ListView(activity);
+ list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override public void onItemClick(AdapterView<?> parent, View view, int which, long id) {
+ String fileChosen = (String) list.getItemAtPosition(which);
+ File chosenFile = getChosenFile(fileChosen);
+ if (chosenFile.isDirectory()) {
+ refresh(chosenFile);
+ } else {
+ if (fileListener != null) {
+ fileListener.fileSelected(chosenFile);
+ }
+ dialog.dismiss();
+ }
+ }
+ });
+ dialog.setContentView(list);
+ dialog.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
+ refresh(Environment.getExternalStorageDirectory());
+ }
+
+ public void showDialog() {
+ dialog.show();
+ }
+
+
+ /**
+ * Sort, filter and display the files for the given path.
+ */
+ private void refresh(File path) {
+ this.currentPath = path;
+ if (path.exists()) {
+ File[] dirs = path.listFiles(new FileFilter() {
+ @Override public boolean accept(File file) {
+ return (file.isDirectory() && file.canRead());
+ }
+ });
+ File[] files = path.listFiles(new FileFilter() {
+ @Override public boolean accept(File file) {
+ if (!file.isDirectory()) {
+ if (!file.canRead()) {
+ return false;
+ } else if (extension == null) {
+ return true;
+ } else {
+ return file.getName().toLowerCase().endsWith(extension);
+ }
+ } else {
+ return false;
+ }
+ }
+ });
+
+ // convert to an array
+ int i = 0;
+ String[] fileList;
+ if (path.getParentFile() == null) {
+ fileList = new String[dirs.length + files.length];
+ } else {
+ fileList = new String[dirs.length + files.length + 1];
+ fileList[i++] = PARENT_DIR;
+ }
+ Arrays.sort(dirs);
+ Arrays.sort(files);
+ for (File dir : dirs) { fileList[i++] = dir.getName(); }
+ for (File file : files ) { fileList[i++] = file.getName(); }
+
+ // refresh the user interface
+ dialog.setTitle(currentPath.getPath());
+ list.setAdapter(new ArrayAdapter(activity,
+ android.R.layout.simple_list_item_1, fileList) {
+ @Override public View getView(int pos, View view, ViewGroup parent) {
+ view = super.getView(pos, view, parent);
+ ((TextView) view).setSingleLine(true);
+ return view;
+ }
+ });
+ }
+ }
+
+
+ /**
+ * Convert a relative filename into an actual File object.
+ */
+ private File getChosenFile(String fileChosen) {
+ if (fileChosen.equals(PARENT_DIR)) {
+ return currentPath.getParentFile();
+ } else {
+ return new File(currentPath, fileChosen);
+ }
+ }
+}
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import android.widget.Toast;
+import java.io.File;
import org.iotivity.ca.sample_service.R;
+import org.iotivity.ca.service.FileChooser;
+import org.iotivity.ca.service.FileChooser.FileSelectedListener;
public class MainActivity extends Activity {
MsgType.NON.name(), MsgType.ACK.name(), MsgType.RESET.name() };
private final CharSequence[] mResponseResultCheckBoxItems = {
- ResponseResult.CA_SUCCESS.name(), ResponseResult.CA_CREATED.name(),
- ResponseResult.CA_DELETED.name(), ResponseResult.CA_VALID.name(),
- ResponseResult.CA_CHANGED.name(), ResponseResult.CA_CONTENT.name(),
- ResponseResult.CA_EMPTY.name(), ResponseResult.CA_BAD_REQ.name(),
- ResponseResult.CA_BAD_OPT.name(), ResponseResult.CA_NOT_FOUND.name(),
- ResponseResult.CA_INTERNAL_SERVER_ERROR.name(),
+ ResponseResult.CA_CREATED.name(), ResponseResult.CA_DELETED.name(),
+ ResponseResult.CA_VALID.name(), ResponseResult.CA_CHANGED.name(),
+ ResponseResult.CA_CONTENT.name(), ResponseResult.CA_EMPTY.name(),
+ ResponseResult.CA_BAD_REQ.name(), ResponseResult.CA_BAD_OPT.name(),
+ ResponseResult.CA_NOT_FOUND.name(), ResponseResult.CA_INTERNAL_SERVER_ERROR.name(),
ResponseResult.CA_RETRANSMIT_TIMEOUT.name() };
private enum Mode {
};
private enum ResponseResult {
- CA_SUCCESS, CA_CREATED, CA_DELETED, CA_VALID, CA_CHANGED, CA_CONTENT, CA_EMPTY,
+ CA_CREATED, CA_DELETED, CA_VALID, CA_CHANGED, CA_CONTENT, CA_EMPTY,
CA_BAD_REQ, CA_BAD_OPT, CA_NOT_FOUND, CA_INTERNAL_SERVER_ERROR, CA_RETRANSMIT_TIMEOUT
}
private Button mRecv_btn = null;
+ private Button mBig_btn = null;
+
private Handler mLogHandler = null;
/**
int uninterestedNetwork = 0;
private boolean isSendResponseSetting = false;
private boolean isSendRequestToAllSetting = false;
+ private boolean isBigData = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
mResponse_Notify_setting_btn = (Button) findViewById(R.id.btn_Request_setting_for_server);
mGetNetworkInfo_btn = (Button) findViewById(R.id.btn_get_network_info);
mRecv_btn = (Button) findViewById(R.id.btn_receive);
+ mBig_btn = (Button) findViewById(R.id.btn_big_data);
+ mBig_btn.setOnClickListener(mSelectLargeDataButtonHandler);
mResponse_btn.setOnClickListener(mSendResponseHandler);
mNotify_btn.setOnClickListener(mNotifyHandler);
DLog.v(TAG, "SendRequest click");
if ( selectedNetwork != -1) {
RM.RMSendRequest(mReqData_ed.getText().toString(), null,
- selectedNetwork, isSecured, msgType);
+ selectedNetwork, isSecured, msgType, false);
}
else {
DLog.v(TAG, "Please Select Network Type");
}
};
+ private OnClickListener mSelectLargeDataButtonHandler = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ isBigData = true;
+ checkSendNetworkType("Select Send Network Type");
+ }
+ };
+
private void checkInterestedNetwork(String title) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
@Override
public void onClick(DialogInterface dialog, int which) {
- if (selectedResponseValue == ResponseResult.CA_SUCCESS.ordinal()) {
- responseValue = 200;
- DLog.v(TAG, "Response Value is CA_SUCCESS");
- } else if (selectedResponseValue == ResponseResult.CA_CREATED
- .ordinal()) {
+ if (selectedResponseValue == ResponseResult.CA_CREATED.ordinal()) {
responseValue = 201;
DLog.v(TAG, "Response Value is CA_CREATED");
} else if (selectedResponseValue == ResponseResult.CA_DELETED
if (selectedNetworkType == Network.IP.ordinal()) {
selectedNetwork = CA_IP;
- DLog.v(TAG, "Selected Network is CA_IP");
+ DLog.v(TAG, "Selected Network is IP");
} else if (selectedNetworkType == Network.LE.ordinal()) {
selectedNetwork = CA_LE;
DLog.v(TAG, "Selected Network is LE");
selectedNetwork = -1;
}
- if (isSendRequestToAllSetting != true) {
- checkMsgSecured("Select DTLS Type");
+ if (isBigData)
+ {
+ new FileChooser(MainActivity.this).setFileListener(new FileSelectedListener() {
+ public void fileSelected(final File file) {
+ if (selectedNetwork != -1) {
+
+ String path = file.getAbsolutePath();
+ Log.d(TAG, "File Path: " + path);
+
+ RM.RMSendRequest(mReqData_ed.getText().toString(), path,
+ selectedNetwork, isSecured, msgType, true);
+ } else {
+ Toast.makeText(getApplicationContext(),
+ "Request Setting Fisrt!!", Toast.LENGTH_LONG).show();
+ }
+ }
+ } ).showDialog();
+ isBigData = false;
+ } else {
+ if (isSendRequestToAllSetting != true) {
+ checkMsgSecured("Select DTLS Type");
+ }
}
+
isSendRequestToAllSetting = false;
+ isBigData = false;
}
}).show();
}
mNotification_ed.setText(sb.toString());
}
}
-}
+}
\ No newline at end of file
public native void RMFindResource(String uri);
public native void RMSendRequest(String uri, String payload,
- int selectedNetwork, int isSecured, int msgType);
+ int selectedNetwork, int isSecured, int msgType, boolean isBigData);
public native void RMSendReqestToAll(String uri, int selectedNetwork);
#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 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
{
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;
static const uint16_t COAP_PREFIX_LEN = sizeof(COAP_PREFIX) - 1;
static const uint16_t COAPS_PREFIX_LEN = sizeof(COAPS_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\"],"
"\"if\":[\"oic.if.baseline\"],\"obs\":1,\"sec\":1,\"port\":"
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))
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))
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);
if (!env || !obj)
return;
}
- if (!payload)
- {
- LOGE("payload is NULL");
- }
-
if (!uri)
{
LOGE("Invalid input parameter : uri");
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((char *) 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((char *) requestData.payload, length, NORMAL_INFO_DATA, resourceURI);
- requestData.payloadSize = length;
}
requestData.type = messageType;
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);
}
}
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);
}
}
{
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)
{
}
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)
}
// #2. copy uri for parse
- int32_t len = strlen(uri) - startIndex;
+ size_t len = strlen(uri) - startIndex;
if (len <= 0)
{
return;
}
- memcpy(cloneUri, &uri[startIndex], sizeof(char) * len);
- cloneUri[len] = '\0';
+ OICStrcpy(cloneUri, len+1, &uri[startIndex]);
- char *pAddress = cloneUri;
- LOGI("pAddress : %s", pAddress);
+ char *pstr = NULL;
+ //filter out the resource uri
+ char *pUrl = strtok_r(cloneUri, "/", &pstr);
- int res = get_address_set(pAddress, address);
- if (res == -1)
+ if (pUrl)
{
- LOGE("address parse error");
+ LOGI("pAddress : %s", pUrl);
+ int res = get_address_set(pUrl, address);
+ if (res == -1)
+ {
+ LOGE("address parse error");
- free(cloneUri);
- return;
+ return;
+ }
+ }
+ else
+ {
+ LOGE("strtok_r error, could not get the address");
}
return;
(*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;
+ size_t 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);
+ fseek(file, 0, SEEK_SET);
+
+ LOGI("file size: %d", 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(¤t_time);
+ time_info = localtime(¤t_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)
+ {
+ sprintf(path, 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);
+}
* Signature: (Ljava/lang/String;Ljava/lang/String;III)V
*/
JNIEXPORT void JNICALL Java_org_iotivity_ca_service_RMInterface_RMSendRequest
- (JNIEnv *, jobject, jstring, jstring, jint, jint, jint);
+ (JNIEnv *, jobject, jstring, jstring, jint, jint, jint, jboolean);
/*
* Class: org_iotivity_ca_service_RMInterface
android:layout_toRightOf="@id/btn_receive"
android:text="@string/get_network_info" />
+ <Button
+ android:id="@+id/btn_big_data"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@id/btn_get_network_info"
+ android:text="big data" />
+
</RelativeLayout>
</RelativeLayout>
android:layout_height="wrap_content" />
</ScrollView>
-</RelativeLayout>
+</RelativeLayout>
\ No newline at end of file
Serial.println("============");
Serial.println("Enter Resp Code:");
Serial.println("For Ex: Empty : 0");
- Serial.println("Success: 200");
Serial.println("Created: 201");
Serial.println("Deleted: 202");
Serial.println("Valid : 203");
#define SYSTEM_INVOKE_ERROR 127
#define SYSTEM_ERROR -1
+#ifdef WITH_BWT
#define BLOCK_SIZE(arg) (1 << ((arg) + 4))
+#endif
/**
* @def RS_IDENTITY
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 SECURE_INFO_DATA[] =
"{\"oc\":[{\"href\":\"%s\",\"prop\":{\"rt\":[\"core.led\"],"
printf("Enter the URI like below....\n");
printf("coap://10.11.12.13:4545/resource_uri ( for IP )\n");
printf("coap://10:11:12:13:45:45/resource_uri ( for BT )\n");
+ printf("coap+tcp://10:11:12:13:45:45/resource_uri ( for TCP )\n");
}
else
{
printf("Enter the URI like below....\n");
printf("coap://10.11.12.13:4545/resource_uri ( for IP )\n");
printf("coap://10:11:12:13:45:45/resource_uri ( for BT )\n");
+ printf("coap+tcp://10:11:12:13:45:45/resource_uri ( for TCP )\n");
printf("uri : ");
char uri[MAX_BUF_LEN] = { 0 };
printf("IP : 0\n");
printf("GATT : 1\n");
printf("RFCOMM : 2\n");
+ printf("TCP : 4\n");
printf("select : ");
char buf[MAX_BUF_LEN] = { 0 };
int number = buf[0] - '0';
- if (number < 0 || number > 3)
+ if (number < 0 || number > 4)
{
printf("Invalid network type\n");
return;
printf("IP : 0\n");
printf("GATT : 1\n");
printf("RFCOMM : 2\n");
+ printf("TCP : 4\n");
printf("select : ");
char buf[MAX_BUF_LEN] = { 0 };
int number = buf[0] - '0';
- if (number < 0 || number > 3)
+ if (number < 0 || number > 4)
{
printf("Invalid network type\n");
return;
if (CA_ADAPTER_IP == tempInfo[index].adapter)
{
printf("Port: %d\n", tempInfo[index].port);
- }
- printf("Secured: %s\n\n", (tempInfo[index].flags & CA_SECURE) ? "true" : "false");
+ printf("Secured: %s flag : %x\n\n", (tempInfo[index].flags & CA_SECURE) ? "true" :
+ "false", tempInfo[index].flags);
- if (tempInfo[index].flags & CA_SECURE)
- {
- g_local_secure_port = tempInfo[index].port;
- printf("Secured: in global %d\n\n", g_local_secure_port);
+ if (tempInfo[index].flags & CA_SECURE)
+ {
+ g_local_secure_port = tempInfo[index].port;
+ printf("Secured: in global %d\n\n", g_local_secure_port);
+ }
}
}
}
}
+#ifdef WITH_BWT
// if received message is bulk data, create output file
if ((requestInfo->info.payload) &&
(requestInfo->info.payloadSize > BLOCK_SIZE(CA_DEFAULT_BLOCK_SIZE)))
{
create_file(requestInfo->info.payload, requestInfo->info.payloadSize);
}
+#endif
printf("Send response with URI\n");
send_response(object, &requestInfo->info);
}
}
+#ifdef WITH_BWT
// if received message is bulk data, create output file
if ((responseInfo->info.payload) &&
(responseInfo->info.payloadSize > BLOCK_SIZE(CA_DEFAULT_BLOCK_SIZE)))
{
create_file(responseInfo->info.payload, responseInfo->info.payloadSize);
}
+#endif
}
void error_handler(const CAEndpoint_t *rep, const CAErrorInfo_t* errorInfo)
printf("\n=============================================\n");
printf("\tselect response code\n");
printf("EMPTY : 0\n");
- printf("SUCCESS : 200\n");
printf("CREATED : 201\n");
printf("DELETED : 202\n");
printf("VALID : 203\n");
printf("IP : 0\n");
printf("GATT : 1\n");
printf("RFCOMM : 2\n");
+ printf("TCP : 4\n");
printf("select : ");
if (CA_STATUS_OK != get_input_data(buf, MAX_BUF_LEN))
int number = buf[0] - '0';
- number = (number < 0 || number > 3) ? 0 : 1 << number;
+ number = (number < 0 || number > 4) ? 0 : 1 << number;
- if (number == 1)
+ switch (number)
{
- g_selected_nw_type = CA_ADAPTER_IP;
- return CA_STATUS_OK;
+ case CA_ADAPTER_IP:
+ case CA_ADAPTER_GATT_BTLE:
+ case CA_ADAPTER_RFCOMM_BTEDR:
+ case CA_ADAPTER_TCP:
+ g_selected_nw_type = number;
+ return CA_STATUS_OK;
+ default:
+ return CA_NOT_SUPPORTED;
}
- if (number == 2)
- {
- g_selected_nw_type = CA_ADAPTER_GATT_BTLE;
- return CA_STATUS_OK;
- }
- if (number == 3)
- {
- g_selected_nw_type = CA_ADAPTER_RFCOMM_BTEDR;
- return CA_STATUS_OK;
- }
-
- return CA_NOT_SUPPORTED;
}
CAResult_t get_input_data(char *buf, int32_t length)
startIndex = COAP_PREFIX_LEN;
*flags = CA_IPV4;
}
+ else if (strncmp(COAP_TCP_PREFIX, uri, COAP_TCP_PREFIX_LEN) == 0)
+ {
+ printf("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;
printf("\n=============================================\n");
printf("\tselect response code\n");
printf("EMPTY : 0\n");
- printf("SUCCESS : 200\n");
printf("CREATED : 201\n");
printf("DELETED : 202\n");
printf("VALID : 203\n");
'adapter_util/caadapterutils.c')])
env.AppendUnique(CA_SRC = [os.path.join(ca_path,
'adapter_util/cafragmentation.c')])
-if ca_os in ['android', 'tizen']:
- env.AppendUnique(CA_SRC=[os.path.join(ca_path, 'adapter_util/ifaddrs.c')])
if env.get('SECURED') == '1':
env.AppendUnique(CA_SRC = [os.path.join(ca_path,
'adapter_util/caadapternetdtls.c')])
'external/inc')])
ca_common_src = None
+
+if env.get('ROUTING') == 'GW':
+ env.AppendUnique(CPPDEFINES = ['ROUTING_GATEWAY'])
+elif env.get('ROUTING') == 'EP':
+ env.AppendUnique(CPPDEFINES = ['ROUTING_EP'])
+
if ca_os == 'arduino':
env.AppendUnique(CPPDEFINES = ['SINGLE_THREAD'])
env.AppendUnique(CPPDEFINES = ['WITH_ARDUINO'])
env.AppendUnique(CA_SRC = ca_common_src)
if 'ALL' in ca_transport:
- transports = [ 'ip_adapter', 'bt_edr_adapter', 'bt_le_adapter' ]
+ transports = [ 'ip_adapter', 'bt_edr_adapter', 'bt_le_adapter']
+ if ca_os == 'linux':
+ transports.append ('tcp_adapter')
if with_ra:
transports.append ('ra_adapter')
env.SConscript(dirs = [
if 'BLE' in ca_transport:
env.SConscript(os.path.join(ca_path, 'bt_le_adapter/SConscript'))
+if 'TCP' in ca_transport:
+ env.SConscript(os.path.join(ca_path, 'tcp_adapter/SConscript'))
+
print "Include path is %s" % env.get('CPPPATH')
print "Files path is %s" % env.get('CA_SRC')
if ca_os in ['android', 'tizen']:
*/
static CAGetDTLSCredentialsHandler g_getCredentialsCallback = NULL;
-static CAEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer)
+static CASecureEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer)
{
uint32_t list_index = 0;
uint32_t list_length = 0;
return NULL;
}
- CAEndpoint_t *peerInfo;
+ CASecureEndpoint_t *peerInfo = NULL;
list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
for (list_index = 0; list_index < list_length; list_index++)
{
- peerInfo = (CAEndpoint_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index);
+ peerInfo = (CASecureEndpoint_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index);
if (NULL == peerInfo)
{
continue;
}
- if((0 == strncmp(peer->addr, peerInfo->addr, MAX_ADDR_STR_SIZE_CA)) &&
- (peer->port == peerInfo->port))
+ if((0 == strncmp(peer->addr, peerInfo->endpoint.addr, MAX_ADDR_STR_SIZE_CA)) &&
+ (peer->port == peerInfo->endpoint.port))
{
return peerInfo;
}
return NULL;
}
-static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint16_t port,
- const unsigned char *id, uint16_t id_length, CATransportFlags_t flag)
+static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port,
+ const unsigned char *id, uint16_t id_length)
{
if(NULL == peerAddr
|| NULL == id
return CA_STATUS_INVALID_PARAM;
}
- CAEndpoint_t *peer = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
+ CASecureEndpoint_t *peer = (CASecureEndpoint_t *)OICCalloc(1, sizeof (CASecureEndpoint_t));
if (NULL == peer)
{
OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfo malloc failed!");
return CA_MEMORY_ALLOC_FAILED;
}
- OICStrcpy(peer->addr, sizeof(peer->addr), peerAddr);
- peer->port = port;
- peer->flags = flag;
- peer->flags |= CA_SECURE;
- peer->adapter = CA_ADAPTER_IP;
+ OICStrcpy(peer->endpoint.addr, sizeof(peer->endpoint.addr), peerAddr);
+ peer->endpoint.port = port;
memcpy(peer->identity.id, id, id_length);
peer->identity.id_length = id_length;
- if(NULL != GetPeerInfo(peer))
+ if (NULL != GetPeerInfo(&peer->endpoint))
{
OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList peer already exist");
OICFree(peer);
return CA_STATUS_FAILED;
}
- CAResult_t result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peer);
- if (CA_STATUS_OK != result)
+ bool result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peer);
+ if (!result)
{
OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
OICFree(peer);
+ return CA_STATUS_FAILED;
}
- return result;
+ return CA_STATUS_OK;
}
static void CAFreePeerInfoList()
return CA_STATUS_FAILED;
}
- CAResult_t result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg);
- if (CA_STATUS_OK != result)
+ bool result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg);
+ if (!result)
{
OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
+ return CA_STATUS_FAILED;
}
OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
- return result;
+ return CA_STATUS_OK;
}
stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
- CAEndpoint_t endpoint = { 0 };
- CAConvertAddrToName(&(addrInfo->addr.st), endpoint.addr, &endpoint.port);
- endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
- endpoint.flags |= CA_SECURE;
- endpoint.adapter = CA_ADAPTER_IP;
- int type = 0;
+ CASecureEndpoint_t sep =
+ { .endpoint =
+ { .adapter = CA_ADAPTER_IP, .flags =
+ ((addrInfo->addr.st.ss_family == AF_INET) ? CA_IPV4 : CA_IPV6) | CA_SECURE, .port = 0 },
+ .identity =
+ { 0 } };
+ CAConvertAddrToName(&(addrInfo->addr.st), sep.endpoint.addr, &sep.endpoint.port);
if (NULL == g_caDtlsContext)
{
return 0;
}
+ int type = 0;
if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
(NULL != g_caDtlsContext->adapterCallbacks[type].recvCallback))
{
// Get identity of the source of packet
- CAEndpoint_t *peerInfo = GetPeerInfo(&endpoint);
+ CASecureEndpoint_t *peerInfo = GetPeerInfo(&sep.endpoint);
if (peerInfo)
{
- endpoint.identity = peerInfo->identity;
+ sep.identity = peerInfo->identity;
}
- g_caDtlsContext->adapterCallbacks[type].recvCallback(&endpoint, buf, bufLen);
+ g_caDtlsContext->adapterCallbacks[type].recvCallback(&sep, buf, bufLen);
}
else
{
stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
- CAEndpoint_t endpoint;
+ CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
+
CAConvertAddrToName(&(addrInfo->addr.st), endpoint.addr, &endpoint.port);
endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
endpoint.flags |= CA_SECURE;
endpoint.adapter = CA_ADAPTER_IP;
+ endpoint.interface = session->ifindex;
int type = 0;
//Mutex is not required for g_caDtlsContext. It will be called in same thread.
OIC_LOG(INFO, NET_DTLS_TAG, "Peer closing connection");
stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
- char peerAddr[MAX_ADDR_STR_SIZE_CA] = {0};
+ char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
uint16_t port = 0;
CAConvertAddrToName(&(addrInfo->addr.st), peerAddr, &port);
CARemovePeerFromPeerInfoList(peerAddr, port);
// data structure when handshake completes. Therefore, currently this is a
// workaround to cache remote end-point identity when tinyDTLS asks for PSK.
stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
- char peerAddress[MAX_ADDR_STR_SIZE_CA] = {0};
+ char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
uint16_t port = 0;
- CAConvertAddrToName(&(addrInfo->addr.st), peerAddress, &port);
-
- CATransportFlags_t flag =
- addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
+ CAConvertAddrToName(&(addrInfo->addr.st), peerAddr, &port);
- CAResult_t result = CAAddIdToPeerInfoList(peerAddress,
- port, desc, descLen, flag);
+ CAResult_t result = CAAddIdToPeerInfoList(peerAddr, port, desc, descLen);
if(CA_STATUS_OK != result )
{
OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
dtls_enables_anon_ecdh(g_caDtlsContext->dtlsContext,
enable == true ? DTLS_CIPHER_ENABLE : DTLS_CIPHER_DISABLE);
ca_mutex_unlock(g_dtlsContextMutex);
- OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA is %s",
+ OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 is %s",
enable ? "enabled" : "disabled");
OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
return CA_STATUS_OK;
}
-CAResult_t CAAdapterNetDtlsDecrypt(const CAEndpoint_t *endpoint,
+CAResult_t CAAdapterNetDtlsDecrypt(const CASecureEndpoint_t *sep,
uint8_t *data, uint32_t dataLen)
{
OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
- VERIFY_NON_NULL_RET(endpoint, NET_DTLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
+ VERIFY_NON_NULL_RET(sep, NET_DTLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM);
stCADtlsAddrInfo_t addrInfo = { 0 };
- CAConvertNameToAddr(endpoint->addr, endpoint->port, &(addrInfo.addr.st));
+ CAConvertNameToAddr(sep->endpoint.addr, sep->endpoint.port, &(addrInfo.addr.st));
addrInfo.ifIndex = 0;
addrInfo.size = CASizeOfAddrInfo(&addrInfo);
static jobject g_Context = NULL;
#endif
-void CALogPDUData(coap_pdu_t *pdu)
-{
- VERIFY_NON_NULL_VOID(pdu, CA_ADAPTER_UTILS_TAG, "pdu");
- OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "PDU Maker - payload : %s", pdu->data);
-
- OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "PDU Maker - type : %d", pdu->hdr->type);
-
- OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "PDU Maker - code : %d", pdu->hdr->code);
-
- OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "PDU Maker - id : %d", pdu->hdr->id);
-
- OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "PDU Maker - token : %s", pdu->hdr->token);
-}
-
#ifdef WITH_ARDUINO
CAResult_t CAParseIPv4AddressInternal(const char *ipAddrStr, uint8_t *ipAddr,
size_t ipAddrLen, uint16_t *port)
#include "cafragmentation.h"
/**
- * @var CA_FRAGMENTATION_TAG
- * @brief debugging tag for fragmentation module
+ * Debugging tag for fragmentation module.
*/
#define CA_FRAGMENTATION_TAG "CA_FRAGMENTATION"
-CAResult_t CAGenerateHeader(char *header, uint32_t length)
+CAResult_t CAGenerateHeader(uint8_t *header,
+ size_t headerLength,
+ size_t dataLength)
{
OIC_LOG(DEBUG, CA_FRAGMENTATION_TAG, "IN");
VERIFY_NON_NULL(header, CA_FRAGMENTATION_TAG, "header is NULL");
- memset(header, 0x0, sizeof(char) * CA_HEADER_LENGTH);
- if(length > MAX_DATA_LENGTH_SUPPORTED)
+ if (headerLength < CA_HEADER_LENGTH)
{
- OIC_LOG(DEBUG, CA_FRAGMENTATION_TAG,
- "Given length is more than 4095.It will be truncated");
+ return CA_STATUS_FAILED;
}
- //if length is more than 4095 then it will be truncated.
- header[1] = length & 0xFF;
- length >>= 8;
- header[0] = length & 0x0F;
- header[0] = header[0] | 0x40; // Adding version 0100.(Not used. Future use)
+
+ if (dataLength > MAX_DATA_LENGTH_SUPPORTED)
+ {
+ OIC_LOG_V(WARNING,
+ CA_FRAGMENTATION_TAG,
+ "Given length is more than %d. It will be truncated.",
+ MAX_DATA_LENGTH_SUPPORTED);
+ }
+
+ // Only bother initializing the header section of the buffer. It
+ // is up to the caller to handle the data section.
+ memset(header, 0, CA_HEADER_LENGTH);
+
+ // If length is more than 4095 then it will be truncated.
+ header[1] = dataLength & 0xFF;
+ dataLength >>= 8;
+ header[0] = dataLength & 0x0F;
+ header[0] = header[0] | 0x40; // Adding version 0100.
+ // (Not used. Future use)
OIC_LOG(DEBUG, CA_FRAGMENTATION_TAG, "OUT");
return CA_STATUS_OK;
}
-uint32_t CAParseHeader(const char *header)
+uint32_t CAParseHeader(const uint8_t *header, size_t length)
{
OIC_LOG(DEBUG, CA_FRAGMENTATION_TAG, "IN");
VERIFY_NON_NULL_RET(header, CA_FRAGMENTATION_TAG, "header is NULL", 0);
- uint32_t dataLen = ((header[0] & 0x0F) << 8) | (header[1] & 0xFF);
+ uint32_t dataLen = 0;
+
+ if (length >= CA_HEADER_LENGTH)
+ {
+ dataLen = ((header[0] & 0x0F) << 8) | (header[1] & 0xFF);
+ }
OIC_LOG(DEBUG, CA_FRAGMENTATION_TAG, "OUT");
+
return dataLen;
}
-
+++ /dev/null
-/*
-Copyright (c) 2013, Kenneth MacKay
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <net/if.h>
-#include "ifaddrs.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netpacket/packet.h>
-#include <net/if_arp.h>
-#include <netinet/in.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <sys/ioctl.h>
-
-typedef struct NetlinkList
-{
- struct NetlinkList *m_next;
- struct nlmsghdr *m_data;
- unsigned int m_size;
-} NetlinkList;
-
-static int netlink_socket(void)
-{
- int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if(l_socket < 0)
- {
- return -1;
- }
-
- struct sockaddr_nl l_addr;
- memset(&l_addr, 0, sizeof(l_addr));
- l_addr.nl_family = AF_NETLINK;
- if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0)
- {
- close(l_socket);
- return -1;
- }
-
- return l_socket;
-}
-
-static int netlink_send(int p_socket, int p_request)
-{
- struct
- {
- struct nlmsghdr m_hdr;
- struct rtgenmsg m_msg;
- } l_data;
-
- memset(&l_data, 0, sizeof(l_data));
-
- l_data.m_hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
- l_data.m_hdr.nlmsg_type = p_request;
- l_data.m_hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
- l_data.m_hdr.nlmsg_pid = 0;
- l_data.m_hdr.nlmsg_seq = p_socket;
- l_data.m_msg.rtgen_family = AF_UNSPEC;
-
- struct sockaddr_nl l_addr;
- memset(&l_addr, 0, sizeof(l_addr));
- l_addr.nl_family = AF_NETLINK;
- return (sendto(p_socket, &l_data.m_hdr, l_data.m_hdr.nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
-}
-
-static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
-{
- struct msghdr l_msg;
- struct iovec l_iov = { p_buffer, p_len };
- struct sockaddr_nl l_addr;
-
- for(;;)
- {
- l_msg.msg_name = (void *)&l_addr;
- l_msg.msg_namelen = sizeof(l_addr);
- l_msg.msg_iov = &l_iov;
- l_msg.msg_iovlen = 1;
- l_msg.msg_control = NULL;
- l_msg.msg_controllen = 0;
- l_msg.msg_flags = 0;
- int l_result = recvmsg(p_socket, &l_msg, 0);
-
- if(l_result < 0)
- {
- if(errno == EINTR)
- {
- continue;
- }
- return -2;
- }
-
- if(l_msg.msg_flags & MSG_TRUNC)
- { // buffer was too small
- return -1;
- }
- return l_result;
- }
-}
-
-static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
-{
- size_t l_size = 4096;
- void *l_buffer = NULL;
-
- for(;;)
- {
- free(l_buffer);
- l_buffer = malloc(l_size);
- if (l_buffer == NULL)
- {
- return NULL;
- }
-
- int l_read = netlink_recv(p_socket, l_buffer, l_size);
- *p_size = l_read;
- if(l_read == -2)
- {
- free(l_buffer);
- return NULL;
- }
- if(l_read >= 0)
- {
- pid_t l_pid = getpid();
- struct nlmsghdr *l_hdr;
- for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
- {
- if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
- {
- continue;
- }
-
- if(l_hdr->nlmsg_type == NLMSG_DONE)
- {
- *p_done = 1;
- break;
- }
-
- if(l_hdr->nlmsg_type == NLMSG_ERROR)
- {
- free(l_buffer);
- return NULL;
- }
- }
- return l_buffer;
- }
-
- l_size *= 2;
- }
-}
-
-static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
-{
- NetlinkList *l_item = malloc(sizeof(NetlinkList));
- if (l_item == NULL)
- {
- return NULL;
- }
-
- l_item->m_next = NULL;
- l_item->m_data = p_data;
- l_item->m_size = p_size;
- return l_item;
-}
-
-static void freeResultList(NetlinkList *p_list)
-{
- NetlinkList *l_cur;
- while(p_list)
- {
- l_cur = p_list;
- p_list = p_list->m_next;
- free(l_cur->m_data);
- free(l_cur);
- }
-}
-
-static NetlinkList *getResultList(int p_socket, int p_request)
-{
- if(netlink_send(p_socket, p_request) < 0)
- {
- return NULL;
- }
-
- NetlinkList *l_list = NULL;
- NetlinkList *l_end = NULL;
- int l_size;
- int l_done = 0;
- while(!l_done)
- {
- struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
- if(!l_hdr)
- { // error
- freeResultList(l_list);
- return NULL;
- }
-
- NetlinkList *l_item = newListItem(l_hdr, l_size);
- if (!l_item)
- {
- freeResultList(l_list);
- return NULL;
- }
- if(!l_list)
- {
- l_list = l_item;
- }
- else
- {
- l_end->m_next = l_item;
- }
- l_end = l_item;
- }
- return l_list;
-}
-
-static size_t maxSize(size_t a, size_t b)
-{
- return (a > b ? a : b);
-}
-
-static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
-{
- switch(p_family)
- {
- case AF_INET:
- return sizeof(struct sockaddr_in);
- case AF_INET6:
- return sizeof(struct sockaddr_in6);
- case AF_PACKET:
- return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
- default:
- return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
- }
-}
-
-static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
-{
- switch(p_family)
- {
- case AF_INET:
- memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
- break;
- case AF_INET6:
- memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
- break;
- case AF_PACKET:
- memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
- ((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
- break;
- default:
- memcpy(p_dest->sa_data, p_data, p_size);
- break;
- }
- p_dest->sa_family = p_family;
-}
-
-static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
-{
- if(!*p_resultList)
- {
- *p_resultList = p_entry;
- }
- else
- {
- struct ifaddrs *l_cur = *p_resultList;
- while(l_cur->ifa_next)
- {
- l_cur = l_cur->ifa_next;
- }
- l_cur->ifa_next = p_entry;
- }
-}
-
-static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
-{
- struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
-
- size_t l_nameSize = 0;
- size_t l_addrSize = 0;
- size_t l_dataSize = 0;
-
- size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
- struct rtattr *l_rta;
- for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
- {
- //void *l_rtaData = RTA_DATA(l_rta);
- size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
- switch(l_rta->rta_type)
- {
- case IFLA_ADDRESS:
- case IFLA_BROADCAST:
- l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
- break;
- case IFLA_IFNAME:
- l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
- break;
- case IFLA_STATS:
- l_dataSize += NLMSG_ALIGN(l_rtaSize);
- break;
- default:
- break;
- }
- }
-
- struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize);
- if (l_entry == NULL)
- {
- return -1;
- }
- memset(l_entry, 0, sizeof(struct ifaddrs));
- l_entry->ifa_name = "";
-
- char *l_index = ((char *)l_entry) + sizeof(struct ifaddrs);
- char *l_name = l_index + sizeof(int);
- char *l_addr = l_name + l_nameSize;
- char *l_data = l_addr + l_addrSize;
-
- // save the interface index so we can look it up when handling the addresses.
- memcpy(l_index, &l_info->ifi_index, sizeof(int));
-
- l_entry->ifa_flags = l_info->ifi_flags;
-
- l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
- for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
- {
- void *l_rtaData = RTA_DATA(l_rta);
- size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
- switch(l_rta->rta_type)
- {
- case IFLA_ADDRESS:
- case IFLA_BROADCAST:
- {
- size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
- makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
- ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
- ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
- if(l_rta->rta_type == IFLA_ADDRESS)
- {
- l_entry->ifa_addr = (struct sockaddr *)l_addr;
- }
- else
- {
- l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
- }
- l_addr += NLMSG_ALIGN(l_addrLen);
- break;
- }
- case IFLA_IFNAME:
- strncpy(l_name, l_rtaData, l_rtaDataSize);
- l_name[l_rtaDataSize] = '\0';
- l_entry->ifa_name = l_name;
- break;
- case IFLA_STATS:
- memcpy(l_data, l_rtaData, l_rtaDataSize);
- l_entry->ifa_data = l_data;
- break;
- default:
- break;
- }
- }
-
- addToEnd(p_resultList, l_entry);
- return 0;
-}
-
-static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks)
-{
- int l_num = 0;
- struct ifaddrs *l_cur = *p_links;
- while(l_cur && l_num < p_numLinks)
- {
- char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs);
- int l_index;
- memcpy(&l_index, l_indexPtr, sizeof(int));
- if(l_index == p_index)
- {
- return l_cur;
- }
-
- l_cur = l_cur->ifa_next;
- ++l_num;
- }
- return NULL;
-}
-
-static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks)
-{
- struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
- struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks);
-
- if(l_info->ifa_family == AF_PACKET)
- {
- return 0;
- }
-
- size_t l_nameSize = 0;
- size_t l_addrSize = 0;
-
- int l_addedNetmask = 0;
-
- size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
- struct rtattr *l_rta;
- for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
- {
- //void *l_rtaData = RTA_DATA(l_rta);
- size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
-
- switch(l_rta->rta_type)
- {
- case IFA_ADDRESS:
- case IFA_LOCAL:
- if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
- { // make room for netmask
- l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
- l_addedNetmask = 1;
- }
- case IFA_BROADCAST:
- l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
- break;
- case IFA_LABEL:
- l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
- break;
- default:
- break;
- }
- }
-
- struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
- if (l_entry == NULL)
- {
- return -1;
- }
- memset(l_entry, 0, sizeof(struct ifaddrs));
- l_entry->ifa_name = (l_interface ? l_interface->ifa_name : "");
-
- char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
- char *l_addr = l_name + l_nameSize;
-
- l_entry->ifa_flags = l_info->ifa_flags;
- if(l_interface)
- {
- l_entry->ifa_flags |= l_interface->ifa_flags;
- }
-
- l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
- for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
- {
- void *l_rtaData = RTA_DATA(l_rta);
- size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
- switch(l_rta->rta_type)
- {
- case IFA_ADDRESS:
- case IFA_BROADCAST:
- case IFA_LOCAL:
- {
- size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
- makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
- if(l_info->ifa_family == AF_INET6)
- {
- if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
- {
- ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
- }
- }
-
- if(l_rta->rta_type == IFA_ADDRESS)
- { // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address
- if(l_entry->ifa_addr)
- {
- l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
- }
- else
- {
- l_entry->ifa_addr = (struct sockaddr *)l_addr;
- }
- }
- else if(l_rta->rta_type == IFA_LOCAL)
- {
- if(l_entry->ifa_addr)
- {
- l_entry->ifa_dstaddr = l_entry->ifa_addr;
- }
- l_entry->ifa_addr = (struct sockaddr *)l_addr;
- }
- else
- {
- l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
- }
- l_addr += NLMSG_ALIGN(l_addrLen);
- break;
- }
- case IFA_LABEL:
- strncpy(l_name, l_rtaData, l_rtaDataSize);
- l_name[l_rtaDataSize] = '\0';
- l_entry->ifa_name = l_name;
- break;
- default:
- break;
- }
- }
-
- if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
- {
- unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
- unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
- char l_mask[16] = {0};
- unsigned i;
- for(i=0; i<(l_prefix/8); ++i)
- {
- l_mask[i] = 0xff;
- }
- if(l_prefix % 8)
- {
- l_mask[i] = 0xff << (8 - (l_prefix % 8));
- }
-
- makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
- l_entry->ifa_netmask = (struct sockaddr *)l_addr;
- }
-
- addToEnd(p_resultList, l_entry);
- return 0;
-}
-
-static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
-{
- int l_numLinks = 0;
- pid_t l_pid = getpid();
- for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
- {
- unsigned int l_nlsize = p_netlinkList->m_size;
- struct nlmsghdr *l_hdr;
- for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
- {
- if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
- {
- continue;
- }
-
- if(l_hdr->nlmsg_type == NLMSG_DONE)
- {
- break;
- }
-
- if(l_hdr->nlmsg_type == RTM_NEWLINK)
- {
- if(interpretLink(l_hdr, p_resultList) == -1)
- {
- return -1;
- }
- ++l_numLinks;
- }
- }
- }
- return l_numLinks;
-}
-
-static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
-{
- pid_t l_pid = getpid();
- for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
- {
- unsigned int l_nlsize = p_netlinkList->m_size;
- struct nlmsghdr *l_hdr;
- for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
- {
- if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
- {
- continue;
- }
-
- if(l_hdr->nlmsg_type == NLMSG_DONE)
- {
- break;
- }
-
- if(l_hdr->nlmsg_type == RTM_NEWADDR)
- {
- if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1)
- {
- return -1;
- }
- }
- }
- }
- return 0;
-}
-
-int getifaddrs(struct ifaddrs **ifap)
-{
- if(!ifap)
- {
- return -1;
- }
- *ifap = NULL;
-
- int l_socket = netlink_socket();
- if(l_socket < 0)
- {
- return -1;
- }
-
- NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK);
- if(!l_linkResults)
- {
- close(l_socket);
- return -1;
- }
-
- NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR);
- if(!l_addrResults)
- {
- close(l_socket);
- freeResultList(l_linkResults);
- return -1;
- }
-
- int l_result = 0;
- int l_numLinks = interpretLinks(l_socket, l_linkResults, ifap);
- if(l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1)
- {
- l_result = -1;
- }
-
- freeResultList(l_linkResults);
- freeResultList(l_addrResults);
- close(l_socket);
- return l_result;
-}
-
-void freeifaddrs(struct ifaddrs *ifa)
-{
- struct ifaddrs *l_cur;
- while(ifa)
- {
- l_cur = ifa;
- ifa = ifa->ifa_next;
- free(l_cur);
- }
-}
-
-
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-//#include <string.h>
-//#include <unistd.h>
-//#include <linux/sockios.h>
-//#include <net/if.h>
-//#include <sys/socket.h>
-//#include <sys/ioctl.h>
-
-/*
- * Map an interface name into its corresponding index.
- * Returns 0 on error, as 0 is not a valid index.
- */
-unsigned int if_nametoindex(const char *ifname)
-{
- int index;
- int ctl_sock;
- struct ifreq ifr;
-
- memset(&ifr, 0, sizeof(struct ifreq));
- strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
- ifr.ifr_name[IFNAMSIZ - 1] = 0;
-
- index = 0;
- if ((ctl_sock = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {
- if (ioctl(ctl_sock, SIOCGIFINDEX, &ifr) >= 0) {
- index = ifr.ifr_ifindex;
- }
- close(ctl_sock);
- }
- return index;
-}
if (!info)
{
OIC_LOG(ERROR, TAG, "endpoint info is null");
- return CA_STATUS_FAILED;
+ return CA_STATUS_INVALID_PARAM;
}
- int32_t netInfoSize = 1;
-
char *macAddress = NULL;
CAResult_t ret = CAEDRGetInterfaceInfo(&macAddress);
- OIC_LOG_V(ERROR, TAG, "address : %s", macAddress);
- if (NULL == macAddress)
- {
- OIC_LOG(ERROR, TAG, "mac address is null");
-
- return CA_STATUS_FAILED;
- }
if (CA_STATUS_OK != ret)
{
OIC_LOG_V(ERROR, TAG, "Failed to get interface info [%d]", ret);
-
OICFree(macAddress);
return ret;
}
+ if (!macAddress)
+ {
+ OIC_LOG(ERROR, TAG, "mac address is null");
+ return CA_STATUS_FAILED;
+ }
+ OIC_LOG_V(DEBUG, TAG, "address : %s", macAddress);
+
// Create local endpoint using util function
CAEndpoint_t *endpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, CA_ADAPTER_RFCOMM_BTEDR,
macAddress, 0);
}
// copy unicast server information
+ int32_t netInfoSize = 1;
CAEndpoint_t *netInfo = (CAEndpoint_t *)OICMalloc(sizeof(CAEndpoint_t) * netInfoSize);
if (NULL == netInfo)
{
OIC_LOG(DEBUG, TAG, "OUT");
}
-CAResult_t CAEDRManagerReadData(void)
+CAResult_t CAEDRManagerReadData()
{
OIC_LOG(DEBUG, TAG, "IN");
return CA_NOT_SUPPORTED;
}
-CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const void *data,
+CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const uint8_t *data,
uint32_t dataLength)
{
+ VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
+ VERIFY_NON_NULL(data, TAG, "data is null");
OIC_LOG(DEBUG, TAG, "IN");
- CAResult_t result = CAEDRSendUnicastMessage(remoteAddress, (const char*) data, dataLength);
+ CAResult_t result = CAEDRSendUnicastMessage(remoteAddress, data, dataLength);
OIC_LOG(DEBUG, TAG, "OUT");
return result;
}
-CAResult_t CAEDRClientSendMulticastData(const void *data, uint32_t dataLength)
+CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength)
{
+ VERIFY_NON_NULL(data, TAG, "data is null");
OIC_LOG(DEBUG, TAG, "IN");
- CAResult_t result = CAEDRSendMulticastMessage((const char*) data, dataLength);
+ CAResult_t result = CAEDRSendMulticastMessage(data, dataLength);
OIC_LOG(DEBUG, TAG, "OUT");
return result;
}
// It will be updated when android EDR support is added
-void CAEDRClientUnsetCallbacks(void)
+void CAEDRClientUnsetCallbacks()
{
OIC_LOG(DEBUG, TAG, "IN");
}
// It will be updated when android EDR support is added
-void CAEDRClientDisconnectAll(void)
+void CAEDRClientDisconnectAll()
{
OIC_LOG(DEBUG, TAG, "IN");
g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
}
-CAResult_t CAEDRSendUnicastMessage(const char* address, const char* data, uint32_t dataLen)
+CAResult_t CAEDRSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "CAEDRSendUnicastMessage(%s, %s)", address, data);
+ VERIFY_NON_NULL(address, TAG, "address is null");
+ VERIFY_NON_NULL(data, TAG, "data is null");
CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen);
return result;
}
-CAResult_t CAEDRSendMulticastMessage(const char* data, uint32_t dataLen)
+CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
{
+ VERIFY_NON_NULL(data, TAG, "data is null");
OIC_LOG_V(DEBUG, TAG, "CAEDRSendMulticastMessage(%s)", data);
bool isAttached = false;
{
(*g_jvm)->DetachCurrentThread(g_jvm);
}
+ (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
+ (*env)->DeleteLocalRef(env, jni_address);
return;
}
(*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
+ (*env)->DeleteLocalRef(env, jni_address);
}
OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
}
}
-CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const char* data, uint32_t dataLen)
+CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const uint8_t* data, uint32_t dataLen)
{
+ VERIFY_NON_NULL(address, TAG, "address is null");
+ VERIFY_NON_NULL(data, TAG, "data is null");
OIC_LOG_V(DEBUG, TAG, "CAEDRSendUnicastMessageImpl, address: %s, data: %s", address, data);
bool isAttached = false;
METHODID_STRINGNONPARAM);
jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
- jsize i;
- for (i = 0; i < length; i++)
+ for (jsize i = 0; i < length; i++)
{
OIC_LOG(DEBUG, TAG, "[EDR][Native] start to check device");
// get name, address from BT device
const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~device name is %s", name);
(*env)->ReleaseStringUTFChars(env, j_str_name, name);
+ (*env)->DeleteLocalRef(env, j_str_name);
}
jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
- OIC_LOG_V(DEBUG, TAG,
- "[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress);
-
+ (*env)->DeleteLocalRef(env, j_obj_device);
if (!remoteAddress)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] remoteAddress is null");
{
(*g_jvm)->DetachCurrentThread(g_jvm);
}
+
+ (*env)->DeleteLocalRef(env, j_str_address);
+ (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
+ (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
return CA_STATUS_INVALID_PARAM;
}
- if (!address)
- {
- OIC_LOG(ERROR, TAG, "[EDR][Native] address is null");
- if (isAttached)
- {
- (*g_jvm)->DetachCurrentThread(g_jvm);
- }
- (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
- return CA_STATUS_INVALID_PARAM;
- }
+ OIC_LOG_V(DEBUG, TAG,
+ "[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress);
+
// find address
if (!strcmp(remoteAddress, address))
{
CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
+ (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
+ (*env)->DeleteLocalRef(env, j_str_address);
if (CA_STATUS_OK != res)
{
- (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
+ (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
+ (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
return res;
}
+ break;
}
(*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
+ (*env)->DeleteLocalRef(env, j_str_address);
}
+ (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
+ (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
+
if (isAttached)
{
(*g_jvm)->DetachCurrentThread(g_jvm);
return CA_STATUS_OK;
}
-CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const char* data, uint32_t dataLen)
+CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen)
{
+ VERIFY_NON_NULL(data, TAG, "data is null");
OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %s, %d", data, dataLen);
// get bonded device list
METHODID_STRINGNONPARAM);
jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
- jsize i;
- for (i = 0; i < length; i++)
+ for (jsize i = 0; i < length; i++)
{
// get name, address from BT device
jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~device name is %s", name);
(*env)->ReleaseStringUTFChars(env, j_str_name, name);
+ (*env)->DeleteLocalRef(env, j_str_name);
}
jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
+ (*env)->DeleteLocalRef(env, j_obj_device);
OIC_LOG_V(DEBUG, TAG,
"[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress);
// find address
CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
(*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
+ (*env)->DeleteLocalRef(env, j_str_address);
if (CA_STATUS_OK != res)
{
OIC_LOG_V(ERROR, TAG, "CASendMulticastMessageImpl, failed to send message to : %s",
}
}
+ (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
+ (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
+
return CA_STATUS_OK;
}
/**
* EDR Method
*/
-CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const char *data,
+CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
uint32_t dataLength)
{
+ VERIFY_NON_NULL(address, TAG, "address is null");
+ VERIFY_NON_NULL(data, TAG, "data is null");
OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btSendData logic start : %s, %d", data, dataLength);
if (!CAEDRNativeIsEnableBTAdapter(env))
// connect before send data
OIC_LOG(DEBUG, TAG, "[EDR][Native] connect before send data");
- if (NULL == address)
+ CAResult_t res = CAEDRNativeConnect(env, address);
+ if (CA_STATUS_OK != res)
{
- OIC_LOG(ERROR, TAG, "[EDR][Native] remote address is empty");
- return CA_STATUS_INVALID_PARAM;
- }
- else
- {
- CAResult_t res = CAEDRNativeConnect(env, address);
- if (CA_STATUS_OK != res)
- {
- return res;
- }
+ return res;
}
}
if (!jni_mid_getOutputStream)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_mid_getOutputStream is null");
+ (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
return CA_STATUS_FAILED;
}
if (!jni_obj_socket)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_socket is not available");
+ (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
return CA_STATUS_FAILED;
}
if (!jni_obj_outputStream)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_obj_outputStream is null");
+ (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
return CA_STATUS_FAILED;
}
if (!jni_cid_OutputStream)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_cid_OutputStream is null");
+ (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+ (*env)->DeleteLocalRef(env, jni_obj_outputStream);
return CA_STATUS_FAILED;
}
if (!jni_mid_write)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_mid_write is null");
+ (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+ (*env)->DeleteLocalRef(env, jni_obj_outputStream);
+ (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
return CA_STATUS_FAILED;
}
- jbyteArray jbuf;
- jbuf = (*env)->NewByteArray(env, dataLength);
+ jbyteArray jbuf = (*env)->NewByteArray(env, dataLength);
(*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data);
(*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0,
(jint) dataLength);
+ (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+ (*env)->DeleteLocalRef(env, jni_obj_outputStream);
+ (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
+ (*env)->DeleteLocalRef(env, jbuf);
+
if ((*env)->ExceptionCheck(env))
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: Write Error!!!");
CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
{
+ VERIFY_NON_NULL(address, TAG, "address is null");
OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect..");
if (!CAEDRNativeIsEnableBTAdapter(env))
if (!jni_mid_getDefaultAdapter)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_getDefaultAdapter is null");
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
return CA_STATUS_FAILED;
}
if (!jni_obj_BTAdapter)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_BTAdapter is null");
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
return CA_STATUS_FAILED;
}
jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
"getRemoteDevice",
METHODID_BT_DEVICEPARAM);
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
if (!jni_mid_getRemoteDevice)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_getRemoteDevice is null");
+ (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
return CA_STATUS_FAILED;
}
jstring jni_address = (*env)->NewStringUTF(env, address);
jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
jni_mid_getRemoteDevice, jni_address);
+ (*env)->DeleteLocalRef(env, jni_address);
+ (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
if (!jni_obj_remoteBTDevice)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_remoteBTDevice is null");
if (!jni_cid_BluetoothDevice)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_BluetoothDevice is null");
+ (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
return CA_STATUS_FAILED;
}
jmethodID jni_mid_createSocket = (*env)->GetMethodID(
env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord",
"(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;");
+ (*env)->DeleteLocalRef(env, jni_cid_BluetoothDevice);
if (!jni_mid_createSocket)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_createSocket is null");
+ (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
return CA_STATUS_FAILED;
}
if (!jni_cid_uuid)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_uuid is null");
+ (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
return CA_STATUS_FAILED;
}
if (!jni_mid_fromString)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_fromString is null");
+ (*env)->DeleteLocalRef(env, jni_cid_uuid);
+ (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
return CA_STATUS_FAILED;
}
if (!jni_uuid)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_uuid is null");
+ (*env)->DeleteLocalRef(env, jni_cid_uuid);
+ (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
return CA_STATUS_FAILED;
}
jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
jni_uuid);
+ (*env)->DeleteLocalRef(env, jni_cid_uuid);
+ (*env)->DeleteLocalRef(env, jni_uuid);
if (!jni_obj_uuid)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_uuid is null");
+ (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
return CA_STATUS_FAILED;
}
// create socket
jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice,
jni_mid_createSocket, jni_obj_uuid);
+ (*env)->DeleteLocalRef(env, jni_obj_uuid);
+ (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
if (!jni_obj_BTSocket)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_BTSocket is null");
if (!jni_cid_BTSocket)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_BTSocket is null");
+ (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
return CA_STATUS_FAILED;
}
jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V");
+ (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
if (!jni_mid_connect)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_connect is null");
+ (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
return CA_STATUS_FAILED;
}
if (!jni_socket)
{
OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_socket is null");
+ (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
return CA_STATUS_FAILED;
}
ca_mutex_lock(g_mutexObjectList);
CAEDRNativeAddDeviceSocketToList(env, jni_socket);
+ (*env)->DeleteGlobalRef(env, jni_socket);
+ (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
ca_mutex_unlock(g_mutexObjectList);
// update state
void CAEDRNativeSocketClose(JNIEnv *env, const char *address)
{
+ VERIFY_NON_NULL_VOID(address, TAG, "address is null");
jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
if (!jni_cid_BTSocket)
* @retval ::CA_STATUS_OK Successful.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
-CAResult_t CAEDRSendUnicastMessage(const char *address, const char *data, uint32_t dataLen);
+CAResult_t CAEDRSendUnicastMessage(const char *address, const uint8_t *data, uint32_t dataLen);
/**
* Send data for multicast.
* @retval ::CA_STATUS_OK Successful.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
-CAResult_t CAEDRSendMulticastMessage(const char *data, uint32_t dataLen);
+CAResult_t CAEDRSendMulticastMessage(const uint8_t *data, uint32_t dataLen);
/**
* Get Local EDR Address.
* @retval ::CA_STATUS_OK Successful.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
-CAResult_t CAEDRSendUnicastMessageImpl(const char *address, const char *data, uint32_t dataLen);
+CAResult_t CAEDRSendUnicastMessageImpl(const char *address, const uint8_t *data, uint32_t dataLen);
/**
* Send data for multicast (implement).
* @retval ::CA_STATUS_OK Successful.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
-CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const char *data, uint32_t dataLen);
+CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t *data, uint32_t dataLen);
/**
* EDR Method
* @param[in] dataLength Length of data.
* @return ::CA_STATUS_OK or Appropriate error code.
*/
-CAResult_t CAEDRNativeSendData(JNIEnv *env, const char* address, const char* data,
+CAResult_t CAEDRNativeSendData(JNIEnv *env, const char* address, const uint8_t* data,
uint32_t dataLength);
/**
if (NULL == g_networkChangeCb)
{
OIC_LOG_V(DEBUG, TAG, "gNetworkChangeCb is null", status);
+ return;
}
jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
******************************************************************/
#include <stdio.h>
-#include <unistd.h>
#include <string.h>
#include <jni.h>
// if new socket object is added in socket list after below logic is ran.
// new socket will be started to read after next while loop
uint32_t length = CAEDRGetSocketListLength();
- if (0 == length)
+ if (0 != length)
{
- OIC_LOG(DEBUG, TAG, "socket list is empty");
- sleep(1);
- }
-
- uint32_t idx;
- for (idx = 0; idx < length; idx++)
- {
- OIC_LOG(DEBUG, TAG, "start CAEDRNativeReadData");
- CAEDRNativeReadData(env, idx, ctx->type);
- sleep(1);
+ for (uint32_t idx = 0; idx < length; idx++)
+ {
+ OIC_LOG(DEBUG, TAG, "start CAEDRNativeReadData");
+ CAEDRNativeReadData(env, idx, ctx->type);
+ }
}
}
CAAdapterAcceptThreadContext_t *ctx = (CAAdapterAcceptThreadContext_t *) data;
- if (NULL == ctx)
- {
- OIC_LOG(ERROR, TAG, "[EDR] AcceptThread: ctx is null");
- if (isAttached)
- {
- (*g_jvm)->DetachCurrentThread(g_jvm);
- }
- return;
- }
-
// it should be initialized for restart accept thread
ca_mutex_lock(g_mutexAcceptServer);
g_stopAccept = false;
"()Ljava/io/InputStream;");
OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btReadData: get InputStream..%d, %s", id, address);
- if (!jni_obj_socket)
+ jobject jni_obj_inputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
+ jni_mid_getInputStream);
+ if (!jni_obj_inputStream)
{
(*env)->DeleteLocalRef(env, jni_cid_BTsocket);
(*env)->DeleteLocalRef(env, jni_str_address);
- OIC_LOG(ERROR, TAG, "[EDR][Native] jni_obj_socket is not available anymore..");
+ OIC_LOG(ERROR, TAG, "[EDR] btReadData: jni_obj_inputStream is null");
return CA_STATUS_FAILED;
}
- jobject jni_obj_inputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
- jni_mid_getInputStream);
OIC_LOG(DEBUG, TAG, "[EDR][Native] btReadData: ready inputStream..");
jclass jni_cid_InputStream = (*env)->FindClass(env, "java/io/InputStream");
jbyteArray jbuf = (*env)->NewByteArray(env, MAX_PDU_BUFFER);
- if (!jni_obj_socket)
- {
- (*env)->DeleteLocalRef(env, jni_cid_InputStream);
- (*env)->DeleteLocalRef(env, jni_obj_inputStream);
- (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
- (*env)->DeleteLocalRef(env, jni_str_address);
-
- OIC_LOG(ERROR, TAG, "[EDR][Native] jni_obj_socket is not available anymore...");
- return CA_STATUS_FAILED;
- }
-
ca_mutex_lock(g_mutexInputStream);
if (!g_inputStream)
{
jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
"getDefaultAdapter",
METHODID_OBJECTNONPARAM);
- if (!jni_cid_BTAdapter)
+ if (!jni_mid_getDefaultAdapter)
{
- OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_cid_BTAdapter is null");
+ OIC_LOG(ERROR, TAG, "[EDR][Native] btListen: jni_mid_getDefaultAdapter is null");
return NULL;
}
jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_InputStream, "close", "()V");
(*env)->CallVoidMethod(env, g_inputStream, jni_mid_close);
(*env)->DeleteGlobalRef(env, g_inputStream);
+ g_inputStream = NULL;
}
if (g_serverSocket)
}
(*env)->CallVoidMethod(env, g_serverSocket, jni_mid_accept);
(*env)->DeleteGlobalRef(env, g_serverSocket);
+ g_serverSocket = NULL;
OIC_LOG(DEBUG, TAG, "[EDR][Native] close accept obj");
}
}
-
{
(*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
(*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_obj_setPairedDevices);
OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: jni_cid_Set is null");
return NULL;
{
(*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
(*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_obj_setPairedDevices);
OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: jni_mid_toArray is null");
return NULL;
{
(*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
(*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_obj_setPairedDevices);
OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: jni_arrayPairedDevices is null");
return NULL;
(*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
(*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_obj_setPairedDevices);
return jni_arrayPairedDevices;
}
OIC_LOG_V(DEBUG, TAG, "[EDR][Native] remove state : %s", remoteAddress);
OICFree(state);
- CAEDRReorderingDeviceList(index);
+ u_arraylist_remove(g_deviceStateList, index);
break;
}
}
return STATE_DISCONNECTED;
}
-void CAEDRReorderingDeviceList(uint32_t index)
-{
- if (index >= g_deviceStateList->length)
- {
- return;
- }
-
- if (index < g_deviceStateList->length - 1)
- {
- memmove(&g_deviceStateList->data[index], &g_deviceStateList->data[index + 1],
- (g_deviceStateList->length - index - 1) * sizeof(void *));
- }
-
- g_deviceStateList->size--;
- g_deviceStateList->length--;
-}
-
/**
* Device Socket Object List
*/
OIC_LOG(DEBUG, TAG, "Set Socket Object to Array");
}
(*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
+ (*env)->DeleteLocalRef(env, jni_remoteAddress);
}
bool CAEDRNativeIsDeviceSocketInList(JNIEnv *env, const char* remoteAddress)
}
jstring jni_setAddress = CAEDRNativeGetAddressFromDeviceSocket(env, jarrayObj);
+ (*env)->DeleteLocalRef(env, jarrayObj);
if (!jni_setAddress)
{
OIC_LOG(DEBUG, TAG, "[EDR][Native] jni_setAddress is null");
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
- CAEDRReorderingDeviceSocketList(index);
+ u_arraylist_remove(g_deviceObjectList, index);
break;
}
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, address, remoteAddress);
- CAEDRReorderingDeviceSocketList(index);
+ u_arraylist_remove(g_deviceObjectList, index);
break;
}
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
{
OIC_LOG_V(ERROR, TAG, "[EDR][Native] remove object : %s", remoteAddress);
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+ (*env)->DeleteLocalRef(env, jni_setAddress);
return jarrayObj;
}
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+ (*env)->DeleteLocalRef(env, jni_setAddress);
}
return NULL;
return length;
}
-
-void CAEDRReorderingDeviceSocketList(uint32_t index)
-{
- if (index >= g_deviceObjectList->length)
- {
- return;
- }
-
- if (index < g_deviceObjectList->length - 1)
- {
- memmove(&g_deviceObjectList->data[index], &g_deviceObjectList->data[index + 1],
- (g_deviceObjectList->length - index - 1) * sizeof(void *));
- }
-
- g_deviceObjectList->size--;
- g_deviceObjectList->length--;
-}
CAConnectedState_t CAEDRIsConnectedDevice(const char *remoteAddress);
/**
- * Reordering for the list.
- * @param[in] index index of device list that want to reordering.
- */
-void CAEDRReorderingDeviceList(uint32_t index);
-
-/**
* This function will create the device socket list.
*/
void CAEDRNativeCreateDeviceSocketList();
*/
uint32_t CAEDRGetSocketListLength();
-/**
- * Reordering for the list.
- * @param[in] index index of device list that want to reordering.
- */
-void CAEDRReorderingDeviceSocketList(uint32_t index);
#ifdef __cplusplus
} /* extern "C" */
#endif
#include "caedrinterface.h"
#include "caadapterutils.h"
#include "logger.h"
+#include "cafragmentation.h"
#include "caqueueingthread.h"
#include "oic_malloc.h"
#include "caremotehandler.h"
*/
static bool g_serverState = false;
+/**
+ * Stores information of all the senders.
+ *
+ * This structure will be used to track and defragment all incoming
+ * data packet.
+ */
+typedef struct
+{
+ uint32_t recvDataLen;
+ uint32_t totalDataLen;
+ uint8_t *defragData;
+ CAEndpoint_t *remoteEndpoint;
+} CAEDRSenderInfo_t;
+
+/**
+ * Sender information.
+ */
+static u_arraylist_t *g_senderInfo = NULL;
+
static CAResult_t CAStartServer();
static CAResult_t CAEDRInitializeQueueHandlers();
CAResult_t CAEDRInitializeSendHandler();
void CAAdapterDataSendHandler(void *context);
void CAAdapterDataReceiverHandler(void *context);
CAResult_t CAAdapterStopQueue();
-void CAAdapterRecvData(const char *remoteAddress, const void *data, uint32_t dataLength,
+void CAAdapterRecvData(const char *remoteAddress, const uint8_t *data, uint32_t dataLength,
uint32_t *sentLength);
void CAEDRNotifyNetworkStatus(CANetworkStatus_t status);
void CAEDROnNetworkStatusChanged(void *context);
-CAResult_t CAAdapterSendData(const char *remoteAddress, const char *serviceUUID, const void *data,
+CAResult_t CAAdapterSendData(const char *remoteAddress, const char *serviceUUID, const uint8_t *data,
uint32_t dataLength, uint32_t *sentLength);
CAEDRNetworkEvent *CAEDRCreateNetworkEvent(CAEndpoint_t *connectivity,
CANetworkStatus_t status);
-CAResult_t CAEDRClientSendData(const char *remoteAddress, const void *data,
+
+CAResult_t CAEDRClientSendData(const char *remoteAddress,
+ const uint8_t *data,
uint32_t dataLength);
+
/**
* @fn CACreateEDRData
* @brief Helper function to create CAEDRData
*/
-static CAEDRData *CACreateEDRData(const CAEndpoint_t *remoteEndpoint, const void *data,
+static CAEDRData *CACreateEDRData(const CAEndpoint_t *remoteEndpoint, const uint8_t *data,
uint32_t dataLength);
/**
static void CAEDRDataDestroyer(void *data, uint32_t size);
-static void CAEDRErrorHandler(const char *remoteAddress, const void *data,
+static void CAEDRErrorHandler(const char *remoteAddress, const uint8_t *data,
uint32_t dataLength, CAResult_t result);
+static void CAEDRClearSenderInfo();
+
CAResult_t CAInitializeEDR(CARegisterConnectivityCallback registerCallback,
CANetworkPacketReceivedCallback packetReceivedCallback,
CANetworkChangeCallback networkStateChangeCallback,
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
- // Stop EDR adapter
- CAStopEDR();
// Terminate EDR Network Monitor
CAEDRTerminateNetworkMonitor();
return CA_MEMORY_ALLOC_FAILED;
}
+ g_senderInfo = u_arraylist_create();
+ if (!g_senderInfo)
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "ClientInfo memory allcation failed!");
+ OICFree(g_recvQueueHandle);
+ g_recvQueueHandle = NULL;
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
if (CA_STATUS_OK != CAQueueingThreadInitialize(g_recvQueueHandle, g_edrThreadPool,
CAAdapterDataReceiverHandler,
CAEDRDataDestroyer))
{
OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to Initialize send queue thread");
+ u_arraylist_free(&g_senderInfo);
+ OICFree(g_recvQueueHandle);
+ g_recvQueueHandle = NULL;
return CA_STATUS_FAILED;
}
g_recvQueueHandle = NULL;
}
+ CAEDRClearSenderInfo();
+
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
}
return;
}
- CAResult_t result = CAEDRClientSendData(remoteAddress, message->data,
- message->dataLen);
- if(CA_STATUS_OK != result)
+ uint32_t dataSegmentLength = message->dataLen + CA_HEADER_LENGTH;
+
+ uint8_t *header = (uint8_t *) OICCalloc(CA_HEADER_LENGTH, sizeof(uint8_t));
+ VERIFY_NON_NULL_VOID(header, EDR_ADAPTER_TAG, "Memory allocation failed");
+
+ uint8_t* dataSegment = (uint8_t *) OICCalloc(dataSegmentLength, sizeof(uint8_t));
+ if (NULL == dataSegment)
+ {
+ CAEDRErrorHandler(remoteAddress, message->data, message->dataLen, CA_SEND_FAILED);
+ OICFree(header);
+ return;
+ }
+
+ CAResult_t result = CAGenerateHeader(header, CA_HEADER_LENGTH, message->dataLen);
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Generate header failed");
+ OICFree(header);
+ OICFree(dataSegment);
+ CAEDRErrorHandler(remoteAddress, message->data, message->dataLen, result);
+ return;
+ }
+
+ memcpy(dataSegment, header, CA_HEADER_LENGTH);
+ OICFree(header);
+
+ memcpy(dataSegment + CA_HEADER_LENGTH, message->data, message->dataLen);
+
+ result = CAEDRClientSendData(remoteAddress, dataSegment, dataSegmentLength);
+ OICFree(dataSegment);
+
+ if (CA_STATUS_OK != result)
{
OIC_LOG(ERROR, EDR_ADAPTER_TAG, "CAEDRClientSendData API failed");
CAEDRErrorHandler(remoteAddress, message->data, message->dataLen, result);
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
}
-CAResult_t CAEDRClientSendData(const char *remoteAddress, const void *data,
+CAResult_t CAEDRClientSendData(const char *remoteAddress,
+ const uint8_t *data,
uint32_t dataLength)
{
return result;
}
+static void CAEDRClearSenderInfo()
+{
+ OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
+
+ uint32_t listIndex = 0;
+ uint32_t listLength = u_arraylist_length(g_senderInfo);
+ for (listIndex = 0; listIndex < listLength; listIndex++)
+ {
+ CAEDRSenderInfo_t *info = (CAEDRSenderInfo_t *) u_arraylist_get(g_senderInfo, listIndex);
+ if (!info)
+ {
+ continue;
+ }
+
+ OICFree(info->defragData);
+ CAFreeEndpoint(info->remoteEndpoint);
+ OICFree(info);
+ }
+ u_arraylist_free(&g_senderInfo);
+ OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
+}
+
+static CAResult_t CAEDRGetSenderInfo(const char *edrAddress,
+ CAEDRSenderInfo_t **senderInfo,
+ uint32_t *senderIndex)
+{
+ VERIFY_NON_NULL_RET(edrAddress,
+ EDR_ADAPTER_TAG,
+ "NULL edr address argument",
+ CA_STATUS_INVALID_PARAM);
+ VERIFY_NON_NULL_RET(senderIndex,
+ EDR_ADAPTER_TAG,
+ "NULL index argument",
+ CA_STATUS_INVALID_PARAM);
+
+ const uint32_t listLength = u_arraylist_length(g_senderInfo);
+ const uint32_t addrLength = strlen(edrAddress);
+ for (uint32_t index = 0; index < listLength; index++)
+ {
+ CAEDRSenderInfo_t *info = (CAEDRSenderInfo_t *) u_arraylist_get(g_senderInfo, index);
+ if (!info || !(info->remoteEndpoint))
+ {
+ continue;
+ }
+
+ if (!strncmp(info->remoteEndpoint->addr, edrAddress, addrLength))
+ {
+ *senderIndex = index;
+ if (senderInfo)
+ {
+ *senderInfo = info;
+ }
+ return CA_STATUS_OK;
+ }
+ }
+
+ return CA_STATUS_FAILED;
+}
+
void CAAdapterDataReceiverHandler(void *context)
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN_CAAdapterDataReceiverHandler");
+ if (NULL == g_networkPacketReceivedCallback)
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "g_networkPacketReceivedCallback is NULL");
+ return;
+ }
+
CAEDRData *message = (CAEDRData *) context;
if (NULL == message || NULL == message->remoteEndpoint)
{
OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to get message!");
return;
}
+ uint32_t dataLen = 0;
- CAEndpoint_t *remoteEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
- CA_ADAPTER_RFCOMM_BTEDR,
- message->remoteEndpoint->addr,
- 0);
+ CAEDRSenderInfo_t *senderInfo = NULL;
+ uint32_t senderIndex = 0;
+
+ while (dataLen < message->dataLen)
+ {
+ if(CA_STATUS_OK != CAEDRGetSenderInfo(message->remoteEndpoint->addr,
+ &senderInfo, &senderIndex))
+ {
+ OIC_LOG_V(DEBUG, EDR_ADAPTER_TAG, "This is a new client [%s]",
+ message->remoteEndpoint->addr);
+ }
- OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Sending data up !");
- g_networkPacketReceivedCallback(remoteEndpoint, message->data, message->dataLen);
+ if (!senderInfo)
+ {
+ CAEDRSenderInfo_t *newSender = OICMalloc(sizeof(CAEDRSenderInfo_t));
+ if (!newSender)
+ {
+ return;
+ }
+ newSender->recvDataLen = 0;
+ newSender->totalDataLen = 0;
+ newSender->defragData = NULL;
+ newSender->remoteEndpoint = NULL;
+
+ OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Parsing the header");
+ newSender->totalDataLen = CAParseHeader(message->data + dataLen,
+ message->dataLen - dataLen);
+ if(!(newSender->totalDataLen))
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Total Data Length is parsed as 0!!!");
+ OICFree(newSender);
+ return;
+ }
- CAFreeEndpoint(remoteEndpoint);
+ OIC_LOG_V(DEBUG, EDR_ADAPTER_TAG, "Total data to be accumulated [%u] bytes",
+ newSender->totalDataLen);
+ OIC_LOG_V(DEBUG, EDR_ADAPTER_TAG, "data received in the first packet [%u] bytes",
+ message->dataLen);
+
+ newSender->defragData = OICCalloc(newSender->totalDataLen,
+ sizeof(*newSender->defragData));
+ if (NULL == newSender->defragData)
+ {
+ OICFree(newSender);
+ return;
+ }
+
+ newSender->remoteEndpoint = CACloneEndpoint(message->remoteEndpoint);
+ if (NULL == newSender->remoteEndpoint)
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "remoteEndpoint is NULL!");
+ OICFree(newSender->defragData);
+ OICFree(newSender);
+ return;
+ }
+
+ if (message->dataLen - CA_HEADER_LENGTH - dataLen <= newSender->totalDataLen)
+ {
+ memcpy(newSender->defragData, message->data + dataLen + CA_HEADER_LENGTH,
+ message->dataLen - dataLen - CA_HEADER_LENGTH);
+ newSender->recvDataLen += message->dataLen - dataLen - CA_HEADER_LENGTH;
+ u_arraylist_add(g_senderInfo,(void *)newSender);
+ dataLen = message->dataLen;
+ }
+ else
+ {
+ memcpy(newSender->defragData, message->data + dataLen + CA_HEADER_LENGTH,
+ newSender->totalDataLen);
+ newSender->recvDataLen = newSender->totalDataLen;
+ u_arraylist_add(g_senderInfo,(void *)newSender);
+ dataLen += newSender->totalDataLen + CA_HEADER_LENGTH;
+ }
+ //Getting newSender index position in g_senderInfo array list
+ if (CA_STATUS_OK !=
+ CAEDRGetSenderInfo(newSender->remoteEndpoint->addr, NULL, &senderIndex))
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Existing sender index not found!!");
+ OICFree(newSender->defragData);
+ CAFreeEndpoint(newSender->remoteEndpoint);
+ OICFree(newSender);
+ return;
+ }
+ senderInfo = newSender;
+ }
+ else
+ {
+ if (senderInfo->recvDataLen + message->dataLen - dataLen <= senderInfo->totalDataLen)
+ {
+ OIC_LOG_V(DEBUG, EDR_ADAPTER_TAG, "Copying the data of length [%d]",
+ message->dataLen - dataLen);
+ memcpy(senderInfo->defragData + senderInfo->recvDataLen, message->data + dataLen,
+ message->dataLen - dataLen);
+ senderInfo->recvDataLen += message->dataLen - dataLen;
+ OIC_LOG_V(DEBUG, EDR_ADAPTER_TAG, "totalDatalength [%d] recveived Datalen [%d]",
+ senderInfo->totalDataLen, senderInfo->recvDataLen);
+ dataLen = message->dataLen;
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, EDR_ADAPTER_TAG, "Copying the data of length [%d]",
+ senderInfo->totalDataLen - senderInfo->recvDataLen);
+ memcpy(senderInfo->defragData + senderInfo->recvDataLen, message->data + dataLen,
+ senderInfo->totalDataLen - senderInfo->recvDataLen);
+ dataLen += senderInfo->totalDataLen - senderInfo->recvDataLen;
+ senderInfo->recvDataLen = senderInfo->totalDataLen;
+ OIC_LOG_V(DEBUG, EDR_ADAPTER_TAG, "totalDatalength [%d] recveived Datalen [%d]",
+ senderInfo->totalDataLen, senderInfo->recvDataLen);
+ }
+ }
+
+ if (senderInfo->totalDataLen == senderInfo->recvDataLen)
+ {
+ OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Sending data up !");
+
+ CASecureEndpoint_t sep = {.endpoint = *(senderInfo->remoteEndpoint)};
+ g_networkPacketReceivedCallback(&sep, senderInfo->defragData, senderInfo->recvDataLen);
+ u_arraylist_remove(g_senderInfo, senderIndex);
+ senderInfo->remoteEndpoint = NULL;
+ senderInfo->defragData = NULL;
+ OICFree(senderInfo);
+ senderInfo = NULL;
+ }
+ }
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT_CAAdapterDataReceiverHandler");
}
return CA_STATUS_OK;
}
-void CAAdapterRecvData(const char *remoteAddress, const void *data, uint32_t dataLength,
+void CAAdapterRecvData(const char *remoteAddress, const uint8_t *data, uint32_t dataLength,
uint32_t *sentLength)
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
}
-void CAEDRErrorHandler(const char *remoteAddress, const void *data,
+void CAEDRErrorHandler(const char *remoteAddress, const uint8_t *data,
uint32_t dataLength, CAResult_t result)
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
}
-CAResult_t CAAdapterSendData(const char *remoteAddress, const char *serviceUUID, const void *data,
+CAResult_t CAAdapterSendData(const char *remoteAddress, const char *serviceUUID, const uint8_t *data,
uint32_t dataLength, uint32_t *sentLength)
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN - CAAdapterSendData");
}
CAEDRData *CACreateEDRData(const CAEndpoint_t *remoteEndpoint,
- const void *data, uint32_t dataLength)
+ const uint8_t *data, uint32_t dataLength)
{
CAEDRData *edrData = (CAEDRData *)OICMalloc(sizeof (CAEDRData));
if (!edrData)
#include "cacommon.h"
#include "caedrdevicelist.h"
+#define MICROSECS_PER_SEC 1000000
+
+/**
+ * Condition to check if OIC supported device is found.
+ */
+static ca_cond g_deviceDescCond = NULL;
+
+/**
+ * Flag that will be set when EDR adapter is stopped.
+ */
+static bool g_isStopping = false;
+
/**
* Mutex to synchronize the access to Bluetooth device information list.
*/
return;
}
device->serviceSearched = true;
+ // Signal the wait to send the data.
+ ca_cond_signal(g_deviceDescCond);
ca_mutex_unlock(g_edrDeviceListMutex);
}
else
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
+ g_isStopping = false;
// Register for discovery and rfcomm socket connection callbacks
bt_adapter_set_device_discovery_state_changed_cb(CAEDRDeviceDiscoveryCallback, NULL);
bt_device_set_service_searched_cb(CAEDRServiceSearchedCallback, NULL);
// Stop the device discovery process
CAEDRStopDeviceDiscovery();
+ // Signal the conditional wait for discovery of devices.
+ g_isStopping = true;
+ ca_cond_signal(g_deviceDescCond);
+
// reset bluetooth adapter callbacks
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Resetting the callbacks");
bt_adapter_unset_device_discovery_state_changed_cb();
g_edrDeviceListMutex = ca_mutex_new();
}
+ if (!g_deviceDescCond)
+ {
+ g_deviceDescCond = ca_cond_new();
+ }
+
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
}
g_edrDeviceListMutex = NULL;
}
+ if (g_deviceDescCond)
+ {
+ ca_cond_free(g_deviceDescCond);
+ g_deviceDescCond = NULL;
+ }
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
}
}
-CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const void *data,
+CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress,
+ const uint8_t *data,
uint32_t dataLength)
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
return CA_STATUS_OK;
}
-CAResult_t CAEDRClientSendMulticastData(const void *data, uint32_t dataLength)
+CAResult_t CAEDRClientSendMulticastData(const uint8_t *data,
+ uint32_t dataLength)
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
// Send the packet to all OIC devices
ca_mutex_lock(g_edrDeviceListMutex);
+
+ // Check if any device is discovered.
+ if (NULL == g_edrDeviceList)
+ {
+ // Wait for BT devices to be discovered.
+
+ // Number of times to wait for discovery to complete.
+ int const RETRIES = 5;
+
+ uint64_t const TIMEOUT = 2 * MICROSECS_PER_SEC; // Microseconds
+
+ bool devicesDiscovered = false;
+ for (size_t i = 0; NULL == g_edrDeviceList && i < RETRIES && !g_isStopping;
+ ++i)
+ {
+ if (ca_cond_wait_for(g_deviceDescCond, g_edrDeviceListMutex,
+ TIMEOUT) == 0)
+ {
+ devicesDiscovered = true;
+ }
+ }
+ if (!devicesDiscovered || g_isStopping)
+ {
+ goto exit;
+ }
+ }
+
EDRDeviceList *curList = g_edrDeviceList;
CAResult_t result = CA_STATUS_FAILED;
while (curList != NULL)
if (-1 == device->socketFD)
{
- OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN1");
// Check if the device service search is finished
if (false == device->serviceSearched)
{
CARemoveEDRDataFromList(&device->pendingDataList);
continue;
}
- OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN2");
}
else
{
- OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN3");
result = CAEDRSendData(device->socketFD, data, dataLength);
if (CA_STATUS_OK != result)
{
OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to send data to [%s] !",
device->remoteAddress);
}
- OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN4");
}
}
+exit:
ca_mutex_unlock(g_edrDeviceListMutex);
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
uint32_t sentLength = 0;
- g_edrPacketReceivedCallback(device->remoteAddress, data->data,
- (uint32_t)data->data_size, &sentLength);
+ g_edrPacketReceivedCallback(device->remoteAddress,
+ (uint8_t *) data->data,
+ (uint32_t) data->data_size,
+ &sentLength);
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
}
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
VERIFY_NON_NULL(data, EDR_ADAPTER_TAG, "Data is null");
- VERIFY_NON_NULL(sentDataLen, EDR_ADAPTER_TAG, "Sent data length holder is null");
if (0 > serverFD)
{
}
if (g_mainloop)
- g_main_loop_unref(g_mainloop);
-
+ {
+ g_main_loop_quit(g_mainloop);
+ }
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
#define TAG PCF("CA_LE_CLIENT")
+#define MICROSECS_PER_SEC 1000000
+
static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;";
static const char CLASSPATH_BT_ADAPTER[] = "android/bluetooth/BluetoothAdapter";
static const char CLASSPATH_BT_UUID[] = "java/util/UUID";
static ca_mutex g_SendFinishMutex = NULL;
static ca_mutex g_threadMutex = NULL;
static ca_cond g_threadCond = NULL;
+static ca_cond g_deviceDescCond = NULL;
static ca_mutex g_threadSendMutex = NULL;
static ca_mutex g_gattObjectMutex = NULL;
static ca_mutex g_deviceStateListMutex = NULL;
+static ca_mutex g_scanMutex = NULL;
+
static CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
//getting jvm
return ret;
}
+ g_deviceDescCond = ca_cond_new();
+
// init mutex for send logic
g_threadCond = ca_cond_new();
}
g_isStartedLEClient = true;
+ if (isAttached)
+ {
+ (*g_jvm)->DetachCurrentThread(g_jvm);
+ }
+
return CA_STATUS_OK;
}
}
g_isStartedMulticastServer = false;
- g_isStartedScan = false;
+ CALEClientSetScanFlag(false);
CALEClientSetSendFinishFlag(false);
CALEClientTerminateGattMutexVariables();
+ ca_cond_free(g_deviceDescCond);
ca_cond_free(g_threadCond);
+ g_deviceDescCond = NULL;
+ g_threadCond = NULL;
+
if (isAttached)
{
(*g_jvm)->DetachCurrentThread(g_jvm);
CALEClientUpdateSendCnt(env);
}
-CAResult_t CALEClientSendUnicastMessage(const char* address, const char* data,
+CAResult_t CALEClientSendUnicastMessage(const char* address,
+ const uint8_t* data,
const uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessage(%s, %s)", address, data);
+ OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessage(%s, %p)", address, data);
VERIFY_NON_NULL(address, TAG, "address is null");
VERIFY_NON_NULL(data, TAG, "data is null");
return CALEClientSendUnicastMessageImpl(address, data, dataLen);
}
-CAResult_t CALEClientSendMulticastMessage(const char* data, const uint32_t dataLen)
+CAResult_t CALEClientSendMulticastMessage(const uint8_t* data,
+ const uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "CALEClientSendMulticastMessage(%s)", data);
+ OIC_LOG_V(DEBUG, TAG, "CALEClientSendMulticastMessage(%p)", data);
VERIFY_NON_NULL(data, TAG, "data is null");
if (!g_jvm)
g_clientErrorCallback = callback;
}
-CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const char* data,
+CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* data,
const uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessageImpl, address: %s, data: %s", address,
+ OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessageImpl, address: %s, data: %p", address,
data);
VERIFY_NON_NULL(address, TAG, "address is null");
VERIFY_NON_NULL(data, TAG, "data is null");
(*g_jvm)->DetachCurrentThread(g_jvm);
}
- ret = CALECheckSendState(address);
- if(CA_STATUS_OK != ret)
- {
- OIC_LOG(ERROR, TAG, "send has failed");
- goto error_exit;
- }
-
// start LE Scan again
ret = CALEClientStartScan();
if (CA_STATUS_OK != ret)
{
OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
ca_mutex_unlock(g_threadSendMutex);
+ if (isAttached)
+ {
+ (*g_jvm)->DetachCurrentThread(g_jvm);
+ }
return res;
}
{
(*g_jvm)->DetachCurrentThread(g_jvm);
}
+
+ if (g_clientErrorCallback)
+ {
+ g_clientErrorCallback(address, data, dataLen, CA_SEND_FAILED);
+ }
ca_mutex_unlock(g_threadSendMutex);
return CA_SEND_FAILED;
}
-CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const char* data,
+CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data,
const uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %s, %d", data, dataLen);
+ OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %p, %u", data, dataLen);
VERIFY_NON_NULL(data, TAG, "data is null");
VERIFY_NON_NULL(env, TAG, "env is null");
{
(*env)->DeleteGlobalRef(env, g_sendBuffer);
}
- jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
- (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
- g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
+
+ if (0 == u_arraylist_length(g_deviceList))
+ {
+ // Wait for LE peripherals to be discovered.
+
+ // Number of times to wait for discovery to complete.
+ static size_t const RETRIES = 5;
+
+ static uint64_t const TIMEOUT =
+ 2 * MICROSECS_PER_SEC; // Microseconds
+
+ bool devicesDiscovered = false;
+ for (size_t i = 0;
+ 0 == u_arraylist_length(g_deviceList) && i < RETRIES;
+ ++i)
+ {
+ if (ca_cond_wait_for(g_deviceDescCond,
+ g_threadSendMutex,
+ TIMEOUT) == 0)
+ {
+ devicesDiscovered = true;
+ }
+ }
+
+ if (!devicesDiscovered)
+ {
+ goto error_exit;
+ }
+ }
// connect to gatt server
CAResult_t res = CALEClientStopScan();
ca_mutex_unlock(g_threadSendMutex);
return res;
}
-
uint32_t length = u_arraylist_length(g_deviceList);
g_targetCnt = length;
- if (0 == length)
- {
- goto error_exit;
- }
+
+ jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
+ (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
+ g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
for (uint32_t index = 0; index < length; index++)
{
res = CALEClientSendData(env, jarrayObj);
if (res != CA_STATUS_OK)
{
- OIC_LOG(ERROR, TAG, "BT device[%d] - send has failed");
+ OIC_LOG(ERROR, TAG, "BT device - send has failed");
}
jstring jni_address = CALEGetAddressFromBTDevice(env, jarrayObj);
continue;
}
- res = CALECheckSendState(address);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG_V(INFO, TAG, "multicast : send has failed for this device[%s]", address);
- g_clientErrorCallback(address, data, dataLen, res);
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
- continue;
- }
-
(*env)->ReleaseStringUTFChars(env, jni_address, address);
}
else
{
OIC_LOG(DEBUG, TAG, "startLeScan is started");
- g_isStartedScan = true;
+ CALEClientSetScanFlag(true);
}
return CA_STATUS_OK;
else
{
OIC_LOG(DEBUG, TAG, "startLeScan With UUID is started");
- g_isStartedScan = true;
+ CALEClientSetScanFlag(true);
}
return CA_STATUS_OK;
}
else
{
- g_isStartedScan = false;
+ CALEClientSetScanFlag(false);
}
if (isAttached)
return ret;
}
+void CALEClientSetScanFlag(bool flag)
+{
+ ca_mutex_lock(g_scanMutex);
+ g_isStartedScan = flag;
+ ca_mutex_unlock(g_scanMutex);
+}
+
CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
{
OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl");
{
jobject gdevice = (*env)->NewGlobalRef(env, device);
u_arraylist_add(g_deviceList, gdevice);
+ ca_cond_signal(g_deviceDescCond);
OIC_LOG(DEBUG, TAG, "Set Object to Array as Element");
}
(*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, address, remoteAddress);
- CALEClientReorderingList(index, g_deviceList);
+ if (NULL == u_arraylist_remove(g_deviceList, index))
+ {
+ OIC_LOG(ERROR, TAG, "List removal failed.");
+ ca_mutex_unlock(g_deviceListMutex);
+ return CA_STATUS_FAILED;
+ }
ca_mutex_unlock(g_deviceListMutex);
return CA_STATUS_OK;
}
(*env)->DeleteGlobalRef(env, jarrayObj);
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
+
+ if (NULL == u_arraylist_remove(g_gattObjectList, index))
+ {
+ OIC_LOG(ERROR, TAG, "List removal failed.");
+ ca_mutex_unlock(g_gattObjectMutex);
+ return CA_STATUS_FAILED;
+ }
ca_mutex_unlock(g_gattObjectMutex);
- return CALEClientReorderingList(index, g_gattObjectList);
+ return CA_STATUS_OK;
}
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
+ if (NULL == u_arraylist_remove(g_gattObjectList, index))
+ {
+ OIC_LOG(ERROR, TAG, "List removal failed.");
+ ca_mutex_unlock(g_gattObjectMutex);
+ return CA_STATUS_FAILED;
+ }
ca_mutex_unlock(g_gattObjectMutex);
- return CALEClientReorderingList(index, g_gattObjectList);
+ return CA_STATUS_OK;
}
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
OIC_LOG_V(DEBUG, TAG, "remove state : %s", remoteAddress);
OICFree(state);
- CAResult_t res = CALEClientReorderingList(index, g_deviceStateList);
- if(CA_STATUS_OK != res)
+ if (NULL == u_arraylist_remove(g_deviceStateList, index))
{
- OIC_LOG(ERROR, TAG, "CALEClientReorderingList has failed");
- return res;
+ OIC_LOG(ERROR, TAG, "List removal failed.");
+ return CA_STATUS_FAILED;
}
+
return CA_STATUS_OK;
}
}
}
}
-CAResult_t CALEClientReorderingList(uint32_t index, u_arraylist_t *list)
-{
- if (!list)
- {
- OIC_LOG(ERROR, TAG, "list is null");
- return CA_STATUS_FAILED;
- }
-
- if (index >= list->length)
- {
- OIC_LOG(ERROR, TAG, "index is not available");
- return CA_STATUS_FAILED;
- }
-
- if (index < list->length - 1)
- {
- memmove(&list->data[index], &list->data[index + 1],
- (list->length - index - 1) * sizeof(void *));
- }
-
- list->size--;
- list->length--;
-
- return CA_STATUS_OK;
-}
-
/**
* Check Sent Count for remove g_sendBuffer
*/
}
}
+ if (NULL == g_scanMutex)
+ {
+ g_scanMutex = ca_mutex_new();
+ if (NULL == g_scanMutex)
+ {
+ OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
+ return CA_STATUS_FAILED;
+ }
+ }
+
OIC_LOG(DEBUG, TAG, "OUT");
return CA_STATUS_OK;
}
ca_mutex_free(g_SendFinishMutex);
g_SendFinishMutex = NULL;
+ ca_mutex_free(g_scanMutex);
+ g_scanMutex = NULL;
+
OIC_LOG(DEBUG, TAG, "OUT");
}
CALEClientTerminate();
}
-CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const char *data,
+CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const uint8_t *data,
uint32_t dataLen, CALETransferType_t type,
int32_t position)
{
return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
}
-CAResult_t CAUpdateCharacteristicsToAllGattServers(const char *data, uint32_t dataLen)
+CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
{
OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
VERIFY_NON_NULL(data, TAG, "data is null");
goto error_exit;
}
}
- else if (GATT_SUCCESS == status && STATE_DISCONNECTED == newstate) // le disconnected
+ else // le disconnected
{
CAResult_t res = CALEClientStartScan();
if (CA_STATUS_OK != res)
{
OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
+ goto error_exit;
}
jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
if (!jni_address)
{
OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
+ goto error_exit;
}
const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
if (address)
{
- res = CALEClientUpdateDeviceState(address, STATE_DISCONNECTED,
- STATE_CHARACTER_NO_CHANGE,
- STATE_SEND_NONE);
+ res = CALEClientRemoveDeviceState(address);
if (CA_STATUS_OK != res)
{
- OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
+ OIC_LOG(ERROR, TAG, "CALEClientRemoveDeviceState has failed");
+ goto error_exit;
}
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
- }
-
- res = CALEClientGattClose(env, gatt);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
- }
- }
- else // error
- {
- // update state
- jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
- if (!jni_address)
- {
- OIC_LOG(ERROR, TAG, "jni_address is null");
- goto error_exit;
-
- }
- const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
- if (address)
- {
- CAResult_t res = CALEClientUpdateDeviceState(address, STATE_DISCONNECTED,
- STATE_CHARACTER_NO_CHANGE,
- STATE_SEND_FAILED);
+ res = CALEClientRemoveGattObjForAddr(env, jni_address);
if (CA_STATUS_OK != res)
{
- OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
+ OIC_LOG(ERROR, TAG, "CALEClientRemoveGattObjForAddr has failed");
+ goto error_exit;
}
+
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
}
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
- CAResult_t res = CALEClientGattClose(env, gatt);
+ res = CALEClientGattClose(env, gatt);
if (CA_STATUS_OK != res)
{
OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
}
-
- goto error_exit;
}
return;
{
OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
}
+
+ if (g_clientErrorCallback)
+ {
+ jint length = (*env)->GetArrayLength(env, data);
+ g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
+ }
+
CALEClientSendFinish(env, gatt);
}
else
VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
VERIFY_NON_NULL_VOID(data, TAG, "data is null");
- // get Byte Array and covert to char*
+ // get Byte Array and convert to uint8_t*
jint length = (*env)->GetArrayLength(env, data);
jboolean isCopy;
jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
- OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - raw data received : %s",
+ OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - raw data received : %p",
jni_byte_responseData);
- char* receivedData = (char*) OICMalloc(sizeof(char) * length + 1);
+ uint8_t* receivedData = OICMalloc(length);
if (!receivedData)
{
- OIC_LOG(ERROR, TAG, "recevicedData is null");
+ OIC_LOG(ERROR, TAG, "receivedData is null");
return;
}
- memcpy(receivedData, (const char*) jni_byte_responseData, length);
- receivedData[length] = '\0';
+ memcpy(receivedData, jni_byte_responseData, length);
(*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
return;
}
- OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %s, %d",
+ OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
receivedData, length);
ca_mutex_lock(g_bleServerBDAddressMutex);
* @param[in] data Data received from remote device.
* @pre Callback must be registered using CALESetCallback(CAPacketReceiveCallback callback)
*/
-typedef void (*CAPacketReceiveCallback)(const char *address, const char *data);
+typedef void (*CAPacketReceiveCallback)(const char *address, const uint8_t *data);
/**
* initialize JNI object.
* @param[in] dataLen data length.
* @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
-CAResult_t CALEClientSendUnicastMessage(const char *address, const char *data,
+CAResult_t CALEClientSendUnicastMessage(const char *address, const uint8_t *data,
const uint32_t dataLen);
/**
* @param[in] dataLen data length.
* @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
-CAResult_t CALEClientSendMulticastMessage(const char *data, const uint32_t dataLen);
+CAResult_t CALEClientSendMulticastMessage(const uint8_t *data, const uint32_t dataLen);
/**
* start unicast server.
* @param[in] dataLen data length.
* @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
-CAResult_t CALEClientSendUnicastMessageImpl(const char *address, const char *data,
+CAResult_t CALEClientSendUnicastMessageImpl(const char *address, const uint8_t *data,
const uint32_t dataLen);
/**
* @param[in] dataLen data length.
* @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
-CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const char *data,
+CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t *data,
const uint32_t dataLen);
/**
CAResult_t CALEClientStopScan();
/**
+ * set ble scanning flag.
+ * @param[in] flag scan flag.
+ */
+void CALEClientSetScanFlag(bool flag);
+
+/**
* stop scan (implement).
* @param[in] env JNI interface pointer.
* @param[in] callback callback to receive device object by scanning.
void CALEClientCreateDeviceList();
/**
- * Reordering for device state list.
- * @param[in] index index of device list that want to reordering.
- * @param[in] list the list to reorder.
- * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
- */
-CAResult_t CALEClientReorderingList(uint32_t index, u_arraylist_t *list);
-
-/**
* update the counter which data is sent to remote device.
* @param[in] env JNI interface pointer.
*/
if (!gCALEDeviceStateChangedCallback)
{
OIC_LOG_V(ERROR, TAG, "gNetworkChangeCb is null", status);
+ return;
}
if (BT_STATE_ON == status) // STATE_ON:12
{
CANetworkStatus_t newStatus = CA_INTERFACE_UP;
+ CALEClientCreateDeviceList();
+ CALEServerCreateCachedDeviceList();
+
+ CAResult_t res = CALEClientStartScan();
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
+ }
+
+ res = CALEStartAdvertise();
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEStartAdvertise has failed");
+ }
+
gCALEDeviceStateChangedCallback(newStatus);
}
else if (BT_STATE_OFF == status) // STATE_OFF:10
OIC_LOG(ERROR, TAG, "CALEClientRemoveAllScanDevices has failed");
}
+ res = CALEClientRemoveAllDeviceState();
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientRemoveAllDeviceState has failed");
+ }
+
// remove obej for server
res = CALEServerRemoveAllDevices(env);
if (CA_STATUS_OK != res)
OIC_LOG(ERROR, TAG, "CALEServerRemoveAllDevices has failed");
}
+ CALEClientSetScanFlag(false);
+
CANetworkStatus_t newStatus = CA_INTERFACE_DOWN;
gCALEDeviceStateChangedCallback(newStatus);
}
jclass jni_cid_bluetoothGattCharacteristic = (*env)->FindClass(env, "android/bluetooth/"
"BluetoothGattCharacteristic");
- if (!jni_cid_bluetoothGattService)
+ if (!jni_cid_bluetoothGattCharacteristic)
{
OIC_LOG(ERROR, TAG, "jni_cid_bluetoothGattCharacteristic is null");
return NULL;
"getService",
"(Ljava/util/UUID;)Landroid/bluetooth/"
"BluetoothGattService;");
- if (!jni_cid_bluetoothGattService)
+ if (!jni_mid_getService)
{
OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
return NULL;
return CA_STATUS_OK;
}
+CAResult_t CALEStartAdvertise()
+{
+ if (!g_jvm)
+ {
+ OIC_LOG(ERROR, TAG, "g_jvm is null");
+ return CA_STATUS_FAILED;
+ }
+
+ bool isAttached = false;
+ JNIEnv* env;
+ jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+ if (JNI_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
+ res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
+
+ if (JNI_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
+ return CA_STATUS_FAILED;
+ }
+ isAttached = true;
+ }
+
+ // start advertise
+ CAResult_t ret = CALEServerStartAdvertise(env, g_leAdvertiseCallback);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed");
+ }
+
+ if (isAttached)
+ {
+ (*g_jvm)->DetachCurrentThread(g_jvm);
+ }
+ return ret;
+}
+
CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback)
{
OIC_LOG(DEBUG, TAG, "IN - CALEServerStartAdvertise");
"getDefaultAdapter",
"()Landroid/bluetooth/"
"BluetoothAdapter;");
- if (!jni_cid_leAdvertiser)
+ if (!jni_mid_getDefaultAdapter)
{
- OIC_LOG(ERROR, TAG, "jni_cid_leAdvertiser is null");
+ OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
return CA_STATUS_FAILED;
}
isAttached = true;
}
- CAResult_t ret = CALEServerStopMulticastServer(0);
+ CAResult_t ret = CALEServerGattClose(env, g_bluetoothGattServer);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG(ERROR, TAG, "CALEServerGattClose has failed");
+ }
+
+ ret = CALEServerStopMulticastServer(0);
if (CA_STATUS_OK != ret)
{
OIC_LOG(ERROR, TAG, "CALEServerStopMulticastServer has failed");
OIC_LOG(DEBUG, TAG, "OUT - CALEServerTerminate");
}
-CAResult_t CALEServerSendUnicastMessage(const char* address, const char* data, uint32_t dataLen)
+CAResult_t CALEServerSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "IN - CALEServerSendUnicastMessage(%s, %s)", address, data);
+ OIC_LOG_V(DEBUG, TAG, "IN - CALEServerSendUnicastMessage(%s, %p)", address, data);
VERIFY_NON_NULL(address, TAG, "address is null");
VERIFY_NON_NULL(data, TAG, "data is null");
return ret;
}
-CAResult_t CALEServerSendMulticastMessage(const char* data, uint32_t dataLen)
+CAResult_t CALEServerSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "IN - CALEServerSendMulticastMessage(%s)", data);
+ OIC_LOG_V(DEBUG, TAG, "IN - CALEServerSendMulticastMessage(%p)", data);
VERIFY_NON_NULL(data, TAG, "data is null");
if (!g_jvm)
g_packetReceiveCallback = callback;
}
-CAResult_t CALEServerSendUnicastMessageImpl(JNIEnv *env, const char* address, const char* data,
+CAResult_t CALEServerSendUnicastMessageImpl(JNIEnv *env, const char* address, const uint8_t* data,
uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "IN - CALEServerSendUnicastMessageImpl, address: %s, data: %s",
+ OIC_LOG_V(DEBUG, TAG, "IN - CALEServerSendUnicastMessageImpl, address: %s, data: %p",
address, data);
VERIFY_NON_NULL(env, TAG, "env is null");
VERIFY_NON_NULL(address, TAG, "address is null");
return CA_STATUS_OK;
}
-CAResult_t CALEServerSendMulticastMessageImpl(JNIEnv *env, const char *data, uint32_t dataLen)
+CAResult_t CALEServerSendMulticastMessageImpl(JNIEnv *env, const uint8_t *data, uint32_t dataLen)
{
OIC_LOG_V(DEBUG, TAG, "IN - CALEServerSendMulticastMessageImpl, send to, data: %s", data);
VERIFY_NON_NULL(env, TAG, "env is null");
(*env)->ReleaseStringUTFChars(env, address, remoteAddress);
(*env)->DeleteGlobalRef(env, jarrayObj);
- CAResult_t res = CALEServerReorderinglist(index);
- if (CA_STATUS_OK != res)
+ if (NULL == u_arraylist_remove(g_connectedDeviceList, index))
{
- OIC_LOG(ERROR, TAG, "CALEServerReorderinglist has failed");
+ OIC_LOG(ERROR, TAG, "List removal failed.");
ca_mutex_unlock(g_connectedDeviceListMutex);
- return res;
+ return CA_STATUS_FAILED;
}
ca_mutex_unlock(g_connectedDeviceListMutex);
return CA_STATUS_OK;
return CA_STATUS_FAILED;
}
-CAResult_t CALEServerReorderinglist(uint32_t index)
-{
- if (!g_connectedDeviceList)
- {
- OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null");
- return CA_STATUS_FAILED;
- }
-
- if (index >= g_connectedDeviceList->length)
- {
- OIC_LOG(ERROR, TAG, "index is not available");
- return CA_STATUS_FAILED;
- }
-
- if (index < g_connectedDeviceList->length - 1)
- {
- memmove(&g_connectedDeviceList->data[index], &g_connectedDeviceList->data[index + 1],
- (g_connectedDeviceList->length - index - 1) * sizeof(void *));
- }
-
- g_connectedDeviceList->size--;
- g_connectedDeviceList->length--;
-
- return CA_STATUS_OK;
-}
-
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeServerInterface_caLeRegisterGattServerCallback(JNIEnv *env, jobject obj,
jobject callback)
else if (newState == jni_int_state_disconnected)
{
OIC_LOG(DEBUG, TAG, "LE DISCONNECTED");
- CAResult_t res = CALEServerGattClose(env, g_bluetoothGattServer);
- if (CA_STATUS_OK != res)
+
+ jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
+ CAResult_t ret = CALEServerRemoveDevice(env, jni_remoteAddress);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG(ERROR, TAG, "CALEServerRemoveDevice has failed");
+ }
+
+ // start advertise
+ ret = CALEServerStartAdvertise(env, g_leAdvertiseCallback);
+ if (CA_STATUS_OK != ret)
{
- OIC_LOG(ERROR, TAG, "CALEServerGattClose has failed");
+ OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed");
}
}
else
VERIFY_NON_NULL_VOID(device, TAG, "device");
VERIFY_NON_NULL_VOID(data, TAG, "data");
- // get Byte Array and covert to char*
+ // get Byte Array and covert to uint8_t*
jint length = (*env)->GetArrayLength(env, data);
jboolean isCopy;
jbyte *jni_byte_requestData = (jbyte *) (*env)->GetByteArrayElements(env, data, &isCopy);
- char* requestData = NULL;
- requestData = (char*) OICMalloc(sizeof(char) * length + 1);
+ uint8_t* requestData = NULL;
+ requestData = OICMalloc(length);
if (!requestData)
{
OIC_LOG(ERROR, TAG, "requestData is null");
return;
}
- memcpy(requestData, (const char*) jni_byte_requestData, length);
- requestData[length] = '\0';
+ memcpy(requestData, jni_byte_requestData, length);
(*env)->ReleaseByteArrayElements(env, data, jni_byte_requestData, JNI_ABORT);
jstring jni_address = CALEGetAddressFromBTDevice(env, device);
return;
}
- OIC_LOG_V(DEBUG, TAG, "remote device address : %s, %s, %d", address, requestData, length);
+ OIC_LOG_V(DEBUG, TAG, "remote device address : %s, %p, %d", address, requestData, length);
ca_mutex_lock(g_bleClientBDAddressMutex);
uint32_t sentLength = 0;
VERIFY_NON_NULL_VOID(env, TAG, "env");
VERIFY_NON_NULL_VOID(obj, TAG, "obj");
- OIC_LOG_V(ERROR, TAG, "LE Advertise Start Failure Callback(%d)",
- errorCode);
+ OIC_LOG_V(INFO, TAG, "LE Advertise Start Failure Callback(%d)", errorCode);
}
/**
}
CAResult_t CAUpdateCharacteristicsToGattClient(const char *address,
- const char *charValue,
+ const uint8_t *charValue,
uint32_t charValueLen)
{
CAResult_t result = CA_SEND_FAILED;
return result;
}
-CAResult_t CAUpdateCharacteristicsToAllGattClients(const char *charValue,
+CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *charValue,
uint32_t charValueLen)
{
OIC_LOG(DEBUG, TAG, "IN");
* @param[in] data Data received from remote device.
* @pre Callback must be registered using CALEServerSetCallback(CAPacketReceiveCallback callback).
*/
-typedef void (*CAPacketReceiveCallback)(const char *address, const char *data);
+typedef void (*CAPacketReceiveCallback)(const char *address, const uint8_t *data);
/**
* initialize server for BLE.
* @param[in] dataLen data length.
* @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
-CAResult_t CALEServerSendUnicastMessage(const char *address, const char *data, uint32_t dataLen);
+CAResult_t CALEServerSendUnicastMessage(const char *address, const uint8_t *data, uint32_t dataLen);
/**
* send data for multicast (interface).
* @param[in] dataLen data length.
* @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
-CAResult_t CALEServerSendMulticastMessage(const char *data, uint32_t dataLen);
+CAResult_t CALEServerSendMulticastMessage(const uint8_t *data, uint32_t dataLen);
/**
* start multicast server (start advertise).
* @param[in] dataLen data length.
* @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
-CAResult_t CALEServerSendUnicastMessageImpl(JNIEnv *env, const char *address, const char *data,
+CAResult_t CALEServerSendUnicastMessageImpl(JNIEnv *env, const char *address, const uint8_t *data,
uint32_t dataLen);
/**
* @param[in] dataLen data length
* @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
-CAResult_t CALEServerSendMulticastMessageImpl(JNIEnv *env, const char *data, uint32_t dataLen);
+CAResult_t CALEServerSendMulticastMessageImpl(JNIEnv *env, const uint8_t *data, uint32_t dataLen);
/**
* set context of application.
/**
* start advertise in gatt server.
+ */
+CAResult_t CALEStartAdvertise();
+
+/**
+ * start advertise in gatt server.
* @param[in] env JNI interface pointer.
* @param[in] advertiseCallback callback to be notified on reception of
* advertisement result.
CAResult_t CALEServerRemoveDevice(JNIEnv *env, jstring address);
/**
- * Reordering for the list (connected device list).
- * @param[in] index index of device list that want to reordering.
- * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
- */
-CAResult_t CALEServerReorderinglist(uint32_t index);
-
-/**
* initialize mutex.
* @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
#define MAX_EVENT_COUNT 20
static bool g_serverRunning = false;
-static char *g_coapBuffer = NULL;
+static uint8_t *g_coapBuffer = NULL;
/**
* @var g_receivedDataLen
if (NULL == g_coapBuffer)
{
OIC_LOG(DEBUG, TAG, "IN");
- char headerArray[CA_HEADER_LENGTH] = "";
+ uint8_t headerArray[CA_HEADER_LENGTH];
while (CAIsLEDataAvailable() && g_receivedDataLen < CA_HEADER_LENGTH)
{
headerArray[g_receivedDataLen++] = CALEReadData();
}
- g_packetDataLen = CAParseHeader(headerArray);
+ g_packetDataLen = CAParseHeader(headerArray, CA_HEADER_LENGTH);
if (g_packetDataLen > COAP_MAX_PDU_SIZE)
{
return;
}
- g_coapBuffer = (char *)OICCalloc((size_t)g_packetDataLen, sizeof(char));
+ g_coapBuffer = (uint8_t *)OICCalloc((size_t)g_packetDataLen, 1);
if (NULL == g_coapBuffer)
{
OIC_LOG(ERROR, TAG, "malloc");
if (g_receivedDataLen == g_packetDataLen)
{
OIC_LOG(DEBUG, TAG, "Read Comp BLE Pckt");
- g_coapBuffer[g_receivedDataLen] = '\0';
if (g_receivedDataLen > 0)
{
- OIC_LOG_V(DEBUG, TAG, "recv dataLen=%d", g_receivedDataLen);
+ OIC_LOG_V(DEBUG, TAG, "recv dataLen=%u", g_receivedDataLen);
uint32_t sentLength = 0;
// g_coapBuffer getting freed by CAMesssageHandler
g_bleServerDataReceivedCallback("", g_coapBuffer,
{
return ble_connected();
}
-char CALEReadData()
+
+uint8_t CALEReadData()
{
- return (char)ble_read();
+ return (uint8_t)ble_read();
}
CAResult_t CALEDoEvents()
return CA_STATUS_OK;
}
-CAResult_t CAUpdateCharacteristicsToAllGattClients(const char *char_value,
+CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *char_value,
uint32_t valueLength)
{
// ble_write_bytes() api can send only max of 255 bytes at a time
* API to read data from BLE shield.
* @return - Data read.
*/
-char CALEReadData();
+uint8_t CALEReadData();
/**
* API to perform BLE events.
*/
typedef struct
{
- CAEndpoint_t *remoteEndpoint; /**< Remote endpoint contains the
- information of remote device. */
- void *data; /**< Data to be transmitted over LE transport. */
- uint32_t dataLen; /**< Length of the data being transmitted. */
+ /// Remote endpoint contains the information of remote device.
+ CAEndpoint_t *remoteEndpoint;
+
+ /// Data to be transmitted over LE transport.
+ uint8_t *data;
+
+ /// Length of the data being transmitted.
+ uint32_t dataLen;
} CALEData_t;
/**
{
uint32_t recvDataLen;
uint32_t totalDataLen;
- char *defragData;
+ uint8_t *defragData;
CAEndpoint_t *remoteEndpoint;
} CABLESenderInfo_t;
* @param[in] adapter_state New state of the adapter to be notified to
* the upper layer.
*/
-static void CALEDeviceStateChangedCb( CAAdapterState_t adapter_state);
+static void CALEDeviceStateChangedCb(CAAdapterState_t adapter_state);
/**
* Used to initialize all required mutex variable for LE Adapter
/**
* Prepares and notify error through error callback.
- *
*/
static void CALEErrorHandler(const char *remoteAddress,
- const void *data,
+ const uint8_t *data,
uint32_t dataLen,
CAResult_t result);
static CAQueueingThread_t *g_bleServerSendQueueHandle = NULL;
/**
- * Starting LE connectivity adapters.
- *
- * As its peer to peer it does not require to start any servers.
- *
- * @return ::CA_STATUS_OK or Appropriate error code.
- */
-static CAResult_t CAStartLE();
-
-/**
- * Start listening server for receiving multicast search requests.
- *
- * Transport Specific Behavior:
- * LE Starts GATT Server with prefixed UUID and Characteristics
- * per OIC Specification.
- * @return ::CA_STATUS_OK or Appropriate error code.
- */
-static CAResult_t CAStartLEListeningServer();
-
-/**
- * Sarting discovery of servers for receiving multicast
- * advertisements.
- *
- * Transport Specific Behavior:
- * LE Starts GATT Server with prefixed UUID and Characteristics
- * per OIC Specification.
- *
- * @return ::CA_STATUS_OK or Appropriate error code
- */
-static CAResult_t CAStartLEDiscoveryServer();
-
-/**
- * Send data to the endpoint using the adapter connectivity.
- *
- * @param[in] endpoint Remote Endpoint information (like MAC address,
- * reference URI and connectivity type) to which
- * the unicast data has to be sent.
- * @param[in] data Data which required to be sent.
- * @param[in] dataLen Size of data to be sent.
- *
- * @note dataLen must be > 0.
- *
- * @return The number of bytes sent on the network, or -1 on error.
- */
-static int32_t CASendLEUnicastData(const CAEndpoint_t *endpoint,
- const void *data,
- uint32_t dataLen);
-
-/**
- * Send multicast data to the endpoint using the LE connectivity.
- *
- * @param[in] endpoint Remote Endpoint information to which the
- * multicast data has to be sent.
- * @param[in] data Data which required to be sent.
- * @param[in] dataLen Size of data to be sent.
- *
- * @note dataLen must be > 0.
- *
- * @return The number of bytes sent on the network, or -1 on error.
- */
-static int32_t CASendLEMulticastData(const CAEndpoint_t *endpoint,
- const void *data,
- uint32_t dataLen);
-
-/**
- * Get LE Connectivity network information.
- *
- * @param[out] info Local connectivity information structures.
- * @param[out] size Number of local connectivity structures.
- *
- * @return ::CA_STATUS_OK or Appropriate error code.
- */
-static CAResult_t CAGetLEInterfaceInformation(CAEndpoint_t **info,
- uint32_t *size);
-
-/**
- * Read Synchronous API callback.
- *
- * @return ::CA_STATUS_OK or Appropriate error code.
- */
-static CAResult_t CAReadLEData();
-
-/**
- * Stopping the adapters and close socket connections.
- *
- * LE Stops all GATT servers and GATT Clients.
- *
- * @return ::CA_STATUS_OK or Appropriate error code.
- */
-static CAResult_t CAStopLE();
-
-/**
- * Terminate the LE connectivity adapter.
- *
- * Configuration information will be deleted from further use.
- */
-static void CATerminateLE();
-
-/**
- * This function will receive the data from the GattServer and add the
- * data to the Server receiver queue.
- *
- * @param[in] remoteAddress Remote address of the device from where
- * data is received.
- * @param[in] data Actual data recevied from the remote
- * device.
- * @param[in] dataLength Length of the data received from the
- * remote device.
- * @param[in] sentLength Length of the data sent from the remote
- * device.
- *
- * @return ::CA_STATUS_OK or Appropriate error code.
- * @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
- * @retval ::CA_STATUS_FAILED Operation failed.
- *
- */
-static CAResult_t CALEAdapterServerReceivedData(const char *remoteAddress,
- const void *data,
- uint32_t dataLength,
- uint32_t *sentLength);
-
-/**
- * This function will receive the data from the GattClient and add the
- * data into the Client receiver queue.
- *
- * @param[in] remoteAddress Remote address of the device from where
- * data is received.
- * @param[in] data Actual data recevied from the remote
- * device.
- * @param[in] dataLength Length of the data received from the
- * remote device.
- * @param[in] sentLength Length of the data sent from the remote
- * device.
- *
- * @return ::CA_STATUS_OK or Appropriate error code.
- * @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
- * @retval ::CA_STATUS_FAILED Operation failed.
- */
-static CAResult_t CALEAdapterClientReceivedData(const char *remoteAddress,
- const void *data,
- uint32_t dataLength,
- uint32_t *sentLength);
-
-/**
- * Set the NetworkPacket received callback to CA layer from adapter
- * layer.
- *
- * @param[in] callback Callback handle sent from the upper layer.
- */
-static void CASetLEReqRespAdapterCallback(CANetworkPacketReceivedCallback callback);
-
-/**
- * Push the data from CA layer to the Sender processor queue.
- *
- * @param[in] remoteEndpoint Remote endpoint information of the
- * server.
- * @param[in] data Data to be transmitted from LE.
- * @param[in] dataLen Length of the Data being transmitted.
- *
- * @return ::CA_STATUS_OK or Appropriate error code.
- * @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
- * @retval ::CA_STATUS_FAILED Operation failed.
- */
-static CAResult_t CALEAdapterServerSendData(const CAEndpoint_t *remoteEndpoint,
- const void *data,
- uint32_t dataLen);
-
-/**
- * Push the data from CA layer to the Sender processor queue.
- *
- * @param[in] remoteEndpoint Remote endpoint information of the
- * server.
- * @param[in] data Data to be transmitted from LE.
- * @param[in] dataLen Length of the Data being transmitted.
- *
- * @return ::CA_STATUS_OK or Appropriate error code.
- * @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
- * @retval ::CA_STATUS_FAILED Operation failed.
- */
-static CAResult_t CALEAdapterClientSendData(const CAEndpoint_t *remoteEndpoint,
- const void *data,
- uint32_t dataLen);
-
-/**
* This function will be associated with the sender queue for
* GattServer.
*
* @retval ::CA_STATUS_FAILED Operation failed.
*/
static CALEData_t *CACreateLEData(const CAEndpoint_t *remoteEndpoint,
- const void *data,
+ const uint8_t *data,
uint32_t dataLength);
/**
OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
}
-static CAResult_t CALEGetSenderInfo(char *leAddress,
+static CAResult_t CALEGetSenderInfo(const char *leAddress,
CABLESenderInfo_t **senderInfo,
uint32_t *senderIndex)
{
- VERIFY_NON_NULL_RET(leAddress, CALEADAPTER_TAG, "Ble-Address in-param NULL", CA_STATUS_FAILED);
- VERIFY_NON_NULL_RET(senderIndex, CALEADAPTER_TAG, "Index in-param NULL", CA_STATUS_FAILED);
-
- uint32_t listLength = u_arraylist_length(g_senderInfo);
- uint32_t addrLength = strlen(leAddress);
+ VERIFY_NON_NULL_RET(leAddress,
+ CALEADAPTER_TAG,
+ "NULL BLE address argument",
+ CA_STATUS_INVALID_PARAM);
+ VERIFY_NON_NULL_RET(senderIndex,
+ CALEADAPTER_TAG,
+ "NULL index argument",
+ CA_STATUS_INVALID_PARAM);
+
+ const uint32_t listLength = u_arraylist_length(g_senderInfo);
+ const uint32_t addrLength = strlen(leAddress);
for (uint32_t index = 0; index < listLength; index++)
{
CABLESenderInfo_t *info = (CABLESenderInfo_t *) u_arraylist_get(g_senderInfo, index);
if(!senderInfo)
{
- CABLESenderInfo_t *newSender = (CABLESenderInfo_t*)OICMalloc(sizeof(CABLESenderInfo_t));
+ CABLESenderInfo_t *newSender = OICMalloc(sizeof(CABLESenderInfo_t));
if(!newSender)
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed for new sender");
newSender->remoteEndpoint = NULL;
OIC_LOG(DEBUG, CALEADAPTER_TAG, "Parsing the header");
- newSender->totalDataLen = CAParseHeader((char*)bleData->data);
+ newSender->totalDataLen = CAParseHeader(bleData->data,
+ bleData->dataLen);
if(!(newSender->totalDataLen))
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Total Data Length is parsed as 0!!!");
OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "data received in the first packet [%u] bytes",
bleData->dataLen);
- newSender->defragData = (char *) OICCalloc(newSender->totalDataLen + 1, sizeof(char));
+ newSender->defragData = OICCalloc(newSender->totalDataLen + 1,
+ sizeof(*newSender->defragData));
if (NULL == newSender->defragData)
{
ca_mutex_unlock(g_bleReceiveDataMutex);
return;
}
+
OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending data up !");
- g_networkPacketReceivedCallback(senderInfo->remoteEndpoint,
- senderInfo->defragData, senderInfo->recvDataLen);
+
+ const CASecureEndpoint_t tmp =
+ {
+ .endpoint = *senderInfo->remoteEndpoint
+ };
+
+ g_networkPacketReceivedCallback(&tmp,
+ senderInfo->defragData,
+ senderInfo->recvDataLen);
ca_mutex_unlock(g_bleAdapterReqRespCbMutex);
u_arraylist_remove(g_senderInfo, senderIndex);
senderInfo->remoteEndpoint = NULL;
{
OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
- CALEData_t *bleData = (CALEData_t *) threadData;
+ CALEData_t * const bleData = (CALEData_t *) threadData;
if (!bleData)
{
OIC_LOG(DEBUG, CALEADAPTER_TAG, "Invalid bledata!");
return;
}
- char *header = (char *) OICCalloc(CA_HEADER_LENGTH, sizeof(char));
+ uint8_t * const header = OICCalloc(CA_HEADER_LENGTH, 1);
VERIFY_NON_NULL_VOID(header, CALEADAPTER_TAG, "Malloc failed");
- int32_t totalLength = bleData->dataLen + CA_HEADER_LENGTH;
+ const uint32_t totalLength = bleData->dataLen + CA_HEADER_LENGTH;
+
+ OIC_LOG_V(DEBUG,
+ CALEADAPTER_TAG,
+ "Server total Data length with header is [%u]",
+ totalLength);
+
+ uint8_t * const dataSegment = OICCalloc(totalLength, 1);
- OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server total Data length with header is [%d]", totalLength);
- char *dataSegment = (char *) OICCalloc(totalLength + 1, sizeof(char));
if (NULL == dataSegment)
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failed");
return;
}
- CAResult_t result = CAGenerateHeader(header, bleData->dataLen);
+ CAResult_t result = CAGenerateHeader(header,
+ CA_HEADER_LENGTH,
+ bleData->dataLen);
if (CA_STATUS_OK != result )
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Generate header failed");
OICFree(header);
OICFree(dataSegment);
- return ;
+ return;
}
memcpy(dataSegment, header, CA_HEADER_LENGTH);
OICFree(header);
- int32_t length = 0;
+ uint32_t length = 0;
if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength)
{
length = totalLength;
CA_SUPPORTED_BLE_MTU_SIZE - CA_HEADER_LENGTH);
}
- int32_t iter = totalLength / CA_SUPPORTED_BLE_MTU_SIZE;
- int32_t index = 0;
+ uint32_t iter = totalLength / CA_SUPPORTED_BLE_MTU_SIZE;
+ uint32_t index = 0;
+
// Send the first segment with the header.
- if (NULL != bleData->remoteEndpoint) //Sending Unicast Data
+ if (NULL != bleData->remoteEndpoint) // Sending Unicast Data
{
OIC_LOG(DEBUG, CALEADAPTER_TAG, "Server Sending Unicast Data");
+
result = CAUpdateCharacteristicsToGattClient(
bleData->remoteEndpoint->addr, dataSegment, length);
+
if (CA_STATUS_OK != result)
{
- OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]", result);
- g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+ OIC_LOG_V(ERROR,
+ CALEADAPTER_TAG,
+ "Update characteristics failed, result [%d]",
+ result);
+
+ g_errorHandler(bleData->remoteEndpoint,
+ bleData->data,
+ bleData->dataLen,
+ result);
OICFree(dataSegment);
return;
}
- OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", length);
+ OIC_LOG_V(DEBUG,
+ CALEADAPTER_TAG,
+ "Server Sent data length [%u]",
+ length);
for (index = 1; index < iter; index++)
{
// Send the remaining header.
- OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Sending the chunk number [%d]", index);
- result = CAUpdateCharacteristicsToGattClient(
- bleData->remoteEndpoint->addr,
- bleData->data + ((index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH),
- CA_SUPPORTED_BLE_MTU_SIZE);
+ OIC_LOG_V(DEBUG,
+ CALEADAPTER_TAG,
+ "Sending the chunk number [%u]",
+ index);
+
+ result =
+ CAUpdateCharacteristicsToGattClient(
+ bleData->remoteEndpoint->addr,
+ bleData->data + ((index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH),
+ CA_SUPPORTED_BLE_MTU_SIZE);
if (CA_STATUS_OK != result)
{
OIC_LOG_V(ERROR, CALEADAPTER_TAG,
CA_SUPPORTED_BLE_MTU_SIZE);
}
- int32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE;
+ const uint32_t remainingLen =
+ totalLength % CA_SUPPORTED_BLE_MTU_SIZE;
+
if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
{
- // send the last segment of the data (Ex: 22 bytes of 622 bytes of data when MTU is 200)
+ // send the last segment of the data (Ex: 22 bytes of 622
+ // bytes of data when MTU is 200)
OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk");
result = CAUpdateCharacteristicsToGattClient(
bleData->remoteEndpoint->addr,
remainingLen);
if (CA_STATUS_OK != result)
{
- OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]",
- result);
- g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+ OIC_LOG_V(ERROR,
+ CALEADAPTER_TAG,
+ "Update characteristics failed, result [%d]",
+ result);
+ g_errorHandler(bleData->remoteEndpoint,
+ bleData->data,
+ bleData->dataLen,
+ result);
OICFree(dataSegment);
return;
}
OICFree(dataSegment);
return;
}
- OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]", CA_SUPPORTED_BLE_MTU_SIZE);
+ OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%u]", CA_SUPPORTED_BLE_MTU_SIZE);
}
- int32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE;
+ const uint32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE;
if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
{
// send the last segment of the data (Ex: 22 bytes of 622 bytes of data when MTU is 200)
return;
}
- char *header = (char *) OICCalloc(CA_HEADER_LENGTH, sizeof(char));
+ uint8_t * const header = OICCalloc(CA_HEADER_LENGTH, 1);
VERIFY_NON_NULL_VOID(header, CALEADAPTER_TAG, "Malloc failed");
- uint32_t totalLength = bleData->dataLen + CA_HEADER_LENGTH;
- char *dataSegment = (char *) OICCalloc(totalLength + 1, sizeof(char));
+ const uint32_t totalLength = bleData->dataLen + CA_HEADER_LENGTH;
+ uint8_t *dataSegment = OICCalloc(totalLength, 1);
if (NULL == dataSegment)
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Malloc failed");
return;
}
- CAResult_t result = CAGenerateHeader(header, bleData->dataLen);
+ CAResult_t result = CAGenerateHeader(header,
+ CA_HEADER_LENGTH,
+ bleData->dataLen);
if (CA_STATUS_OK != result )
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Generate header failed");
if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength)
{
length = totalLength;
- OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "length [%d]", length);
- memcpy(dataSegment + CA_HEADER_LENGTH, bleData->data, bleData->dataLen);
+ memcpy(dataSegment + CA_HEADER_LENGTH,
+ bleData->data,
+ bleData->dataLen);
}
else
{
length = CA_SUPPORTED_BLE_MTU_SIZE;
- OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "length [%d]", length);
- memcpy(dataSegment + CA_HEADER_LENGTH, bleData->data,
+ memcpy(dataSegment + CA_HEADER_LENGTH,
+ bleData->data,
CA_SUPPORTED_BLE_MTU_SIZE - CA_HEADER_LENGTH);
}
- uint32_t iter = totalLength / CA_SUPPORTED_BLE_MTU_SIZE;
+ const uint32_t iter = totalLength / CA_SUPPORTED_BLE_MTU_SIZE;
uint32_t index = 0;
if (NULL != bleData->remoteEndpoint) //Sending Unicast Data
{
OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending Unicast Data");
// Send the first segment with the header.
- result = CAUpdateCharacteristicsToGattServer(bleData->remoteEndpoint->addr,
- dataSegment,
- length,
- LE_UNICAST, 0);
+ result =
+ CAUpdateCharacteristicsToGattServer(
+ bleData->remoteEndpoint->addr,
+ dataSegment,
+ length,
+ LE_UNICAST,
+ 0);
if (CA_STATUS_OK != result)
{
- OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]", result);
- g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
+ OIC_LOG_V(ERROR,
+ CALEADAPTER_TAG,
+ "Update characteristics failed, result [%d]",
+ result);
+ g_errorHandler(bleData->remoteEndpoint,
+ bleData->data,
+ bleData->dataLen,
+ result);
OICFree(dataSegment);
- return ;
+ return;
}
- OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Client Sent Data length is [%d]", length);
+ OIC_LOG_V(DEBUG,
+ CALEADAPTER_TAG,
+ "Client Sent Data length is [%u]",
+ length);
+
for (index = 1; index < iter; index++)
{
// Send the remaining header.
LE_UNICAST, 0);
if (CA_STATUS_OK != result)
{
- OIC_LOG_V(ERROR, CALEADAPTER_TAG, "Update characteristics failed, result [%d]",
- result);
+ OIC_LOG_V(ERROR,
+ CALEADAPTER_TAG,
+ "Update characteristics failed, result [%d]",
+ result);
g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
OICFree(dataSegment);
return;
CA_SUPPORTED_BLE_MTU_SIZE);
}
- uint32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE;
+ const uint32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE;
if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
{
- // send the last segment of the data (Ex: 22 bytes of 622 bytes of data when MTU is 200)
+ // send the last segment of the data (Ex: 22 bytes of 622
+ // bytes of data when MTU is 200)
OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk");
result = CAUpdateCharacteristicsToGattServer(
bleData->remoteEndpoint->addr,
}
uint32_t remainingLen = totalLength % CA_SUPPORTED_BLE_MTU_SIZE;
- if ( remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
+ if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
{
- // send the last segment of the data (Ex: 22 bytes of 622 bytes of data when MTU is 200)
+ // send the last segment of the data (Ex: 22 bytes of 622
+ // bytes of data when MTU is 200)
OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk");
- result = CAUpdateCharacteristicsToAllGattServers(
- bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH,
- remainingLen);
+ result =
+ CAUpdateCharacteristicsToAllGattServers(
+ bleData->data + (index * CA_SUPPORTED_BLE_MTU_SIZE) - CA_HEADER_LENGTH,
+ remainingLen);
if (CA_STATUS_OK != result)
{
OIC_LOG_V(ERROR, CALEADAPTER_TAG,
}
static CALEData_t *CACreateLEData(const CAEndpoint_t *remoteEndpoint,
- const void *data,
+ const uint8_t *data,
uint32_t dataLength)
{
- CALEData_t *bleData = (CALEData_t *) OICMalloc(sizeof(CALEData_t));
+ CALEData_t * const bleData = OICMalloc(sizeof(CALEData_t));
+
if (!bleData)
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!");
}
bleData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
- bleData->data = (void *)OICCalloc(dataLength + 1, 1);
+ bleData->data = OICCalloc(dataLength + 1, 1);
+
if (NULL == bleData->data)
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Memory allocation failed!");
CAFreeLEData(bleData);
return NULL;
}
+
memcpy(bleData->data, data, dataLength);
bleData->dataLen = dataLength;
OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
}
+/**
+ * Starting LE connectivity adapters.
+ *
+ * As its peer to peer it does not require to start any servers.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+static CAResult_t CAStartLE();
+
+/**
+ * Start listening server for receiving multicast search requests.
+ *
+ * Transport Specific Behavior:
+ * LE Starts GATT Server with prefixed UUID and Characteristics
+ * per OIC Specification.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+static CAResult_t CAStartLEListeningServer();
+
+/**
+ * Sarting discovery of servers for receiving multicast
+ * advertisements.
+ *
+ * Transport Specific Behavior:
+ * LE Starts GATT Server with prefixed UUID and Characteristics
+ * per OIC Specification.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code
+ */
+static CAResult_t CAStartLEDiscoveryServer();
+
+/**
+ * Send data to the endpoint using the adapter connectivity.
+ *
+ * @param[in] endpoint Remote Endpoint information (like MAC address,
+ * reference URI and connectivity type) to which
+ * the unicast data has to be sent.
+ * @param[in] data Data which required to be sent.
+ * @param[in] dataLen Size of data to be sent.
+ *
+ * @note dataLen must be > 0.
+ *
+ * @return The number of bytes sent on the network, or -1 on error.
+ */
+static int32_t CASendLEUnicastData(const CAEndpoint_t *endpoint,
+ const void *data,
+ uint32_t dataLen);
+
+/**
+ * Send multicast data to the endpoint using the LE connectivity.
+ *
+ * @param[in] endpoint Remote Endpoint information to which the
+ * multicast data has to be sent.
+ * @param[in] data Data which required to be sent.
+ * @param[in] dataLen Size of data to be sent.
+ *
+ * @note dataLen must be > 0.
+ *
+ * @return The number of bytes sent on the network, or -1 on error.
+ */
+static int32_t CASendLEMulticastData(const CAEndpoint_t *endpoint,
+ const void *data,
+ uint32_t dataLen);
+
+/**
+ * Get LE Connectivity network information.
+ *
+ * @param[out] info Local connectivity information structures.
+ * @param[out] size Number of local connectivity structures.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+static CAResult_t CAGetLEInterfaceInformation(CAEndpoint_t **info,
+ uint32_t *size);
+
+/**
+ * Read Synchronous API callback.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+static CAResult_t CAReadLEData();
+
+/**
+ * Stopping the adapters and close socket connections.
+ *
+ * LE Stops all GATT servers and GATT Clients.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+static CAResult_t CAStopLE();
+
+/**
+ * Terminate the LE connectivity adapter.
+ *
+ * Configuration information will be deleted from further use.
+ */
+static void CATerminateLE();
+
+/**
+ * This function will receive the data from the GattServer and add the
+ * data to the Server receiver queue.
+ *
+ * @param[in] remoteAddress Remote address of the device from where
+ * data is received.
+ * @param[in] data Actual data recevied from the remote
+ * device.
+ * @param[in] dataLength Length of the data received from the
+ * remote device.
+ * @param[in] sentLength Length of the data sent from the remote
+ * device.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
+ * @retval ::CA_STATUS_FAILED Operation failed.
+ *
+ */
+static CAResult_t CALEAdapterServerReceivedData(const char *remoteAddress,
+ const uint8_t *data,
+ uint32_t dataLength,
+ uint32_t *sentLength);
+
+/**
+ * This function will receive the data from the GattClient and add the
+ * data into the Client receiver queue.
+ *
+ * @param[in] remoteAddress Remote address of the device from where
+ * data is received.
+ * @param[in] data Actual data recevied from the remote
+ * device.
+ * @param[in] dataLength Length of the data received from the
+ * remote device.
+ * @param[in] sentLength Length of the data sent from the remote
+ * device.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
+ * @retval ::CA_STATUS_FAILED Operation failed.
+ */
+static CAResult_t CALEAdapterClientReceivedData(const char *remoteAddress,
+ const uint8_t *data,
+ uint32_t dataLength,
+ uint32_t *sentLength);
+
+/**
+ * Set the NetworkPacket received callback to CA layer from adapter
+ * layer.
+ *
+ * @param[in] callback Callback handle sent from the upper layer.
+ */
+static void CASetLEReqRespAdapterCallback(CANetworkPacketReceivedCallback callback);
+
+/**
+ * Push the data from CA layer to the Sender processor queue.
+ *
+ * @param[in] remoteEndpoint Remote endpoint information of the
+ * server.
+ * @param[in] data Data to be transmitted from LE.
+ * @param[in] dataLen Length of the Data being transmitted.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
+ * @retval ::CA_STATUS_FAILED Operation failed.
+ */
+static CAResult_t CALEAdapterServerSendData(const CAEndpoint_t *remoteEndpoint,
+ const uint8_t *data,
+ uint32_t dataLen);
+
+/**
+ * Push the data from CA layer to the Sender processor queue.
+ *
+ * @param[in] remoteEndpoint Remote endpoint information of the
+ * server.
+ * @param[in] data Data to be transmitted from LE.
+ * @param[in] dataLen Length of the Data being transmitted.
+ *
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
+ * @retval ::CA_STATUS_FAILED Operation failed.
+ */
+static CAResult_t CALEAdapterClientSendData(const CAEndpoint_t *remoteEndpoint,
+ const uint8_t *data,
+ uint32_t dataLen);
+
CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback,
CANetworkPacketReceivedCallback reqRespCallback,
CANetworkChangeCallback netCallback,
static CAResult_t CAStartLE()
{
- OIC_LOG(DEBUG, CALEADAPTER_TAG, __func__);
+ OIC_LOG(DEBUG, CALEADAPTER_TAG, "CAStartLE");
return CAStartLEAdapter();
}
static CAResult_t CAStartLEListeningServer()
{
OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
+#ifndef ROUTING_GATEWAY
CAResult_t result = CA_STATUS_OK;
#ifndef SINGLE_THREAD
result = CAInitLEServerQueues();
OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
return CA_STATUS_OK;
+#else
+ // Routing Gateway only supports BLE client mode.
+ OIC_LOG(ERROR, CALEADAPTER_TAG, "LE server not supported in Routing Gateway");
+ return CA_NOT_SUPPORTED;
+#endif
}
static CAResult_t CAStartLEDiscoveryServer()
OIC_LOG(ERROR, CALEADAPTER_TAG, "Send unicast data failed\n");
if (g_errorHandler)
{
- g_errorHandler((void *) endpoint, (void *) data, dataLen, result);
+ g_errorHandler(endpoint, data, dataLen, result);
}
ca_mutex_unlock(g_bleIsServerMutex);
return -1;
return res;
}
-static void CALEDeviceStateChangedCb( CAAdapterState_t adapter_state)
+static void CALEDeviceStateChangedCb(CAAdapterState_t adapter_state)
{
OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
VERIFY_NON_NULL_VOID(g_localBLEAddress, CALEADAPTER_TAG, "g_localBLEAddress is null");
- CAEndpoint_t localEndpoint = {.adapter = CA_DEFAULT_ADAPTER};
+ CAEndpoint_t localEndpoint = { .adapter = CA_ADAPTER_GATT_BTLE };
ca_mutex_lock(g_bleLocalAddressMutex);
- OICStrcpy(localEndpoint.addr, sizeof(localEndpoint.addr), g_localBLEAddress);
+ OICStrcpy(localEndpoint.addr,
+ sizeof(localEndpoint.addr),
+ g_localBLEAddress);
ca_mutex_unlock(g_bleLocalAddressMutex);
g_bleAdapterState = adapter_state;
}
static CAResult_t CALEAdapterClientSendData(const CAEndpoint_t *remoteEndpoint,
- const void *data,
+ const uint8_t *data,
uint32_t dataLen)
{
OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
VERIFY_NON_NULL_RET(g_bleClientSendQueueHandle, CALEADAPTER_TAG, "g_bleClientSendQueueHandle",
CA_STATUS_FAILED);
- OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data Sending to LE layer [%d]", dataLen);
+ OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data Sending to LE layer [%u]", dataLen);
CALEData_t *bleData = CACreateLEData(remoteEndpoint, data, dataLen);
if (!bleData)
}
static CAResult_t CALEAdapterServerSendData(const CAEndpoint_t *remoteEndpoint,
- const void *data,
+ const uint8_t *data,
uint32_t dataLen)
{
OIC_LOG(DEBUG, CALEADAPTER_TAG, "IN");
VERIFY_NON_NULL(data, CALEADAPTER_TAG, "Param data is NULL");
#ifdef SINGLE_THREAD
- char header[CA_HEADER_LENGTH] = {0};
+ uint8_t header[CA_HEADER_LENGTH] = { 0 };
- CAResult_t result = CAGenerateHeader(header, dataLen);
+ CAResult_t result =
+ CAGenerateHeader(header, CA_HEADER_LENGTH, dataLen);
if (CA_STATUS_OK != result)
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Generate header failed");
- return -1;
+ return CA_STATUS_FAILED;
}
if (!CAIsLEConnected())
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "le not conn");
- return -1;
+ return CA_STATUS_FAILED;
}
result = CAUpdateCharacteristicsToAllGattClients(header, CA_HEADER_LENGTH);
if (CA_STATUS_OK != result)
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Update characteristics failed");
- return -1;
+ return CA_STATUS_FAILED;
}
- int32_t dataLimit = dataLen / CA_SUPPORTED_BLE_MTU_SIZE;
- for (int32_t iter = 0; iter < dataLimit; iter++)
+ const uint32_t dataLimit = dataLen / CA_SUPPORTED_BLE_MTU_SIZE;
+ for (uint32_t iter = 0; iter < dataLimit; iter++)
{
- result = CAUpdateCharacteristicsToAllGattClients((data +
- (iter * CA_SUPPORTED_BLE_MTU_SIZE)),
- CA_SUPPORTED_BLE_MTU_SIZE);
+ result =
+ CAUpdateCharacteristicsToAllGattClients(
+ data + (iter * CA_SUPPORTED_BLE_MTU_SIZE),
+ CA_SUPPORTED_BLE_MTU_SIZE);
+
if (CA_STATUS_OK != result)
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Update characteristics failed");
- return -1;
+ return CA_STATUS_FAILED;
}
+
CALEDoEvents();
}
- uint8_t remainingLen = dataLen % CA_SUPPORTED_BLE_MTU_SIZE;
- if(remainingLen)
+ const uint32_t remainingLen = dataLen % CA_SUPPORTED_BLE_MTU_SIZE;
+ if (remainingLen)
{
- result = CAUpdateCharacteristicsToAllGattClients((data +
- (dataLimit * CA_SUPPORTED_BLE_MTU_SIZE)),
- remainingLen);
+ result =
+ CAUpdateCharacteristicsToAllGattClients(
+ data + (dataLimit * CA_SUPPORTED_BLE_MTU_SIZE),
+ remainingLen);
if (CA_STATUS_OK != result)
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Update characteristics failed");
- return -1;
+ return CA_STATUS_FAILED;
}
CALEDoEvents();
}
OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data Sending to LE layer [%d]", dataLen);
- CALEData_t *bleData = CACreateLEData(remoteEndpoint, data, dataLen);
+ CALEData_t * const bleData =
+ CACreateLEData(remoteEndpoint, data, dataLen);
+
if (!bleData)
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to create bledata!");
return CA_MEMORY_ALLOC_FAILED;
}
+
// Add message to send queue
ca_mutex_lock(g_bleServerSendDataMutex);
- CAQueueingThreadAddData(g_bleServerSendQueueHandle, bleData, sizeof(CALEData_t));
+ CAQueueingThreadAddData(g_bleServerSendQueueHandle,
+ bleData,
+ sizeof(CALEData_t));
ca_mutex_unlock(g_bleServerSendDataMutex);
#endif
OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT");
}
static CAResult_t CALEAdapterServerReceivedData(const char *remoteAddress,
- const void *data,
+ const uint8_t *data,
uint32_t dataLength,
uint32_t *sentLength)
{
#ifdef SINGLE_THREAD
if(g_networkPacketReceivedCallback)
{
- CAEndpoint_t endPoint = { 0 }; // will be filled by upper layer
- endPoint.adapter = CA_ADAPTER_GATT_BTLE;
- g_networkPacketReceivedCallback(&endPoint, data, dataLength);
+ // will be filled by upper layer
+ const CASecureEndpoint_t endpoint =
+ { .endpoint = { .adapter = CA_ADAPTER_GATT_BTLE } };
+
+
+ g_networkPacketReceivedCallback(&endpoint, data, dataLength);
}
#else
- VERIFY_NON_NULL_RET(g_bleReceiverQueue, CALEADAPTER_TAG, "g_bleReceiverQueue",
+ VERIFY_NON_NULL_RET(g_bleReceiverQueue,
+ CALEADAPTER_TAG,
+ "g_bleReceiverQueue",
CA_STATUS_FAILED);
//Add message to data queue
- CAEndpoint_t *remoteEndpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS,
- CA_ADAPTER_GATT_BTLE,
- remoteAddress, 0);
+ CAEndpoint_t * const remoteEndpoint =
+ CACreateEndpointObject(CA_DEFAULT_FLAGS,
+ CA_ADAPTER_GATT_BTLE,
+ remoteAddress,
+ 0);
+
if (NULL == remoteEndpoint)
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to create remote endpoint !");
}
// Create bleData to add to queue
- OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data received from LE layer [%d]", dataLength);
+ OIC_LOG_V(DEBUG,
+ CALEADAPTER_TAG,
+ "Data received from LE layer [%d]",
+ dataLength);
+
+ CALEData_t * const bleData =
+ CACreateLEData(remoteEndpoint, data, dataLength);
- CALEData_t *bleData = CACreateLEData(remoteEndpoint, data, dataLength);
if (!bleData)
{
OIC_LOG(ERROR, CALEADAPTER_TAG, "Failed to create bledata!");
}
static CAResult_t CALEAdapterClientReceivedData(const char *remoteAddress,
- const void *data,
+ const uint8_t *data,
uint32_t dataLength,
uint32_t *sentLength)
{
return CA_STATUS_FAILED;
}
- OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data received from LE layer [%d]", dataLength);
+ OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Data received from LE layer [%u]", dataLength);
// Create bleData to add to queue
CALEData_t *bleData = CACreateLEData(remoteEndpoint, data, dataLength);
}
static void CALEErrorHandler(const char *remoteAddress,
- const void *data,
+ const uint8_t *data,
uint32_t dataLen,
CAResult_t result)
{
OIC_LOG(DEBUG, CALEADAPTER_TAG, "CALEErrorHandler IN");
VERIFY_NON_NULL_VOID(data, CALEADAPTER_TAG, "Data is null");
+
CAEndpoint_t *rep = CACreateEndpointObject(CA_DEFAULT_FLAGS,
CA_ADAPTER_GATT_BTLE,
remoteAddress,
0);
- //if required, will be used to build remote end point
+
+ // if required, will be used to build remote endpoint
g_errorHandler(rep, data, dataLen, result);
CAFreeEndpoint(rep);
+
OIC_LOG(DEBUG, CALEADAPTER_TAG, "CALEErrorHandler OUT");
}
}
if (iter != NULL)
+ {
g_variant_iter_free(iter);
+ }
}
static void CALEOnPropertiesChanged(GDBusConnection * connection,
gsize length = 0;
char const ** const UUIDs = g_variant_get_strv(prop, &length);
- /**
- * @note It would have been nice to use @c g_strv_contains() here,
- * but we would need to run it twice: once for the uppercase
- * form of the UUID and once for for the lowercase form.
- * Just run the loop manually, and use @c strcasecmp()
- * instead.
- */
+ /*
+ It would have been nice to use g_strv_contains() here, but we
+ would need to run it twice: once for the uppercase form of the
+ UUID and once for for the lowercase form. Just run the loop
+ manually, and use strcasecmp() instead.
+ */
char const * const * const end = UUIDs + length;
for (char const * const * u = UUIDs; u != end; ++u)
{
// Only stop if we were previously started.
if (!CALECheckStarted())
+ {
return result;
+ }
// Stop the event loop thread regardless of previous errors.
CALEStopEventLoop(&g_context);
// Only start if we were previously stopped.
if (CALECheckStarted())
+ {
return result;
+ }
/**
* Spawn a thread to run the GLib event loop that will drive D-Bus
&g_context);
if (result != CA_STATUS_OK)
+ {
return result;
+ }
/*
Wait until initialization completes before continuing, basically
}
CAResult_t CAUpdateCharacteristicsToGattClient(char const * address,
- char const * charValue,
- uint32_t charValueLen)
+ uint8_t const * value,
+ uint32_t valueLen)
{
(void)address;
- (void)charValue;
- (void)charValueLen;
+ (void)value;
+ (void)valueLen;
/**
* @todo To be implemented shortly as part of the effort to
* address a critical code review that stated this BLE
return CA_NOT_SUPPORTED;
}
-CAResult_t CAUpdateCharacteristicsToAllGattClients(char const * charValue,
- uint32_t charValueLen)
+CAResult_t CAUpdateCharacteristicsToAllGattClients(uint8_t const * value,
+ uint32_t valueLen)
{
- (void)charValue;
- (void)charValueLen;
+ (void)value;
+ (void)valueLen;
/**
* @todo To be implemented shortly as part of the effort to
* address a critical code review that stated this BLE
CAResult_t CAUpdateCharacteristicsToGattServer(
char const * remoteAddress,
- char const * data,
+ uint8_t const * data,
uint32_t dataLen,
CALETransferType_t type,
int32_t position)
return CA_NOT_SUPPORTED;
}
-CAResult_t CAUpdateCharacteristicsToAllGattServers(char const * data,
+CAResult_t CAUpdateCharacteristicsToAllGattServers(uint8_t const * data,
uint32_t length)
{
OIC_LOG(DEBUG, TAG, "Send data to all");
the server, and the server is handling that write request.
*/
+ // GLib maps an octet to a guchar, which is of size 1.
gsize len = 0;
gconstpointer const data =
- g_variant_get_fixed_array(value,
- &len,
- 1); // sizeof(guchar) == 1
+ g_variant_get_fixed_array(value, &len, 1);
CAGattCharacteristic * const c = user_data;
*/
static bool CAGattClientSendRequestData(GDBusProxy * characteristic,
CALEContext * context,
- char const * data,
+ uint8_t const * data,
size_t length)
{
assert(context != NULL);
}
CAResult_t CAGattClientSendData(void const * method_info,
- void const * data,
+ uint8_t const * data,
size_t length)
{
assert(method_info != NULL);
return CAGattClientSendRequestData(characteristic,
info->context,
- (char const *) data,
+ data,
length);
}
CAResult_t CAGattClientSendDataToAll(void const * method_info,
- void const * data,
+ uint8_t const * data,
size_t length)
{
assert(method_info != NULL);
result = CAGattClientSendRequestData(characteristic,
info->context,
- (char const *) data,
+ data,
length);
}
* @see @c CAGattSendMethod() for further details.
*/
bool CAGattSendRequest(void const * method_info,
- void const * data,
+ uint8_t const * data,
size_t length);
// ---------------------------------------------------------------
* @return @c CA_STATUS_OK on success, @c CA_STATUS_FAILED otherwise.
*/
CAResult_t CAGattClientSendDataToAll(void const * method_info,
- void const * data,
+ uint8_t const * data,
size_t length);
*info = g_null_info;
}
-bool CAGattRecv(CAGattRecvInfo * info, char const * data, uint32_t length)
+bool CAGattRecv(CAGattRecvInfo * info,
+ uint8_t const * data,
+ uint32_t length)
{
uint32_t sent_length = 0;
* @return @c true on success, @c false otherwise.
*/
bool CAGattRecv(CAGattRecvInfo * info,
- char const * data,
+ uint8_t const * data,
uint32_t length);
#define TZ_BLE_CLIENT_TAG "TZ_BLE_GATT_CLIENT"
/**
- * @var g_bLEServiceList
- * @brief This contains the list of OIC services a client connect to.
+ * This contains the list of OIC services a client connect to.
*/
static BLEServiceList *g_bLEServiceList = NULL;
void CABleGattCharacteristicChangedCb(bt_gatt_attribute_h characteristic,
unsigned char *value,
- int valueLen, void *userData)
+ int valueLen,
+ void *userData)
{
OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
}
CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress,
- const char *data, uint32_t dataLen,
+ const uint8_t *data, uint32_t dataLen,
CALETransferType_t type, int32_t position)
{
OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
VERIFY_NON_NULL(bleServiceInfo, TZ_BLE_CLIENT_TAG, "bleServiceInfo is NULL");
- OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Updating the data of length [%d] to [%s] ", dataLen,
+ OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Updating the data of length [%u] to [%s] ", dataLen,
bleServiceInfo->bdAddress);
OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG, "Updating to write char [%s]",
bleServiceInfo->read_char);
- OIC_LOG_V(DEBUG, TZ_BLE_CLIENT_TAG,
- "Updating the data of length [%d] to [%s]", dataLen,
- bleServiceInfo->bdAddress);
-
int result = bt_gatt_set_characteristic_value(bleServiceInfo->write_char, (unsigned char *)data,
dataLen);
if (BT_ERROR_NONE != result)
return CA_STATUS_OK;
}
-CAResult_t CAUpdateCharacteristicsToAllGattServers(const char *data,
+CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data,
uint32_t dataLen)
{
OIC_LOG(DEBUG, TZ_BLE_CLIENT_TAG, "IN");
* @param[in] userData The user data passed from the request function.
*/
void CABleGattCharacteristicChangedCb(bt_gatt_attribute_h characteristic,
- unsigned char *value, int valueLen, void *userData);
+ unsigned char *value,
+ int valueLen,
+ void *userData);
/**
* This is the callback which will be called after the characteristics changed.
*
*/
CAResult_t CABleClientSenderQueueEnqueueMessage
(const CAEndpoint_t *remoteEndpoint,
- const void *data, uint32_t dataLen);
+ const uint8_t *data, uint32_t dataLen);
/**
* This is the thread which will be used for processing sender queue.
return;
}
- char *charReadUUID = CA_GATT_RESPONSE_CHRC_UUID;
- char charReadValue[] = {33, 44, 55, 66}; // These are initial random values
+ static const char charReadUUID[] = CA_GATT_RESPONSE_CHRC_UUID;
+ uint8_t charReadValue[] = {33, 44, 55, 66}; // These are initial random values
ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charReadUUID, charReadValue,
CA_BLE_INITIAL_BUF_SIZE, true); // For Read Characteristics.
return;
}
- char *charWriteUUID = CA_GATT_REQUEST_CHRC_UUID;
- char charWriteValue[] = {33, 44, 55, 66}; // These are initial random values
+ static const char charWriteUUID[] = CA_GATT_REQUEST_CHRC_UUID;
+ uint8_t charWriteValue[] = {33, 44, 55, 66}; // These are initial random values
ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charWriteUUID, charWriteValue,
}
void CABleGattRemoteCharacteristicWriteCb(char *charPath,
- unsigned char *charValue,
- int charValueLen, const char *remoteAddress, void *userData)
+ unsigned char *charValue,
+ int charValueLen,
+ const char *remoteAddress,
+ void *userData)
{
OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
return;
}
- OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "charPath = [%s] charValue = [%s] len [%d]", charPath,
- charValue, charValueLen);
+ OIC_LOG_V(DEBUG,
+ TZ_BLE_SERVER_TAG,
+ "charPath = [%s] charValue = [%p] len [%d]",
+ charPath,
+ charValue,
+ charValueLen);
- char *data = (char *)OICMalloc(sizeof(char) * charValueLen + 1);
+ uint8_t *data = OICMalloc(charValueLen);
if (NULL == data)
{
OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "Malloc failed!");
return;
}
- OICStrcpy(data, charValueLen + 1, charValue);
+ memcpy(data, charValue, charValueLen);
ca_mutex_lock(g_bleReqRespCbMutex);
if (NULL == g_bleServerDataReceivedCallback)
}
CAResult_t CAAddNewCharacteristicsToGattServer(const char *svcPath, const char *charUUID,
- const char *charValue, int charValueLen, bool read)
+ const uint8_t *charValue, int charValueLen, bool read)
{
OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
- char *charFlags[1];
+ const char *charFlags[1];
if(read)
{
charFlags[0] = "notify";
size_t flagLen = sizeof(charFlags) / sizeof(charFlags[0]);
char *charPath = NULL;
- int ret = bt_gatt_add_characteristic(charUUID, charValue, charValueLen, charFlags, flagLen,
- svcPath, &charPath);
+ int ret =
+ bt_gatt_add_characteristic(charUUID,
+ (const char *) charValue,
+ charValueLen,
+ charFlags,
+ flagLen,
+ svcPath,
+ &charPath);
if (0 != ret || NULL == charPath)
{
}
CAResult_t CAUpdateCharacteristicsToGattClient(const char *address,
- const char *charValue,
+ const uint8_t *charValue,
uint32_t charValueLen)
{
OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
return CA_STATUS_FAILED;
}
- char *data = (char *) OICCalloc(sizeof(char), (charValueLen + 1));
+ char *data = OICCalloc(charValueLen, 1);
if (NULL == data)
{
OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "malloc failed!");
return CA_STATUS_FAILED;
}
- OICStrcpy(data, charValueLen + 1, charValue);
+ memcpy(data, charValue, charValueLen); // Binary data
- OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "updating characteristics char [%s] data [%s] dataLen [%d]",
+ OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "updating characteristics char [%s] data [%p] dataLen [%u]",
(const char *)g_gattReadCharPath, data, charValueLen);
- int ret = bt_gatt_update_characteristic(g_gattReadCharPath, data, charValueLen, address);
+ int ret =
+ bt_gatt_update_characteristic(g_gattReadCharPath,
+ data,
+ charValueLen,
+ address);
if (0 != ret)
{
OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG,
return CA_STATUS_OK;
}
-CAResult_t CAUpdateCharacteristicsToAllGattClients(const char *charValue, uint32_t charValueLen)
+CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *charValue, uint32_t charValueLen)
{
OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN");
return CA_STATUS_FAILED;
}
- char *data = (char *) OICMalloc(sizeof(char) * (charValueLen + 1));
+ char *data = OICMalloc(charValueLen);
if (NULL == data)
{
OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "malloc failed!");
return CA_STATUS_FAILED;
}
- OICStrcpy(data, charValueLen + 1, charValue);
+ memcpy(data, charValue, charValueLen); // Binary data
- OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "updating characteristics char [%s] data [%s] dataLen [%d]",
+ OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "updating characteristics char [%s] data [%p] dataLen [%u]",
(const char *)g_gattReadCharPath, data, charValueLen);
- int ret = bt_gatt_update_characteristic(g_gattReadCharPath, data, charValueLen, NULL);
+ int ret =
+ bt_gatt_update_characteristic(g_gattReadCharPath,
+ data,
+ charValueLen,
+ NULL);
if (0 != ret)
{
OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG,
* @return ::CA_STATUS_OK or Appropriate error code.
*/
CAResult_t CAAddNewCharacteristicsToGattServer(const char *svcPath, const char *charUUID,
- const char *charValue, int charValueLen,
+ const uint8_t *charValue, int charValueLen,
bool read);
/**
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CABleServerSenderQueueEnqueueMessage
- (const CAEndpoint_t *remoteEndpoint, const void *data, uint32_t dataLen);
+ (const CAEndpoint_t *remoteEndpoint, const uint8_t *data, uint32_t dataLen);
/**
* This is the thread which will be used for processing receiver queue.
// context for block-wise transfer
static CABlockWiseContext_t g_context = { 0 };
+static bool CACheckPayloadLength(const CAData_t *sendData)
+{
+ size_t payloadLen = 0;
+ CAGetPayloadInfo(sendData, &payloadLen);
+
+ // check if message has to be transfered to a block
+ size_t maxBlockSize = BLOCK_SIZE(CA_DEFAULT_BLOCK_SIZE);
+ OIC_LOG_V(DEBUG, TAG, "payloadLen=%d, maxBlockSize=%d", payloadLen, maxBlockSize);
+
+ if (payloadLen <= maxBlockSize)
+ {
+ return false;
+ }
+
+ return true;
+}
+
CAResult_t CAInitializeBlockWiseTransfer(CASendThreadFunc sendThreadFunc,
CAReceiveThreadFunc receivedThreadFunc)
{
{
OIC_LOG(DEBUG, TAG, "IN");
- if (NULL == g_context.blockDataListMutex)
+ if (!g_context.blockDataListMutex)
{
g_context.blockDataListMutex = ca_mutex_new();
- if (NULL == g_context.blockDataListMutex)
+ if (!g_context.blockDataListMutex)
{
OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
return CA_STATUS_FAILED;
}
}
- if (NULL == g_context.blockDataSenderMutex)
+ if (!g_context.blockDataSenderMutex)
{
g_context.blockDataSenderMutex = ca_mutex_new();
- if (NULL == g_context.blockDataSenderMutex)
+ if (!g_context.blockDataSenderMutex)
{
OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
CATerminateBlockWiseMutexVariables();
VERIFY_NON_NULL(sendData, TAG, "sendData");
// check if message type is CA_MSG_RESET
- if (NULL != sendData->responseInfo)
+ if (sendData->responseInfo)
{
if (CA_MSG_RESET == sendData->responseInfo->info.type)
{
if (CA_STATUS_OK != res)
{
// #2. if it is not included, add the data into list
- if (NULL == currData)
+ if (!currData)
{
OIC_LOG(DEBUG, TAG, "There is no block data");
+
+ bool isBlock = CACheckPayloadLength(sendData);
+ if (!isBlock)
+ {
+ if (sendData->requestInfo)
+ {
+ currData = CACreateNewBlockData(sendData);
+ if (!currData)
+ {
+ OIC_LOG(ERROR, TAG, "failed to create block data");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+ }
+ return CA_NOT_SUPPORTED;
+ }
currData = CACreateNewBlockData(sendData);
- if (NULL == currData)
+ if (!currData)
{
OIC_LOG(ERROR, TAG, "failed to create block data");
return CA_MEMORY_ALLOC_FAILED;
{
// #4. send block message
OIC_LOG(DEBUG, TAG, "send first block msg");
- res = CAAddSendThreadQueue(currData->sentData, (const CABlockDataID_t *)&currData->blockDataId);
+ res = CAAddSendThreadQueue(currData->sentData,
+ (const CABlockDataID_t *)&currData->blockDataId);
if (CA_STATUS_OK != res)
{
OIC_LOG(ERROR, TAG, "add has failed");
VERIFY_NON_NULL(blockID, TAG, "blockID");
CAData_t *cloneData = CACloneCAData(sendData);
- if (NULL == cloneData)
+ if (!cloneData)
{
OIC_LOG(ERROR, TAG, "clone has failed");
CARemoveBlockDataFromList(blockID);
VERIFY_NON_NULL(currData, TAG, "currData");
VERIFY_NON_NULL(currData->sentData, TAG, "currData->sentData");
- size_t payloadLen = 0;
- CAGetPayloadInfo(currData->sentData, &payloadLen);
-
- // check if message has to be transfered to a block
- size_t maxBlockSize = BLOCK_SIZE(CA_DEFAULT_BLOCK_SIZE);
- if (payloadLen <= maxBlockSize)
+ bool isBlock = CACheckPayloadLength(currData->sentData);
+ if (!isBlock)
{
- OIC_LOG_V(DEBUG, TAG, "payloadLen=%d, maxBlockSize=%d", payloadLen, maxBlockSize);
return CA_NOT_SUPPORTED;
}
// set block option (COAP_OPTION_BLOCK2 or COAP_OPTION_BLOCK1)
- if (NULL != currData->sentData->requestInfo) // request message
+ if (currData->sentData->requestInfo) // request message
{
currData->type = COAP_OPTION_BLOCK1;
}
VERIFY_NON_NULL(receivedData, TAG, "receivedData");
// check if received message type is CA_MSG_RESET
- if (CA_EMPTY == pdu->hdr->code)
+ if (CA_EMPTY == pdu->hdr->coap_hdr_udp_t.code)
{
OIC_LOG(DEBUG, TAG, "code is CA_EMPTY..");
// check if there is error code
if (!isBlock1 && !isBlock2)
{
- uint32_t code = CA_RESPONSE_CODE(pdu->hdr->code);
+ uint32_t code = CA_RESPONSE_CODE(pdu->hdr->coap_hdr_udp_t.code);
if (CA_REQUEST_ENTITY_INCOMPLETE == code)
{
CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
- (CAToken_t)pdu->hdr->token,
- pdu->hdr->token_length,
+ (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
+ pdu->hdr->coap_hdr_udp_t.token_length,
endpoint->port);
if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
}
CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
- if (NULL == data)
+ if (!data)
{
OIC_LOG(ERROR, TAG, "getting has failed");
CADestroyBlockID(blockDataID);
if (COAP_OPTION_BLOCK2 == data->type)
{
- coap_block_t *block2 = CAGetBlockOption(blockDataID,
- COAP_OPTION_BLOCK2);
- if (NULL == block2)
+ coap_block_t *block2 = CAGetBlockOption(blockDataID, COAP_OPTION_BLOCK2);
+ if (!block2)
{
OIC_LOG(ERROR, TAG, "block is null");
CADestroyBlockID(blockDataID);
}
else if (COAP_OPTION_BLOCK1 == data->type)
{
- coap_block_t *block1 = CAGetBlockOption(blockDataID,
- COAP_OPTION_BLOCK1);
- if (NULL == block1)
+ coap_block_t *block1 = CAGetBlockOption(blockDataID, COAP_OPTION_BLOCK1);
+ if (!block1)
{
OIC_LOG(ERROR, TAG, "block is null");
CADestroyBlockID(blockDataID);
// and sent data remain in block data list, remove block data
if (receivedData->responseInfo)
{
- CAResult_t res = CAGetTokenFromBlockDataList(pdu, endpoint,
- receivedData->responseInfo);
- if (CA_STATUS_OK != res)
+ CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
+ (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
+ pdu->hdr->coap_hdr_udp_t.token_length,
+ endpoint->port);
+ if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
{
- OIC_LOG(ERROR, TAG, "fail to get token");
- return res;
+ OIC_LOG(ERROR, TAG, "blockId is null");
+ CADestroyBlockID(blockDataID);
+ return CA_STATUS_FAILED;
}
+
+ CARemoveBlockDataFromList(blockDataID);
+ CADestroyBlockID(blockDataID);
}
return CA_NOT_SUPPORTED;
}
case CA_OPTION2_CON:
// add data to send thread
data = CAGetDataSetFromBlockDataList(blockID);
- if (NULL == data)
+ if (!data)
{
OIC_LOG(ERROR, TAG, "it's unavailable");
return CA_STATUS_FAILED;
if (data->requestInfo)
{
- data->requestInfo->info.messageId = pdu->hdr->id;
+ data->requestInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
}
if (data->responseInfo)
{
- data->responseInfo->info.messageId = pdu->hdr->id;
+ data->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
}
res = CAAddSendThreadQueue(data, blockID);
return res;
}
- if (CA_MSG_NONCONFIRM == pdu->hdr->type)
+ if (CA_MSG_NONCONFIRM == pdu->hdr->coap_hdr_udp_t.type)
{
// remove data from list
res = CARemoveBlockDataFromList(blockID);
break;
case CA_OPTION1_NO_ACK_BLOCK:
- if (CA_MSG_CONFIRM == pdu->hdr->type)
+ if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type)
{
// add data to send thread
res = CASendBlockMessage(pdu, CA_MSG_ACKNOWLEDGE, blockWiseStatus,
break;
case CA_BLOCK_INCOMPLETE:
- if (CA_MSG_CONFIRM == pdu->hdr->type || CA_MSG_ACKNOWLEDGE == pdu->hdr->type)
+ if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type ||
+ CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
{
// add data to send thread
res = CASendErrorMessage(pdu, blockWiseStatus,
break;
case CA_BLOCK_TOO_LARGE:
- if (CA_MSG_ACKNOWLEDGE == pdu->hdr->type)
+ if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
{
res = CASendBlockMessage(pdu, CA_MSG_CONFIRM, blockWiseStatus,
blockID);
return res;
}
}
- else if (CA_MSG_CONFIRM == pdu->hdr->type)
+ else if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type)
{
res = CASendErrorMessage(pdu, blockWiseStatus,
CA_REQUEST_ENTITY_TOO_LARGE,
VERIFY_NON_NULL(blockID, TAG, "blockID");
CAData_t *data = CAGetDataSetFromBlockDataList(blockID);
- if (NULL == data)
+ if (!data)
{
OIC_LOG(ERROR, TAG, "CAData is unavailable");
return CA_STATUS_FAILED;
if (data->responseInfo)
{
OIC_LOG(DEBUG, TAG, "set ACK message");
- data->responseInfo->info.messageId = pdu->hdr->id;
+ data->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
data->responseInfo->info.type = CA_MSG_ACKNOWLEDGE;
if (CA_OPTION1_NO_ACK_LAST_BLOCK == status)
{
// create error responseInfo
CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockID);
- if (NULL == data)
+ if (!data)
{
OIC_LOG(ERROR, TAG, "data is unavailable");
return CA_STATUS_FAILED;
CAData_t *cloneData = NULL;
if (data->sentData && data->sentData->responseInfo)
{
- data->sentData->responseInfo->info.messageId = pdu->hdr->id;
+ data->sentData->responseInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
data->sentData->responseInfo->info.type = CA_MSG_ACKNOWLEDGE;
data->sentData->responseInfo->result = responseResult;
cloneData = CACloneCAData(data->sentData);
- if (NULL == cloneData)
+ if (!cloneData)
{
OIC_LOG(ERROR, TAG, "clone has failed");
return CA_MEMORY_ALLOC_FAILED;
else if (data->sentData)
{
cloneData = CACreateNewDataSet(pdu, data->sentData->remoteEndpoint);
-
if(!cloneData)
{
OIC_LOG(ERROR, TAG, PCF("CACreateNewDataSet failed"));
// total block data have to notify to Application
CAData_t *cloneData = CACloneCAData(receivedData);
- if (NULL == cloneData)
+ if (!cloneData)
{
OIC_LOG(ERROR, TAG, "clone has failed");
return CA_MEMORY_ALLOC_FAILED;
size_t fullPayloadLen = 0;
CAPayload_t fullPayload = CAGetPayloadFromBlockDataList(blockID,
&fullPayloadLen);
- if (NULL != fullPayload)
+ if (fullPayload)
{
CAResult_t res = CAUpdatePayloadToCAData(cloneData, fullPayload, fullPayloadLen);
if (CA_STATUS_OK != res)
{
OIC_LOG(ERROR, TAG, "update has failed");
CADestroyDataSet(cloneData);
- return CA_STATUS_FAILED;
+ return res;
}
}
OIC_LOG_V(INFO, TAG, "num:%d, M:%d, sze:%d", block.num, block.m, block.szx);
CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
- (CAToken_t)pdu->hdr->token,
- pdu->hdr->token_length,
+ (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
+ pdu->hdr->coap_hdr_udp_t.token_length,
endpoint->port);
if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
OIC_LOG(DEBUG, TAG, "no message in list");
CAData_t *data = CACreateNewDataSet(pdu, endpoint);
- if (NULL == data)
+ if (!data)
{
OIC_LOG(ERROR, TAG, "data is null");
CADestroyBlockID(blockDataID);
}
CABlockData_t *currData = CACreateNewBlockData(data);
- if (NULL == currData)
+ if (!currData)
{
OIC_LOG(ERROR, TAG, "currData is null");
CADestroyDataSet(data);
CADestroyBlockID(blockDataID);
return CA_STATUS_FAILED;
}
+ CADestroyDataSet(data);
}
// update BLOCK OPTION1 type
}
CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
- if (NULL == data)
+ if (!data)
{
OIC_LOG(ERROR, TAG, "getting has failed");
CADestroyBlockID(blockDataID);
uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN;
// received type from remote device
- if (CA_MSG_ACKNOWLEDGE == pdu->hdr->type)
+ if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
{
- uint32_t code = CA_RESPONSE_CODE(pdu->hdr->code);
+ uint32_t code = CA_RESPONSE_CODE(pdu->hdr->coap_hdr_udp_t.code);
if (0 == block.m &&
(CA_REQUEST_ENTITY_INCOMPLETE != code && CA_REQUEST_ENTITY_TOO_LARGE != code))
{
&(data->payloadLength));
// check if received payload is exact
- if (CA_MSG_CONFIRM == pdu->hdr->type)
+ if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type)
{
blockWiseStatus = CACheckBlockErrorType(data, &block, receivedData,
COAP_OPTION_BLOCK1, dataLen);
VERIFY_NON_NULL(receivedData, TAG, "receivedData");
CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
- (CAToken_t)pdu->hdr->token,
- pdu->hdr->token_length,
+ (CAToken_t)pdu->hdr->coap_hdr_udp_t.token,
+ pdu->hdr->coap_hdr_udp_t.token_length,
endpoint->port);
if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
OIC_LOG(DEBUG, TAG, "no msg in list.");
CAData_t *data = CACreateNewDataSet(pdu, endpoint);
- if (NULL == data)
+ if (!data)
{
OIC_LOG(ERROR, TAG, "data is null");
CADestroyBlockID(blockDataID);
}
CABlockData_t *currData = CACreateNewBlockData(data);
- if (NULL == currData)
+ if (!currData)
{
OIC_LOG(ERROR, TAG, "data is null");
CADestroyDataSet(data);
CADestroyBlockID(blockDataID);
return CA_STATUS_FAILED;
}
+ CADestroyDataSet(data);
}
// set Block Option Type
}
CABlockData_t *data = CAGetBlockDataFromBlockDataList(blockDataID);
- if (NULL == data)
+ if (!data)
{
OIC_LOG(ERROR, TAG, "getting has failed");
CARemoveBlockDataFromList(blockDataID);
}
uint8_t blockWiseStatus = CA_BLOCK_UNKNOWN;
- if (0 == block.num && CA_GET == pdu->hdr->code && 0 == block.m)
+ if (0 == block.num && CA_GET == pdu->hdr->coap_hdr_udp_t.code && 0 == block.m)
{
OIC_LOG(INFO, TAG, "first block number");
else
{
// received type from remote device
- if (CA_MSG_ACKNOWLEDGE == pdu->hdr->type ||
- (CA_MSG_NONCONFIRM == pdu->hdr->type && NULL != receivedData->responseInfo))
+ if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type ||
+ (CA_MSG_NONCONFIRM == pdu->hdr->coap_hdr_udp_t.type &&
+ NULL != receivedData->responseInfo))
{
OIC_LOG(DEBUG, TAG, "received ACK or NON");
&(data->payloadLength));
// check if received payload is exact
- if (CA_MSG_ACKNOWLEDGE == pdu->hdr->type)
+ if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
{
blockWiseStatus = CACheckBlockErrorType(data, &block, receivedData,
COAP_OPTION_BLOCK2, dataLen);
{
OIC_LOG(DEBUG, TAG, "M bit is 1");
- if (CA_MSG_ACKNOWLEDGE == pdu->hdr->type)
+ if (CA_MSG_ACKNOWLEDGE == pdu->hdr->coap_hdr_udp_t.type)
{
blockWiseStatus = CA_OPTION2_ACK;
}
// update block data
CAResult_t res = CA_STATUS_OK;
- uint32_t code = CA_RESPONSE_CODE(pdu->hdr->code);
+ uint32_t code = CA_RESPONSE_CODE(pdu->hdr->coap_hdr_udp_t.code);
if (CA_REQUEST_ENTITY_INCOMPLETE == code || CA_REQUEST_ENTITY_TOO_LARGE == code)
{
if (CA_BLOCK_INCOMPLETE != status && CA_BLOCK_TOO_LARGE != status)
{
// negotiate block size
- res = CANegotiateBlockSize(currData, block, pdu->hdr->type, blockType);
+ res = CANegotiateBlockSize(currData, block, pdu->hdr->coap_hdr_udp_t.type, blockType);
if (CA_STATUS_OK != res)
{
OIC_LOG(ERROR, TAG, "negotiation has failed");
VERIFY_NON_NULL(blockID, TAG, "blockID");
// if CON message is sent, update messageId in block-wise transfer list
- if (CA_MSG_CONFIRM == pdu->hdr->type)
+ if (CA_MSG_CONFIRM == pdu->hdr->coap_hdr_udp_t.type)
{
CAData_t * cadata = CAGetDataSetFromBlockDataList(blockID);
- if (NULL == cadata)
+ if (!cadata)
{
OIC_LOG(ERROR, TAG, "CAData is unavailable");
return CA_STATUS_FAILED;
}
- if (NULL != cadata->requestInfo)
+ if (cadata->requestInfo)
{
- cadata->requestInfo->info.messageId = pdu->hdr->id;
+ cadata->requestInfo->info.messageId = pdu->hdr->coap_hdr_udp_t.id;
}
}
return CA_STATUS_OK;
}
-CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t info,
+CAResult_t CAAddBlockOption(coap_pdu_t **pdu, const CAInfo_t *info,
const CAEndpoint_t *endpoint)
{
OIC_LOG(DEBUG, TAG, "IN-AddBlockOption");
VERIFY_NON_NULL(pdu, TAG, "pdu");
VERIFY_NON_NULL((*pdu), TAG, "(*pdu)");
VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr");
+ VERIFY_NON_NULL(info, TAG, "info");
VERIFY_NON_NULL(endpoint, TAG, "endpoint");
size_t dataLength = 0;
- if (info.payload)
+ if (info->payload)
{
- dataLength = info.payloadSize;
+ dataLength = info->payloadSize;
OIC_LOG_V(DEBUG, TAG, "dataLength - %d", dataLength);
}
OIC_LOG_V(DEBUG, TAG, "previous payload - %s", (*pdu)->data);
- uint32_t code = CA_RESPONSE_CODE((*pdu)->hdr->code);
+ uint32_t code = CA_RESPONSE_CODE((*pdu)->hdr->coap_hdr_udp_t.code);
if (CA_REQUEST_ENTITY_INCOMPLETE == code)
{
OIC_LOG(INFO, TAG, "don't use option");
}
CABlockDataID_t* blockDataID = CACreateBlockDatablockId(
- (CAToken_t)(*pdu)->hdr->token,
- (*pdu)->hdr->token_length,
+ (CAToken_t)(*pdu)->hdr->coap_hdr_udp_t.token,
+ (*pdu)->hdr->coap_hdr_udp_t.token_length,
endpoint->port);
if(NULL == blockDataID || NULL == blockDataID->id || blockDataID->idLength < 1)
{
OIC_LOG(DEBUG, TAG, "no BLOCK option");
// if response data is so large. it have to send as block transfer
- if (!coap_add_data(*pdu, dataLength, (const unsigned char *) info.payload))
+ if (!coap_add_data(*pdu, dataLength, (const unsigned char *) info->payload))
{
OIC_LOG(INFO, TAG, "it have to use block");
}
else
{
OIC_LOG(INFO, TAG, "not Blockwise Transfer");
+ CADestroyBlockID(blockDataID);
+ return CA_STATUS_OK;
}
}
return CA_STATUS_OK;
}
-CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t info, size_t dataLength,
+CAResult_t CAAddBlockOption2(coap_pdu_t **pdu, const CAInfo_t *info, size_t dataLength,
const CABlockDataID_t *blockID)
{
OIC_LOG(DEBUG, TAG, "IN-AddBlockOption2");
VERIFY_NON_NULL(pdu, TAG, "pdu");
VERIFY_NON_NULL((*pdu), TAG, "(*pdu)");
VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr");
+ VERIFY_NON_NULL(info, TAG, "info");
VERIFY_NON_NULL(blockID, TAG, "blockID");
// get set block data from CABlock list-set.
CALogBlockInfo(block2);
uint8_t code = 0;
- if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->type ||
- (CA_MSG_NONCONFIRM == (*pdu)->hdr->type && CA_GET != (*pdu)->hdr->code))
+ if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->coap_hdr_udp_t.type ||
+ (CA_MSG_NONCONFIRM == (*pdu)->hdr->coap_hdr_udp_t.type &&
+ CA_GET != (*pdu)->hdr->coap_hdr_udp_t.code))
{
int32_t res = coap_write_block_opt(block2, COAP_OPTION_BLOCK2, *pdu, dataLength);
switch (res)
}
}
- if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info.payload,
+ if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info->payload,
block2->num, block2->szx))
{
OIC_LOG(ERROR, TAG, "Data length is smaller than the start index");
}
else
{
- if (CA_MSG_NONCONFIRM == (*pdu)->hdr->type)
+ if (CA_MSG_NONCONFIRM == (*pdu)->hdr->coap_hdr_udp_t.type)
{
OIC_LOG(DEBUG, TAG, "NON, send next block..");
// update block data
return CA_STATUS_FAILED;
}
-CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t info, size_t dataLength,
+CAResult_t CAAddBlockOption1(coap_pdu_t **pdu, const CAInfo_t *info, size_t dataLength,
const CABlockDataID_t *blockID)
{
OIC_LOG(DEBUG, TAG, "IN-AddBlockOption1");
VERIFY_NON_NULL(pdu, TAG, "pdu");
VERIFY_NON_NULL((*pdu), TAG, "(*pdu)");
VERIFY_NON_NULL((*pdu)->hdr, TAG, "(*pdu)->hdr");
+ VERIFY_NON_NULL(info, TAG, "info");
VERIFY_NON_NULL(blockID, TAG, "blockID");
// get set block data from CABlock list-set.
- coap_block_t *block1 = CAGetBlockOption(blockID,
- COAP_OPTION_BLOCK1);
- if (NULL == block1)
+ coap_block_t *block1 = CAGetBlockOption(blockID, COAP_OPTION_BLOCK1);
+ if (!block1)
{
OIC_LOG(ERROR, TAG, "getting has failed");
return CA_STATUS_FAILED;
CALogBlockInfo(block1);
- if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->type)
+ if (CA_MSG_ACKNOWLEDGE == (*pdu)->hdr->coap_hdr_udp_t.type)
{
OIC_LOG(DEBUG, TAG, "option1 and ACK msg..");
CAResult_t res = CAAddBlockOptionImpl(*pdu, block1, COAP_OPTION_BLOCK1);
}
}
- if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info.payload,
+ if (!coap_add_block(*pdu, dataLength, (const unsigned char *) info->payload,
block1->num, block1->szx))
{
OIC_LOG(ERROR, TAG, "Data length is smaller than the start index");
}
// check the message type and if message type is NON, next block message will be sent
- if (CA_MSG_NONCONFIRM == (*pdu)->hdr->type)
+ if (CA_MSG_NONCONFIRM == (*pdu)->hdr->coap_hdr_udp_t.type)
{
if (block1->m)
{
VERIFY_NON_NULL(block, TAG, "block");
coap_option *option = (coap_option *) OICMalloc(sizeof(coap_option));
- if (NULL == option)
+ if (!option)
{
OIC_LOG(ERROR, TAG, "out of memory");
return CA_MEMORY_ALLOC_FAILED;
option->length = coap_encode_var_bytes(buf,
((block->num << BLOCK_NUMBER_IDX)
| (block->m << BLOCK_M_BIT_IDX) | block->szx));
- if (!coap_add_option(pdu, option->key, option->length, buf))
+ if (!coap_add_option(pdu, option->key, option->length, buf, coap_udp))
{
OIC_LOG(ERROR, TAG, "coap_add_option has failed");
OICFree(option);
unsigned char value[BLOCKWISE_OPTION_BUFFER] = { 0 };
unsigned int optionLength = coap_encode_var_bytes(value, dataLength);
- if (!coap_add_option(pdu, sizeType, optionLength, value))
+ if (!coap_add_option(pdu, sizeType, optionLength, value, coap_udp))
{
OIC_LOG(ERROR, TAG, "failed to add size option");
return CA_STATUS_FAILED;
// memory allocation for the received block payload
size_t prePayloadLen = currData->receivedPayloadLen;
- if (NULL != blockPayload)
+ if (blockPayload)
{
- if (0 != currData->payloadLength)
+ if (currData->payloadLength)
{
// in case the block message has the size option
// allocate the memory for the total payload
- if (true == isSizeOption)
+ if (isSizeOption)
{
CAPayload_t prePayload = currData->payload;
OIC_LOG(DEBUG, TAG, "allocate memory for the total payload");
- currData->payload = (CAPayload_t) OICCalloc(currData->payloadLength + 1,
- sizeof(char));
+ currData->payload = (CAPayload_t) OICCalloc(1, currData->payloadLength);
if (NULL == currData->payload)
{
OIC_LOG(ERROR, TAG, "out of memory");
{
OIC_LOG(DEBUG, TAG, "allocate memory for the received block payload");
- size_t totalPayloadLen = prePayloadLen + blockPayloadLen + 1;
- void *newPayload = realloc(currData->payload, totalPayloadLen);
+ size_t totalPayloadLen = prePayloadLen + blockPayloadLen;
+ CAPayload_t newPayload = OICRealloc(currData->payload, totalPayloadLen);
if (NULL == newPayload)
{
OIC_LOG(ERROR, TAG, "out of memory");
}
// update the total payload
- memset(newPayload + prePayloadLen, 0, blockPayloadLen + 1);
+ memset(newPayload + prePayloadLen, 0, blockPayloadLen);
currData->payload = newPayload;
memcpy(currData->payload + prePayloadLen, blockPayload, blockPayloadLen);
}
VERIFY_NON_NULL_RET(pdu->hdr, TAG, "pdu->hdr", NULL);
VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", NULL);
- CAInfo_t responseData = { .tokenLength = pdu->hdr->token_length };
+ CAInfo_t responseData = { .tokenLength = pdu->hdr->coap_hdr_udp_t.token_length };
responseData.token = (CAToken_t) OICMalloc(responseData.tokenLength);
- if (NULL == responseData.token)
+ if (!responseData.token)
{
OIC_LOG(ERROR, TAG, "out of memory");
return NULL;
}
- memcpy(responseData.token, pdu->hdr->token, responseData.tokenLength);
+ memcpy(responseData.token, pdu->hdr->coap_hdr_udp_t.token, responseData.tokenLength);
CAResponseInfo_t* responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t));
- if (NULL == responseInfo)
+ if (!responseInfo)
{
OIC_LOG(ERROR, TAG, "out of memory");
OICFree(responseData.token);
responseInfo->info = responseData;
CAData_t *data = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
- if (NULL == data)
+ if (!data)
{
OIC_LOG(ERROR, TAG, "out of memory");
OICFree(responseInfo);
VERIFY_NON_NULL_RET(data, TAG, "data", NULL);
CAData_t *clone = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
- if (NULL == clone)
+ if (!clone)
{
OIC_LOG(ERROR, TAG, "out of memory");
return NULL;
clone->remoteEndpoint = CACloneEndpoint(data->remoteEndpoint);
}
- if (NULL != data->options && 0 < data->numOptions)
- {
- // copy data
- CAHeaderOption_t *headerOption = (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t)
- * data->numOptions);
- if (NULL == headerOption)
- {
- OIC_LOG(ERROR, TAG, "Out of memory");
- CADestroyDataSet(clone);
- return NULL;
- }
- memcpy(headerOption, data->options, sizeof(CAHeaderOption_t) * data->numOptions);
-
- clone->options = headerOption;
- }
-
return clone;
}
VERIFY_NON_NULL(data, TAG, "data is NULL");
VERIFY_NON_NULL(payload, TAG, "payload is NULL");
- if (NULL != data->requestInfo)
+ CAPayload_t newPayload = NULL;
+ switch (data->dataType)
{
- // allocate payload field
- if (NULL != data->requestInfo->info.payload)
- {
- char *temp = (char *) OICCalloc(payloadLen, sizeof(char));
- if (NULL == temp)
+ case CA_REQUEST_DATA:
+ // allocate payload field
+ newPayload = OICRealloc(data->requestInfo->info.payload, payloadLen);
+ if (!newPayload)
{
OIC_LOG(ERROR, TAG, "out of memory");
return CA_STATUS_FAILED;
}
- memcpy(temp, payload, payloadLen);
-
- // save the full payload
- OICFree(data->requestInfo->info.payload);
- data->requestInfo->info.payload = (CAPayload_t) temp;
- }
- data->requestInfo->info.payloadSize = payloadLen;
- }
+ data->requestInfo->info.payload = newPayload;
+ memcpy(data->requestInfo->info.payload, payload, payloadLen);
+ data->requestInfo->info.payloadSize = payloadLen;
+ break;
- if (NULL != data->responseInfo)
- {
- // allocate payload field
- if (NULL != data->responseInfo->info.payload)
- {
- char *temp = (char *) OICCalloc(payloadLen, sizeof(char));
- if (NULL == temp)
+ case CA_RESPONSE_DATA:
+ // allocate payload field
+ newPayload = OICRealloc(data->responseInfo->info.payload, payloadLen);
+ if (!newPayload)
{
OIC_LOG(ERROR, TAG, "out of memory");
return CA_STATUS_FAILED;
}
- memcpy(temp, payload, payloadLen);
+ data->responseInfo->info.payload = newPayload;
+ memcpy(data->responseInfo->info.payload, payload, payloadLen);
+ data->responseInfo->info.payloadSize = payloadLen;
+ break;
- // save the full payload
- OICFree(data->responseInfo->info.payload);
- data->responseInfo->info.payload = (CAPayload_t) temp;
- }
- data->responseInfo->info.payloadSize = payloadLen;
+ default:
+ // does not occur case
+ OIC_LOG(ERROR, TAG, "not supported data type");
+ return CA_NOT_SUPPORTED;
}
OIC_LOG(DEBUG, TAG, "OUT-UpdatePayload");
VERIFY_NON_NULL_RET(data, TAG, "data", NULL);
VERIFY_NON_NULL_RET(payloadLen, TAG, "payloadLen", NULL);
- if (NULL != data->requestInfo)
+ if (data->requestInfo)
{
- if (NULL != data->requestInfo->info.payload)
+ if (data->requestInfo->info.payload)
{
*payloadLen = data->requestInfo->info.payloadSize;
return data->requestInfo->info.payload;
}
else
{
- if (NULL != data->responseInfo->info.payload)
+ if (data->responseInfo->info.payload)
{
*payloadLen = data->responseInfo->info.payloadSize;
return data->responseInfo->info.payload;
if (NULL != currData->sentData && NULL != currData->sentData->requestInfo)
{
- if (pdu->hdr->id == currData->sentData->requestInfo->info.messageId &&
+ if (pdu->hdr->coap_hdr_udp_t.id == currData->sentData->requestInfo->info.messageId &&
endpoint->adapter == currData->sentData->remoteEndpoint->adapter)
{
if (NULL != currData->sentData->requestInfo->info.token)
{
CABlockData_t *currData = (CABlockData_t *) u_arraylist_get(g_context.dataList, i);
- if (NULL == currData)
+ if (!currData)
{
continue;
}
- if (NULL != sendData->requestInfo) // sendData is requestMessage
+ if (sendData->requestInfo) // sendData is requestMessage
{
OIC_LOG(DEBUG, TAG, "Send request");
if (NULL != currData->blockDataId
CADestroyBlockID(blockDataID);
}
}
- else if (NULL != sendData->responseInfo) // sendData is responseMessage
+ else if (sendData->responseInfo) // sendData is responseMessage
{
OIC_LOG(DEBUG, TAG, "Send response");
if (NULL != currData->blockDataId
// create block data
CABlockData_t *data = (CABlockData_t *) OICCalloc(1, sizeof(CABlockData_t));
- if (NULL == data)
+ if (!data)
{
OIC_LOG(ERROR, TAG, "memory alloc has failed");
return NULL;
{
OIC_LOG(ERROR, TAG, "blockId is null");
CADestroyBlockID(blockDataID);
+ CADestroyDataSet(data->sentData);
+ OICFree(data);
return NULL;
}
data->blockDataId = blockDataID;
ca_mutex_lock(g_context.blockDataListMutex);
- CAResult_t res = u_arraylist_add(g_context.dataList, (void *) data);
- if (CA_STATUS_OK != res)
+ bool res = u_arraylist_add(g_context.dataList, (void *) data);
+ if (!res)
{
OIC_LOG(ERROR, TAG, "add has failed");
CADestroyBlockID(data->blockDataId);
+ CADestroyDataSet(data->sentData);
OICFree(data);
ca_mutex_unlock(g_context.blockDataListMutex);
return NULL;
if (CABlockidMatches(currData, blockID))
{
CABlockData_t *removedData = u_arraylist_remove(g_context.dataList, i);
- if (NULL == removedData)
+ if (!removedData)
{
OIC_LOG(ERROR, TAG, "data is NULL");
ca_mutex_unlock(g_context.blockDataListMutex);
{
CADestroyDataSet(currData->sentData);
}
- OICFree(currData->payload);
CADestroyBlockID(currData->blockDataId);
+ OICFree(currData->payload);
+ OICFree(currData);
ca_mutex_unlock(g_context.blockDataListMutex);
return CA_STATUS_OK;
}
CAFreeEndpoint(data->remoteEndpoint);
CADestroyRequestInfoInternal(data->requestInfo);
CADestroyResponseInfoInternal(data->responseInfo);
- OICFree(data->options);
OICFree(data);
}
port[1] = (char)(portNumber & 0xFF);
CABlockDataID_t* blockDataID = (CABlockDataID_t *) OICMalloc(sizeof(CABlockDataID_t));
+ if (!blockDataID)
+ {
+ OIC_LOG(ERROR, TAG, "memory alloc has failed");
+ return NULL;
+ }
blockDataID->idLength = tokenLength + sizeof(port);
blockDataID->id = (uint8_t *) OICMalloc(blockDataID->idLength);
if (!blockDataID->id)
#include "caadapternetdtls.h"
#endif
+#ifdef TCP_ADAPTER
+#include "catcpadapter.h"
+#endif
+
CAGlobals_t caglobals = { 0 };
#define TAG "CA_CONN_MGR"
if (interestedNetwork & CA_ADAPTER_IP)
{
res = CAAddNetworkType(CA_ADAPTER_IP);
- OIC_LOG_V(ERROR, TAG, "CAAddNetworkType(CA_IP_ADAPTER) function returns error : %d", res);
+ OIC_LOG_V(DEBUG, TAG, "CAAddNetworkType(CA_IP_ADAPTER) function returns result: %d", res);
}
else if (interestedNetwork & CA_ADAPTER_RFCOMM_BTEDR)
{
res = CAAddNetworkType(CA_ADAPTER_RFCOMM_BTEDR);
- OIC_LOG_V(ERROR, TAG, "CAAddNetworkType(CA_RFCOMM_ADAPTER) function returns error : %d", res);
+ OIC_LOG_V(DEBUG, TAG, "CAAddNetworkType(CA_RFCOMM_ADAPTER) function returns result : %d", res);
}
else if (interestedNetwork & CA_ADAPTER_GATT_BTLE)
{
res = CAAddNetworkType(CA_ADAPTER_GATT_BTLE);
- OIC_LOG_V(ERROR, TAG, "CAAddNetworkType(CA_GATT_ADAPTER) function returns error : %d", res);
+ OIC_LOG_V(DEBUG, TAG, "CAAddNetworkType(CA_GATT_ADAPTER) function returns result : %d", res);
}
- #ifdef RA_ADAPTER
+#ifdef RA_ADAPTER
else if (interestedNetwork & CA_ADAPTER_REMOTE_ACCESS)
{
res = CAAddNetworkType(CA_ADAPTER_REMOTE_ACCESS);
- OIC_LOG_V(ERROR, TAG, "CAAddNetworkType(CA_ADAPTER_REMOTE_ACCESS) function returns error : %d",
- res);
+ OIC_LOG_V(DEBUG, TAG,
+ "CAAddNetworkType(CA_ADAPTER_REMOTE_ACCESS) function returns result : %d", res);
+ }
+#endif
+
+#ifdef TCP_ADAPTER
+ else if (interestedNetwork & CA_ADAPTER_TCP)
+ {
+ res = CAAddNetworkType(CA_ADAPTER_TCP);
+ OIC_LOG_V(DEBUG, TAG,
+ "CAAddNetworkType(CA_ADAPTER_TCP) function returns result : %d", res);
}
- #endif
+#endif
+
else
{
res = CA_NOT_SUPPORTED;
if (nonInterestedNetwork & CA_ADAPTER_IP)
{
res = CARemoveNetworkType(CA_ADAPTER_IP);
- OIC_LOG_V(ERROR, TAG, "CARemoveNetworkType(CA_IP_ADAPTER) function returns error : %d", res);
+ OIC_LOG_V(DEBUG, TAG, "CARemoveNetworkType(CA_IP_ADAPTER) function returns result : %d", res);
}
else if (nonInterestedNetwork & CA_ADAPTER_RFCOMM_BTEDR)
{
res = CARemoveNetworkType(CA_ADAPTER_RFCOMM_BTEDR);
- OIC_LOG_V(ERROR, TAG, "CARemoveNetworkType(CA_RFCOMM_ADAPTER) function returns error : %d", res);
+ OIC_LOG_V(DEBUG, TAG, "CARemoveNetworkType(CA_RFCOMM_ADAPTER) function returns result : %d", res);
}
else if (nonInterestedNetwork & CA_ADAPTER_GATT_BTLE)
{
res = CARemoveNetworkType(CA_ADAPTER_GATT_BTLE);
- OIC_LOG_V(ERROR, TAG, "CARemoveNetworkType(CA_GATT_ADAPTER) function returns error : %d", res);
+ OIC_LOG_V(DEBUG, TAG, "CARemoveNetworkType(CA_GATT_ADAPTER) function returns result : %d", res);
}
- #ifdef RA_ADAPTER
+#ifdef RA_ADAPTER
else if (nonInterestedNetwork & CA_ADAPTER_REMOTE_ACCESS)
{
res = CARemoveNetworkType(CA_ADAPTER_REMOTE_ACCESS);
- OIC_LOG_V(ERROR, TAG, "CARemoveNetworkType(CA_ADAPTER_REMOTE_ACCESS) function returns error : %d",
- res);
+ OIC_LOG_V(DEBUG, TAG, "CARemoveNetworkType(CA_ADAPTER_REMOTE_ACCESS) function returns result : %d",
+ res);
}
- #endif
+#endif
+
+
+#ifdef TCP_ADAPTER
+ else if (nonInterestedNetwork & CA_ADAPTER_TCP)
+ {
+ res = CARemoveNetworkType(CA_ADAPTER_TCP);
+ OIC_LOG_V(DEBUG, TAG, "CARemoveNetworkType(CA_ADAPTER_TCP) function returns result : %d",
+ res);
+ }
+#endif
+
else
{
res = CA_STATUS_FAILED;
#include "caraadapter.h"
#endif
-#define TAG "CA_INTRFC_CNTRLR"
-#ifdef RA_ADAPTER
-#include "caraadapter.h"
+#ifdef TCP_ADAPTER
+#include "catcpadapter.h"
#endif
+#define TAG "CA_INTRFC_CNTRLR"
#define CA_MEMORY_ALLOC_CHECK(arg) {if (arg == NULL) \
{OIC_LOG(ERROR, TAG, "memory error");goto memory_error_exit;} }
-#ifdef RA_ADAPTER
+#ifdef TCP_ADAPTER
+#define CA_TRANSPORT_TYPE_NUM 5
+#elif RA_ADAPTER
#define CA_TRANSPORT_TYPE_NUM 4
#else
#define CA_TRANSPORT_TYPE_NUM 3
case CA_ADAPTER_RFCOMM_BTEDR:
return 2;
- #ifdef RA_ADAPTER
+#ifdef RA_ADAPTER
case CA_ADAPTER_REMOTE_ACCESS:
return 3;
- #endif
+#endif
+
+#ifdef TCP_ADAPTER
+ case CA_ADAPTER_TCP:
+ return 4;
+#endif
default:
break;
}
#endif
-static void CAReceivedPacketCallback(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLen)
+static void CAReceivedPacketCallback(const CASecureEndpoint_t *sep,
+ const void *data, uint32_t dataLen)
{
OIC_LOG(DEBUG, TAG, "IN");
- // Call the callback.
if (g_networkPacketReceivedCallback != NULL)
{
- g_networkPacketReceivedCallback(endpoint, data, dataLen);
+ g_networkPacketReceivedCallback(sep, data, dataLen);
}
else
{
handle);
#endif /* RA_ADAPTER */
-
+#ifdef TCP_ADAPTER
+ CAInitializeTCP(CARegisterCallback, CAReceivedPacketCallback, CANetworkChangedCallback,
+ CAAdapterErrorHandleCallback, handle);
+#endif /* TCP_ADAPTER */
}
void CASetPacketReceivedCallback(CANetworkPacketReceivedCallback callback)
const void *data, uint32_t dataLen,
CAResult_t result);
-static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, const void *data,
- CADataType_t dataType);
+static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint,
+ const CARemoteId_t *identity,
+ const void *data, CADataType_t dataType);
static void CASendErrorInfo(const CAEndpoint_t *endpoint, const CAInfo_t *info,
CAResult_t result);
#endif
static void CADestroyData(void *data, uint32_t size);
static void CALogPayloadInfo(CAInfo_t *info);
-static bool CADropSecondRequest(const CAEndpoint_t *endpoint, uint16_t messageId);
+static bool CADropSecondMessage(CAHistory_t *history, const CAEndpoint_t *endpoint, uint16_t id,
+ CAToken_t token, uint8_t tokenLength);
#ifdef WITH_BWT
void CAAddDataToSendThread(CAData_t *data)
static bool CAIsSelectedNetworkAvailable()
{
u_arraylist_t *list = CAGetSelectedNetworkList();
- if (!list || list->length == 0)
+ if (!list || u_arraylist_length(list) == 0)
{
OIC_LOG(ERROR, TAG, "No selected network");
return false;
return true;
}
-static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, const void *data, CADataType_t dataType)
+static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint,
+ const CARemoteId_t *identity,
+ const void *data, CADataType_t dataType)
{
OIC_LOG(DEBUG, TAG, "CAGenerateHandlerData IN");
CAInfo_t *info = NULL;
return NULL;
}
- result = CAGetResponseInfoFromPDU(data, resInfo);
+ result = CAGetResponseInfoFromPDU(data, resInfo, endpoint);
if (CA_STATUS_OK != result)
{
OIC_LOG(ERROR, TAG, "CAGetResponseInfoFromPDU Failed");
}
cadata->responseInfo = resInfo;
info = &resInfo->info;
+ if (identity)
+ {
+ info->identity = *identity;
+ }
OIC_LOG(DEBUG, TAG, "Response Info :");
CALogPayloadInfo(info);
}
return NULL;
}
- result = CAGetRequestInfoFromPDU(data, reqInfo);
+ result = CAGetRequestInfoFromPDU(data, endpoint, reqInfo);
if (CA_STATUS_OK != result)
{
OIC_LOG(ERROR, TAG, "CAGetRequestInfoFromPDU failed");
return NULL;
}
- if (CADropSecondRequest(endpoint, reqInfo->info.messageId))
+ if (CADropSecondMessage(&caglobals.ca.requestHistory, endpoint, reqInfo->info.messageId,
+ reqInfo->info.token, reqInfo->info.tokenLength))
{
OIC_LOG(ERROR, TAG, "Second Request with same Token, Drop it");
CAFreeEndpoint(ep);
cadata->requestInfo = reqInfo;
info = &reqInfo->info;
+ if (identity)
+ {
+ info->identity = *identity;
+ }
OIC_LOG(DEBUG, TAG, "Request Info :");
CALogPayloadInfo(info);
}
return NULL;
}
- CAResult_t result = CAGetErrorInfoFromPDU(data, errorInfo);
+ CAResult_t result = CAGetErrorInfoFromPDU(data, endpoint, errorInfo);
if (CA_STATUS_OK != result)
{
OIC_LOG(ERROR, TAG, "CAGetErrorInfoFromPDU failed");
cadata->errorInfo = errorInfo;
info = &errorInfo->info;
+ if (identity)
+ {
+ info->identity = *identity;
+ }
OIC_LOG(DEBUG, TAG, "error Info :");
CALogPayloadInfo(info);
}
resInfo->info.type = CAGetMessageTypeFromPduBinaryData(pdu, size);
resInfo->info.messageId = CAGetMessageIdFromPduBinaryData(pdu, size);
- CAResult_t res = CAGetTokenFromPDU((const coap_hdr_t *) pdu, &(resInfo->info));
+ CAResult_t res = CAGetTokenFromPDU((const coap_hdr_t *) pdu, &(resInfo->info),
+ endpoint);
if (CA_STATUS_OK != res)
{
OIC_LOG(ERROR, TAG, "fail to get Token from retransmission list");
CADestroyErrorInfoInternal(cadata->errorInfo);
}
- OICFree(cadata->options);
OICFree(cadata);
OIC_LOG(DEBUG, TAG, "CADestroyData OUT");
}
if (SEND_TYPE_UNICAST == type)
{
-
OIC_LOG(DEBUG,TAG,"Unicast message");
+#ifdef ROUTING_GATEWAY
+ /*
+ * When forwarding a packet, do not attempt retransmission as its the responsibility of
+ * packet originator node
+ */
+ bool skipRetransmission = false;
+#endif
+
if (NULL != data->requestInfo)
{
OIC_LOG(DEBUG, TAG, "requestInfo is available..");
info = &data->requestInfo->info;
+#ifdef ROUTING_GATEWAY
+ skipRetransmission = data->requestInfo->info.skipRetransmission;
+#endif
pdu = CAGeneratePDU(data->requestInfo->method, info, data->remoteEndpoint);
}
else if (NULL != data->responseInfo)
OIC_LOG(DEBUG, TAG, "responseInfo is available..");
info = &data->responseInfo->info;
+#ifdef ROUTING_GATEWAY
+ skipRetransmission = data->responseInfo->info.skipRetransmission;
+#endif
pdu = CAGeneratePDU(data->responseInfo->result, info, data->remoteEndpoint);
}
else
if (NULL != pdu)
{
#ifdef WITH_BWT
- if (CA_ADAPTER_GATT_BTLE != data->remoteEndpoint->adapter)
+ if (CA_ADAPTER_GATT_BTLE != data->remoteEndpoint->adapter
+#ifdef TCP_ADAPTER
+ && CA_ADAPTER_TCP != data->remoteEndpoint->adapter
+#endif
+ )
{
// Blockwise transfer
if (NULL != info)
{
- CAResult_t res = CAAddBlockOption(&pdu, *info,
+ CAResult_t res = CAAddBlockOption(&pdu, info,
data->remoteEndpoint);
if (CA_STATUS_OK != res)
{
}
}
#endif
- CALogPDUInfo(pdu);
+ CALogPDUInfo(pdu, data->remoteEndpoint);
res = CASendUnicastData(data->remoteEndpoint, pdu->hdr, pdu->length);
if (CA_STATUS_OK != res)
coap_delete_pdu(pdu);
return res;
}
- // for retransmission
- res = CARetransmissionSentData(&g_retransmissionContext, data->remoteEndpoint, pdu->hdr,
- pdu->length);
- if ((CA_STATUS_OK != res) && (CA_NOT_SUPPORTED != res))
+
+#ifdef TCP_ADAPTER
+ if (CA_ADAPTER_TCP == data->remoteEndpoint->adapter)
{
- //when retransmission not supported this will return CA_NOT_SUPPORTED, ignore
- OIC_LOG_V(INFO, TAG, "retransmission is not enabled due to error, res : %d", res);
- coap_delete_pdu(pdu);
- return res;
+ OIC_LOG(INFO, TAG, "retransmission will be not worked");
+ }
+ else
+#endif
+#ifdef ROUTING_GATEWAY
+ if(!skipRetransmission)
+#endif
+ {
+ // for retransmission
+ res = CARetransmissionSentData(&g_retransmissionContext, data->remoteEndpoint,
+ pdu->hdr, pdu->length);
+ if ((CA_STATUS_OK != res) && (CA_NOT_SUPPORTED != res))
+ {
+ //when retransmission not supported this will return CA_NOT_SUPPORTED, ignore
+ OIC_LOG_V(INFO, TAG, "retransmission is not enabled due to error, res : %d", res);
+ coap_delete_pdu(pdu);
+ return res;
+ }
}
coap_delete_pdu(pdu);
if (NULL != pdu)
{
#ifdef WITH_BWT
- if (CA_ADAPTER_GATT_BTLE != data->remoteEndpoint->adapter)
+ if (CA_ADAPTER_GATT_BTLE != data->remoteEndpoint->adapter
+#ifdef TCP_ADAPTER
+ && CA_ADAPTER_TCP != data->remoteEndpoint->adapter
+#endif
+ )
{
// Blockwise transfer
- CAResult_t res = CAAddBlockOption(&pdu, data->requestInfo->info,
+ CAResult_t res = CAAddBlockOption(&pdu, &data->requestInfo->info,
data->remoteEndpoint);
if (CA_STATUS_OK != res)
{
}
}
#endif
- CALogPDUInfo(pdu);
+ }
+ else
+ {
+ OIC_LOG(ERROR,TAG,"Failed to generate multicast PDU");
+ CASendErrorInfo(data->remoteEndpoint, info, CA_SEND_FAILED);
+ return CA_SEND_FAILED;
+ }
+ }
+ else if (NULL != data->responseInfo)
+ {
+ OIC_LOG(DEBUG, TAG, "responseInfo is available..");
+
+ info = &data->responseInfo->info;
+ pdu = CAGeneratePDU(data->responseInfo->result, info, data->remoteEndpoint);
- res = CASendMulticastData(data->remoteEndpoint, pdu->hdr, pdu->length);
- if (CA_STATUS_OK != res)
+ if (NULL != pdu)
+ {
+#ifdef WITH_BWT
+ if (CA_ADAPTER_GATT_BTLE != data->remoteEndpoint->adapter
+#ifdef TCP_ADAPTER
+ && CA_ADAPTER_TCP != data->remoteEndpoint->adapter
+#endif
+ )
{
- OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
- CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res);
- coap_delete_pdu(pdu);
- return res;
+ // Blockwise transfer
+ if (NULL != info)
+ {
+ CAResult_t res = CAAddBlockOption(&pdu, info,
+ data->remoteEndpoint);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(INFO, TAG, "to write block option has failed");
+ CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res);
+ coap_delete_pdu(pdu);
+ return res;
+ }
+ }
}
-
- coap_delete_pdu(pdu);
+#endif
}
else
{
}
else
{
- OIC_LOG(ERROR, TAG, "request info is empty");
+ OIC_LOG(ERROR, TAG, "request or response info is empty");
return CA_SEND_FAILED;
}
+
+ CALogPDUInfo(pdu, data->remoteEndpoint);
+
+ OIC_LOG(DEBUG, TAG, "pdu to send :");
+ OIC_LOG_BUFFER(DEBUG, TAG, pdu->hdr, pdu->length);
+
+ res = CASendMulticastData(data->remoteEndpoint, pdu->hdr, pdu->length);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
+ CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res);
+ coap_delete_pdu(pdu);
+ return res;
+ }
+
+ coap_delete_pdu(pdu);
}
- OIC_LOG(DEBUG, TAG, "OUT");
return CA_STATUS_OK;
}
#endif
/*
- * If a second message arrives with the same token and the other address
+ * If a second message arrives with the same message ID, token and the other address
* family, drop it. Typically, IPv6 beats IPv4, so the IPv4 message is dropped.
- * This can be made more robust (for instance, another message could arrive
- * in between), but it is good enough for now.
*/
-static bool CADropSecondRequest(const CAEndpoint_t *endpoint, uint16_t messageId)
+static bool CADropSecondMessage(CAHistory_t *history, const CAEndpoint_t *ep, uint16_t id,
+ CAToken_t token, uint8_t tokenLength)
{
- if (!endpoint)
+ if (!ep)
{
return true;
}
- if (endpoint->adapter != CA_ADAPTER_IP)
+ if (ep->adapter != CA_ADAPTER_IP)
{
return false;
}
+ if (!caglobals.ip.dualstack)
+ {
+ return false;
+ }
+
+ if (tokenLength > CA_MAX_TOKEN_LEN)
+ {
+ /*
+ * If token length is more than CA_MAX_TOKEN_LEN,
+ * we compare the first CA_MAX_TOKEN_LEN bytes only.
+ */
+ tokenLength = CA_MAX_TOKEN_LEN;
+ }
bool ret = false;
- CATransportFlags_t familyFlags = endpoint->flags & CA_IPFAMILY_MASK;
+ CATransportFlags_t familyFlags = ep->flags & CA_IPFAMILY_MASK;
- if (messageId == caglobals.ca.previousRequestMessageId)
+ for (size_t i = 0; i < sizeof(history->items) / sizeof(history->items[0]); i++)
{
- if ((familyFlags ^ caglobals.ca.previousRequestFlags) == CA_IPFAMILY_MASK)
+ CAHistoryItem_t *item = &(history->items[i]);
+ if (id == item->messageId && tokenLength == item->tokenLength
+ && memcmp(item->token, token, tokenLength) == 0)
{
- if (familyFlags & CA_IPV6)
- {
- OIC_LOG(INFO, TAG, "IPv6 duplicate response ignored");
- }
- else
+ if ((familyFlags ^ item->flags) == CA_IPFAMILY_MASK)
{
- OIC_LOG(INFO, TAG, "IPv4 duplicate response ignored");
+ OIC_LOG_V(INFO, TAG, "IPv%c duplicate message ignored",
+ familyFlags & CA_IPV6 ? '6' : '4');
+ ret = true;
+ break;
}
- ret = true;
}
}
- caglobals.ca.previousRequestFlags = familyFlags;
- caglobals.ca.previousRequestMessageId = messageId;
+
+ history->items[history->nextIndex].flags = familyFlags;
+ history->items[history->nextIndex].messageId = id;
+ if (token && tokenLength)
+ {
+ memcpy(history->items[history->nextIndex].token, token, tokenLength);
+ history->items[history->nextIndex].tokenLength = tokenLength;
+ }
+
+ if (++history->nextIndex >= HISTORYSIZE)
+ {
+ history->nextIndex = 0;
+ }
+
return ret;
}
-static void CAReceivedPacketCallback(const CAEndpoint_t *remoteEndpoint, const void *data, uint32_t dataLen)
+static void CAReceivedPacketCallback(const CASecureEndpoint_t *sep,
+ const void *data, uint32_t dataLen)
{
OIC_LOG(DEBUG, TAG, "IN");
- VERIFY_NON_NULL_VOID(remoteEndpoint, TAG, "remoteEndpoint");
+ VERIFY_NON_NULL_VOID(sep, TAG, "remoteEndpoint");
VERIFY_NON_NULL_VOID(data, TAG, "data");
+ OIC_LOG(DEBUG, TAG, "received pdu data :");
+ OIC_LOG_BUFFER(DEBUG, TAG, data, dataLen);
+
uint32_t code = CA_NOT_FOUND;
CAData_t *cadata = NULL;
- coap_pdu_t *pdu = (coap_pdu_t *) CAParsePDU((const char *) data, dataLen, &code);
+ coap_pdu_t *pdu = (coap_pdu_t *) CAParsePDU((const char *) data, dataLen, &code,
+ &(sep->endpoint));
if (NULL == pdu)
{
OIC_LOG(ERROR, TAG, "Parse PDU failed");
OIC_LOG_V(DEBUG, TAG, "code = %d", code);
if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code)
{
- cadata = CAGenerateHandlerData(remoteEndpoint, pdu, CA_REQUEST_DATA);
+ cadata = CAGenerateHandlerData(&(sep->endpoint), &(sep->identity), pdu, CA_REQUEST_DATA);
if (!cadata)
{
OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, CAGenerateHandlerData failed!");
}
else
{
- cadata = CAGenerateHandlerData(remoteEndpoint, pdu, CA_RESPONSE_DATA);
+ cadata = CAGenerateHandlerData(&(sep->endpoint), &(sep->identity), pdu, CA_RESPONSE_DATA);
if (!cadata)
{
OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, CAGenerateHandlerData failed!");
return;
}
- // for retransmission
- void *retransmissionPdu = NULL;
- CARetransmissionReceivedData(&g_retransmissionContext, cadata->remoteEndpoint, pdu->hdr,
- pdu->length, &retransmissionPdu);
-
- // get token from saved data in retransmission list
- if (retransmissionPdu && CA_EMPTY == code)
+#ifdef TCP_ADAPTER
+ if (CA_ADAPTER_TCP == sep->endpoint.adapter)
+ {
+ OIC_LOG(INFO, TAG, "retransmission is not supported");
+ }
+ else
+#endif
{
- if (cadata->responseInfo)
+ // for retransmission
+ void *retransmissionPdu = NULL;
+ CARetransmissionReceivedData(&g_retransmissionContext, cadata->remoteEndpoint, pdu->hdr,
+ pdu->length, &retransmissionPdu);
+
+ // get token from saved data in retransmission list
+ if (retransmissionPdu && CA_EMPTY == code)
{
- CAInfo_t *info = &cadata->responseInfo->info;
- CAResult_t res = CAGetTokenFromPDU((const coap_hdr_t *)retransmissionPdu,
- info);
- if (CA_STATUS_OK != res)
+ if (cadata->responseInfo)
{
- OIC_LOG(ERROR, TAG, "fail to get Token from retransmission list");
- OICFree(info->token);
- info->tokenLength = 0;
+ CAInfo_t *info = &cadata->responseInfo->info;
+ CAResult_t res = CAGetTokenFromPDU((const coap_hdr_t *)retransmissionPdu,
+ info, &(sep->endpoint));
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "fail to get Token from retransmission list");
+ OICFree(info->token);
+ info->tokenLength = 0;
+ }
}
}
+ OICFree(retransmissionPdu);
}
- OICFree(retransmissionPdu);
}
cadata->type = SEND_TYPE_UNICAST;
CAProcessReceivedData(cadata);
#else
#ifdef WITH_BWT
- if (CA_ADAPTER_GATT_BTLE != remoteEndpoint->adapter)
+ if (CA_ADAPTER_GATT_BTLE != sep->endpoint.adapter
+#ifdef TCP_ADAPTER
+ && CA_ADAPTER_TCP != sep->endpoint.adapter
+#endif
+ )
+ {
+ CAResult_t res = CAReceiveBlockWiseData(pdu, &(sep->endpoint), cadata, dataLen);
+ if (CA_NOT_SUPPORTED == res)
{
- CAResult_t res = CAReceiveBlockWiseData(pdu, remoteEndpoint, cadata, dataLen);
- if (CA_NOT_SUPPORTED == res)
- {
- OIC_LOG(ERROR, TAG, "this message does not have block option");
- CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
- }
- else
- {
- CADestroyData(cadata, sizeof(CAData_t));
- }
+ OIC_LOG(ERROR, TAG, "this message does not have block option");
+ CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
}
else
-#endif
{
- CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
+ CADestroyData(cadata, sizeof(CAData_t));
}
+ }
+ else
+#endif
+ {
+ CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t));
+ }
#endif
coap_delete_pdu(pdu);
CADataType_t dataType)
{
OIC_LOG(DEBUG, TAG, "CAPrepareSendData IN");
- CAInfo_t *info = NULL;
CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
if (!cadata)
}
cadata->type = request->isMulticast ? SEND_TYPE_MULTICAST : SEND_TYPE_UNICAST;
- info = &request->info;
cadata->requestInfo = request;
}
else if(CA_RESPONSE_DATA == dataType)
return NULL;
}
- cadata->type = SEND_TYPE_UNICAST;
- info = &response->info;
+ cadata->type = response->isMulticast ? SEND_TYPE_MULTICAST : SEND_TYPE_UNICAST;
cadata->responseInfo = response;
}
else
return NULL;
}
- if (NULL != info->options && 0 < info->numOptions)
- {
- uint8_t numOptions = info->numOptions;
- // copy data
- CAHeaderOption_t *headerOption = (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t)
- * numOptions);
- if(!headerOption)
- {
- OIC_LOG(ERROR, TAG, "memory allocation failed");
- CADestroyData(cadata, sizeof(CAData_t));
- return NULL;
- }
-
- memcpy(headerOption, info->options, sizeof(CAHeaderOption_t) * numOptions);
-
- cadata->options = headerOption;
- cadata->numOptions = numOptions;
- }
-
CAEndpoint_t* ep = CACloneEndpoint(endpoint);
if (!ep)
{
CADestroyData(data, sizeof(CAData_t));
#else
#ifdef WITH_BWT
- if (CA_ADAPTER_GATT_BTLE != object->adapter)
+ if (CA_ADAPTER_GATT_BTLE != object->adapter
+#ifdef TCP_ADAPTER
+ && CA_ADAPTER_TCP != object->adapter
+#endif
+ )
{
// send block data
CAResult_t res = CASendBlockWiseData(data);
CADestroyData(data, sizeof(CAData_t));
#else
#ifdef WITH_BWT
- if (CA_ADAPTER_GATT_BTLE != object->adapter)
+ if (CA_ADAPTER_GATT_BTLE != object->adapter
+#ifdef TCP_ADAPTER
+ && CA_ADAPTER_TCP != object->adapter
+#endif
+ )
{
// send block data
CAResult_t res = CASendBlockWiseData(data);
OIC_LOG(DEBUG, TAG, "OUT");
}
-void CALogPDUInfo(coap_pdu_t *pdu)
+void CALogPDUInfo(coap_pdu_t *pdu, const CAEndpoint_t *endpoint)
{
VERIFY_NON_NULL_VOID(pdu, TAG, "pdu");
OIC_LOG_V(DEBUG, TAG, "PDU Maker - payload : %s", pdu->data);
- OIC_LOG_V(DEBUG, TAG, "PDU Maker - type : %d", pdu->hdr->type);
+#ifdef TCP_ADAPTER
+ if (CA_ADAPTER_TCP == endpoint->adapter)
+ {
+ OIC_LOG(DEBUG, TAG, "pdu header data :");
+ OIC_LOG_BUFFER(DEBUG, TAG, pdu->hdr, pdu->length);
+ }
+ else
+#endif
+ {
+ OIC_LOG_V(DEBUG, TAG, "PDU Maker - type : %d", pdu->hdr->coap_hdr_udp_t.type);
- OIC_LOG_V(DEBUG, TAG, "PDU Maker - code : %d", pdu->hdr->code);
+ OIC_LOG_V(DEBUG, TAG, "PDU Maker - code : %d", pdu->hdr->coap_hdr_udp_t.code);
- OIC_LOG(DEBUG, TAG, "PDU Maker - token :");
+ OIC_LOG(DEBUG, TAG, "PDU Maker - token :");
- OIC_LOG_BUFFER(DEBUG, TAG, pdu->hdr->token, pdu->hdr->token_length);
+ OIC_LOG_BUFFER(DEBUG, TAG, pdu->hdr->coap_hdr_udp_t.token,
+ pdu->hdr->coap_hdr_udp_t.token_length);
+ }
}
static void CALogPayloadInfo(CAInfo_t *info)
{
if(info)
{
- if (!info->options)
+ if (info->options)
{
for (uint32_t i = 0; i < info->numOptions; i++)
{
}
}
- if (!info->payload)
+ if (info->payload)
{
OIC_LOG_V(DEBUG, TAG, "payload: %p(%u)", info->payload,
info->payloadSize);
}
- if (!info->token)
+ if (info->token)
{
OIC_LOG(DEBUG, TAG, "token:");
OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *) info->token,
uint32_t code = CA_NOT_FOUND;
//Do not free remoteEndpoint and data. Currently they will be freed in data thread
//Get PDU data
- coap_pdu_t *pdu = (coap_pdu_t *)CAParsePDU((const char *)data, dataLen, &code);
+ coap_pdu_t *pdu = (coap_pdu_t *)CAParsePDU((const char *)data, dataLen, &code, endpoint);
if (NULL == pdu)
{
OIC_LOG(ERROR, TAG, "Parse PDU failed");
return;
}
- CAData_t *cadata = CAGenerateHandlerData(endpoint, pdu, CA_ERROR_DATA);
+ CAData_t *cadata = CAGenerateHandlerData(endpoint, NULL, pdu, CA_ERROR_DATA);
if(!cadata)
{
OIC_LOG(ERROR, TAG, "CAErrorHandler, CAGenerateHandlerData failed!");
static uint32_t NETWORK_RA = CA_ADAPTER_REMOTE_ACCESS;
#endif
+#ifdef TCP_ADAPTER
+static uint32_t NETWORK_TCP = CA_ADAPTER_TCP;
+#endif
+
CAResult_t CAAddNetworkType(CATransportAdapter_t transportType)
{
OIC_LOG(DEBUG, TAG, "IN");
return CA_MEMORY_ALLOC_FAILED;
}
}
- CAResult_t res = CA_STATUS_OK;
+ bool res = true;
switch (transportType)
{
case CA_ADAPTER_IP:
break;
#endif /* RA_ADAPTER */
+#ifdef TCP_ADAPTER
+ case CA_ADAPTER_TCP:
+
+ OIC_LOG(DEBUG, TAG, "Add network type(TCP)");
+ if (u_arraylist_contains(g_selectedNetworkList, &NETWORK_TCP))
+ {
+ goto exit;
+ }
+ res = u_arraylist_add(g_selectedNetworkList, &NETWORK_TCP);
+ break;
+#endif /* TCP_ADAPTER */
+
default:
break;
}
- if (CA_STATUS_OK != res)
+ if (!res)
{
OIC_LOG_V(ERROR, TAG, "Add arraylist failed[Err code: %d]", res);
- return res;
+ return CA_STATUS_FAILED;
}
// start selected interface adapter
- res = CAStartAdapter(transportType);
+ CAResult_t result = CAStartAdapter(transportType);
OIC_LOG(DEBUG, TAG, "OUT");
- return res;
+ return result;
exit:
OIC_LOG(DEBUG, TAG, "This adapter is already enabled");
break;
#endif /* RA_ADAPTER */
+#ifdef TCP_ADAPTER
+ case CA_ADAPTER_TCP:
+ OIC_LOG(DEBUG, TAG, "Remove network type(TCP)");
+ u_arraylist_remove(g_selectedNetworkList, index);
+ break;
+#endif /* TCP_ADAPTER */
+
default:
break;
}
static unsigned int SEED = 0;
-CAResult_t CAGetRequestInfoFromPDU(const coap_pdu_t *pdu, CARequestInfo_t *outReqInfo)
+CAResult_t CAGetRequestInfoFromPDU(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
+ CARequestInfo_t *outReqInfo)
{
OIC_LOG(DEBUG, TAG, "IN");
}
uint32_t code = CA_NOT_FOUND;
- CAResult_t ret = CAGetInfoFromPDU(pdu, &code, &(outReqInfo->info));
+ CAResult_t ret = CAGetInfoFromPDU(pdu, endpoint, &code, &(outReqInfo->info));
outReqInfo->method = code;
OIC_LOG(DEBUG, TAG, "OUT");
return ret;
}
-CAResult_t CAGetResponseInfoFromPDU(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo)
+CAResult_t CAGetResponseInfoFromPDU(const coap_pdu_t *pdu, CAResponseInfo_t *outResInfo,
+ const CAEndpoint_t *endpoint)
{
OIC_LOG(DEBUG, TAG, "IN");
}
uint32_t code = CA_NOT_FOUND;
- CAResult_t ret = CAGetInfoFromPDU(pdu, &code, &(outResInfo->info));
+ CAResult_t ret = CAGetInfoFromPDU(pdu, endpoint, &code, &(outResInfo->info));
outResInfo->result = code;
OIC_LOG(DEBUG, TAG, "OUT");
return ret;
}
-CAResult_t CAGetErrorInfoFromPDU(const coap_pdu_t *pdu, CAErrorInfo_t *errorInfo)
+CAResult_t CAGetErrorInfoFromPDU(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
+ CAErrorInfo_t *errorInfo)
{
OIC_LOG(DEBUG, TAG, "IN");
}
uint32_t code = 0;
- CAResult_t ret = CAGetInfoFromPDU(pdu, &code, &errorInfo->info);
+ CAResult_t ret = CAGetInfoFromPDU(pdu, endpoint, &code, &errorInfo->info);
OIC_LOG(DEBUG, TAG, "OUT");
return ret;
}
{
OIC_LOG(DEBUG, TAG, "IN");
+ VERIFY_NON_NULL_RET(info, TAG, "info", NULL);
+ VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", NULL);
+
coap_pdu_t *pdu = NULL;
// RESET have to use only 4byte (empty message)
if (CA_MSG_RESET == info->type || (CA_EMPTY == code && CA_MSG_ACKNOWLEDGE == info->type))
{
OIC_LOG(DEBUG, TAG, "code is empty");
- if (!(pdu = CAGeneratePDUImpl((code_t) code, NULL, info, endpoint)))
+ if (!(pdu = CAGeneratePDUImpl((code_t) code, info, endpoint, NULL)))
{
OIC_LOG(ERROR, TAG, "pdu NULL");
return NULL;
return NULL;
}
- pdu = CAGeneratePDUImpl((code_t) code, optlist, info, endpoint);
+ pdu = CAGeneratePDUImpl((code_t) code, info, endpoint, optlist);
if (NULL == pdu)
{
OIC_LOG(ERROR, TAG, "pdu NULL");
return pdu;
}
-coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode)
+coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode,
+ const CAEndpoint_t *endpoint)
{
OIC_LOG(DEBUG, TAG, "IN");
return NULL;
}
- coap_pdu_t *outpdu = coap_new_pdu();
+ coap_transport_type transport;
+#ifdef TCP_ADAPTER
+ if (CA_ADAPTER_TCP == endpoint->adapter)
+ {
+ transport = coap_get_tcp_header_type_from_initbyte(((unsigned char *)data)[0] >> 4);
+ }
+ else
+#endif
+ {
+ transport = coap_udp;
+ }
+
+ coap_pdu_t *outpdu = coap_new_pdu(transport, length);
if (NULL == outpdu)
{
OIC_LOG(ERROR, TAG, "outpdu is null");
return NULL;
}
- if (0 >= coap_pdu_parse((unsigned char *) data, length, outpdu))
+ OIC_LOG_V(DEBUG, TAG, "pdu parse-transport type : %d", transport);
+
+ int ret = coap_pdu_parse((unsigned char *) data, length, outpdu, transport);
+ OIC_LOG_V(DEBUG, TAG, "pdu parse ret: %d", ret);
+ if (0 >= ret)
{
OIC_LOG(ERROR, TAG, "pdu parse failed");
coap_delete_pdu(outpdu);
return NULL;
}
+#ifdef TCP_ADAPTER
+ if (CA_ADAPTER_TCP == endpoint->adapter)
+ {
+ OIC_LOG(INFO, TAG, "there is no version info in coap header");
+ }
+ else
+#endif
+ {
+ if (outpdu->hdr->coap_hdr_udp_t.version != COAP_DEFAULT_VERSION)
+ {
+ OIC_LOG_V(ERROR, TAG, "coap version is not available : %d",
+ outpdu->hdr->coap_hdr_udp_t.version);
+ coap_delete_pdu(outpdu);
+ return NULL;
+ }
+ if (outpdu->hdr->coap_hdr_udp_t.token_length > CA_MAX_TOKEN_LEN)
+ {
+ OIC_LOG_V(ERROR, TAG, "token length has been exceed : %d",
+ outpdu->hdr->coap_hdr_udp_t.token_length);
+ coap_delete_pdu(outpdu);
+ return NULL;
+ }
+ }
+
if (outCode)
{
- (*outCode) = (uint32_t) CA_RESPONSE_CODE(outpdu->hdr->code);
+ (*outCode) = (uint32_t) CA_RESPONSE_CODE(coap_get_code(outpdu, transport));
}
OIC_LOG(DEBUG, TAG, "OUT");
return outpdu;
}
-coap_pdu_t *CAGeneratePDUImpl(code_t code, coap_list_t *options, const CAInfo_t *info,
- const CAEndpoint_t *endpoint)
+coap_pdu_t *CAGeneratePDUImpl(code_t code, const CAInfo_t *info,
+ const CAEndpoint_t *endpoint, coap_list_t *options)
{
OIC_LOG(DEBUG, TAG, "IN");
- VERIFY_NON_NULL_RET(info, TAG, "info is NULL", NULL);
+ VERIFY_NON_NULL_RET(info, TAG, "info", NULL);
+ VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", NULL);
+
+ coap_transport_type transport;
+ unsigned int length = COAP_MAX_PDU_SIZE;
+#ifdef TCP_ADAPTER
+ unsigned int headerLength = 0;
+ if (CA_ADAPTER_TCP == endpoint->adapter)
+ {
+ if (options)
+ {
+ for (coap_list_t *opt = options; opt; opt = opt->next)
+ {
+ headerLength += COAP_OPTION_LENGTH(*(coap_option *) opt->data) + 1;
+ }
+ }
+
+ if (info->payloadSize > 0)
+ {
+ headerLength = headerLength + info->payloadSize + 1;
+ }
+ transport = coap_get_tcp_header_type_from_size(headerLength);
+ length = headerLength + coap_get_tcp_header_length_for_transport(transport)
+ + info->tokenLength;
+ }
+ else
+#endif
+ {
+ transport = coap_udp;
+ }
- coap_pdu_t *pdu = coap_new_pdu();
+ coap_pdu_t *pdu = coap_new_pdu(transport, length);
if (NULL == pdu)
{
return NULL;
}
- OIC_LOG_V(DEBUG, TAG, "msgID is %d", info->messageId);
- uint16_t message_id;
- if (0 == info->messageId)
- {
- /* initialize message id */
- prng((uint8_t * ) &message_id, sizeof(message_id));
+ OIC_LOG_V(DEBUG, TAG, "transport type: %d, payload size: %d",
+ transport, info->payloadSize);
- OIC_LOG_V(DEBUG, TAG, "gen msg id=%d", message_id);
+#ifdef TCP_ADAPTER
+ if (CA_ADAPTER_TCP == endpoint->adapter)
+ {
+ coap_add_length(pdu, transport, headerLength);
}
else
+#endif
{
- /* use saved message id */
- message_id = info->messageId;
+ OIC_LOG_V(DEBUG, TAG, "msgID is %d", info->messageId);
+ uint16_t message_id;
+ if (0 == info->messageId)
+ {
+ /* initialize message id */
+ prng((uint8_t * ) &message_id, sizeof(message_id));
+
+ OIC_LOG_V(DEBUG, TAG, "gen msg id=%d", message_id);
+ }
+ else
+ {
+ /* use saved message id */
+ message_id = info->messageId;
+ }
+ pdu->hdr->coap_hdr_udp_t.id = message_id;
+ OIC_LOG_V(DEBUG, TAG, "messageId in pdu is %d, %d", message_id, pdu->hdr->coap_hdr_udp_t.id);
+
+ pdu->hdr->coap_hdr_udp_t.type = info->type;
}
- pdu->hdr->id = message_id;
- OIC_LOG_V(DEBUG, TAG, "messageId in pdu is %d, %d", message_id, pdu->hdr->id);
- pdu->hdr->type = info->type;
- pdu->hdr->code = COAP_RESPONSE_CODE(code);
+ coap_add_code(pdu, transport, code);
if (info->token && CA_EMPTY != code)
{
OIC_LOG_V(DEBUG, TAG, "token info token length: %d, token :", tokenLength);
OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *)info->token, tokenLength);
- int32_t ret = coap_add_token(pdu, tokenLength, (unsigned char *)info->token);
+ int32_t ret = coap_add_token(pdu, tokenLength, (unsigned char *)info->token, transport);
if (0 == ret)
{
OIC_LOG(ERROR, TAG, "can't add token");
{
OIC_LOG_V(DEBUG, TAG, "[%s] opt will be added.",
COAP_OPTION_DATA(*(coap_option *) opt->data));
+
+ OIC_LOG_V(DEBUG, TAG, "[%d] pdu length", pdu->length);
coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *) opt->data),
COAP_OPTION_LENGTH(*(coap_option *) opt->data),
- COAP_OPTION_DATA(*(coap_option *) opt->data));
+ COAP_OPTION_DATA(*(coap_option *) opt->data), transport);
}
}
+ OIC_LOG_V(DEBUG, TAG, "[%d] pdu length after option", pdu->length);
+
bool enabledPayload = false;
#ifndef WITH_BWT
enabledPayload = true;
#endif
- if (enabledPayload || CA_ADAPTER_GATT_BTLE == endpoint->adapter)
+ if (enabledPayload || CA_ADAPTER_GATT_BTLE == endpoint->adapter
+#ifdef TCP_ADAPTER
+ || CA_ADAPTER_TCP == endpoint->adapter
+#endif
+ )
{
if (NULL != info->payload && 0 < info->payloadSize)
{
}
else
{
- if ((info->options + i)->optionData && (info->options + i)->optionLength > 0)
+ OIC_LOG_V(DEBUG, TAG, "Head opt ID: %d", id);
+ OIC_LOG_V(DEBUG, TAG, "Head opt data: %s", (info->options + i)->optionData);
+ OIC_LOG_V(DEBUG, TAG, "Head opt length: %d", (info->options + i)->optionLength);
+ int ret = coap_insert(optlist,
+ CACreateNewOptionNode(id, (info->options + i)->optionLength,
+ (info->options + i)->optionData),
+ CAOrderOpts);
+ if (ret <= 0)
{
- OIC_LOG_V(DEBUG, TAG, "Head opt ID: %d", id);
- OIC_LOG_V(DEBUG, TAG, "Head opt data: %s", (info->options + i)->optionData);
- OIC_LOG_V(DEBUG, TAG, "Head opt length: %d", (info->options + i)->optionLength);
- int ret = coap_insert(optlist,
- CACreateNewOptionNode(id, (info->options + i)->optionLength,
- (info->options + i)->optionData),
- CAOrderOpts);
- if (ret <= 0)
- {
- return CA_STATUS_INVALID_PARAM;
- }
+ return CA_STATUS_INVALID_PARAM;
}
}
}
+ // insert one extra header with the payload format if applicable.
+ if (CA_FORMAT_UNDEFINED != info->payloadFormat)
+ {
+ coap_list_t* node = NULL;
+ uint8_t buf[3] = {0};
+ switch (info->payloadFormat) {
+ case CA_FORMAT_APPLICATION_CBOR:
+ node = CACreateNewOptionNode(
+ COAP_OPTION_CONTENT_FORMAT,
+ coap_encode_var_bytes(buf, (uint16_t)COAP_MEDIATYPE_APPLICATION_CBOR),
+ (char *)buf);
+ break;
+ default:
+ OIC_LOG_V(ERROR, TAG, "format option:[%d] not supported", info->payloadFormat);
+ }
+ if (!node)
+ {
+ OIC_LOG(ERROR, TAG, "format option not created");
+ return CA_STATUS_INVALID_PARAM;
+ }
+ int ret = coap_insert(optlist, node, CAOrderOpts);
+ if (ret <= 0)
+ {
+ coap_delete(node);
+ OIC_LOG(ERROR, TAG, "format option not inserted in header");
+ return CA_STATUS_INVALID_PARAM;
+ }
+ }
+ if (CA_FORMAT_UNDEFINED != info->acceptFormat)
+ {
+ coap_list_t* node = NULL;
+ uint8_t buf[3] = {0};
+ switch (info->acceptFormat) {
+ case CA_FORMAT_APPLICATION_CBOR:
+ node = CACreateNewOptionNode(
+ COAP_OPTION_ACCEPT,
+ coap_encode_var_bytes(buf, (uint16_t)COAP_MEDIATYPE_APPLICATION_CBOR),
+ (char *)buf);
+ break;
+ default:
+ OIC_LOG_V(ERROR, TAG, "format option:[%d] not supported", info->acceptFormat);
+ }
+ if (!node)
+ {
+ OIC_LOG(ERROR, TAG, "format option not created");
+ return CA_STATUS_INVALID_PARAM;
+ }
+ int ret = coap_insert(optlist, node, CAOrderOpts);
+ if (ret <= 0)
+ {
+ coap_delete(node);
+ OIC_LOG(ERROR, TAG, "format option not inserted in header");
+ return CA_STATUS_INVALID_PARAM;
+ }
+ }
+
OIC_LOG(DEBUG, TAG, "OUT");
return CA_STATUS_OK;
}
memset(option, 0, sizeof(coap_option) + length + 1);
COAP_OPTION_KEY(*option) = key;
- COAP_OPTION_LENGTH(*option) = length;
- memcpy(COAP_OPTION_DATA(*option), data, length);
+
+ coap_option_def_t* def = coap_opt_def(key);
+ if (NULL != def && coap_is_var_bytes(def))
+ {
+ if (length > def->max)
+ {
+ // make sure we shrink the value so it fits the coap option definition
+ // by truncating the value, disregard the leading bytes.
+ OIC_LOG_V(DEBUG, TAG, "Option [%d] data size [%d] shrunk to [%d]",
+ def->key, length, def->max);
+ data = &(data[length-def->max]);
+ length = def->max;
+ }
+ // Shrink the encoding length to a minimum size for coap
+ // options that support variable length encoding.
+ COAP_OPTION_LENGTH(*option) = coap_encode_var_bytes(
+ COAP_OPTION_DATA(*option),
+ coap_decode_var_bytes((unsigned char *)data, length));
+ }
+ else
+ {
+ COAP_OPTION_LENGTH(*option) = length;
+ memcpy(COAP_OPTION_DATA(*option), data, length);
+ }
/* we can pass NULL here as delete function since option is released automatically */
coap_list_t *node = coap_new_listnode(option, NULL);
{
if (COAP_OPTION_URI_PATH != opt_iter.type && COAP_OPTION_URI_QUERY != opt_iter.type
&& COAP_OPTION_BLOCK1 != opt_iter.type && COAP_OPTION_BLOCK2 != opt_iter.type
- && COAP_OPTION_SIZE1 != opt_iter.type && COAP_OPTION_SIZE2 != opt_iter.type)
+ && COAP_OPTION_SIZE1 != opt_iter.type && COAP_OPTION_SIZE2 != opt_iter.type
+ && COAP_OPTION_CONTENT_FORMAT != opt_iter.type
+ && COAP_OPTION_ACCEPT != opt_iter.type)
{
count++;
}
return count;
}
-CAResult_t CAGetInfoFromPDU(const coap_pdu_t *pdu, uint32_t *outCode, CAInfo_t *outInfo)
+CAResult_t CAGetInfoFromPDU(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
+ uint32_t *outCode, CAInfo_t *outInfo)
{
OIC_LOG(DEBUG, TAG, "IN");
return CA_STATUS_INVALID_PARAM;
}
+ coap_transport_type transport;
+#ifdef TCP_ADAPTER
+ if (CA_ADAPTER_TCP == endpoint->adapter)
+ {
+ transport = coap_get_tcp_header_type_from_initbyte(((unsigned char *)pdu->hdr)[0] >> 4);
+ }
+ else
+#endif
+ {
+ transport = coap_udp;
+ }
+
coap_opt_iterator_t opt_iter;
- coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL);
+ coap_option_iterator_init((coap_pdu_t *) pdu, &opt_iter, COAP_OPT_ALL, transport);
if (outCode)
{
- (*outCode) = (uint32_t) CA_RESPONSE_CODE(pdu->hdr->code);
+ (*outCode) = (uint32_t) CA_RESPONSE_CODE(coap_get_code(pdu, transport));
}
// init HeaderOption list
outInfo->numOptions = count;
- // set type
- outInfo->type = pdu->hdr->type;
+#ifdef TCP_ADAPTER
+ if (CA_ADAPTER_TCP == endpoint->adapter)
+ {
+ // set type
+ outInfo->type = CA_MSG_NONCONFIRM;
+ outInfo->payloadFormat = CA_FORMAT_UNDEFINED;
+ }
+ else
+#endif
+ {
+ // set type
+ outInfo->type = pdu->hdr->coap_hdr_udp_t.type;
- // set message id
- outInfo->messageId = pdu->hdr->id;
+ // set message id
+ outInfo->messageId = pdu->hdr->coap_hdr_udp_t.id;
+ outInfo->payloadFormat = CA_FORMAT_UNDEFINED;
+ outInfo->acceptFormat = CA_FORMAT_UNDEFINED;
+ }
if (count > 0)
{
while ((option = coap_option_next(&opt_iter)))
{
char buf[COAP_MAX_PDU_SIZE] = {0};
- if (CAGetOptionData((uint8_t *)(COAP_OPT_VALUE(option)),
- COAP_OPT_LENGTH(option), (uint8_t *)buf, sizeof(buf)))
+ uint32_t bufLength =
+ CAGetOptionData(opt_iter.type, (uint8_t *)(COAP_OPT_VALUE(option)),
+ COAP_OPT_LENGTH(option), (uint8_t *)buf, sizeof(buf));
+ if (bufLength)
{
OIC_LOG_V(DEBUG, TAG, "COAP URI element : %s", buf);
- uint32_t bufLength = strlen(buf);
if (COAP_OPTION_URI_PATH == opt_iter.type || COAP_OPTION_URI_QUERY == opt_iter.type)
{
if (false == isfirstsetflag)
{
OIC_LOG_V(DEBUG, TAG, "option[%d] will be filtering", opt_iter.type);
}
+ else if (COAP_OPTION_CONTENT_FORMAT == opt_iter.type)
+ {
+ if (1 == COAP_OPT_LENGTH(option))
+ {
+ outInfo->payloadFormat = CAConvertFormat((uint8_t)buf[0]);
+ }
+ else
+ {
+ outInfo->payloadFormat = CA_FORMAT_UNSUPPORTED;
+ OIC_LOG_V(DEBUG, TAG, "option[%d] has an unsupported format [%d]",
+ opt_iter.type, (uint8_t)buf[0]);
+ }
+ }
+ else if (COAP_OPTION_ACCEPT == opt_iter.type)
+ {
+ if (1 == COAP_OPT_LENGTH(option))
+ {
+ outInfo->acceptFormat = CAConvertFormat((uint8_t)buf[0]);
+ }
+ else
+ {
+ outInfo->acceptFormat = CA_FORMAT_UNSUPPORTED;
+ }
+ OIC_LOG_V(DEBUG, TAG, "option[%d] has an unsupported format [%d]",
+ opt_iter.type, (uint8_t)buf[0]);
+ }
else
{
if (idx < count)
{
- uint32_t length = bufLength;
-
- if (length <= CA_MAX_HEADER_OPTION_DATA_LENGTH)
+ if (bufLength <= sizeof(outInfo->options[0].optionData))
{
outInfo->options[idx].optionID = opt_iter.type;
- outInfo->options[idx].optionLength = length;
+ outInfo->options[idx].optionLength = bufLength;
outInfo->options[idx].protocolID = CA_COAP_ID;
- memcpy(outInfo->options[idx].optionData, buf, length);
+ memcpy(outInfo->options[idx].optionData, buf, bufLength);
idx++;
}
}
}
}
+ unsigned char* token = NULL;
+ unsigned int token_length = 0;
+ coap_get_token(pdu->hdr, transport, &token, &token_length);
+
// set token data
- if (pdu->hdr->token_length > 0)
+ if (token_length > 0)
{
- OIC_LOG_V(DEBUG, TAG, "inside token length : %d", pdu->hdr->token_length);
- outInfo->token = (char *) OICMalloc(pdu->hdr->token_length);
+ OIC_LOG_V(DEBUG, TAG, "inside token length : %d", token_length);
+ outInfo->token = (char *) OICMalloc(token_length);
if (NULL == outInfo->token)
{
OIC_LOG(ERROR, TAG, "Out of memory");
OICFree(outInfo->options);
return CA_MEMORY_ALLOC_FAILED;
}
- memcpy(outInfo->token, pdu->hdr->token, pdu->hdr->token_length);
+ memcpy(outInfo->token, token, token_length);
}
- outInfo->tokenLength = pdu->hdr->token_length;
+ outInfo->tokenLength = token_length;
// set payload data
size_t dataSize;
return CA_STATUS_FAILED;
}
-CAResult_t CAGetTokenFromPDU(const coap_hdr_t *pdu_hdr, CAInfo_t *outInfo)
+CAResult_t CAGetTokenFromPDU(const coap_hdr_t *pdu_hdr, CAInfo_t *outInfo,
+ const CAEndpoint_t *endpoint)
{
OIC_LOG(DEBUG, TAG, "IN");
if (NULL == pdu_hdr)
return CA_STATUS_INVALID_PARAM;
}
+ coap_transport_type transport;
+#ifdef TCP_ADAPTER
+ if (CA_ADAPTER_TCP == endpoint->adapter)
+ {
+ transport = coap_get_tcp_header_type_from_initbyte(((unsigned char *)pdu_hdr)[0] >> 4);
+ }
+ else
+#endif
+ {
+ transport = coap_udp;
+ }
+
+ unsigned char* token = NULL;
+ unsigned int token_length = 0;
+ coap_get_token(pdu_hdr, transport, &token, &token_length);
+
// set token data
- if (pdu_hdr->token_length > 0)
+ if (token_length > 0)
{
- OIC_LOG_V(DEBUG, TAG, "token len:%d", pdu_hdr->token_length);
- outInfo->token = (char *) OICMalloc(pdu_hdr->token_length);
+ OIC_LOG_V(DEBUG, TAG, "token len:%d", token_length);
+ outInfo->token = (char *) OICMalloc(token_length);
if (NULL == outInfo->token)
{
- OIC_LOG(ERROR, TAG, "out of memory");
+ OIC_LOG(ERROR, TAG, "Out of memory");
return CA_MEMORY_ALLOC_FAILED;
}
- memcpy(outInfo->token, pdu_hdr->token, pdu_hdr->token_length);
+ memcpy(outInfo->token, token, token_length);
}
- outInfo->tokenLength = pdu_hdr->token_length;
+ outInfo->tokenLength = token_length;
OIC_LOG(DEBUG, TAG, "OUT");
OIC_LOG(DEBUG, TAG, "OUT");
}
-uint32_t CAGetOptionData(const uint8_t *data, uint32_t len, uint8_t *option, uint32_t buflen)
+uint32_t CAGetOptionData(uint16_t key, const uint8_t *data, uint32_t len,
+ uint8_t *option, uint32_t buflen)
{
- if (0 == buflen || 0 == len)
- {
- OIC_LOG(ERROR, TAG, "len 0");
- return 0;
- }
-
- if (NULL == data || NULL == option)
+ if (0 == buflen)
{
- OIC_LOG(ERROR, TAG, "data/option NULL");
+ OIC_LOG(ERROR, TAG, "buflen 0");
return 0;
}
return 0;
}
- memcpy(option, data, len);
- option[len] = '\0';
+ coap_option_def_t* def = coap_opt_def(key);
+ if(NULL != def && coap_is_var_bytes(def) && 0 == len) {
+ // A 0 length option is permitted in CoAP but the
+ // rest or the stack is unaware of variable byte encoding
+ // should remain that way so a 0 byte of length 1 is inserted.
+ len = 1;
+ option[0]=0;
+ } else {
+ memcpy(option, data, len);
+ option[len] = '\0';
+ }
return len;
}
coap_hdr_t *hdr = (coap_hdr_t *) pdu;
- return (CAMessageType_t) hdr->type;
+ return (CAMessageType_t) hdr->coap_hdr_udp_t.type;
}
uint16_t CAGetMessageIdFromPduBinaryData(const void *pdu, uint32_t size)
coap_hdr_t *hdr = (coap_hdr_t *) pdu;
- return hdr->id;
+ return hdr->coap_hdr_udp_t.id;
}
CAResponseResult_t CAGetCodeFromPduBinaryData(const void *pdu, uint32_t size)
coap_hdr_t *hdr = (coap_hdr_t *) pdu;
- return (CAResponseResult_t) CA_RESPONSE_CODE(hdr->code);
+ return (CAResponseResult_t) CA_RESPONSE_CODE(hdr->coap_hdr_udp_t.code);
+}
+
+CAPayloadFormat_t CAConvertFormat(uint8_t format)
+{
+ switch (format)
+ {
+ case COAP_MEDIATYPE_TEXT_PLAIN:
+ return CA_FORMAT_TEXT_PLAIN;
+ case COAP_MEDIATYPE_APPLICATION_LINK_FORMAT:
+ return CA_FORMAT_APPLICATION_LINK_FORMAT;
+ case COAP_MEDIATYPE_APPLICATION_XML:
+ return CA_FORMAT_APPLICATION_XML;
+ case COAP_MEDIATYPE_APPLICATION_OCTET_STREAM:
+ return CA_FORMAT_APPLICATION_OCTET_STREAM;
+ case COAP_MEDIATYPE_APPLICATION_RDF_XML:
+ return CA_FORMAT_APPLICATION_RDF_XML;
+ case COAP_MEDIATYPE_APPLICATION_EXI:
+ return CA_FORMAT_APPLICATION_EXI;
+ case COAP_MEDIATYPE_APPLICATION_JSON:
+ return CA_FORMAT_APPLICATION_JSON;
+ case COAP_MEDIATYPE_APPLICATION_CBOR:
+ return CA_FORMAT_APPLICATION_CBOR;
+ default:
+ return CA_FORMAT_UNSUPPORTED;
+ }
}
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <sys/syscall.h>
#include <sys/types.h>
#include "caqueueingthread.h"
OIC_LOG(DEBUG, TAG, "wake up..");
}
- // mutex unlock
- ca_mutex_unlock(thread->threadMutex);
+
// check stop flag
if (thread->isStop)
{
+ // mutex unlock
+ ca_mutex_unlock(thread->threadMutex);
continue;
}
// get data
u_queue_message_t *message = u_queue_get_element(thread->dataQueue);
+ // mutex unlock
+ ca_mutex_unlock(thread->threadMutex);
if (NULL == message)
{
continue;
#include "caipinterface.h"
#include <sys/types.h>
-#include <ifaddrs.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include "logger.h"
#include "oic_malloc.h"
#include "oic_string.h"
+#include "org_iotivity_ca_CaIpInterface.h"
#define TAG "IP_MONITOR"
-char *getHostIPAddress(const char *ifa_name) {
- static char address[INET_ADDRSTRLEN] = {};
- memset(&address, 0, INET_ADDRSTRLEN);
- struct ifreq ifr;
- int sck, status, len = sizeof(ifr.ifr_name) - 1;
- char *ip;
+static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family,
+ uint32_t addr, int flags);
- if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
+ const char *name, int family, uint32_t addr, int flags);
+
+CAResult_t CAIPJniInit();
+
+#define MAX_INTERFACE_INFO_LENGTH 1024 // allows 32 interfaces from SIOCGIFCONF
+
+CAResult_t CAIPStartNetworkMonitor()
+{
+ return CAIPJniInit();
+}
+
+CAResult_t CAIPStopNetworkMonitor()
+{
+ return CA_STATUS_OK;
+}
+
+int CAGetPollingInterval(int interval)
+{
+ return interval;
+}
+
+CAInterface_t *CAFindInterfaceChange()
+{
+ char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
+ struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
+
+ int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
+ if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
return NULL;
}
- strncpy(ifr.ifr_name, ifa_name, len);
- ifr.ifr_name[len] = '\0';
- if ((status = ioctl(sck, SIOCGIFADDR, &ifr)) < 0) {
- close(sck);
+ CAInterface_t *foundNewInterface = NULL;
+
+ struct ifreq* ifr = ifc.ifc_req;
+ size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
+ size_t ifreqsize = ifc.ifc_len;
+
+ CAIfItem_t *previous = (CAIfItem_t *)OICMalloc(ifreqsize);
+ if (!previous)
+ {
+ OIC_LOG(ERROR, TAG, "OICMalloc failed");
return NULL;
}
- close(sck);
- ip = inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr);
- len = sizeof(address) - 1;
- strncpy(address, ip, len);
- address[len] = '\0';
- return address;
-}
-u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
-{
- if (desiredIndex < 0)
+ memcpy(previous, caglobals.ip.nm.ifItems, ifreqsize);
+ size_t numprevious = caglobals.ip.nm.numIfItems;
+
+ if (ifreqsize > caglobals.ip.nm.sizeIfItems)
{
- OIC_LOG_V(ERROR, TAG, "invalid index : %d", desiredIndex);
- return NULL;
+
+ CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
+ if (!items)
+ {
+ OIC_LOG(ERROR, TAG, "OICRealloc failed");
+ OICFree(previous);
+ return NULL;
+ }
+ caglobals.ip.nm.ifItems = items;
+ caglobals.ip.nm.sizeIfItems = ifreqsize;
}
+ caglobals.ip.nm.numIfItems = 0;
+ for (size_t i = 0; i < interfaces; i++)
+ {
+ struct ifreq* item = &ifr[i];
+ char *name = item->ifr_name;
+ struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr;
+ uint32_t ipv4addr = sa4->sin_addr.s_addr;
+
+ if (ioctl(s, SIOCGIFFLAGS, item) < 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
+ continue;
+ }
+ int16_t flags = item->ifr_flags;
+ if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
+ {
+ continue;
+ }
+ if (ioctl(s, SIOCGIFINDEX, item) < 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
+ continue;
+ }
+
+ int ifIndex = item->ifr_ifindex;
+ caglobals.ip.nm.ifItems[i].ifIndex = ifIndex; // refill interface list
+ caglobals.ip.nm.numIfItems++;
+
+ if (foundNewInterface)
+ {
+ continue; // continue updating interface list
+ }
+
+ // see if this interface didn't previously exist
+ bool found = false;
+ for (size_t j = 0; j < numprevious; j++)
+ {
+ if (ifIndex == previous[j].ifIndex)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ {
+ OIC_LOG_V(INFO, TAG, "Interface found: %s", name);
+ continue;
+ }
+
+ foundNewInterface = CANewInterfaceItem(ifIndex, name, AF_INET, ipv4addr, flags);
+ }
+
+ OICFree(previous);
+ return foundNewInterface;
+}
+
+u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
+{
u_arraylist_t *iflist = u_arraylist_create();
if (!iflist)
{
return NULL;
}
- char* ipAddr = getHostIPAddress("wlan0");
- if (NULL == ipAddr)
+ char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
+ struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
+
+ int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
+ if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
{
- OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno));
+ OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
u_arraylist_destroy(iflist);
return NULL;
}
- OIC_LOG_V(DEBUG, TAG, "Got ifaddrs:: %s", ipAddr);
- struct in_addr inaddr;
- inet_pton(AF_INET, ipAddr, &(inaddr));
+ struct ifreq* ifr = ifc.ifc_req;
+ size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
+ size_t ifreqsize = ifc.ifc_len;
- CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));;
- OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, "wlan0");
- ifitem->index = 0; //if_nametoindex("wlan0");
- ifitem->family = AF_INET; //we support ipv4 only
- ifitem->ipv4addr = inaddr.s_addr;
- ifitem->flags = IFF_UP|IFF_RUNNING;
-
- CAResult_t result = u_arraylist_add(iflist, ifitem);
- if (CA_STATUS_OK != result)
+ if (ifreqsize > caglobals.ip.nm.sizeIfItems)
{
- OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
- goto exit;
+ CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
+ if (!items)
+ {
+ OIC_LOG(ERROR, TAG, "OICRealloc failed");
+ goto exit;
+ }
+ caglobals.ip.nm.ifItems = items;
+ caglobals.ip.nm.sizeIfItems = ifreqsize;
}
- OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
+ caglobals.ip.nm.numIfItems = 0;
+ for (size_t i = 0; i < interfaces; i++)
+ {
+ CAResult_t result = CA_STATUS_OK;
+ struct ifreq* item = &ifr[i];
+ char *name = item->ifr_name;
+ struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr;
+ uint32_t ipv4addr = sa4->sin_addr.s_addr;
+
+ if (ioctl(s, SIOCGIFFLAGS, item) < 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
+ continue;
+ }
+ int16_t flags = item->ifr_flags;
+ if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
+ {
+ continue;
+ }
+ if (ioctl(s, SIOCGIFINDEX, item) < 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
+ continue;
+ }
+
+ int ifindex = item->ifr_ifindex;
+ caglobals.ip.nm.ifItems[i].ifIndex = ifindex;
+ caglobals.ip.nm.numIfItems++;
+
+ if (desiredIndex && (ifindex != desiredIndex))
+ {
+ continue;
+ }
+ // Add IPv4 interface
+ result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags);
+ if (CA_STATUS_OK != result)
+ {
+ goto exit;
+ }
+
+ // Add IPv6 interface
+ result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags);
+ if (CA_STATUS_OK != result)
+ {
+ goto exit;
+ }
+ }
return iflist;
exit:
return NULL;
}
+static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
+ const char *name, int family, uint32_t addr, int flags)
+{
+ CAInterface_t *ifitem = CANewInterfaceItem(index, name, family, addr, flags);
+ if (!ifitem)
+ {
+ return CA_STATUS_FAILED;
+ }
+ bool result = u_arraylist_add(iflist, ifitem);
+ if (!result)
+ {
+ OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+ OICFree(ifitem);
+ return CA_STATUS_FAILED;
+ }
+
+ return CA_STATUS_OK;
+}
+
+static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family,
+ uint32_t addr, int flags)
+{
+ CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t));
+ if (!ifitem)
+ {
+ OIC_LOG(ERROR, TAG, "Malloc failed");
+ return NULL;
+ }
+
+ OICStrcpy(ifitem->name, sizeof (ifitem->name), name);
+ ifitem->index = index;
+ ifitem->family = family;
+ ifitem->ipv4addr = addr;
+ ifitem->flags = flags;
+
+ return ifitem;
+}
+
+CAResult_t CAIPJniInit()
+{
+ OIC_LOG(DEBUG, TAG, "CAIPJniInit_IN");
+
+ JavaVM *jvm = CANativeJNIGetJavaVM();
+ if (!jvm)
+ {
+ OIC_LOG(ERROR, TAG, "Could not get JavaVM pointer");
+ return CA_STATUS_FAILED;
+ }
+
+ jobject context = CANativeJNIGetContext();
+ if (!context)
+ {
+ OIC_LOG(ERROR, TAG, "unable to get application context");
+ return CA_STATUS_FAILED;
+ }
+
+ JNIEnv* env;
+ if ((*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
+ {
+ OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
+ return CA_STATUS_FAILED;
+ }
+
+ jclass cls_Context = (*env)->FindClass(env, "android/content/Context");
+ if (!cls_Context)
+ {
+ OIC_LOG(ERROR, TAG, "Could not get context object class");
+ return CA_STATUS_FAILED;
+ }
+
+ jmethodID mid_getApplicationContext = (*env)->GetMethodID(env, cls_Context,
+ "getApplicationContext",
+ "()Landroid/content/Context;");
+ if (!mid_getApplicationContext)
+ {
+ OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
+ return CA_STATUS_FAILED;
+ }
+
+ jobject jApplicationContext = (*env)->CallObjectMethod(env, context,
+ mid_getApplicationContext);
+ if (!jApplicationContext)
+ {
+ OIC_LOG(ERROR, TAG, "Could not get application context");
+ return CA_STATUS_FAILED;
+ }
+
+ jclass cls_CaIpInterface = (*env)->FindClass(env, "org/iotivity/ca/CaIpInterface");
+ if (!cls_CaIpInterface)
+ {
+ OIC_LOG(ERROR, TAG, "Could not get CaIpInterface class");
+ return CA_STATUS_FAILED;
+ }
+
+ jmethodID mid_CaIpInterface_ctor = (*env)->GetMethodID(env, cls_CaIpInterface, "<init>",
+ "(Landroid/content/Context;)V");
+ if (!mid_CaIpInterface_ctor)
+ {
+ OIC_LOG(ERROR, TAG, "Could not get CaIpInterface constructor method");
+ return CA_STATUS_FAILED;
+ }
+
+ (*env)->NewObject(env, cls_CaIpInterface, mid_CaIpInterface_ctor, jApplicationContext);
+ OIC_LOG(DEBUG, TAG, "Create CaIpInterface instance, success");
+
+ OIC_LOG(DEBUG, TAG, "CAIPJniInit_OUT");
+ return CA_STATUS_OK;
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaIpInterface_caIpStateEnabled(JNIEnv *env, jclass class)
+{
+ (void)env;
+ (void)class;
+ OIC_LOG(DEBUG, TAG, "caIpStateEnabled");
+
+ CAWakeUpForChange();
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaIpInterface_caIpStateDisabled(JNIEnv *env, jclass class)
+{
+ (void)env;
+ (void)class;
+ OIC_LOG(DEBUG, TAG, "caIpStateDisabled");
+
+ CAIPGetInterfaceInformation(0);
+}
// defined & used (as-is defined in the linux socket headers).
#define AF_INET (2)
+CAResult_t CAIPStartNetworkMonitor()
+{
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAIPStopNetworkMonitor()
+{
+ return CA_STATUS_OK;
+}
+
/// Retrieves the IP address assigned to Arduino Ethernet shield
void CAArduinoGetInterfaceAddress(uint32_t *address)
{
u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
{
- CAResult_t result;
+ bool result = true;
u_arraylist_t *iflist = u_arraylist_create();
if (!iflist)
CAArduinoGetInterfaceAddress(&ifitem->ipv4addr);
result = u_arraylist_add(iflist, ifitem);
- if (CA_STATUS_OK != result)
+ if (!result)
{
OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
goto exit;
}
- OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
+ OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
return iflist;
// defined & used (as-is defined in the linux socket headers).
#define AF_INET (2)
+CAResult_t CAIPStartNetworkMonitor()
+{
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAIPStopNetworkMonitor()
+{
+ return CA_STATUS_OK;
+}
+
/// Retrieves the IP address assigned to Arduino WiFi shield
void CAArduinoGetInterfaceAddress(uint32_t *address)
{
u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
{
- CAResult_t result = CA_STATUS_OK;
+ bool result = true;
u_arraylist_t *iflist = u_arraylist_create();
if (!iflist)
CAArduinoGetInterfaceAddress(&ifitem->ipv4addr);
result = u_arraylist_add(iflist, ifitem);
- if (CA_STATUS_OK != result)
+ if (!result)
{
OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
goto exit;
}
- OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
+ OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
return iflist;
g_unicastSocket = serverFD;
CAIPSetUnicastSocket(g_unicastSocket);
CAIPSetUnicastPort(g_unicastPort);
+ caglobals.ip.u4.port = *port;
+
OIC_LOG_V(DEBUG, TAG, "g_unicastPort: %u", g_unicastPort);
OIC_LOG_V(DEBUG, TAG, "g_unicastSocket: %d", g_unicastSocket);
OIC_LOG(DEBUG, TAG, "OUT");
g_multicastSocket = serverFD;
g_isMulticastServerStarted = true;
+
OIC_LOG_V(DEBUG, TAG, "gMulticastPort: %d", multicastPort);
OIC_LOG_V(DEBUG, TAG, "g_multicastSocket: %d", g_multicastSocket);
OIC_LOG(DEBUG, TAG, "OUT");
CAResult_t ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false);
if (CA_STATUS_OK != ret)
{
- OIC_LOG_V(DEBUG, TAG, "Start unicast serv failed[%d]", ret);
+ OIC_LOG_V(ERROR, TAG, "Start unicast server failed[%d]", ret);
+ return ret;
}
ret = CAIPStartMulticastServer("0.0.0.0", "224.0.1.187", 5683);
if (CA_STATUS_OK != ret)
OIC_LOG(DEBUG, TAG, "IN");
close(g_unicastSocket);
g_unicastSocket = 0;
+ caglobals.ip.u4.port = 0;
OIC_LOG(DEBUG, TAG, "OUT");
return CA_STATUS_OK;
}
OIC_LOG(DEBUG, TAG, "IN");
if (g_packetReceivedCallback)
{
- CAEndpoint_t ep;
- strncpy(ep.addr, ipAddress, MAX_ADDR_STR_SIZE_CA);
- ep.port = port;
- ep.flags = CA_IPV4;
- ep.adapter = CA_ADAPTER_IP;
- g_packetReceivedCallback(&ep, data, dataLength);
+ CASecureEndpoint_t sep =
+ {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = CA_IPV4, .port = port}};
+ OICStrcpy(sep.endpoint.addr, sizeof(sep.endpoint.addr), ipAddress);
+ g_packetReceivedCallback(&sep, data, dataLength);
}
OIC_LOG(DEBUG, TAG, "OUT");
}
{
CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
- OICStrcpy(eps[j].addr, CA_INTERFACE_NAME_SIZE, ifitem->name);
+ unsigned char *addr= (unsigned char *) &(ifitem->ipv4addr);
+ snprintf(eps[j].addr, MAX_ADDR_STR_SIZE_CA, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
+
eps[j].flags = CA_IPV4;
eps[j].adapter = CA_ADAPTER_IP;
eps[j].interface = 0;
- eps[j].port = 0;
+ eps[j].port = caglobals.ip.u4.port;
j++;
}
Udp.begin((uint16_t ) *port);
gServerRunning = true;
g_unicastPort = *port;
+ caglobals.ip.u4.port = *port;
OIC_LOG(DEBUG, TAG, "OUT");
return CA_STATUS_OK;
}
CAResult_t ret = CAIPStartUnicastServer("0.0.0.0", &unicastPort, false);
if (CA_STATUS_OK != ret)
{
- OIC_LOG_V(DEBUG, TAG, "Start unicast serv failed[%d]", ret);
+ OIC_LOG_V(ERROR, TAG, "Start unicast server failed[%d]", ret);
+ return ret;
}
ret = CAIPStartMulticastServer("0.0.0.0", "224.0.1.187", 5683);
if (CA_STATUS_OK != ret)
Udp.stop();
gServerRunning = false;
+ caglobals.ip.u4.port = 0;
OIC_LOG(DEBUG, TAG, "OUT");
return CA_STATUS_OK;
}
OIC_LOG(DEBUG, TAG, "IN");
if (gPacketReceivedCallback)
{
- CAEndpoint_t ep;
- strncpy(ep.addr, ipAddress, MAX_ADDR_STR_SIZE_CA);
- ep.port = port;
- ep.flags = CA_IPV4;
- ep.adapter = CA_ADAPTER_IP;
- gPacketReceivedCallback(&ep, data, dataLength);
+ CASecureEndpoint_t sep =
+ {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = CA_IPV4, .port = port}};
+
+ OICStrcpy(sep.endpoint.addr, sizeof(sep.endpoint.addr), ipAddress);
+ gPacketReceivedCallback(&sep, data, dataLength);
OIC_LOG(DEBUG, TAG, "Notified network packet");
}
OIC_LOG(DEBUG, TAG, "OUT");
{
CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
- OICStrcpy(eps[j].addr, CA_INTERFACE_NAME_SIZE, ifitem->name);
+ unsigned char *addr= (unsigned char *) &(ifitem->ipv4addr);
+ snprintf(eps[j].addr, MAX_ADDR_STR_SIZE_CA, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
+
eps[j].flags = CA_IPV4;
eps[j].adapter = CA_ADAPTER_IP;
eps[j].interface = 0;
- eps[j].port = 0;
+ eps[j].port = caglobals.ip.u4.port;
j++;
}
*/
static CAErrorHandleCallback g_errorCallback = NULL;
-static void CAIPPacketReceivedCB(const CAEndpoint_t *endpoint,
+static void CAIPPacketReceivedCB(const CASecureEndpoint_t *endpoint,
const void *data, uint32_t dataLength);
#ifdef __WITH_DTLS__
static void CAIPPacketSendCB(CAEndpoint_t *endpoint,
}
#endif
-void CAIPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data,
+
+void CAIPPacketReceivedCB(const CASecureEndpoint_t *sep, const void *data,
uint32_t dataLength)
{
OIC_LOG(DEBUG, TAG, "IN");
- VERIFY_NON_NULL_VOID(endpoint, TAG, "ipAddress is NULL");
+ VERIFY_NON_NULL_VOID(sep, TAG, "sep is NULL");
VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
- OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
+ OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", sep->endpoint.addr, sep->endpoint.port);
if (g_networkPacketCallback)
{
- g_networkPacketCallback(endpoint, data, dataLength);
+ g_networkPacketCallback(sep, data, dataLength);
}
OIC_LOG(DEBUG, TAG, "OUT");
}
}
caglobals.ip.ipv6enabled = flags & CA_IPV6;
caglobals.ip.ipv4enabled = flags & CA_IPV4;
+ caglobals.ip.dualstack = caglobals.ip.ipv6enabled && caglobals.ip.ipv4enabled;
}
CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
{
OIC_LOG(DEBUG, TAG, "IN");
+ CAIPStartNetworkMonitor();
#ifdef SINGLE_THREAD
uint16_t unicastPort = 55555;
// Address is hardcoded as we are using Single Interface
CAIPDeinitializeQueueHandles();
#endif
+ CAIPStopNetworkMonitor();
CAIPStopServer();
OIC_LOG(DEBUG, TAG, "OUT");
#include "caipinterface.h"
-#ifndef __APPLE__
-#include <asm/types.h>
-#else
- #ifndef IPV6_ADD_MEMBERSHIP
- #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
- #endif
-#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
static void CAApplyInterfaces();
static void CAFindReadyMessage();
static void CASelectReturned(fd_set *readFds, int ret);
+static void CAProcessNewInterface(CAInterface_t *ifchanged);
static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags);
#define SET(TYPE, FDS) \
}
else
{
+ CAInterface_t *ifchanged = CAFindInterfaceChange();
+ if (ifchanged)
+ {
+ CAProcessNewInterface(ifchanged);
+ OICFree(ifchanged);
+ }
break;
}
return CA_STATUS_FAILED;
}
- CAEndpoint_t ep = { .adapter = CA_ADAPTER_IP,
- .flags = flags };
+ CASecureEndpoint_t sep =
+ {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = flags}};
if (flags & CA_IPV6)
{
- ep.interface = ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id;
+ sep.endpoint.interface = ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id;
((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id = 0;
}
- CAConvertAddrToName(&srcAddr, ep.addr, &ep.port);
+ CAConvertAddrToName(&srcAddr, sep.endpoint.addr, &sep.endpoint.port);
if (flags & CA_SECURE)
{
#ifdef __WITH_DTLS__
- int ret = CAAdapterNetDtlsDecrypt(&ep, (uint8_t *)recvBuffer, recvLen);
+ int ret = CAAdapterNetDtlsDecrypt(&sep, (uint8_t *)recvBuffer, recvLen);
OIC_LOG_V(DEBUG, TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret);
#else
OIC_LOG(ERROR, TAG, "Encrypted message but no DTLS");
{
if (g_packetReceivedCallback)
{
- g_packetReceivedCallback(&ep, recvBuffer, recvLen);
+ g_packetReceivedCallback(&sep, recvBuffer, recvLen);
}
}
OIC_LOG_V(DEBUG, TAG,
"socket summary: u6=%d, u6s=%d, u4=%d, u4s=%d, m6=%d, m6s=%d, m4=%d, m4s=%d",
- caglobals.ip.u6.fd, caglobals.ip.u6s.fd,
- caglobals.ip.u4.fd, caglobals.ip.u4s.fd,
- caglobals.ip.m6.fd, caglobals.ip.m6s.fd,
- caglobals.ip.m4.fd, caglobals.ip.m4s.fd);
+ caglobals.ip.u6.fd, caglobals.ip.u6s.fd, caglobals.ip.u4.fd, caglobals.ip.u4s.fd,
+ caglobals.ip.m6.fd, caglobals.ip.m6s.fd, caglobals.ip.m4.fd, caglobals.ip.m4s.fd);
+ OIC_LOG_V(DEBUG, TAG,
+ "port summary: u6 port=%d, u6s port=%d, u4 port=%d, u4s port=%d, m6 port=%d,"
+ "m6s port=%d, m4 port=%d, m4s port=%d",
+ caglobals.ip.u6.port, caglobals.ip.u6s.port, caglobals.ip.u4.port,
+ caglobals.ip.u4s.port, caglobals.ip.m6.port, caglobals.ip.m6s.port,
+ caglobals.ip.m4.port, caglobals.ip.m4s.port);
// create pipe for fast shutdown
CAInitializePipe();
CHECKFD(caglobals.ip.shutdownFds[0]);
// create source of network interface change notifications
CAInitializeNetlink();
+ caglobals.ip.selectTimeout = CAGetPollingInterval(caglobals.ip.selectTimeout);
+
CAApplyInterfaces();
caglobals.ip.terminate = false;
OIC_LOG(DEBUG, TAG, "OUT");
}
+void CAWakeUpForChange()
+{
+ if (caglobals.ip.shutdownFds[1] != -1)
+ {
+ ssize_t len = 0;
+ do
+ {
+ len = write(caglobals.ip.shutdownFds[1], "w", 1);
+ } while ((len == -1) && (errno == EINTR));
+ if ((len == -1) && (errno != EINTR) && (errno != EPIPE))
+ {
+ OIC_LOG_V(DEBUG, TAG, "write failed: %s", strerror(errno));
+ }
+ }
+}
+
static void applyMulticastToInterface4(struct in_addr inaddr)
{
if (!caglobals.ip.ipv4enabled)
struct ipv6_mreq mreq;
mreq.ipv6mr_multiaddr = *addr;
mreq.ipv6mr_interface = interface;
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof (mreq)))
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq)))
{
if (EADDRINUSE != errno)
{
u_arraylist_destroy(iflist);
}
+static void CAProcessNewInterface(CAInterface_t *ifitem)
+{
+ applyMulticastToInterface6(ifitem->index);
+ struct in_addr inaddr;
+ inaddr.s_addr = ifitem->ipv4addr;
+ applyMulticastToInterface4(inaddr);
+}
static void CAHandleNetlink()
{
#ifdef __linux__
char buf[4096];
struct nlmsghdr *nh;
struct sockaddr_nl sa;
- struct iovec iov = { buf, sizeof(buf) };
- struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
+ struct iovec iov = { buf, sizeof (buf) };
+ struct msghdr msg = { (void *)&sa, sizeof (sa), &iov, 1, NULL, 0, 0 };
size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0);
for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len))
{
- if (nh->nlmsg_type == RTM_NEWLINK)
+ if (nh->nlmsg_type != RTM_NEWLINK)
{
- struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh);
- if ((ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING))
- {
- continue;
- }
+ continue;
+ }
+
+ struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh);
+ if (!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING))
+ {
+ continue;
+ }
- int newIndex = ifi->ifi_index;
+ int newIndex = ifi->ifi_index;
- u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex);
- if (!iflist)
+ u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex);
+ if (!iflist)
+ {
+ OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
+ return;
+ }
+
+ uint32_t listLength = u_arraylist_length(iflist);
+ for (uint32_t i = 0; i < listLength; i++)
+ {
+ CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
+ if (!ifitem)
{
- OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
- return;
+ continue;
}
- uint32_t listLength = u_arraylist_length(iflist);
- for (uint32_t i = 0; i < listLength; i++)
+ if ((int)ifitem->index != newIndex)
{
- CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
- if (!ifitem)
- {
- continue;
- }
-
- if ((int)ifitem->index != newIndex)
- {
- continue;
- }
-
- applyMulticastToInterface6(newIndex);
- struct in_addr inaddr;
- inaddr.s_addr = ifitem->ipv4addr;
- applyMulticastToInterface4(inaddr);
- break; // we found the one we were looking for
+ continue;
}
- u_arraylist_destroy(iflist);
+
+ CAProcessNewInterface(ifitem);
+ break; // we found the one we were looking for
}
+ u_arraylist_destroy(iflist);
}
#endif // __linux__
}
void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
{
-OIC_LOG(DEBUG, TAG, "IN");
+ OIC_LOG(DEBUG, TAG, "IN");
-g_packetReceivedCallback = callback;
+ g_packetReceivedCallback = callback;
-OIC_LOG(DEBUG, TAG, "OUT");
+ OIC_LOG(DEBUG, TAG, "OUT");
}
void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
{
-OIC_LOG(DEBUG, TAG, "IN");
+ OIC_LOG(DEBUG, TAG, "IN");
g_exceptionCallback = callback;
struct sockaddr_storage sock;
CAConvertNameToAddr(endpoint->addr, endpoint->port, &sock);
+ socklen_t socklen;
if (sock.ss_family == AF_INET6)
{
struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)&sock;
{
sock6->sin6_scope_id = endpoint->interface;
}
+ socklen = sizeof(struct sockaddr_in6);
+ }
+ else
+ {
+ socklen = sizeof(struct sockaddr_in);
}
- ssize_t len = sendto(fd, data, dlen, 0, (struct sockaddr *)&sock, sizeof (sock));
+ ssize_t len = sendto(fd, data, dlen, 0, (struct sockaddr *)&sock, socklen);
if (-1 == len)
{
// If logging is not defined/enabled.
}
uint32_t len = u_arraylist_length(iflist);
+ uint32_t length = len;
- CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(len, sizeof (CAEndpoint_t));
+#ifdef __WITH_DTLS__
+ //If DTLS is supported, each interface can support secure port as well
+ length = len * 2;
+#endif
+
+ CAEndpoint_t *eps = (CAEndpoint_t *)OICCalloc(length, sizeof (CAEndpoint_t));
if (!eps)
{
OIC_LOG(ERROR, TAG, "Malloc Failed");
continue;
}
- OICStrcpy(eps[j].addr, CA_INTERFACE_NAME_SIZE, ifitem->name);
- eps[j].flags = ifitem->family == AF_INET6 ? CA_IPV6 : CA_IPV4;
eps[j].adapter = CA_ADAPTER_IP;
eps[j].interface = 0;
- eps[j].port = 0;
+
+ if (ifitem->family == AF_INET6)
+ {
+ eps[j].flags = CA_IPV6;
+ eps[j].port = caglobals.ip.u6.port;
+ }
+ else
+ {
+ eps[j].flags = CA_IPV4;
+ eps[j].port = caglobals.ip.u4.port;
+
+ unsigned char *addr= (unsigned char *) &(ifitem->ipv4addr);
+ snprintf(eps[j].addr, MAX_ADDR_STR_SIZE_CA, "%d.%d.%d.%d",
+ addr[0], addr[1], addr[2], addr[3]);
+ }
+
+#ifdef __WITH_DTLS__
+ j++;
+
+ eps[j].adapter = CA_ADAPTER_IP;
+ eps[j].interface = 0;
+
+ if (ifitem->family == AF_INET6)
+ {
+ eps[j].flags = CA_IPV6 | CA_SECURE;
+ eps[j].port = caglobals.ip.u6s.port;
+ }
+ else
+ {
+ eps[j].flags = CA_IPV4 | CA_SECURE;
+ eps[j].port = caglobals.ip.u4s.port;
+
+ unsigned char *addr= (unsigned char *) &(ifitem->ipv4addr);
+ snprintf(eps[j].addr, MAX_ADDR_STR_SIZE_CA, "%d.%d.%d.%d",
+ addr[0], addr[1], addr[2], addr[3]);
+ }
+#endif
j++;
}
#define TAG "IP_MONITOR"
+CAResult_t CAIPStartNetworkMonitor()
+{
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAIPStopNetworkMonitor()
+{
+ return CA_STATUS_OK;
+}
+
+int CAGetPollingInterval(int interval)
+{
+ return interval;
+}
+
+CAInterface_t *CAFindInterfaceChange()
+{
+ return NULL;
+}
+
u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
{
if (desiredIndex < 0)
struct ifaddrs *ifa = NULL;
for (ifa = ifp; ifa; ifa = ifa->ifa_next)
{
+ if (!ifa->ifa_addr)
+ {
+ continue;
+ }
int family = ifa->ifa_addr->sa_family;
if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family))
{
ifitem->ipv4addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr;
ifitem->flags = ifa->ifa_flags;
- CAResult_t result = u_arraylist_add(iflist, ifitem);
- if (CA_STATUS_OK != result)
+ bool result = u_arraylist_add(iflist, ifitem);
+ if (!result)
{
OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
goto exit;
}
- OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, family);
+ OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, family);
}
freeifaddrs(ifp);
#include <string.h>
#include <errno.h>
#include <unistd.h>
+#include <sys/ioctl.h>
+#include <wifi.h>
#include "caadapterutils.h"
#include "logger.h"
#include "oic_string.h"
#define TAG "IP_MONITOR"
+#define MAX_INTERFACE_INFO_LENGTH (1024)
-u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
+static CAInterface_t *CANewInterfaceItem(int index, char *name, int family,
+ uint32_t addr, int flags);
+
+static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
+ char *name, int family, uint32_t addr, int flags);
+
+static void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap,
+ void *userData);
+
+static void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData);
+
+
+int CAGetPollingInterval(int interval)
{
- u_arraylist_t *iflist = u_arraylist_create();
- if (!iflist)
+ return interval;
+}
+
+CAInterface_t *CAFindInterfaceChange()
+{
+ char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
+ struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
+
+ int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
+ if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
{
- OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
+ OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
return NULL;
}
- struct ifaddrs *ifp = NULL;
- if (-1 == getifaddrs(&ifp))
+ CAInterface_t *foundNewInterface = NULL;
+
+ struct ifreq* ifr = ifc.ifc_req;
+ size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
+ size_t ifreqsize = ifc.ifc_len;
+
+ CAIfItem_t *previous = (CAIfItem_t *)OICMalloc(ifreqsize);
+ if (!previous)
{
- OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno));
- u_arraylist_destroy(iflist);
+ OIC_LOG(ERROR, TAG, "OICMalloc failed");
return NULL;
}
- struct ifaddrs *ifa = NULL;
- for (ifa = ifp; ifa; ifa = ifa->ifa_next)
+ memcpy(previous, caglobals.ip.nm.ifItems, ifreqsize);
+ size_t numprevious = caglobals.ip.nm.numIfItems;
+
+ if (ifreqsize > caglobals.ip.nm.sizeIfItems)
+ {
+
+ CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
+ if (!items)
+ {
+ OIC_LOG(ERROR, TAG, "OICRealloc failed");
+ OICFree(previous);
+ return NULL;
+ }
+ caglobals.ip.nm.ifItems = items;
+ caglobals.ip.nm.sizeIfItems = ifreqsize;
+ }
+
+ caglobals.ip.nm.numIfItems = 0;
+ for (size_t i = 0; i < interfaces; i++)
{
- int family = ifa->ifa_addr->sa_family;
- if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family))
+ struct ifreq* item = &ifr[i];
+ char *name = item->ifr_name;
+ struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr;
+ uint32_t ipv4addr = sa4->sin_addr.s_addr;
+
+ if (ioctl(s, SIOCGIFFLAGS, item) < 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
+ continue;
+ }
+ int16_t flags = item->ifr_flags;
+ if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
{
continue;
}
+ if (ioctl(s, SIOCGIFINDEX, item) < 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
+ continue;
+ }
- int ifindex = if_nametoindex(ifa->ifa_name);
- int length = u_arraylist_length(iflist);
- int already = false;
- for (int i = length-1; i >= 0; i--)
+ int ifIndex = item->ifr_ifindex;
+ caglobals.ip.nm.ifItems[i].ifIndex = ifIndex; // refill interface list
+ caglobals.ip.nm.numIfItems++;
+
+ if (foundNewInterface)
{
- CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
- if (ifitem->index == ifindex && ifitem->family == family)
+ continue; // continue updating interface list
+ }
+
+ // see if this interface didn't previously exist
+ bool found = false;
+ for (size_t j = 0; j < numprevious; j++)
+ {
+ if (ifIndex == previous[j].ifIndex)
{
- already = true;
+ found = true;
break;
}
}
- if (already)
+ if (found)
{
+ OIC_LOG_V(INFO, TAG, "Interface found: %s", name);
continue;
}
- CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));
- if (!ifitem)
+ foundNewInterface = CANewInterfaceItem(ifIndex, name, AF_INET, ipv4addr, flags);
+ }
+
+ OICFree(previous);
+ return foundNewInterface;
+}
+
+CAResult_t CAIPStartNetworkMonitor()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ // Initialize Wifi service
+ wifi_error_e ret = wifi_initialize();
+ if (WIFI_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TAG, "wifi_initialize failed");
+ return CA_STATUS_FAILED;
+ }
+
+ // Set callback for receiving state changes
+ ret = wifi_set_device_state_changed_cb(CAWIFIDeviceStateChangedCb, NULL);
+ if (WIFI_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TAG, "wifi_set_device_state_changed_cb failed");
+ return CA_STATUS_FAILED;
+ }
+
+ // Set callback for receiving connection state changes
+ ret = wifi_set_connection_state_changed_cb(CAWIFIConnectionStateChangedCb, NULL);
+ if (WIFI_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TAG, "wifi_set_connection_state_changed_cb failed");
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAIPStopNetworkMonitor()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ // Reset callback for receiving state changes
+ wifi_error_e ret = wifi_unset_device_state_changed_cb();
+ if (WIFI_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TAG, "wifi_unset_device_state_changed_cb failed");
+ }
+
+ // Reset callback for receiving connection state changes
+ ret = wifi_unset_connection_state_changed_cb();
+ if (WIFI_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TAG, "wifi_unset_connection_state_changed_cb failed");
+ }
+
+ // Deinitialize Wifi service
+ ret = wifi_deinitialize();
+ if (WIFI_ERROR_NONE != ret)
+ {
+ OIC_LOG(ERROR, TAG, "wifi_deinitialize failed");
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
+{
+ u_arraylist_t *iflist = u_arraylist_create();
+ if (!iflist)
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
+ return NULL;
+ }
+
+ char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
+ struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
+
+ int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
+ if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
+ u_arraylist_destroy(iflist);
+ return NULL;
+ }
+
+ struct ifreq* ifr = ifc.ifc_req;
+ size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
+ size_t ifreqsize = ifc.ifc_len;
+
+ if (ifreqsize > caglobals.ip.nm.sizeIfItems)
+ {
+ CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
+ if (!items)
{
- OIC_LOG(ERROR, TAG, "Malloc failed");
+ OIC_LOG(ERROR, TAG, "OICRealloc failed");
goto exit;
}
+ caglobals.ip.nm.ifItems = items;
+ caglobals.ip.nm.sizeIfItems = ifreqsize;
+ }
+
+ caglobals.ip.nm.numIfItems = 0;
+ for (size_t i = 0; i < interfaces; i++)
+ {
+ CAResult_t result = CA_STATUS_OK;
+ struct ifreq* item = &ifr[i];
+ char *name = item->ifr_name;
+ struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr;
+ uint32_t ipv4addr = sa4->sin_addr.s_addr;
+
+ if (ioctl(s, SIOCGIFFLAGS, item) < 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
+ continue;
+ }
+ int16_t flags = item->ifr_flags;
+ if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
+ {
+ continue;
+ }
+ if (ioctl(s, SIOCGIFINDEX, item) < 0)
+ {
+ OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
+ continue;
+ }
- OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, ifa->ifa_name);
- ifitem->index = ifindex;
- ifitem->family = family;
- ifitem->ipv4addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr;
- ifitem->flags = ifa->ifa_flags;
+ int ifindex = item->ifr_ifindex;
+ caglobals.ip.nm.ifItems[i].ifIndex = ifindex;
+ caglobals.ip.nm.numIfItems++;
- CAResult_t result = u_arraylist_add(iflist, ifitem);
+ if (desiredIndex && (ifindex != desiredIndex))
+ {
+ continue;
+ }
+
+ // Add IPv4 interface
+ result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags);
if (CA_STATUS_OK != result)
{
- OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
goto exit;
}
- }
- freeifaddrs(ifp);
+ // Add IPv6 interface
+ result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags);
+ if (CA_STATUS_OK != result)
+ {
+ goto exit;
+ }
+ }
return iflist;
exit:
- freeifaddrs(ifp);
u_arraylist_destroy(iflist);
return NULL;
}
+
+static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
+ char *name, int family, uint32_t addr, int flags)
+{
+ CAInterface_t *ifitem = CANewInterfaceItem(index, name, family, addr, flags);
+ if (!ifitem)
+ {
+ return CA_STATUS_FAILED;
+ }
+ bool result = u_arraylist_add(iflist, ifitem);
+ if (!result)
+ {
+ OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+ OICFree(ifitem);
+ return CA_STATUS_FAILED;
+ }
+
+ return CA_STATUS_OK;
+}
+
+static CAInterface_t *CANewInterfaceItem(int index, char *name, int family,
+ uint32_t addr, int flags)
+{
+ CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t));
+ if (!ifitem)
+ {
+ OIC_LOG(ERROR, TAG, "Malloc failed");
+ return NULL;
+ }
+
+ OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, name);
+ ifitem->index = index;
+ ifitem->family = family;
+ ifitem->ipv4addr = addr;
+ ifitem->flags = flags;
+
+ return ifitem;
+}
+
+void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap,
+ void *userData)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ if (WIFI_CONNECTION_STATE_ASSOCIATION == state
+ || WIFI_CONNECTION_STATE_CONFIGURATION == state)
+ {
+ OIC_LOG(DEBUG, TAG, "Connection is in Association State");
+ return;
+ }
+
+ if (WIFI_CONNECTION_STATE_CONNECTED == state)
+ {
+ CAWakeUpForChange();
+ }
+ else
+ {
+ u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
+ if (!iflist)
+ {
+ OIC_LOG_V(ERROR, TAG, "get interface info failed");
+ return;
+ }
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ if (WIFI_DEVICE_STATE_ACTIVATED == state)
+ {
+ OIC_LOG(DEBUG, TAG, "Wifi is in Activated State");
+ }
+ else
+ {
+ CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL);
+ OIC_LOG(DEBUG, TAG, "Wifi is in Deactivated State");
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
--- /dev/null
+#######################################################
+# Build TCP adapter
+#######################################################
+
+Import('env')
+import os.path
+
+print "Reading TCP adapter script"
+
+target_os = env.get('TARGET_OS')
+inc_files = env.get('CPPPATH')
+secured = env.get('SECURED')
+src_dir = './tcp_adapter/'
+
+
+# Source files to build common for all platforms
+common_files = None
+if target_os == 'linux':
+ common_files = [
+ os.path.join(src_dir, 'catcpadapter.c'),
+ os.path.join(src_dir, 'catcpserver.c') ]
+
+# Get list of target-specific source file base names, i.e. no parent
+# directories prepended to the path.
+#
+# Target-specific SConscript files are expected to return that list.
+target_files = []
+target_sconscript = os.path.join(target_os, 'SConscript')
+
+# Check for the existence of the platform-specific SConscript file
+# relative to the top-level source directory, not the build (variant)
+# directory, before calling that SConscript file to prevent a missing
+# file warning platforms that don't provide one.
+target_sconscript_abspath = str(File(target_sconscript).srcnode().abspath)
+if os.path.exists(target_sconscript_abspath):
+ target_files = env.SConscript(target_sconscript, exports='src_dir')
+
+# Now prepend the appropriate parent directories
+# (e.g. ./ip_adapter/android) to each of the target source files in
+# the list.
+target_files = [ os.path.join(src_dir, target_os, f) for f in target_files ]
+
+# Source files to build for Linux-like platforms
+
+# The list of BLE adapter source files is a combination of both the
+# common and target-specific source file lists.
+env.AppendUnique(CA_SRC = common_files + target_files)
\ No newline at end of file
--- /dev/null
+/* ****************************************************************
+ *
+ * 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 <stdint.h>
+
+#include "catcpadapter.h"
+#include "catcpinterface.h"
+#include "caqueueingthread.h"
+#include "caadapterutils.h"
+#include "camutex.h"
+#include "uarraylist.h"
+#include "caremotehandler.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+
+/**
+ * Logging tag for module name.
+ */
+#define TAG "TCP_ADAP"
+
+/**
+ * Holds internal thread TCP data information.
+ */
+typedef struct
+{
+ CAEndpoint_t *remoteEndpoint;
+ void *data;
+ size_t dataLen;
+ bool isMulticast;
+} CATCPData;
+
+#define CA_TCP_TIMEOUT 1000
+
+#define CA_TCP_LISTEN_BACKLOG 3
+
+/**
+ * Queue handle for Send Data.
+ */
+static CAQueueingThread_t *g_sendQueueHandle = NULL;
+
+/**
+ * Network Packet Received Callback to CA.
+ */
+static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
+
+/**
+ * Network Changed Callback to CA.
+ */
+static CANetworkChangeCallback g_networkChangeCallback = NULL;
+
+/**
+ * error Callback to CA adapter.
+ */
+static CAErrorHandleCallback g_errorCallback = NULL;
+
+static void CATCPPacketReceivedCB(const CAEndpoint_t *endpoint,
+ const void *data, size_t dataLength);
+
+static CAResult_t CATCPInitializeQueueHandles();
+
+static void CATCPDeinitializeQueueHandles();
+
+static void CATCPSendDataThread(void *threadData);
+
+static CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint,
+ const void *data, size_t dataLength,
+ bool isMulticast);
+void CAFreeTCPData(CATCPData *ipData);
+
+static void CADataDestroyer(void *data, size_t size);
+
+CAResult_t CATCPInitializeQueueHandles()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ // Check if the message queue is already initialized
+ if (g_sendQueueHandle)
+ {
+ OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!");
+ return CA_STATUS_OK;
+ }
+
+ // Create send message queue
+ g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
+ if (!g_sendQueueHandle)
+ {
+ OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+ return CA_MEMORY_ALLOC_FAILED;
+ }
+
+ if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle,
+ (const ca_thread_pool_t)caglobals.tcp.threadpool,
+ CATCPSendDataThread, CADataDestroyer))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
+ OICFree(g_sendQueueHandle);
+ g_sendQueueHandle = NULL;
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CATCPDeinitializeQueueHandles()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ CAQueueingThreadDestroy(g_sendQueueHandle);
+ OICFree(g_sendQueueHandle);
+ g_sendQueueHandle = NULL;
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CATCPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status)
+{
+ (void)ipAddress;
+ (void)status;
+ OIC_LOG(DEBUG, TAG, "IN");
+}
+
+void CATCPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data,
+ size_t dataLength)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ VERIFY_NON_NULL_VOID(endpoint, TAG, "ipAddress is NULL");
+ VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
+
+ OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port);
+
+ if (g_networkPacketCallback)
+ {
+ g_networkPacketCallback(endpoint, data, dataLength);
+ }
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CATCPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
+ size_t dataLength, CAResult_t result)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
+
+ VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
+
+ if (g_errorCallback)
+ {
+ g_errorCallback(endpoint, data, dataLength, result);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+static void CAInitializeTCPGlobals()
+{
+ caglobals.tcp.selectTimeout = CA_TCP_TIMEOUT;
+ caglobals.tcp.listenBacklog = CA_TCP_LISTEN_BACKLOG;
+ caglobals.tcp.svrlist = NULL;
+
+ CATransportFlags_t flags = 0;
+ if (caglobals.client)
+ {
+ flags |= caglobals.clientFlags;
+ }
+ if (caglobals.server)
+ {
+ flags |= caglobals.serverFlags;
+ }
+
+ caglobals.tcp.ipv4tcpenabled = flags & CA_IPV4;
+}
+
+CAResult_t CAInitializeTCP(CARegisterConnectivityCallback registerCallback,
+ CANetworkPacketReceivedCallback networkPacketCallback,
+ CANetworkChangeCallback netCallback,
+ CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
+ VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
+ VERIFY_NON_NULL(netCallback, TAG, "netCallback");
+ VERIFY_NON_NULL(handle, TAG, "thread pool handle");
+
+ g_networkChangeCallback = netCallback;
+ g_networkPacketCallback = networkPacketCallback;
+ g_errorCallback = errorCallback;
+
+ CAInitializeTCPGlobals();
+ caglobals.tcp.threadpool = handle;
+
+ CATCPSetPacketReceiveCallback(CATCPPacketReceivedCB);
+ CATCPSetErrorHandler(CATCPErrorHandler);
+
+ CAConnectivityHandler_t TCPHandler = {
+ .startAdapter = CAStartTCP,
+ .startListenServer = CAStartTCPListeningServer,
+ .startDiscoveryServer = CAStartTCPDiscoveryServer,
+ .sendData = CASendTCPUnicastData,
+ .sendDataToAll = CASendTCPMulticastData,
+ .GetnetInfo = CAGetTCPInterfaceInformation,
+ .readData = CAReadTCPData,
+ .stopAdapter = CAStopTCP,
+ .terminate = CATerminateTCP };
+ registerCallback(TCPHandler, CA_ADAPTER_TCP);
+
+ OIC_LOG(INFO, TAG, "OUT IntializeTCP is Success");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStartTCP()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ if (CA_STATUS_OK != CATCPInitializeQueueHandles())
+ {
+ OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
+ CATerminateTCP();
+ return CA_STATUS_FAILED;
+ }
+
+ // Start send queue thread
+ if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
+ return CA_STATUS_FAILED;
+ }
+
+ CAResult_t ret = CATCPStartServer((const ca_thread_pool_t)caglobals.tcp.threadpool);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
+ return ret;
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStartTCPListeningServer()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStartTCPDiscoveryServer()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+static size_t CAQueueTCPData(bool isMulticast, const CAEndpoint_t *endpoint,
+ const void *data, size_t dataLength)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1);
+ VERIFY_NON_NULL_RET(data, TAG, "data", -1);
+
+ if (0 == dataLength)
+ {
+ OIC_LOG(ERROR, TAG, "Invalid Data Length");
+ return -1;
+ }
+
+ VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
+
+ // Create TCPData to add to queue
+ CATCPData *TCPData = CACreateTCPData(endpoint, data, dataLength, isMulticast);
+ if (!TCPData)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to create ipData!");
+ return -1;
+ }
+ // Add message to send queue
+ CAQueueingThreadAddData(g_sendQueueHandle, TCPData, sizeof(CATCPData));
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return dataLength;
+}
+
+int32_t CASendTCPUnicastData(const CAEndpoint_t *endpoint,
+ const void *data, uint32_t dataLength)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ return CAQueueTCPData(false, endpoint, data, dataLength);
+}
+
+int32_t CASendTCPMulticastData(const CAEndpoint_t *endpoint,
+ const void *data, uint32_t dataLength)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ return CAQueueTCPData(true, endpoint, data, dataLength);
+}
+
+CAResult_t CAReadTCPData()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CAStopTCP()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
+ {
+ CAQueueingThreadStop(g_sendQueueHandle);
+ }
+
+ CATCPDeinitializeQueueHandles();
+
+ CATCPStopServer();
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+ return CA_STATUS_OK;
+}
+
+void CATerminateTCP()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ CATCPSetPacketReceiveCallback(NULL);
+
+ CATCPDeinitializeQueueHandles();
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CATCPSendDataThread(void *threadData)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ CATCPData *TCPData = (CATCPData *) threadData;
+ if (!TCPData)
+ {
+ OIC_LOG(DEBUG, TAG, "Invalid TCP data!");
+ return;
+ }
+
+ if (TCPData->isMulticast)
+ {
+ //Processing for sending multicast
+ OIC_LOG(DEBUG, TAG, "Send Multicast Data is called, not supported");
+ return;
+ }
+ else
+ {
+ //Processing for sending unicast
+ CATCPSendData(TCPData->remoteEndpoint, TCPData->data, TCPData->dataLen, false);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+CATCPData *CACreateTCPData(const CAEndpoint_t *remoteEndpoint, const void *data,
+ size_t dataLength, bool isMulticast)
+{
+ VERIFY_NON_NULL_RET(data, TAG, "TCPData is NULL", NULL);
+
+ CATCPData *TCPData = (CATCPData *) OICMalloc(sizeof(CATCPData));
+ if (!TCPData)
+ {
+ OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+ return NULL;
+ }
+
+ TCPData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
+ TCPData->data = (void *) OICMalloc(dataLength);
+ if (!TCPData->data)
+ {
+ OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+ CAFreeTCPData(TCPData);
+ return NULL;
+ }
+
+ memcpy(TCPData->data, data, dataLength);
+ TCPData->dataLen = dataLength;
+
+ TCPData->isMulticast = isMulticast;
+
+ return TCPData;
+}
+
+void CAFreeTCPData(CATCPData *TCPData)
+{
+ VERIFY_NON_NULL_VOID(TCPData, TAG, "TCPData is NULL");
+
+ CAFreeEndpoint(TCPData->remoteEndpoint);
+ OICFree(TCPData->data);
+ OICFree(TCPData);
+}
+
+void CADataDestroyer(void *data, size_t size)
+{
+ if (size < sizeof(CATCPData))
+ {
+ OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %d", data, size);
+ }
+ CATCPData *TCPData = (CATCPData *) data;
+
+ CAFreeTCPData(TCPData);
+}
--- /dev/null
+/* ****************************************************************j
+ *
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/select.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <errno.h>
+#include <sys/poll.h>
+
+#ifndef WITH_ARDUINO
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#endif
+
+#include "catcpinterface.h"
+#include "pdu.h"
+#include "caadapterutils.h"
+#include "camutex.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+
+/**
+ * Logging tag for module name.
+ */
+#define TAG "TCP_SERVER"
+
+/**
+ * Server port number for local test.
+ */
+#define SERVER_PORT 8000
+
+/**
+ * Maximum CoAP over TCP header length
+ * to know the total data length.
+ */
+#define TCP_MAX_HEADER_LEN 6
+
+/**
+ * Default Thread Counts in TCP adapter
+ */
+#define CA_TCP_DEFAULT_THREAD_COUNTS 2
+
+/**
+ * Accept server file descriptor.
+ */
+static int g_acceptServerFD = -1;
+
+/**
+ * Mutex to synchronize device object list.
+ */
+static ca_mutex g_mutexObjectList = NULL;
+
+/**
+ * Conditional mutex to synchronize.
+ */
+static ca_cond g_condObjectList = NULL;
+
+/**
+ * Maintains the current running thread counts.
+ */
+static uint32_t g_threadCounts = CA_TCP_DEFAULT_THREAD_COUNTS;
+
+/**
+ * Maintains the callback to be notified when data received from remote device.
+ */
+static CATCPPacketReceivedCallback g_packetReceivedCallback;
+
+/**
+ * Error callback to update error in TCP.
+ */
+static CATCPErrorHandleCallback g_TCPErrorHandler = NULL;
+
+static CAResult_t CATCPCreateMutex();
+static void CATCPDestroyMutex();
+static CAResult_t CATCPCreateCond();
+static void CATCPDestroyCond();
+static void CAAcceptHandler(void *data);
+static void CAReceiveHandler(void *data);
+static CAResult_t CAReceiveMessage();
+static int CASetNonblocking(int fd);
+static int CATCPCreateSocket(int family, CATCPServerInfo_t *TCPServerInfo);
+static size_t CAGetTotalLengthFromHeader(const unsigned char *recvBuffer);
+static void CATCPDisconnectAll();
+
+static void CATCPDestroyMutex()
+{
+ if (g_mutexObjectList)
+ {
+ ca_mutex_free(g_mutexObjectList);
+ g_mutexObjectList = NULL;
+ }
+}
+
+static CAResult_t CATCPCreateMutex()
+{
+ if (!g_mutexObjectList)
+ {
+ g_mutexObjectList = ca_mutex_new();
+ if (!g_mutexObjectList)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to created mutex!");
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ return CA_STATUS_OK;
+}
+
+static void CATCPDestroyCond()
+{
+ if (g_condObjectList)
+ {
+ ca_cond_free(g_condObjectList);
+ g_condObjectList = NULL;
+ }
+}
+
+static CAResult_t CATCPCreateCond()
+{
+ if (!g_condObjectList)
+ {
+ g_condObjectList = ca_cond_new();
+ if (!g_condObjectList)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to created cond!");
+ return CA_STATUS_FAILED;
+ }
+ }
+ return CA_STATUS_OK;
+}
+
+static void CATCPDisconnectAll()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ ca_mutex_lock(g_mutexObjectList);
+ uint32_t length = u_arraylist_length(caglobals.tcp.svrlist);
+
+ CATCPServerInfo_t *svritem = NULL;
+ for (size_t i = 0; i < length; i++)
+ {
+ svritem = (CATCPServerInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i);
+ if (svritem && svritem->u4tcp.fd >= 0)
+ {
+ shutdown(svritem->u4tcp.fd, SHUT_RDWR);
+ close(svritem->u4tcp.fd);
+ }
+ }
+ u_arraylist_destroy(caglobals.tcp.svrlist);
+
+ ca_mutex_unlock(g_mutexObjectList);
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+static void CAReceiveHandler(void *data)
+{
+ (void)data;
+ OIC_LOG(DEBUG, TAG, "IN - CAReceiveHandler");
+
+ while (!caglobals.tcp.terminate)
+ {
+ CAReceiveMessage();
+ }
+
+ ca_mutex_lock(g_mutexObjectList);
+ // notify the thread
+ g_threadCounts--;
+ if (!g_threadCounts)
+ {
+ ca_cond_signal(g_condObjectList);
+ }
+ ca_mutex_unlock(g_mutexObjectList);
+
+ OIC_LOG(DEBUG, TAG, "OUT - CAReceiveHandler");
+}
+
+static size_t CAGetTotalLengthFromHeader(const unsigned char *recvBuffer)
+{
+ OIC_LOG(DEBUG, TAG, "IN - CAGetTotalLengthFromHeader");
+
+ coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(
+ ((unsigned char *)recvBuffer)[0] >> 4);
+ size_t optPaylaodLen = coap_get_length_from_header((unsigned char *)recvBuffer,
+ transport);
+ size_t headerLen = coap_get_tcp_header_length((unsigned char *)recvBuffer);
+
+ OIC_LOG_V(DEBUG, TAG, "option/paylaod length [%d]", optPaylaodLen);
+ OIC_LOG_V(DEBUG, TAG, "header length [%d]", headerLen);
+ OIC_LOG_V(DEBUG, TAG, "total data length [%d]", headerLen + optPaylaodLen);
+
+ OIC_LOG(DEBUG, TAG, "OUT - CAGetTotalLengthFromHeader");
+ return headerLen + optPaylaodLen;
+}
+
+static CAResult_t CAReceiveMessage()
+{
+ uint32_t length = u_arraylist_length(caglobals.tcp.svrlist);
+
+ size_t i = 0;
+ unsigned char *recvBuffer = NULL;
+ CATCPServerInfo_t *svritem = NULL;
+ for (i = 0; i < length; i++)
+ {
+ svritem = (CATCPServerInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i);
+ if (svritem->u4tcp.fd < 0)
+ {
+ continue;
+ }
+
+ size_t bufSize = TCP_MAX_HEADER_LEN;
+ recvBuffer = (unsigned char *) OICCalloc(1, bufSize);
+ if (!recvBuffer)
+ {
+ OIC_LOG(ERROR, TAG, "out of memory");
+ goto exit;
+ }
+
+ bool isHeaderChecked = false;
+ size_t totalLen = 0;
+ size_t totalReceivedLen = 0;
+ do
+ {
+ ssize_t recvLen = recv(svritem->u4tcp.fd, recvBuffer + totalReceivedLen,
+ bufSize - totalReceivedLen, 0);
+ if (recvLen <= 0)
+ {
+ if(EWOULDBLOCK != errno)
+ {
+ OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno));
+ goto exit;
+ }
+ // if received data length is zero, we are breaking loop.
+ // because we use non-blocking socket to receive data from remote device.
+ if (!totalReceivedLen)
+ {
+ break;
+ }
+ continue;
+ }
+
+ totalReceivedLen += recvLen;
+ if (!isHeaderChecked && totalReceivedLen)
+ {
+ coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(
+ ((unsigned char *)recvBuffer)[0] >> 4);
+ size_t headerLen = coap_get_tcp_header_length_for_transport(transport);
+ if (totalReceivedLen >= headerLen)
+ {
+ // get actual data length from coap over tcp header
+ totalLen = CAGetTotalLengthFromHeader((unsigned char *) recvBuffer);
+ bufSize = totalLen;
+ unsigned char *newBuf = OICRealloc(recvBuffer, bufSize);
+ if (NULL == newBuf)
+ {
+ OIC_LOG(ERROR, TAG, "out of memory");
+ goto exit;
+ }
+ recvBuffer = newBuf;
+ isHeaderChecked = true;
+ }
+ }
+ if (totalLen == totalReceivedLen)
+ {
+ CAEndpoint_t ep = { .adapter = CA_ADAPTER_TCP,
+ .port = svritem->u4tcp.port };
+ strncpy(ep.addr, svritem->addr, sizeof(ep.addr));
+
+ if (g_packetReceivedCallback)
+ {
+ g_packetReceivedCallback(&ep, recvBuffer, totalLen);
+ }
+ OIC_LOG_V(DEBUG, TAG, "received data len:%d", totalLen);
+ break;
+ }
+ } while (!totalLen || totalLen > totalReceivedLen);
+
+ OICFree(recvBuffer);
+ }
+
+ return CA_STATUS_OK;
+
+exit:
+ ca_mutex_lock(g_mutexObjectList);
+ close(svritem->u4tcp.fd);
+ u_arraylist_remove(caglobals.tcp.svrlist, i);
+ ca_mutex_unlock(g_mutexObjectList);
+ OICFree(recvBuffer);
+ return CA_STATUS_FAILED;
+}
+
+// TODO: resolving duplication.
+static int CASetNonblocking(int fd)
+{
+ int fl = fcntl(fd, F_GETFL);
+ if (fl == -1)
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to get existing flags, Error code: %s",
+ strerror(errno));
+ }
+ else if ((fl & O_NONBLOCK) != O_NONBLOCK)
+ {
+ fl = fcntl(fd, F_SETFL, fl | O_NONBLOCK);
+ if (fl == -1)
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to set non-blocking mode, Error code: %s",
+ strerror(errno));
+ }
+ }
+
+ return fl;
+}
+
+static int CATCPCreateSocket(int family, CATCPServerInfo_t *TCPServerInfo)
+{
+ // create tcp socket
+ int fd = socket(family, SOCK_STREAM, IPPROTO_TCP);
+ if (-1 == fd)
+ {
+ OIC_LOG_V(ERROR, TAG, "create socket failed: %s", strerror(errno));
+ goto exit;
+ }
+
+ // set non-blocking socket
+ if (-1 == CASetNonblocking(fd))
+ {
+ goto exit;
+ }
+
+ struct sockaddr_storage sa = { .ss_family = family };
+ CAConvertNameToAddr(TCPServerInfo->addr, TCPServerInfo->u4tcp.port, &sa);
+ socklen_t socklen = sizeof (struct sockaddr_in);
+
+ // connect to TCP server
+ int ret = connect(fd, (struct sockaddr *)&sa, socklen);
+ if (0 == ret)
+ {
+ OIC_LOG(DEBUG, TAG, "connect socket success");
+ }
+ else if (EINPROGRESS == errno)
+ {
+ int error = 0;
+ socklen_t len = sizeof(error);
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
+ {
+ OIC_LOG(ERROR, TAG, "getsockopt() error");
+ goto exit;
+ }
+
+ if (error)
+ {
+ if (ECONNREFUSED == error)
+ {
+ OIC_LOG(ERROR, TAG, "connection refused");
+ goto exit;
+ }
+ OIC_LOG(ERROR, TAG, "failed to connect socket");
+ goto exit;
+ }
+ OIC_LOG(DEBUG, TAG, "connect socket success");
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "failed to connect socket");
+ goto exit;
+ }
+
+ return fd;
+
+exit:
+ if (fd >= 0)
+ {
+ close(fd);
+ }
+ return -1;
+}
+
+static void CAAcceptHandler(void *data)
+{
+ (void)data;
+ OIC_LOG(DEBUG, TAG, "IN - CAAcceptHandler");
+
+ int reuse = 1;
+ struct sockaddr_in server = { .sin_addr.s_addr = INADDR_ANY,
+ .sin_family = AF_INET,
+ .sin_port = htons(SERVER_PORT) };
+
+ g_acceptServerFD = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (g_acceptServerFD < 0)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to create socket");
+ goto exit;
+ }
+
+ if (-1 == setsockopt(g_acceptServerFD, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)))
+ {
+ OIC_LOG(ERROR, TAG, "setsockopt SO_REUSEADDR");
+ goto exit;
+ }
+
+ int serverlen = sizeof(server);
+ if (-1 == bind(g_acceptServerFD, (struct sockaddr *)&server, serverlen))
+ {
+ OIC_LOG(ERROR, TAG, "bind() error");
+ goto exit;
+ }
+
+ if (listen(g_acceptServerFD, caglobals.tcp.listenBacklog) != 0)
+ {
+ OIC_LOG(ERROR, TAG, "listen() error");
+ goto exit;
+ }
+
+ struct pollfd acceptServerFD = { .fd = g_acceptServerFD,
+ .events = POLLIN };
+
+ while (!caglobals.tcp.terminate)
+ {
+ int pollState = poll(&acceptServerFD, 1, caglobals.tcp.selectTimeout);
+ if (pollState < 0)
+ {
+ OIC_LOG_V(FATAL, TAG, "polling error %s", strerror(errno));
+ goto exit;
+ }
+ else if (!pollState)
+ {
+ continue;
+ }
+
+ if (acceptServerFD.revents & POLLIN)
+ {
+ struct sockaddr_storage clientaddr;
+ socklen_t clientlen = sizeof (struct sockaddr_in);
+
+ int sockfd = accept(g_acceptServerFD, (struct sockaddr *)&clientaddr, &clientlen);
+ if (sockfd != -1)
+ {
+ CATCPServerInfo_t *svritem = (CATCPServerInfo_t *) OICMalloc(sizeof (*svritem));
+ if (!svritem)
+ {
+ OIC_LOG(ERROR, TAG, "Out of memory");
+ close(sockfd);
+ return;
+ }
+
+ // set non-blocking socket
+ if (-1 == CASetNonblocking(sockfd))
+ {
+ close(sockfd);
+ OICFree(svritem);
+ continue;
+ }
+ svritem->u4tcp.fd = sockfd;
+
+ CAConvertAddrToName((struct sockaddr_storage *)&clientaddr,
+ (char *) &svritem->addr, &svritem->u4tcp.port);
+
+ ca_mutex_lock(g_mutexObjectList);
+ bool res = u_arraylist_add(caglobals.tcp.svrlist, svritem);
+ if (!res)
+ {
+ OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+ close(sockfd);
+ OICFree(svritem);
+ ca_mutex_unlock(g_mutexObjectList);
+ continue;
+ }
+ ca_mutex_unlock(g_mutexObjectList);
+ }
+ }
+ }
+
+ ca_mutex_lock(g_mutexObjectList);
+ // notify the thread
+ g_threadCounts--;
+ if (!g_threadCounts)
+ {
+ ca_cond_signal(g_condObjectList);
+ }
+ ca_mutex_unlock(g_mutexObjectList);
+
+ OIC_LOG(DEBUG, TAG, "OUT - CAAcceptHandler");
+
+exit:
+ if (g_acceptServerFD >= 0)
+ {
+ close(g_acceptServerFD);
+ }
+ ca_mutex_lock(g_mutexObjectList);
+ g_threadCounts--;
+ if (!g_threadCounts)
+ {
+ ca_cond_signal(g_condObjectList);
+ }
+ ca_mutex_unlock(g_mutexObjectList);
+ return;
+}
+
+CAResult_t CATCPStartServer(const ca_thread_pool_t threadPool)
+{
+ if (caglobals.tcp.started)
+ {
+ return CA_STATUS_OK;
+ }
+
+ if (!caglobals.tcp.ipv4tcpenabled)
+ {
+ caglobals.tcp.ipv4tcpenabled = true; // only needed to run CA tests
+ }
+
+ CAResult_t res = CATCPCreateMutex();
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "failed to create mutex");
+ return res;
+ }
+
+ res = CATCPCreateCond();
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "failed to create cond");
+ return res;
+ }
+
+ ca_mutex_lock(g_mutexObjectList);
+ if (!caglobals.tcp.svrlist)
+ {
+ caglobals.tcp.svrlist = u_arraylist_create();
+ }
+ ca_mutex_unlock(g_mutexObjectList);
+
+ caglobals.tcp.terminate = false;
+
+ res = ca_thread_pool_add_task(threadPool, CAAcceptHandler, NULL);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "thread_pool_add_task failed");
+ return res;
+ }
+ OIC_LOG(DEBUG, TAG, "CAAcceptHandler thread started successfully.");
+
+ res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "thread_pool_add_task failed");
+ return res;
+ }
+ OIC_LOG(DEBUG, TAG, "CAReceiveHandler thread started successfully.");
+
+ caglobals.tcp.started = true;
+
+ return CA_STATUS_OK;
+}
+
+void CATCPStopServer()
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ // mutex lock
+ ca_mutex_lock(g_mutexObjectList);
+
+ // set terminate flag
+ caglobals.tcp.terminate = true;
+
+ ca_cond_wait(g_condObjectList, g_mutexObjectList);
+
+ // mutex unlock
+ ca_mutex_unlock(g_mutexObjectList);
+
+ if (-1 != g_acceptServerFD)
+ {
+ close(g_acceptServerFD);
+ g_acceptServerFD = -1;
+ }
+
+ CATCPDisconnectAll();
+ CATCPDestroyMutex();
+ CATCPDestroyCond();
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CATCPSetPacketReceiveCallback(CATCPPacketReceivedCallback callback)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ g_packetReceivedCallback = callback;
+
+ OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+static size_t CACheckPayloadLength(const void *data, size_t dlen)
+{
+ coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(
+ ((unsigned char *)data)[0] >> 4);
+
+ coap_pdu_t *pdu = coap_new_pdu(transport, dlen);
+ if (!pdu)
+ {
+ OIC_LOG(ERROR, TAG, "outpdu is null");
+ return 0;
+ }
+
+ int ret = coap_pdu_parse((unsigned char *) data, dlen, pdu, transport);
+ if (0 >= ret)
+ {
+ OIC_LOG(ERROR, TAG, "pdu parse failed");
+ coap_delete_pdu(pdu);
+ return 0;
+ }
+
+ size_t payloadLen = 0;
+ if (pdu->data)
+ {
+ payloadLen = (unsigned char *) pdu->hdr + pdu->length - pdu->data;
+ OICFree(pdu);
+ }
+
+ return payloadLen;
+}
+
+static void sendData(const CAEndpoint_t *endpoint,
+ const void *data, size_t dlen)
+{
+ // #1. get TCP Server object from list
+ uint32_t index = 0;
+ CATCPServerInfo_t *svritem = CAGetTCPServerInfoFromList(endpoint->addr, endpoint->port,
+ &index);
+ if (!svritem)
+ {
+ // if there is no connection info, connect to TCP Server
+ svritem = CAConnectToTCPServer(endpoint);
+ if (!svritem)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to create TCP server object");
+ g_TCPErrorHandler(endpoint, data, dlen, CA_SEND_FAILED);
+ return;
+ }
+ }
+
+ // #2. check payload length
+ size_t payloadLen = CACheckPayloadLength(data, dlen);
+ // if payload length is zero, disconnect from TCP server
+ if (!payloadLen)
+ {
+ OIC_LOG(DEBUG, TAG, "payload length is zero, disconnect from remote device");
+ CADisconnectFromTCPServer(endpoint);
+ return;
+ }
+
+ // #3. check connection state
+ if (svritem->u4tcp.fd < 0)
+ {
+ // if file descriptor value is wrong, remove TCP Server info from list
+ OIC_LOG(ERROR, TAG, "Failed to connect to TCP server");
+ CADisconnectFromTCPServer(endpoint);
+ g_TCPErrorHandler(endpoint, data, dlen, CA_SEND_FAILED);
+ return;
+ }
+
+ // #4. send data to TCP Server
+ size_t remainLen = dlen;
+ do
+ {
+ size_t len = send(svritem->u4tcp.fd, data, remainLen, 0);
+ if (-1 == len)
+ {
+ if (EWOULDBLOCK != errno)
+ {
+ OIC_LOG_V(ERROR, TAG, "unicast ipv4tcp sendTo failed: %s", strerror(errno));
+ g_TCPErrorHandler(endpoint, data, dlen, CA_SEND_FAILED);
+ return;
+ }
+ continue;
+ }
+ data += len;
+ remainLen -= len;
+ } while (remainLen > 0);
+
+ OIC_LOG_V(INFO, TAG, "unicast ipv4tcp sendTo is successful: %d bytes", dlen);
+}
+
+void CATCPSendData(CAEndpoint_t *endpoint, const void *data, uint32_t datalen,
+ bool isMulticast)
+{
+ VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
+ VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
+
+ if (!isMulticast)
+ {
+ if (caglobals.tcp.ipv4tcpenabled && (endpoint->adapter & CA_ADAPTER_TCP))
+ {
+ sendData(endpoint, data, datalen);
+ }
+ }
+}
+
+CAResult_t CAGetTCPInterfaceInformation(CAEndpoint_t **info, uint32_t *size)
+{
+ OIC_LOG(DEBUG, TAG, "IN");
+
+ VERIFY_NON_NULL(info, TAG, "info is NULL");
+ VERIFY_NON_NULL(size, TAG, "size is NULL");
+
+ return CA_NOT_SUPPORTED;
+}
+
+CATCPServerInfo_t *CAConnectToTCPServer(const CAEndpoint_t *TCPServerInfo)
+{
+ VERIFY_NON_NULL_RET(TCPServerInfo, TAG, "TCPServerInfo is NULL", NULL);
+
+ // #1. create TCP server object
+ CATCPServerInfo_t *svritem = (CATCPServerInfo_t *) OICMalloc(sizeof (*svritem));
+ if (!svritem)
+ {
+ OIC_LOG(ERROR, TAG, "Out of memory");
+ return NULL;
+ }
+ memcpy(svritem->addr, TCPServerInfo->addr, sizeof(svritem->addr));
+ svritem->u4tcp.port = TCPServerInfo->port;
+
+ // #2. create the socket and connect to TCP server
+ if (caglobals.tcp.ipv4tcpenabled)
+ {
+ svritem->u4tcp.fd = CATCPCreateSocket(AF_INET, svritem);
+ if (-1 == svritem->u4tcp.fd)
+ {
+ OICFree(svritem);
+ return NULL;
+ }
+ }
+
+ // #3. add TCP connection info to list
+ ca_mutex_lock(g_mutexObjectList);
+ if (caglobals.tcp.svrlist)
+ {
+ bool res = u_arraylist_add(caglobals.tcp.svrlist, svritem);
+ if (!res)
+ {
+ OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+ close(svritem->u4tcp.fd);
+ OICFree(svritem);
+ ca_mutex_unlock(g_mutexObjectList);
+ return NULL;
+ }
+ }
+ ca_mutex_unlock(g_mutexObjectList);
+
+ return svritem;
+}
+
+CAResult_t CADisconnectFromTCPServer(const CAEndpoint_t *TCPServerInfo)
+{
+ VERIFY_NON_NULL(TCPServerInfo, TAG, "TCP server info is NULL");
+
+ // #1. get server info
+ uint32_t index = 0;
+ ca_mutex_lock(g_mutexObjectList);
+ CATCPServerInfo_t *svritem = CAGetTCPServerInfoFromList(TCPServerInfo->addr,
+ TCPServerInfo->port,
+ &index);
+ if (!svritem)
+ {
+ OIC_LOG(ERROR, TAG, "there is no connection info");
+ ca_mutex_unlock(g_mutexObjectList);
+ return CA_STATUS_FAILED;
+ }
+
+ // #2. close the socket and remove TCP connection info in list
+ if (svritem->u4tcp.fd >= 0)
+ {
+ close(svritem->u4tcp.fd);
+ }
+ u_arraylist_remove(caglobals.tcp.svrlist, index);
+ ca_mutex_unlock(g_mutexObjectList);
+
+ return CA_STATUS_OK;
+}
+
+CATCPServerInfo_t *CAGetTCPServerInfoFromList(const char *addr, const uint16_t port,
+ uint32_t *index)
+{
+ VERIFY_NON_NULL_RET(addr, TAG, "addr is NULL", NULL);
+ VERIFY_NON_NULL_RET(index, TAG, "index is NULL", NULL);
+
+ // get connection info from list
+ uint32_t length = u_arraylist_length(caglobals.tcp.svrlist);
+
+ for (size_t i = 0; i < length; i++)
+ {
+ CATCPServerInfo_t *svritem = (CATCPServerInfo_t *) u_arraylist_get(
+ caglobals.tcp.svrlist, i);
+ if (!svritem)
+ {
+ continue;
+ }
+
+ if (!strncmp(svritem->addr, addr, sizeof(svritem->addr))
+ && (svritem->u4tcp.port == port))
+ {
+ *index = i;
+ return svritem;
+ }
+ }
+
+ return NULL;
+}
+
+void CATCPSetErrorHandler(CATCPErrorHandleCallback errorHandleCallback)
+{
+ g_TCPErrorHandler = errorHandleCallback;
+}
catests = catest_env.Program('catests', ['catests.cpp',
'caprotocolmessagetest.cpp',
'ca_api_unittest.cpp',
- 'camutex_tests.cpp'
+ 'camutex_tests.cpp',
+ 'uarraylist_test.cpp'
])
Alias("test", [catests])
#include "cainterface.h"
#include "cacommon.h"
+#define CA_TRANSPORT_ADAPTER_SCOPE 1000
class CATests : public testing::Test {
protected:
TEST_F(CATests, SelectNetworkTestBad)
{
//Select disable network
- EXPECT_EQ(CA_NOT_SUPPORTED, CASelectNetwork((CATransportAdapter_t)1000));
+ EXPECT_EQ(CA_NOT_SUPPORTED, CASelectNetwork((CATransportAdapter_t)
+ CA_TRANSPORT_ADAPTER_SCOPE));
}
// check return value when selected network is disable
TEST_F(CATests, UnSelectNetworkTest)
{
//UnSelect disable network
- EXPECT_EQ(CA_STATUS_FAILED, CAUnSelectNetwork((CATransportAdapter_t)1000));
+ EXPECT_EQ(CA_STATUS_FAILED, CAUnSelectNetwork((CATransportAdapter_t)
+ CA_TRANSPORT_ADAPTER_SCOPE));
}
// CAHandlerRequestResponse TC
--- /dev/null
+//******************************************************************
+//
+// 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 "gtest/gtest.h"
+
+#include "uarraylist.h"
+
+class UArrayListF : public testing::Test {
+public:
+ UArrayListF() :
+ testing::Test(),
+ list(NULL)
+ {
+ }
+
+protected:
+ virtual void SetUp()
+ {
+ list = u_arraylist_create();
+ ASSERT_TRUE(list != NULL);
+ }
+
+ virtual void TearDown()
+ {
+ u_arraylist_free(&list);
+ ASSERT_EQ(NULL, list);
+ }
+
+ u_arraylist_t *list;
+};
+
+TEST(UArrayList, Base)
+{
+ u_arraylist_t *list = u_arraylist_create();
+ ASSERT_TRUE(list != NULL);
+
+ u_arraylist_free(&list);
+ ASSERT_EQ(NULL, list);
+}
+
+TEST(UArrayList, CreateMany)
+{
+ for (int i = 0; i < 100; ++i)
+ {
+ u_arraylist_t *list = u_arraylist_create();
+ ASSERT_TRUE(list != NULL);
+
+ u_arraylist_free(&list);
+ ASSERT_EQ(NULL, list);
+ }
+}
+
+TEST(UArrayList, FreeNull)
+{
+ u_arraylist_free(NULL);
+}
+
+TEST_F(UArrayListF, Length)
+{
+ ASSERT_EQ(static_cast<uint32_t>(0), u_arraylist_length(list));
+
+ int dummy = 0;
+ bool rc = u_arraylist_add(list, &dummy);
+ ASSERT_TRUE(rc);
+
+ ASSERT_EQ(static_cast<uint32_t>(1), u_arraylist_length(list));
+
+ // Add a few times without checking, just in case checking has side-effects
+ rc = u_arraylist_add(list, &dummy);
+ ASSERT_TRUE(rc);
+ rc = u_arraylist_add(list, &dummy);
+ ASSERT_TRUE(rc);
+ rc = u_arraylist_add(list, &dummy);
+ ASSERT_TRUE(rc);
+
+ ASSERT_EQ(static_cast<uint32_t>(4), u_arraylist_length(list));
+}
+
+TEST_F(UArrayListF, LengthMulti)
+{
+ ASSERT_EQ(static_cast<uint32_t>(0), u_arraylist_length(list));
+
+ int dummy = 0;
+ for (int i = 0; i < 1000; ++i)
+ {
+ bool rc = u_arraylist_add(list, &dummy);
+ ASSERT_TRUE(rc);
+ }
+
+ ASSERT_EQ(static_cast<uint32_t>(1000), u_arraylist_length(list));
+}
+
+TEST_F(UArrayListF, NoReserve)
+{
+ static const int PAD_SIZE = 10000;
+
+ int dummy = 0;
+
+ //u_arraylist_reserve(list, PAD_SIZE);
+
+ for (int i = 0; i < PAD_SIZE; ++i)
+ {
+ bool rc = u_arraylist_add(list, &dummy);
+ ASSERT_TRUE(rc);
+ }
+}
+
+TEST_F(UArrayListF, Reserve)
+{
+ static const int PAD_SIZE = 10000;
+
+ int dummy = 0;
+
+ u_arraylist_reserve(list, PAD_SIZE);
+
+ for (int i = 0; i < PAD_SIZE; ++i)
+ {
+ bool rc = u_arraylist_add(list, &dummy);
+ ASSERT_TRUE(rc);
+ }
+}
+
+
+TEST_F(UArrayListF, ShrinkToFit)
+{
+ static const int PAD_SIZE = 100;
+
+ int dummy = 0;
+
+ u_arraylist_reserve(list, PAD_SIZE);
+
+ for (int i = 0; i < PAD_SIZE; ++i)
+ {
+ bool rc = u_arraylist_add(list, &dummy);
+ ASSERT_TRUE(rc);
+ }
+
+ for (int i = PAD_SIZE; i > 0; --i)
+ {
+ u_arraylist_remove(list, i);
+ }
+
+ EXPECT_GT(list->capacity, list->length);
+ u_arraylist_shrink_to_fit(list);
+ EXPECT_EQ(list->capacity, list->length);
+}
+
+TEST_F(UArrayListF, Get)
+{
+ ASSERT_EQ(static_cast<uint32_t>(0), u_arraylist_length(list));
+
+ int dummy[1000] = {0};
+ size_t cap = sizeof(dummy) / sizeof(dummy[0]);
+
+ for (size_t i = 0; i < cap; ++i)
+ {
+ bool rc = u_arraylist_add(list, &dummy[i]);
+ ASSERT_TRUE(rc);
+ }
+ ASSERT_EQ(static_cast<uint32_t>(1000), u_arraylist_length(list));
+
+ for (size_t i = 0; i < cap; ++i)
+ {
+ void *value = u_arraylist_get(list, i);
+ ASSERT_TRUE(value != NULL);
+ ASSERT_EQ(&dummy[i], value);
+ }
+}
+
+TEST_F(UArrayListF, Remove)
+{
+ ASSERT_EQ(static_cast<uint32_t>(0), u_arraylist_length(list));
+
+ int dummy[1000] = {0};
+ size_t cap = sizeof(dummy) / sizeof(dummy[0]);
+
+ for (size_t i = 0; i < cap; ++i)
+ {
+ bool rc = u_arraylist_add(list, &dummy[i]);
+ ASSERT_TRUE(rc);
+ }
+ ASSERT_EQ(static_cast<uint32_t>(1000), u_arraylist_length(list));
+
+ // Remove walking forward so as to have a non-trivial case.
+ for (uint32_t idx = 0, old = 0;
+ idx < u_arraylist_length(list);
+ ++idx, old += 2)
+ {
+ void *value = u_arraylist_remove(list, idx);
+ ASSERT_TRUE(value != NULL);
+ ASSERT_EQ(value, &dummy[old]);
+ }
+ ASSERT_EQ(static_cast<uint32_t>(500), u_arraylist_length(list));
+}
+
+TEST_F(UArrayListF, Contains)
+{
+ ASSERT_EQ(static_cast<uint32_t>(0), u_arraylist_length(list));
+
+ int dummy[1000] = {0};
+ size_t cap = sizeof(dummy) / sizeof(dummy[0]);
+
+ for (size_t i = 0; i < cap; ++i)
+ {
+ bool rc = u_arraylist_add(list, &dummy[i]);
+ ASSERT_TRUE(rc);
+ }
+ ASSERT_EQ(static_cast<uint32_t>(1000), u_arraylist_length(list));
+
+ // Remove walking forward so as to have a non-trivial case.
+ for (uint32_t idx = 0, old = 0;
+ idx < u_arraylist_length(list);
+ ++idx, old += 2)
+ {
+ void *value = u_arraylist_remove(list, idx);
+ ASSERT_TRUE(value != NULL);
+ ASSERT_EQ(value, &dummy[old]);
+ }
+ ASSERT_EQ(static_cast<uint32_t>(500), u_arraylist_length(list));
+
+ // Finally, check that the ones we expect are present, and others are not.
+ for (size_t i = 0; i < cap; ++i)
+ {
+ bool shouldBe = (i & 1) != 0;
+ bool found = u_arraylist_contains(list, &dummy[i]);
+ ASSERT_EQ(shouldBe, found) << " for entry " << i;
+ }
+}
+
+// Test to repeatedly add and remove with some contents present so that
+// a poor implmentation will thrash memory.
+TEST_F(UArrayListF, Thrash)
+{
+ static const int PAD_SIZE = 1000;
+ static const int THRASH_COUNT = 1500;
+ ASSERT_EQ(static_cast<uint32_t>(0), u_arraylist_length(list));
+
+ int dummy2 = 0;
+ int dummy[PAD_SIZE] = {0};
+ size_t cap = sizeof(dummy) / sizeof(dummy[0]);
+
+ for (size_t i = 0; i < cap; ++i)
+ {
+ bool rc = u_arraylist_add(list, &dummy[i]);
+ ASSERT_TRUE(rc);
+ }
+ ASSERT_EQ(static_cast<uint32_t>(PAD_SIZE), u_arraylist_length(list));
+
+ // Finally add and remove a lot.
+ for (int i = 0; i < THRASH_COUNT; ++i)
+ {
+ bool rc = u_arraylist_add(list, &dummy2);
+ ASSERT_TRUE(rc);
+ ASSERT_EQ(static_cast<uint32_t>(PAD_SIZE + 1),
+ u_arraylist_length(list));
+
+ ASSERT_EQ(&dummy2,
+ u_arraylist_remove(list, u_arraylist_length(list) - 1));
+
+ ASSERT_EQ(static_cast<uint32_t>(PAD_SIZE), u_arraylist_length(list));
+ }
+}
// Use the PCF macro to wrap strings stored in FLASH on the Arduino
// Example: OC_LOG(INFO, TAG, PCF("Entering function"));
#ifdef ARDUINO
- #define PCF(str) ((PROGMEM const char *)(F(str)))
+#ifdef __cplusplus
+#define PCF(str) ((PROGMEM const char *)(F(str)))
+#else
+#define PCF(str) ((PROGMEM const char *)(PSTR(str)))
+#endif //__cplusplus
#else
#define PCF(str) str
#endif
#define MAX_LOG_V_BUFFER_SIZE (256)
// Log levels
+#ifdef __TIZEN__
+typedef enum {
+ DEBUG = DLOG_DEBUG,
+ INFO = DLOG_INFO,
+ WARNING = DLOG_WARN,
+ ERROR = DLOG_ERROR,
+ FATAL = DLOG_ERROR
+} LogLevel;
+#else
typedef enum {
DEBUG = 0,
INFO,
ERROR,
FATAL
} LogLevel;
-
-#ifdef __TIZEN__
-
-int OCGetTizenLogLevel(LogLevel level);
-
#endif
#ifdef __TIZEN__
#ifdef TB_LOG
#ifdef __TIZEN__
- #define OC_LOG(level,tag,mes) LOG_(LOG_ID_MAIN, OCGetTizenLogLevel(level), tag, mes)
- #define OC_LOG_V(level,tag,fmt,args...) LOG_(LOG_ID_MAIN, OCGetTizenLogLevel(level), tag, fmt,##args)
+ #define OC_LOG(level,tag,mes) LOG_(LOG_ID_MAIN, level, tag, mes)
+ #define OC_LOG_V(level,tag,fmt,args...) LOG_(LOG_ID_MAIN, level, tag, fmt,##args)
#define OC_LOG_BUFFER(level, tag, buffer, bufferSize)
#else // These macros are defined for Linux, Android, and Arduino
#define OC_LOG_INIT() OCLogInit()
- #define OC_LOG(level, tag, logStr) OCLog((level), (tag), (logStr))
- #define OC_LOG_BUFFER(level, tag, buffer, bufferSize) OCLogBuffer((level), (tag), (buffer), (bufferSize))
+ #define OC_LOG_BUFFER(level, tag, buffer, bufferSize) OCLogBuffer((level), PCF(tag), (buffer), (bufferSize))
#ifdef ARDUINO
#define OC_LOG_CONFIG(ctx)
#define OC_LOG_SHUTDOWN()
+ #define OC_LOG(level, tag, logStr) OCLog((level), PCF(tag), PCF(logStr))
// Use full namespace for logInit to avoid function name collision
#define OC_LOG_INIT() OCLogInit()
// Don't define variable argument log function for Arduino
- #define OC_LOG_V(level, tag, ...) OCLogv((level), (tag), __VA_ARGS__)
+ #define OC_LOG_V(level, tag, format, ...) OCLogv((level), PCF(tag), PCF(format), __VA_ARGS__)
#else
#define OC_LOG_CONFIG(ctx) OCLogConfig((ctx))
+ #define OC_LOG(level, tag, logStr) OCLog((level), (tag), (logStr))
#define OC_LOG_SHUTDOWN() OCLogShutdown()
// Define variable argument log function for Linux and Android
#define OC_LOG_V(level, tag, ...) OCLogv((level), (tag), __VA_ARGS__)
#ifndef ARDUINO
-#ifdef __TIZEN__
-
-int OCGetTizenLogLevel(LogLevel level)
-{
- switch(level)
- {
- case DEBUG:
- return DLOG_DEBUG;
- case INFO:
- return DLOG_INFO;
- case WARNING:
- return DLOG_WARN;
- case ERROR:
- return DLOG_ERROR;
- case FATAL:
- return DLOG_FATAL;
- }
- return DLOG_DEBUG;
-}
-
-#else
+#ifndef __TIZEN__
void OCLogConfig(oc_log_ctx_t *ctx) {
logCtx = ctx;
}
}
else
{
-
int min = 0;
int sec = 0;
int ms = 0;
* @param tag - Module name
* @param format - variadic log string
*/
- void OCLogv(LogLevel level, PROGMEM const char * tag, const char * format, ...)
+ void OCLogv(LogLevel level, PROGMEM const char * tag, PROGMEM const char * format, ...)
{
char buffer[LINE_BUFFER_SIZE];
va_list ap;
}
Serial.print(F(": "));
+#ifdef __AVR__
+ vsnprintf_P(buffer, sizeof(buffer), format, ap);
+#else
vsnprintf(buffer, sizeof(buffer), format, ap);
+#endif
for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines
{
if(*p == '\n')
Serial.println();
va_end(ap);
}
- /**
- * Output a variable argument list log string with the specified priority level.
- * Only defined for Arduino as depicted below.
- *
- * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
- * @param tag - Module name
- * @param format - variadic log string
- */
- void OCLogv(LogLevel level, PROGMEM const char * tag, const __FlashStringHelper *format, ...)
- {
- char buffer[LINE_BUFFER_SIZE];
- va_list ap;
- va_start(ap, format);
-
- GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
- Serial.print(buffer);
-
- char c;
- Serial.print(F(": "));
-
- while ((c = pgm_read_byte(tag))) {
- Serial.write(c);
- tag++;
- }
- Serial.print(F(": "));
-
- #ifdef __AVR__
- vsnprintf_P(buffer, sizeof(buffer), (const char *)format, ap); // progmem for AVR
- #else
- vsnprintf(buffer, sizeof(buffer), (const char *)format, ap); // for the rest of the world
- #endif
- for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines
- {
- if(*p == '\n')
- {
- Serial.write('\r');
- }
- Serial.write(*p);
- }
- Serial.println();
- va_end(ap);
- }
-
#endif
-
-
-
#include "ArduinoLoggerTest.h"
#include "logger.h"
-PROGMEM const char tag[] = "Arduino";
-PROGMEM const char msg[] = "Arduino Logger Test";
+#define tag "Arduino"
+#define msg "Arduino Logger Test"
-PROGMEM const char debugMsg[] = "this is a DEBUG message";
-PROGMEM const char infoMsg[] = "this is a INFO message";
-PROGMEM const char warningMsg[] = "this is a WARNING message";
-PROGMEM const char errorMsg[] = "this is a ERROR message";
-PROGMEM const char fatalMsg[] = "this is a FATAL message";
+#define debugMsg "this is a DEBUG message"
+#define infoMsg "this is a INFO message"
+#define warningMsg "this is a WARNING message"
+#define errorMsg "this is a ERROR message"
+#define fatalMsg "this is a FATAL message"
-PROGMEM const char multiLineMsg[] = "this is a DEBUG message\non multiple\nlines";
+#define multiLineMsg "this is a DEBUG message\non multiple\nlines"
//-----------------------------------------------------------------------------
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+// 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,
+// Refer to http://pubs.opengroup.org/stage7tc1/functions/clock_gettime.html
+// and to http://man7.org/linux/man-pages/man2/clock_gettime.2.html
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
#if defined(__ANDROID__) || defined(__linux__) || defined(__APPLE__)
#include "fcntl.h"
#include "unistd.h"
+#include <stdlib.h>
+#include <sys/time.h>
+#include <time.h>
+#if defined(__ANDROID__)
+#include <linux/time.h>
+#endif
#endif
#include "ocrandom.h"
#include <stdio.h>
#ifdef ARDUINO
#include "Arduino.h"
-uint8_t GetRandomBitRaw() {
+uint8_t GetRandomBitRaw()
+{
return analogRead((uint8_t)ANALOG_IN) & 0x1;
}
-uint8_t GetRandomBitRaw2() {
+uint8_t GetRandomBitRaw2()
+{
int a = 0;
- for(;;) {
+ for (;;)
+ {
a = GetRandomBitRaw() | (GetRandomBitRaw()<<1);
- if (a==1){
+ if (a==1)
+ {
return 0; // 1 to 0 transition: log a zero bit
}
- if (a==2){
+ if (a==2)
+ {
return 1;// 0 to 1 transition: log a one bit
}
// For other cases, try again.
}
}
-uint8_t GetRandomBit() {
+uint8_t GetRandomBit()
+{
int a = 0;
- for(;;) {
+ for (;;)
+ {
a = GetRandomBitRaw2() | (GetRandomBitRaw2()<<1);
- if (a==1){
+ if (a==1)
+ {
return 0; // 1 to 0 transition: log a zero bit
}
- if (a==2){
+ if (a==2)
+ {
return 1;// 0 to 1 transition: log a one bit
}
// For other cases, try again.
}
#endif
-int8_t OCSeedRandom() {
-#if defined(__ANDROID__) || defined(__linux__) || defined(__APPLE__)
+int8_t OCSeedRandom()
+{
+#if defined(__ANDROID__) || defined(__linux__) || defined(__APPLE__) || defined(__TIZEN__)
+ // Get current time to Seed.
+ uint64_t currentTime = 0;
+#ifdef __ANDROID__
+ struct timespec getTs;
+ clock_gettime(CLOCK_MONOTONIC, &getTs);
+ currentTime = (getTs.tv_sec * (uint64_t)1000000000 + getTs.tv_nsec)/1000;
+#elif _POSIX_TIMERS > 0
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ currentTime = ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ currentTime = tv.tv_sec * 1000000 + tv.tv_usec;
+#endif
+
int32_t fd = open("/dev/urandom", O_RDONLY);
- if (fd > 0) {
+ if (fd >= 0)
+ {
uint32_t randomSeed = 0;
uint32_t totalRead = 0; //how many integers were read
int32_t currentRead = 0;
- while (totalRead < sizeof(randomSeed)) {
+ while (totalRead < sizeof(randomSeed))
+ {
currentRead = read(fd, (uint8_t*) &randomSeed + totalRead,
sizeof(randomSeed) - totalRead);
- if(currentRead > 0){
+ if (currentRead > 0)
+ {
totalRead += currentRead;
}
}
close(fd);
- srand(randomSeed);
- return 0;
+ srand(randomSeed | currentTime);
}
- close(fd);
- return -1;
+ else
+ {
+ // Do time based seed when problem in accessing "/dev/urandom"
+ srand(currentTime);
+ }
+
+ return 0;
#elif defined ARDUINO
uint32_t result =0;
uint8_t i;
- for (i=32; i--;){
+ for (i=32; i--;)
+ {
result += result + GetRandomBit();
}
randomSeed(result);
}
-void OCFillRandomMem(uint8_t * location, uint16_t len) {
- if(!location){
+void OCFillRandomMem(uint8_t * location, uint16_t len)
+{
+ if (!location)
+ {
return;
}
- for (; len--;){
+ for (; len--;)
+ {
*location++ = OCGetRandomByte();
}
}
-uint32_t OCGetRandom() {
+uint32_t OCGetRandom()
+{
uint32_t result = 0;
OCFillRandomMem((uint8_t*) &result, 4);
return result;
}
-uint8_t OCGetRandomByte(void) {
+uint8_t OCGetRandomByte(void)
+{
#if defined(__ANDROID__) || defined(__linux__) || defined(__APPLE__)
return rand() & 0x00FF;
#elif defined ARDUINO
#endif
}
-uint32_t OCGetRandomRange(uint32_t firstBound, uint32_t secondBound){
+uint32_t OCGetRandomRange(uint32_t firstBound, uint32_t secondBound)
+{
uint32_t base;
uint32_t diff;
uint32_t result;
- if(firstBound > secondBound){
+ if (firstBound > secondBound)
+ {
base = secondBound;
diff = firstBound - secondBound;
- }else if(firstBound < secondBound){
+ }
+ else if (firstBound < secondBound)
+ {
base = firstBound;
diff = secondBound - firstBound;
- }else{
+ }
+ else
+ {
return secondBound;
}
result = ((float)OCGetRandom()/((float)(0xFFFFFFFF))*(float)diff) + (float) base;
#if defined(__ANDROID__)
uint8_t parseUuidChar(char c)
{
- if(isdigit(c))
+ if (isdigit(c))
{
return c - '0';
}
OCRandomUuidResult OCGenerateUuid(uint8_t uuid[UUID_SIZE])
{
- if(!uuid)
+ if (!uuid)
{
return RAND_UUID_INVALID_PARAM;
}
char uuidString[UUID_STRING_SIZE];
int8_t ret = OCGenerateUuidString(uuidString);
- if(ret < 0)
+ if (ret < 0)
{
return ret;
}
OCRandomUuidResult OCGenerateUuidString(char uuidString[UUID_STRING_SIZE])
{
- if(!uuidString)
+ if (!uuidString)
{
return RAND_UUID_INVALID_PARAM;
}
#if defined(__ANDROID__)
int32_t fd = open("/proc/sys/kernel/random/uuid", O_RDONLY);
- if(fd > 0)
+ if (fd > 0)
{
ssize_t readResult = read(fd, uuidString, UUID_STRING_SIZE - 1);
close(fd);
- if(readResult < 0)
+ if (readResult < 0)
{
return RAND_UUID_READ_ERROR;
}
- else if(readResult < UUID_STRING_SIZE - 1)
+ else if (readResult < UUID_STRING_SIZE - 1)
{
uuidString[0] = '\0';
return RAND_UUID_READ_ERROR;
}
uuidString[UUID_STRING_SIZE - 1] = '\0';
- for(char* p = uuidString; *p; ++p)
+ for (char* p = uuidString; *p; ++p)
{
*p = tolower(*p);
}
uint8_t uuid[UUID_SIZE];
int8_t ret = OCGenerateUuid(uuid);
- if(ret != 0)
+ if (ret != 0)
{
return ret;
}
--- /dev/null
+Import('env')
+import os
+
+env.AppendUnique(CPPPATH = [os.path.join(Dir('.').abspath, './include')])
+
+if env.get('TARGET_OS') == 'tizen':
+ env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+else:
+ env.AppendUnique(LIBPATH = [os.path.join(env.get('BUILD_DIR'), 'resource/csdk/routing/')])
+
+env.AppendUnique(LIBS = ['routingmanager'])
+
+local_env = env.Clone()
+
+if env.get('ROUTING') == 'GW':
+ local_env.AppendUnique(CPPPATH = [
+ os.path.join(Dir('.').abspath, './../stack/include'),
+ os.path.join(Dir('.').abspath, './../stack/include/internal'),
+ os.path.join(Dir('.').abspath, './../logger'),
+ os.path.join(Dir('.').abspath, './../../oc_logger/include'),
+ os.path.join(Dir('.').abspath, './../ocrandom/include'),
+ os.path.join(Dir('.').abspath, './../connectivity/api'),
+ os.path.join(Dir('.').abspath, './../connectivity/common/inc'),
+ os.path.join(Dir('.').abspath, './../security/include'),
+ os.path.join(Dir('.').abspath, './../connectivity/external/inc')
+ ])
+elif env.get('ROUTING') == 'EP':
+ local_env.AppendUnique(CPPPATH = [
+ os.path.join(Dir('.').abspath, './../stack/include'),
+ os.path.join(Dir('.').abspath, './../stack/include/internal'),
+ os.path.join(Dir('.').abspath, './../logger'),
+ os.path.join(Dir('.').abspath, './../../oc_logger/include'),
+ os.path.join(Dir('.').abspath, './../connectivity/api'),
+ os.path.join(Dir('.').abspath, './../connectivity/common/inc'),
+ os.path.join(Dir('.').abspath, './../connectivity/external/inc')
+ ])
+
+######################################################################
+# Build flags
+######################################################################
+
+######################################################################
+# Source files and Targets
+######################################################################
+
+if env.get('ROUTING') == 'GW':
+ routing_src = [
+ './src/routingutility.c',
+ './src/routingmanager.c',
+ './src/routingtablemanager.c',
+ './src/routingmanagerinterface.c',
+ './src/routingmessageparser.c',
+ ]
+elif env.get('ROUTING') == 'EP':
+ routing_src = [
+ './src/routingutility.c',
+ ]
+
+routinglib = local_env.StaticLibrary('routingmanager', routing_src)
+local_env.InstallTarget(routinglib, 'routingmanager')
+local_env.UserInstallTargetLib(routinglib, 'routingmanager')
--- /dev/null
+/* ****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the APIs for routing manager.
+ */
+#ifndef ROUTING_MANAGER_H_
+#define ROUTING_MANAGER_H_
+
+#include "octypes.h"
+#include "ocserverrequest.h"
+#include "ocresource.h"
+#include "routingutility.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Initialize the Routing Manager.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+// TODO: Future addition pertaining to security, RM should be given ACL callback from RI.
+OCStackResult RMInitialize();
+
+/**
+ * Terminates the Routing Manager.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMTerminate();
+
+/**
+ * This API will be called from RI layer whenever there is a request for the GATEWAY
+ * Virtual Resource.
+ * @param[in,out] request Request Received.
+ * @param[in] resource Resource handle used for sending the response.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMHandleGatewayRequest(OCServerRequest *request, const OCResource *resource);
+
+/**
+ * API to handle the Response payload. The Gateway entries are parsed from
+ * the payload using routingmessageparser apis, addition or removal of
+ * Gateway entries is performed.
+ * @param[in] devAddr Address of the Device that sent the payload.
+ * @param[in] resource Response payload.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMHandleResponsePayload(const OCDevAddr *devAddr, const OCRepPayload *payload);
+
+/**
+ * Process the routing manager timer to send notification to all the observers.
+ */
+void RMProcess();
+
+/**
+ * API to form the payload with gateway ID.
+ * @param[out] payload Payload generated by routing message parser.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMGetGatewayPayload(OCRepPayload **payload);
+
+/**
+ * API to get the gateway UUID of its own.
+ * @return Gateway UUID.
+ */
+uint32_t RMGetGatewayId();
+
+/**
+ * API to get the multicast sequence number..
+ * @return Multicast sequence number.
+ */
+uint16_t RMGetMcastSeqNumber();
+
+/**
+ * On reception of request from CA, RI sends to this function.
+ * This checks if the route option is present and adds routing information to
+ * to the route option data.
+ * @param[in,out] message Received coap packet.
+ * @param[in] sender RemoteEndpoint which sent the packet.
+ * @param[out] destination Populated by RM by parsing message, CA then forwards packet to
+ * "destination".
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+OCStackResult RMHandleRequest(CARequestInfo_t *message, const CAEndpoint_t *sender,
+ bool *selfDestination);
+
+/**
+ * On reception of response from CA, RI sends to this function.
+ * This checks if the route option is present and adds routing information to
+ * to the route option data.
+ * @param[in,out] message Received coap packet.
+ * @param[in] sender RemoteEndpoint which sent the packet.
+ * @param[out] destination Populated by RM by parsing message to know if response is
+ * for its own.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+OCStackResult RMHandleResponse(CAResponseInfo_t *message, const CAEndpoint_t *sender,
+ bool *selfDestination);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ROUTING_MANAGER_H_ */
--- /dev/null
+/* ****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file is an interface of routing manager and resource interospection layer.
+ */
+#ifndef ROUTING_MANAGER_INTERFACE_H_
+#define ROUTING_MANAGER_INTERFACE_H_
+
+#include "routingmanager.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Creates a Gateway resource and initializes the observer List.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMInitGatewayResource();
+
+/**
+ * Send multicast discover request for the Gateway resource.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMDiscoverGatewayResource();
+
+/**
+ * Send observe request for the gateway device hosting the Gateway resource.
+ * @param[in] devAddr Device address of the Gateway device hosting
+ * the gateway resource.
+ * @param[in] payload Payload to be sent with the request.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMSendObserveRequest(const OCDevAddr *devAddr, OCRepPayload *payload);
+
+/**
+ * Send delete request to all the neighbour nodes.
+ * @param[in] devAddr Device address of the Gateway device hosting
+ * the gateway resource.
+ * @param[in] payload Payload to be sent with the request.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMSendDeleteRequest(const OCDevAddr *devAddr, OCRepPayload *payload);
+
+/**
+ * Send a response for GET/OBSERVE request received for Gateway resource.
+ * @param[in] request Request Received.
+ * @param[in] resource Resource Handle.
+ * @param[in] payload Payload containing Gateway Entries.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMSendResponse(const OCServerRequest *request, const OCResource *resource,
+ const OCRepPayload *payload);
+
+/**
+ * Send notification for list of observers except a particular observer.
+ * @param[in] obsId Observer who shouldn't be sent notification.
+ * @param[in] obsLen Length of Observer ID list.
+ * @param[in] payload Payload containing Gateway Entries.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMSendNotificationForListofObservers(OCObservationId *obsId, uint8_t obsLen,
+ const OCRepPayload *payload);
+
+/**
+ * Adds an observer to the RI stack.
+ * @param[in] request Request handle.
+ * @param[out] obsID Observer ID generated for the requester.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMAddObserverToStack(const OCServerRequest *request, OCObservationId *obsID);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ROUTING_MANAGER_INTERFACE_H_ */
--- /dev/null
+/* ****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the APIs for routing message parser.
+ */
+#ifndef ROUTING_MESSAGE_PARSER_H_
+#define ROUTING_MESSAGE_PARSER_H_
+
+#include "ulinklist.h"
+#include "uarraylist.h"
+#include "octypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Constructs payload with its Gateway ID. This payload is
+ * shared between the gateways during initial discovery.
+ * @param[in] gatewayId Gateway ID.
+ * @param[out] payload Encoded Payload for Gateway ID.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMPConstructGatewayPayload(uint32_t gatewayId, OCRepPayload **payload);
+
+/**
+ * Constructs payload with the Gateway ID and routing table
+ * This payload is shared for any observe response or notification.
+ * @param[in] gatewayId Gateway ID.
+ * @param[in] seqNum Sequence Number of Gateway.
+ * @param[in] routingtable linklist with Routing Table Entries.
+ * @param[in] isUpdateSeqNeeded Response type of payload response/notification.
+ * @param[out] payload Payload with gateway Data.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMPConstructObserveResPayload(uint32_t gatewayId, uint32_t seqNum,
+ const u_linklist_t *routingtable, bool isUpdateSeqNeeded,
+ OCRepPayload **payload);
+
+/**
+ * Constructs payload with the own GatewayID and the nodes that are removed from the routing table.
+ * @param[in] gatewayId Gateway ID.
+ * @param[in] seqNum Sequence Number of Gateway.
+ * @param[in] removedGateways linklist with Removed gateway entries.
+ * @param[in] isUpdateSeqNeeded Response type of payload response/notification.
+ * @param[out] removedPayload Encoded Payloads of removed routing table entries.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMPConstructRemovalPayload(uint32_t gatewayId, uint32_t seqNum,
+ const u_linklist_t *removedGateways, bool isUpdateSeqNeeded,
+ OCRepPayload **removedPayload);
+
+/**
+ * Parse payload for request and get gateway id.
+ * @param[in] payload Payload.
+ * @param[in] payloadSize Payload Size.
+ * @param[out] gatewayId Gateway Id.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMPParseRequestPayload(const uint8_t* payload, size_t payloadSize,
+ uint32_t *gatewayId);
+
+/**
+ * Parse payload for response and get required info.
+ * @param[in] payload Payload with gateways route table encoded.
+ * @param[in/out] seqNum Sequence Number of Gateway.
+ * @param[in/out] gatewayId Gateway Id.
+ * @param[in/out] gatewayTable Parsed routing table from Payload.
+ * @param[out] isUpdateSeqNeeded Response type of payload response/notification.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMPParseResponsePayload(const OCRepPayload *payload, uint32_t *gatewayId,
+ uint32_t *seqNum, u_linklist_t **gatewayTable,
+ bool *isUpdateSeqNeeded);
+
+/**
+ * Frees payload.
+ * @param[in/out] payload Encoded Payload for Gateway ID.
+ * @return NONE.
+ */
+void RMPFreePayload(OCRepPayload *payload);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ROUTING_MESSAGE_PARSER_H_ */
+
--- /dev/null
+/* ****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the APIs for routing table manager.
+ */
+#ifndef ROUTING_TABLE_MANAGER_H_
+#define ROUTING_TABLE_MANAGER_H_
+
+#ifndef SINGLE_THREAD
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#endif
+
+#if defined(__ANDROID__)
+#include <linux/time.h>
+#endif
+#include "ulinklist.h"
+#include "uarraylist.h"
+#include "octypes.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Maximum hop/destination address length.
+ */
+#define MAX_DEST_ADDR_LEN 40
+
+/**
+ * Maximum number of observers for the gateway resource.
+ */
+#define MAX_NUM_OBSERVERS 10
+
+/**
+ * Maximum time after which gateway should send a notification for its existence.
+ * Every 30s gateway will send its existence notification.
+ */
+#define GATEWAY_ALIVE_TIMEOUT 30
+
+/**
+ * The routing table entries are validated for every 40 seconds for its existence.
+ */
+#define ROUTINGTABLE_REFRESH_TIMEOUT 40
+
+/**
+ * The routing table entries are removed if entries are invalid every 45 seconds.
+ */
+#define ROUTINGTABLE_VALIDATION_TIMEOUT 45
+
+/**
+ * Destination Interface Address entries.
+ */
+typedef struct
+{
+ uint32_t observerId; /**< Observer Id. */
+ CAEndpoint_t destIntfAddr; /**< Destination Interface Address. */
+ uint32_t timeElapsed; /**< Time elapsed. */
+ bool isValid; /**< Valid check for Gateway. */
+} RTMDestIntfInfo_t;
+
+/**
+ * Endpoint Address entries.
+ */
+typedef struct
+{
+ uint16_t endpointId; /**< Endpoint Id. */
+ CAEndpoint_t destIntfAddr; /**< Destination Interface Address. */
+} RTMEndpointEntry_t;
+
+/**
+ * Gateway Address entries.
+ */
+typedef struct gatewayAddress
+{
+ uint32_t gatewayId; /**< Gateway Id. */
+ u_arraylist_t *destIntfAddr; /**< Destination Interface Addresses. */
+} RTMGatewayId_t;
+
+/**
+ * Routing table entries at Gateway.
+ */
+typedef struct
+{
+ RTMGatewayId_t *destination; /**< destination Address. */
+ RTMGatewayId_t *nextHop; /**< Next Hop Information. */
+ uint32_t routeCost; /**< routeCost. */
+ uint16_t mcastMessageSeqNum; /**< sequence number for last mcast packet. */
+ uint32_t seqNum; /**< sequence number for notification. */
+} RTMGatewayEntry_t;
+
+/**
+ * Initialize the Routing Table Manager.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @param[in/out] endpointTable Endpoint Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMInitialize(u_linklist_t **gatewayTable, u_linklist_t **endpointTable);
+
+/**
+ * Terminates the Routing Table Manager.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @param[in/out] endpointTable Endpoint Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMTerminate(u_linklist_t **gatewayTable, u_linklist_t **endpointTable);
+
+/**
+ * Frees the gateway table memory with nodes containing structure RTMGatewayEntry_t.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMFreeGatewayRouteTable(u_linklist_t **gatewayTable);
+
+/**
+ * Frees the gateway ID list memory with nodes containing structute RTMGatewayId_t.
+ * @param[in/out] gatewayIdTable Gateway ID list.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMFreeGatewayIdList(u_linklist_t **gatewayIdTable);
+
+/**
+ * Frees the endpoint table memory with nodes containing structute RTMEndpointEntry_t.
+ * @param[in/out] endpointTable Endpoint Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMFreeEndpointRouteTable(u_linklist_t **endpointTable);
+
+/**
+ * Adds the entry to the routing table if the entry for Gateway id is
+ * not preset in Routing table, Updates the Old entry if Entry for
+ * Gateway Id is already present in Routing table i.e routeCost and NextHop
+ * will be updated for efficient hop result.
+ *
+ * @param[in] gatewayId Gateway Id.
+ * @param[in] nextHop Next Hop address.
+ * @param[in] routeCost Shortest Path to Destination - Hopcount.
+ * @param[in] destInterfaces Destination Interface Information.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMAddGatewayEntry(uint32_t gatewayId, uint32_t nextHop, uint32_t routeCost,
+ const RTMDestIntfInfo_t *destInterfaces, u_linklist_t **gatewayTable);
+
+/**
+ * Adds the endpoint entry to the routing table.
+ * @param[in/out] endpointId Endpoint Id.
+ * @param[in] destAddr Destination Address.
+ * @param[in/out] endpointTable Endpoint Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMAddEndpointEntry(uint16_t *endpointId, const CAEndpoint_t *destAddr,
+ u_linklist_t **endpointTable);
+
+/**
+ * Removes the gateway entry from the routing table and also removes
+ * corresponding entries having nexthop as removed gateway.
+ * @param[in] gatewayId Gateway id of node need to be removed.
+ * @param[in/out] removedGatewayNodes Linklist containing removed gateway nodes
+ * list need to be freed by caller.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMRemoveGatewayEntry(uint32_t gatewayId, u_linklist_t **removedGatewayNodes,
+ u_linklist_t **gatewayTable);
+
+/**
+ * Removes the endpoint entry from the routing table.
+ * @param[in] endpointId Endpoint id of node need to be removed.
+ * @param[in/out] endpointTable Endpoint Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMRemoveEndpointEntry(uint16_t endpointId, u_linklist_t **endpointTable);
+
+/**
+ * Removes the gateway entry from the routing table which has gateway id and nexthop as given.
+ * @param[in] gatewayId Gateway Id.
+ * @param[in] nextHop Next Hop address.
+ * @param[in] destInfAdr Destination Address of Next Hop to update time.
+ * @param[in/out] existEntry Entry which has different Next Hop.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMRemoveGatewayDestEntry(uint32_t gatewayId, uint32_t nextHop,
+ const RTMDestIntfInfo_t *destInfAdr,
+ RTMGatewayEntry_t **existEntry, u_linklist_t **gatewayTable);
+/**
+ * Removes the gateway nodes.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMRemoveGateways(u_linklist_t **gatewayTable);
+
+/**
+ * Removes the endpoint nodes.
+ * @param[in/out] endpointTable Endpoint Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMRemoveEndpoints(u_linklist_t **endpointTable);
+
+/**
+ * Gets the neighbour nodes i.e nodes with routecost 1.
+ * @param[in/out] neighbourNodes link list containing neighbouring nodes.
+ this list will be pointer to GatewayIds
+ and must be freed by caller.
+ * @param[in] gatewayTable Gateway Routing Table.
+ * @return NONE.
+ */
+void RTMGetNeighbours(u_linklist_t **neighbourNodes, const u_linklist_t *gatewayTable);
+
+/**
+ * Gets next hop from the routing table.
+ * @param[in] gatewayId Gateway Id.
+ * @param[in] gatewayTable Gateway Routing Table.
+ * @return Next Hop address - returns NULL if it is End Device.
+ */
+RTMGatewayId_t *RTMGetNextHop(uint32_t gatewayId, const u_linklist_t *gatewayTable);
+
+/**
+ * Gets endpoint entry
+ * @param[in] endpointId Endpoint id of node need to be removed.
+ * @param[in] endpointTable Endpoint Routing Table.
+ * @return Endpoint Destination inteface address.
+ */
+CAEndpoint_t *RTMGetEndpointEntry(uint16_t endpointId, const u_linklist_t *endpointTable);
+
+/**
+ * Updates destination interface address of an entry with provided gateway id
+ * as destination.
+ * @param[in] gatewayId Gateway Id of Hop need to be updated.
+ * @param[in] destInterfaces Destination Interface Information.
+ * @param[in] addAdr Add/Remove Dest intf addr.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMUpdateDestinationIntfAdr(uint32_t gatewayId, RTMDestIntfInfo_t destInterfaces,
+ bool addAdr, u_linklist_t **gatewayTable);
+
+/**
+ * Updates Multicast sequence number for gatewayID
+ * @param[in] gatewayId Gateway Id of Hop need to be updated.
+ * @param[in] seqNum sequence number for last cast packet from gateway.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMUpdateMcastSeqNumber(uint32_t gatewayId, uint16_t seqNum,
+ u_linklist_t **gatewayTable);
+
+/**
+ * Prints the routing table
+ * @param[in] gatewayTable Gateway Routing Table.
+ * @param[in] endpointTable Endpoint Routing Table.
+ * @return NONE.
+ */
+void RTMPrintTable(const u_linklist_t *gatewayTable, const u_linklist_t *endpointTable);
+
+/**
+ * Frees the GatewayId
+ * @param[in] gateway Gateway Structure pointer.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @return NONE.
+ */
+void RTMFreeGateway(RTMGatewayId_t *gateway, u_linklist_t **gatewayTable);
+
+/**
+ * Gets the list of observer IDs.
+ * @param[in/out] obsList List of Observation IDs.
+ * @param[in/out] obsListLen Length if Observation ID list.
+ * @param[in] gatewayTable Gateway Routing Table.
+ * @return NONE.
+ */
+void RTMGetObserverList(OCObservationId **obsList, uint8_t *obsListLen,
+ const u_linklist_t *gatewayTable);
+
+/**
+ * Adds a observer address and obsID to the list.
+ * @param[in] obsID Observation ID.
+ * @param[in] devAddr Address of Gateway.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @return NONE.
+ */
+OCStackResult RTMAddObserver(uint32_t obsID, CAEndpoint_t devAddr, u_linklist_t **gatewayTable);
+
+/**
+ * Check if a particular observer address is already registerd and returns
+ * its obsID if present.
+ * @param[in] devAddr Address of Gateway.
+ * @param[in/out] obsID Observation ID.
+ * @param[in] gatewayTable Gateway Routing Table.
+ * @return NONE
+ */
+bool RTMIsObserverPresent(CAEndpoint_t devAddr, OCObservationId *obsID,
+ const u_linklist_t *gatewayTable);
+
+/**
+ * Gets Current Time in Micro Seconds.
+ * @return Current Time.
+ */
+uint64_t RTMGetCurrentTime();
+
+/**
+ * Update Gateway Address Validity.
+ * @param[in/out] invalidTable Removed entries Table.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMUpdateDestAddrValidity(u_linklist_t **invalidTable, u_linklist_t **gatewayTable);
+
+/**
+ * Removes invalid gateways.
+ * @param[in/out] invalidTable Removed entries Table.
+ * @param[in/out] gatewayTable Gateway Routing Table.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMRemoveInvalidGateways(u_linklist_t **invalidTable, u_linklist_t **gatewayTable);
+
+/**
+ * Update Sequence number of Gateway Entry.
+ * @param[in] gatewayId Gateway Id.
+ * @param[in] seqNum Sequence Number of Entry.
+ * @param[in] destInterfaces Destination Interface Information.
+ * @param[out] gatewayTable Gateway Routing Table.
+ * @param[in] forceUpdate To Update parameters forcefully.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RTMUpdateEntryParameters(uint32_t gatewayId, uint32_t seqNum,
+ const RTMDestIntfInfo_t *destAdr, u_linklist_t **gatewayTable,
+ bool forceUpdate);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ROUTING_TABLE_MANAGER_H_ */
+
--- /dev/null
+/* ****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the utility functions used by Routing manager and RI
+ */
+
+#ifndef ROUTING_UTILITY_H_
+#define ROUTING_UTILITY_H_
+
+//TODO Endpoint will also include this file, remove unnecessary includes.
+
+#include "cacommon.h"
+#include "octypes.h"
+#ifdef ROUTING_GATEWAY
+#include "routingmanager.h"
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Maximum source or destination address length added to Route Option.
+ */
+#define MAX_ADDR_LEN 40
+
+/**
+ * Gateway ID length.
+ */
+#define GATEWAY_ID_LENGTH sizeof(uint32_t)
+
+/**
+ * Endpoint ID length.
+ */
+#define ENDPOINT_ID_LENGTH sizeof(uint16_t)
+
+/**
+ * Routing option number.
+ */
+// TODO: We need to define proper Option number.
+#define RM_OPTION_MESSAGE_SWITCHING 65524
+
+/**
+ * Macro to verify the validity of input argument with the return.
+ */
+#define RM_NULL_CHECK_WITH_RET(arg, log_tag, log_message) \
+ if (NULL == arg ){ \
+ OC_LOG_V(ERROR, log_tag, "Invalid input:%s", log_message); \
+ return OC_STACK_INVALID_PARAM; \
+ } \
+
+/**
+ * Macro to verify the validity of input argument.
+ */
+#define RM_NULL_CHECK_VOID(arg, log_tag, log_message) \
+ if (NULL == arg ){ \
+ OC_LOG_V(ERROR, log_tag, "Invalid input:%s", log_message); \
+ return; \
+ } \
+
+/**
+ * Macro to verify the return of an API.
+ */
+#define RM_VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
+ {OC_LOG_V(ERROR, TAG, "%s failed!!", #op); goto exit;} }
+
+/**
+ * This structure is used to hold the hopcount, source and destination address.
+ */
+typedef struct
+{
+ uint32_t srcGw; /**< Source gateway for this packet. */
+ uint32_t destGw; /**< Destination gateway for this packet. */
+ uint16_t mSeqNum; /**< HopCount. */
+ uint16_t srcEp; /**< Source endpoint for this packet. */
+ uint16_t destEp; /**< Destination endpoint for this packet. */
+} RMRouteOption_t;
+
+/**
+ * Adds the destination address to the Route options.
+ * If Route option is already present, it adds the destination address information to
+ * Route option else creates a new Route option with the destination address info.
+ * @param[in] endpoint Destination address.
+ * @param[in,out] options Header options present in the Request/response message.
+ * @param[in,out] numOptions Number of options present in the message.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+OCStackResult RMAddInfo(const char *destination, CAHeaderOption_t **options,
+ uint8_t *numOptions);
+
+/**
+ * Removes the Route Option from the header options.
+ * @param[in,out] options Header options present in request/response message.
+ * @param[in,out] numOptions Number of options present in request/response message.
+ * @param[in,out] endpoint Remote address updated with the actual source of request/response.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+OCStackResult RMUpdateInfo(CAHeaderOption_t **options, uint8_t *numOptions,
+ CAEndpoint_t *endpoint);
+
+/**
+ * Gets the index of the routing option if present.
+ * @param[in] options Header options present in request/response message.
+ * @param[in] numOptions Number of options present in request/response message.
+ * @param[out] index Index of the route option present in Header options.
+ * @return NONE.
+ */
+void RMGetRouteOptionIndex(const CAHeaderOption_t *options, uint8_t numOptions,
+ int8_t *index);
+
+/**
+ * To create a Routing option from the CARouteOption_t structure.
+ * @param[in] optValue Routing information.
+ * @param[out] options Routing information in the form of Header options.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+OCStackResult RMCreateRouteOption(const RMRouteOption_t *optValue, CAHeaderOption_t *options);
+
+/**
+ * To parse the routing option from the Headeroptions.
+ * @param[in] options Routing information in the form of Header options.
+ * @param[out] optValue Route information after parsing.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ */
+OCStackResult RMParseRouteOption(const CAHeaderOption_t *options, RMRouteOption_t *optValue);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ROUTING_MANAGER_H_ */
--- /dev/null
+/* ****************************************************************
+ *
+ * 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 <string.h>
+#include "routingmanager.h"
+#include "routingmanagerinterface.h"
+#include "routingtablemanager.h"
+#include "routingmessageparser.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "ocrandom.h"
+#include "ulinklist.h"
+#include "uarraylist.h"
+#include "ocstackinternal.h"
+#include "include/logger.h"
+
+/**
+ * Logging tag for module name.
+ */
+#define TAG "RM"
+
+/**
+ * Tag for printing the logs of forwarding the packet.
+ */
+#define RM_TAG "RAP"
+
+
+/**
+ * Unique gateway ID generated before hosting a gateway resource.
+ */
+uint32_t g_GatewayID = 0;
+
+/**
+ * Used for assigning unique ID.to endpoint's connected to this gateway
+ */
+static uint16_t g_EndpointCount = 0;
+
+/**
+ * Routing table which holds hop entries of Gateways with routeCost.
+ */
+static u_linklist_t *g_routingGatewayTable = NULL;
+
+/**
+ * List which holds hop entries with Endpoint information.
+ */
+static u_linklist_t *g_routingEndpointTable = NULL;
+
+/**
+ * Current time in microseconds.
+ */
+static uint64_t g_aliveTime = 0;
+
+/**
+ * Time to refresh the table entries.
+ */
+static uint64_t g_refreshTableTime = 0;
+
+/**
+ * Sequence number for the notification.
+ */
+static uint32_t g_sequenceNumber = 1;
+
+/**
+ * To check if the routing table is validated on 25th seconds.
+ */
+static bool g_isValidated = false;
+
+/**
+ * Multi cast Sequence number.
+ */
+static uint16_t g_mcastsequenceNumber = 1;
+
+/**
+ * To check if RM is initialized.
+ */
+static bool g_isRMInitialized = false;
+
+/**
+ * API to handle the GET request received for a Gateway Resource.
+ * @param[in] request Request Received.
+ * @param[in] resource Resource handle used for sending the response.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMHandleGETRequest(const OCServerRequest *request, const OCResource *resource);
+
+/**
+ * API to handle the OBSERVE request received for a Gateway Resource.
+ * @param[in,out] request Request Received.
+ * @param[in] resource Resource handle used for sending the response.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMHandleOBSERVERequest(OCServerRequest *request, const OCResource *resource);
+
+/**
+ * API to handle the OBSERVE request received for a Gateway Resource.
+ * @param[in,out] request Request Received.
+ * @param[in] resource Resource handle used for sending the response.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMHandleDELETERequest(const OCServerRequest *request, const OCResource *resource);
+
+/**
+ * Adds a observer after generating observer ID whenever observe
+ * request is received.
+ * @param[in,out] request Request handle of the Observe request.
+ * Sets the value of observeResult as OC_STACK_OK
+ * if observer is added successfully.
+ * @param[out] obsID Observer ID generated for the observer.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMAddObserver(OCServerRequest *request, OCObservationId *obsID);
+
+/**
+ * Send Notification to all the observers.
+ * @param[in] payload Payload to be sent in notification.
+ * @return ::OC_STACK_OK or Appropriate error code.
+ */
+OCStackResult RMSendNotificationToAll(const OCRepPayload *payload);
+
+/**
+ * Send Delete request to all the neighbour nodes.
+ * @return NONE.
+ */
+void RMSendDeleteToNeighbourNodes();
+
+void RMGenerateGatewayID(uint8_t *id, size_t idLen)
+{
+ OC_LOG(DEBUG, TAG, "RMGenerateGatewayID IN");
+ OCFillRandomMem(id, idLen);
+ OC_LOG(DEBUG, TAG, "RMGenerateGatewayID OUT");
+}
+OCStackResult RMInitialize()
+{
+ OC_LOG(DEBUG, TAG, "RMInitialize IN");
+ if (g_isRMInitialized)
+ {
+ OC_LOG(DEBUG, TAG, "RM already initialized");
+ return OC_STACK_OK;
+ }
+
+ // Initialize the GatewayResource[/oic/gateway].
+ OCStackResult result = RMInitGatewayResource();
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(ERROR, TAG, "RMInitGatewayResource failed[%d]", result);
+ return result;
+ }
+
+ // Generates a 4 byte Gateway ID.
+ RMGenerateGatewayID((uint8_t *)&g_GatewayID, sizeof(g_GatewayID));
+
+ OC_LOG_V(INFO, RM_TAG, "Gateway ID: %u", g_GatewayID);
+
+ // Initialize the Routing table manager.
+ result = RTMInitialize(&g_routingGatewayTable, &g_routingEndpointTable);
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(ERROR, TAG, "RTMInitialize failed[%d]", result);
+ return result;
+ }
+
+ g_isRMInitialized = true;
+
+ // Send a DISCOVER request for the gateway resource.
+ result = RMDiscoverGatewayResource();
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(ERROR, TAG, "RMDiscoverGatewayResource failed[%d]", result);
+ RTMTerminate(&g_routingGatewayTable, &g_routingEndpointTable);
+ return result;
+ }
+
+ // Initialize the timer with the current time.
+ g_aliveTime = RTMGetCurrentTime();
+ g_refreshTableTime = g_aliveTime;
+
+ OC_LOG(DEBUG, TAG, "RMInitialize OUT");
+ return result;
+}
+
+OCStackResult RMTerminate()
+{
+ OC_LOG(DEBUG, TAG, "RMTerminate IN");
+ if (!g_isRMInitialized)
+ {
+ OC_LOG(ERROR, TAG, "RM not initialized");
+ return OC_STACK_ERROR;
+ }
+ // Send DELETE request to neighbour nodes
+ RMSendDeleteToNeighbourNodes();
+
+ OCStackResult result = RTMTerminate(&g_routingGatewayTable, &g_routingEndpointTable);
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(ERROR, TAG, "CARegisterRoutingMessageHandler failed[%d]", result);
+ return result;
+ }
+ g_isRMInitialized = false;
+ OC_LOG(DEBUG, TAG, "RMTerminate OUT");
+ return result;
+}
+
+OCStackResult RMHandleGatewayRequest(OCServerRequest *request, const OCResource *resource)
+{
+ OC_LOG(DEBUG, TAG, "RMHandleGatewayRequest IN");
+
+ if (!g_isRMInitialized)
+ {
+ OC_LOG(ERROR, TAG, "RM not initialized");
+ return OC_STACK_ERROR;
+ }
+
+ RM_NULL_CHECK_WITH_RET(request, TAG, "request");
+ RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
+
+ OC_LOG_V(DEBUG, TAG, "Received request of method: %d", request->method);
+
+ if (OC_REST_GET == request->method)
+ {
+ switch((OCObserveAction)request->observationOption)
+ {
+ case OC_OBSERVE_REGISTER:
+ OC_LOG(DEBUG, TAG, "Received OBSERVE request");
+ RMHandleOBSERVERequest(request, resource);
+ break;
+ case OC_OBSERVE_DEREGISTER:
+ //TODO: Handle this case
+ OC_LOG(DEBUG, TAG, "Received OBSERVE deregister");
+ break;
+ case OC_OBSERVE_NO_OPTION:
+ OC_LOG(DEBUG, TAG, "Received GET request");
+ RMHandleGETRequest(request, resource);
+ break;
+ default:
+ OC_LOG(DEBUG, TAG, "Not Supported by Routing Manager");
+ }
+ }
+ else if (OC_REST_DELETE == request->method)
+ {
+ OC_LOG(DEBUG, TAG, "Received a Delete request");
+ RMHandleDELETERequest(request, resource);
+ }
+ OC_LOG(DEBUG, TAG, "RMHandleGatewayRequest OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RMHandleRequestPayload(OCDevAddr devAddr, const uint8_t *reqPayload,
+ size_t payloadSize)
+{
+ OC_LOG(DEBUG, TAG, "RMHandleRequestPayload IN");
+ RM_NULL_CHECK_WITH_RET(reqPayload, TAG, "reqPayload");
+
+ uint32_t gatewayId = 0;
+
+ OCStackResult result = RMPParseRequestPayload(reqPayload, payloadSize, &gatewayId);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ OC_LOG(INFO, TAG, "RMPParseRequestPayload is success");
+ // Check if the entry is its own.
+ if (gatewayId == g_GatewayID)
+ {
+ OC_LOG(INFO, TAG, "Own Request Received!!");
+ return OC_STACK_CONTINUE;
+ }
+
+ CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
+ CopyDevAddrToEndpoint(&devAddr, &endpoint);
+
+ OC_LOG_V(INFO, TAG, "Add the gateway ID: %u", gatewayId);
+ RTMDestIntfInfo_t destInterfaces = {.observerId = 0};
+ destInterfaces.destIntfAddr = endpoint;
+ result = RTMAddGatewayEntry(gatewayId, 0, 1, &destInterfaces, &g_routingGatewayTable);
+
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG(DEBUG, TAG, "Gateway was not added to the routing table");
+ return result;
+ }
+
+ OC_LOG(INFO, TAG, "Gateway was added");
+ // Create a list to add the updated entries and notify the observers
+ u_linklist_t *updatedTableList = u_linklist_create();
+ if(!updatedTableList)
+ {
+ OC_LOG(DEBUG, TAG, "Failure to notify");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ RTMGatewayId_t gwId = {.gatewayId = gatewayId};
+ RTMGatewayEntry_t newNode;
+ newNode.destination = &gwId;
+ newNode.routeCost = 1;
+ u_linklist_add(updatedTableList, (void *)&newNode);
+ RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
+
+ OCRepPayload *updatedPayload = NULL;
+
+ g_sequenceNumber++;
+ result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
+ updatedTableList, false,
+ &updatedPayload);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+
+ result = RMSendNotificationToAll(updatedPayload);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ RMPFreePayload(updatedPayload);
+
+exit:
+ u_linklist_free(&updatedTableList);
+ OC_LOG(DEBUG, TAG, "RMHandleRequestPayload OUT");
+ return result;
+}
+
+OCStackResult RMHandleResponsePayload(const OCDevAddr *devAddr, const OCRepPayload *respPayload)
+{
+ OC_LOG(DEBUG, TAG, "RMHandleResponsePayload IN");
+ RM_NULL_CHECK_WITH_RET(respPayload, TAG, "respPayload");
+
+ // Parse the Payload to get the Gateway ID of neighbouring node.
+ uint32_t gatewayId = 0;
+ uint32_t seqNum = 0;
+ u_linklist_t *gatewayTableList = NULL;
+ bool isUpdateSeqNum = false;
+
+ OCStackResult result = RMPParseResponsePayload(respPayload, &gatewayId, &seqNum,
+ &gatewayTableList, &isUpdateSeqNum);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ // Check if the entry is its own.
+ if (gatewayId == g_GatewayID)
+ {
+ OC_LOG(INFO, TAG, "-------------->Own entry, continue!!");
+ return OC_STACK_ERROR;
+ }
+ // Convert OCDevAddr to endpoint address
+ CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_FLAGS};
+ CopyDevAddrToEndpoint(devAddr, &endpoint);
+ RTMDestIntfInfo_t destInterfaces = {.observerId = 0};
+ destInterfaces.destIntfAddr = endpoint;
+ if (0 < seqNum)
+ {
+ OC_LOG_V(DEBUG, TAG, "Sequence Number of Resp payload is %d, Forceupdate: %d",
+ seqNum, isUpdateSeqNum);
+ result = RTMUpdateEntryParameters(gatewayId, seqNum, &destInterfaces,
+ &g_routingGatewayTable, isUpdateSeqNum);
+ if (OC_STACK_COMM_ERROR == result)
+ {
+ OC_LOG(ERROR, TAG, "Few packet drops are found, sequence number is not matching");
+ // Send a observe request to the gateway.
+ RMSendObserveRequest(devAddr, NULL);
+ return result;
+ }
+ else if (OC_STACK_DUPLICATE_REQUEST == result)
+ {
+ OC_LOG(ERROR, TAG, "Same sequence number is received");
+ return result;
+ }
+ }
+
+ // Check if the payload is for Removal
+ bool doRemoveEntry = false;
+
+ if (NULL != gatewayTableList && NULL != gatewayTableList->list)
+ {
+ RTMGatewayEntry_t *headPtr = u_linklist_get_data(gatewayTableList->list);
+ if (headPtr && 0 == headPtr->routeCost)
+ {
+ OC_LOG(INFO, TAG, "Remove entry is called");
+ doRemoveEntry = true;
+ }
+ }
+
+ // Create a list to add the updated entries and notify the observers
+ u_linklist_t *updatedTableList = u_linklist_create();
+ u_linklist_t *alternativeRouteList = u_linklist_create();
+ OCRepPayload *updatedPayload = NULL;
+ if (false == doRemoveEntry)
+ {
+ OC_LOG_V(INFO, TAG, "Add the gateway ID: %u", gatewayId);
+ result = RTMAddGatewayEntry(gatewayId, 0, 1, &destInterfaces, &g_routingGatewayTable);
+ if (OC_STACK_OK == result)
+ {
+ OC_LOG(INFO, TAG, "Node was added");
+ RTMGatewayId_t gwId = {.gatewayId = gatewayId};
+ RTMGatewayEntry_t newNode;
+ newNode.destination = &gwId;
+ newNode.routeCost = 1;
+ u_linklist_add(updatedTableList, (void *)&newNode);
+ RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
+
+ if (NULL == gatewayTableList)
+ {
+ OC_LOG(INFO, TAG, "Received a Discover Payload");
+ g_sequenceNumber++;
+ result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
+ updatedTableList, false,
+ &updatedPayload);
+ goto sendNotification;
+ }
+ }
+ }
+
+ // Iterate the Table and get each entry
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(gatewayTableList, &iterTable);
+
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+ // Check if the entry is its own.
+ if (!entry || entry->destination->gatewayId == g_GatewayID)
+ {
+ OC_LOG(INFO, TAG, "Ignore entry, continue!!");
+ u_linklist_get_next(&iterTable);
+ continue;
+ }
+
+ OC_LOG_V(INFO, TAG, "Gateway ID: %u", entry->destination->gatewayId);
+ if (true == doRemoveEntry)
+ {
+ // Remove the entry from RTM.
+ RTMGatewayEntry_t *existEntry = NULL;
+ result = RTMRemoveGatewayDestEntry(entry->destination->gatewayId, gatewayId,
+ &destInterfaces, &existEntry,
+ &g_routingGatewayTable);
+ if (OC_STACK_OK != result && NULL != existEntry)
+ {
+ u_linklist_add(alternativeRouteList, (void *)existEntry);
+ }
+ }
+ else
+ {
+ // Add the entry to RTM.
+ entry->routeCost = entry->routeCost + 1;
+ result = RTMAddGatewayEntry(entry->destination->gatewayId, gatewayId,
+ entry->routeCost, NULL, &g_routingGatewayTable);
+ }
+
+ if (OC_STACK_OK == result)
+ {
+ OC_LOG(INFO, TAG, "Gateway was added/removed");
+ u_linklist_add(updatedTableList, (void *)entry);
+ RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
+ }
+ u_linklist_get_next(&iterTable);
+ }
+
+ if ( 0 < u_linklist_length(alternativeRouteList))
+ {
+ OC_LOG(DEBUG, TAG, "Alternative routing found");
+ // Send the notification.
+ OCRepPayload *removeTablePayload = NULL;
+ g_sequenceNumber++;
+ result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
+ alternativeRouteList, false,
+ &removeTablePayload);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ result = RMSendNotificationToAll(removeTablePayload);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ RMPFreePayload(removeTablePayload);
+ }
+
+ if ( 0 >= u_linklist_length(updatedTableList))
+ {
+ OC_LOG_V(DEBUG, TAG, "No updation is needed, Length is %d", u_linklist_length(updatedTableList));
+ goto exit;
+ }
+
+ g_sequenceNumber++;
+ if (true == doRemoveEntry)
+ {
+ result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, updatedTableList,
+ false, &updatedPayload);
+ }
+ else
+ {
+ result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
+ updatedTableList, false,
+ &updatedPayload);
+ }
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+
+sendNotification:
+ result = RMSendNotificationToAll(updatedPayload);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ RMPFreePayload(updatedPayload);
+
+exit:
+ u_linklist_free(&updatedTableList);
+ u_linklist_free(&gatewayTableList);
+ u_linklist_free(&alternativeRouteList);
+ OC_LOG(DEBUG, TAG, "RMHandleResponsePayload OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RMHandleGETRequest(const OCServerRequest *request, const OCResource *resource)
+{
+ OC_LOG(DEBUG, TAG, "RMHandleGETRequest IN");
+ RM_NULL_CHECK_WITH_RET(request, TAG, "request");
+ RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
+
+ OCRepPayload *payload = NULL;
+ OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload failed[%d]", result);
+ return result;
+ }
+
+ // Send a response for GET request
+ result = RMSendResponse(request, resource, payload);
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(DEBUG, TAG, "Send response failed[%d]", result);
+ return result;
+ }
+
+ RMPFreePayload(payload);
+
+ // Send a observe request
+ result = RMSendObserveRequest(&(request->devAddr), NULL);
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(DEBUG, TAG, "Send response failed[%d]", result);
+ }
+ OC_LOG(DEBUG, TAG, "RMHandleGETRequest OUT");
+ return result;
+}
+
+OCStackResult RMHandleOBSERVERequest(OCServerRequest *request, const OCResource *resource)
+{
+ OC_LOG(DEBUG, TAG, "RMHandleOBSERVERequest IN");
+ RM_NULL_CHECK_WITH_RET(request, TAG, "request");
+ RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
+
+ // Parse payload and add the gateway entry.
+ if (0 < request->payloadSize)
+ {
+ RMHandleRequestPayload(request->devAddr, request->payload, request->payloadSize);
+ }
+
+ // Generate and add observer.
+ OCObservationId obsID = 0;
+ OCStackResult result = RMAddObserver(request, &obsID);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ OC_LOG_V(DEBUG, TAG, "Observer ID is %d", obsID);
+
+
+ // Get the Routing table from RTM
+ OCRepPayload *payload = NULL;
+ RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
+ OC_LOG(DEBUG, TAG, "Construct Routing table payload");
+ result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber,
+ g_routingGatewayTable, true,
+ &payload);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+
+ result = RMSendResponse(request, resource, payload);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ RMPFreePayload(payload);
+exit:
+ OC_LOG(DEBUG, TAG, "RMHandleOBSERVERequest OUT");
+ return result;
+}
+
+OCStackResult RMHandleDELETERequest(const OCServerRequest *request, const OCResource *resource)
+{
+ OC_LOG(DEBUG, TAG, "RMHandleDELETERequest IN");
+ RM_NULL_CHECK_WITH_RET(request, TAG, "request");
+ RM_NULL_CHECK_WITH_RET(resource, TAG, "resource");
+
+ uint32_t gatewayId = 0;
+ OCStackResult result = RMPParseRequestPayload(request->payload, request->payloadSize,
+ &gatewayId);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ OC_LOG(INFO, TAG, "RMPParseRequestPayload is success");
+
+ OC_LOG_V(INFO, TAG, "Remove the gateway ID: %u", gatewayId);
+
+ u_linklist_t *removedGatewayNodes = NULL;
+ result = RTMRemoveGatewayEntry(gatewayId, &removedGatewayNodes, &g_routingGatewayTable);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+
+ if (0 < u_linklist_length(removedGatewayNodes))
+ {
+ OCRepPayload *resPayloads = NULL;
+ g_sequenceNumber++;
+ result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedGatewayNodes,
+ false, &resPayloads);
+ RTMFreeGatewayRouteTable(&removedGatewayNodes);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ result = RMSendNotificationToAll(resPayloads);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
+ }
+
+exit:
+ OC_LOG(DEBUG, TAG, "RMHandleDELETERequest OUT");
+ return result;
+}
+
+OCStackResult RMAddObserver(OCServerRequest *request, OCObservationId *obsID)
+{
+ OC_LOG(DEBUG, TAG, "RMAddObserverForGateway OUT");
+ RM_NULL_CHECK_WITH_RET(request, TAG, "request");
+ RM_NULL_CHECK_WITH_RET(obsID, TAG, "obsID");
+
+ // Generate the ObserverID
+ CAEndpoint_t endpoint = {.adapter = 0};
+ CopyDevAddrToEndpoint(&(request->devAddr), &endpoint);
+
+ // Check if observer is already added.
+ if (true == RTMIsObserverPresent(endpoint, obsID, g_routingGatewayTable))
+ {
+ OC_LOG(DEBUG, TAG, "Observer is present");
+ request->observeResult = OC_STACK_OK;
+ return OC_STACK_OK;
+ }
+
+ OCStackResult result = RMAddObserverToStack(request, obsID);
+ request->observeResult = result;
+ if (OC_STACK_OK == result)
+ {
+ OC_LOG(DEBUG, TAG, "Added observer successfully");
+
+ // Add the observer to the list.
+ result = RTMAddObserver(*obsID, endpoint, &g_routingGatewayTable);
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(DEBUG, TAG, "RMAddObserver failed[%d]", result);
+ }
+ }
+ OC_LOG(DEBUG, TAG, "RMAddObserverForGateway OUT");
+ return result;
+}
+
+OCStackResult RMSendNotificationToAll(const OCRepPayload *payload)
+{
+ OC_LOG(DEBUG, TAG, "RMSendNotificationToAll IN");
+ RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
+
+ OCObservationId *obsList = NULL;
+ uint8_t obsLen = 0;
+ // Get the complete observer list.
+ RTMGetObserverList(&obsList, &obsLen, g_routingGatewayTable);
+ OCStackResult result = OC_STACK_OK;
+ OC_LOG_V(DEBUG, TAG, "Number of observers is %d", obsLen);
+ if (0 < obsLen)
+ {
+ // Send notification to the list of observers.
+ OC_LOG_V(DEBUG, TAG, "Sending notification with Sequence Number: %d", g_sequenceNumber);
+ result = RMSendNotificationForListofObservers(obsList, obsLen, payload);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ g_aliveTime = RTMGetCurrentTime();
+ }
+
+exit:
+ OICFree(obsList);
+ OC_LOG(DEBUG, TAG, "RMSendNotificationToAll OUT");
+ return result;
+}
+
+void RMProcess()
+{
+ if (!g_isRMInitialized)
+ {
+ return;
+ }
+
+ OCStackResult result = OC_STACK_OK;
+ uint64_t currentTime = RTMGetCurrentTime();
+ if (GATEWAY_ALIVE_TIMEOUT <= currentTime - g_aliveTime)
+ {
+ g_aliveTime = currentTime;
+ // Construct a payload with only the current sequence number.
+ OCRepPayload *payload = NULL;
+ result = RMPConstructObserveResPayload(g_GatewayID, g_sequenceNumber, NULL,
+ false, &payload);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+
+ OC_LOG(DEBUG, TAG, "Sending the alive notification to all");
+ // Send notification for every 15s to all the neighbours.
+ result = RMSendNotificationToAll(payload);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ }
+
+ if (ROUTINGTABLE_VALIDATION_TIMEOUT <= currentTime - g_refreshTableTime)
+ {
+ OC_LOG(DEBUG, TAG, "Validating the routing table");
+ u_linklist_t *removedEntries = NULL;
+ // Remove the invalid gateway entries.
+ RTMRemoveInvalidGateways(&removedEntries, &g_routingGatewayTable);
+ if (0 < u_linklist_length(removedEntries))
+ {
+ OCRepPayload *resPayloads = NULL;
+ g_sequenceNumber++;
+ result = RMPConstructRemovalPayload(g_GatewayID, g_sequenceNumber, removedEntries,
+ false, &resPayloads);
+ RTMFreeGatewayRouteTable(&removedEntries);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ result = RMSendNotificationToAll(resPayloads);
+ RM_VERIFY_SUCCESS(result, OC_STACK_OK);
+ RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
+ }
+ g_refreshTableTime = currentTime;
+ g_isValidated = false;
+ goto exit;
+ }
+
+ if (!g_isValidated && ROUTINGTABLE_REFRESH_TIMEOUT <= (currentTime - g_refreshTableTime))
+ {
+ OC_LOG_V(DEBUG, TAG, "Refreshing the routing table: %u", currentTime);
+ u_linklist_t* invalidInterfaces = NULL;
+ RTMUpdateDestAddrValidity(&invalidInterfaces, &g_routingGatewayTable);
+ if (0 < u_linklist_length(invalidInterfaces))
+ {
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(invalidInterfaces, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMDestIntfInfo_t *entry = (RTMDestIntfInfo_t *) u_linklist_get_data(iterTable);
+ if(!entry)
+ {
+ u_linklist_get_next(&iterTable);
+ continue;
+ }
+ OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
+ CopyEndpointToDevAddr(&(entry->destIntfAddr), &devAddr);
+ RMSendObserveRequest(&devAddr, NULL);
+ u_linklist_get_next(&iterTable);
+ }
+ }
+ g_isValidated = true;
+ RTMPrintTable(g_routingGatewayTable, g_routingEndpointTable);
+ u_linklist_free(&invalidInterfaces);
+ }
+
+exit:
+ return;
+}
+
+OCStackResult RMGetGatewayPayload(OCRepPayload **payload)
+{
+ OC_LOG(DEBUG, TAG, "RMGetGatewayPayload IN");
+ OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, payload);
+ OC_LOG_V(DEBUG, TAG, "RMPConstructDiscoverPayload result is %d", result);
+ OC_LOG(DEBUG, TAG, "RMGetGatewayPayload OUT");
+ return result;
+}
+
+void RMSendDeleteToNeighbourNodes()
+{
+ OC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes IN");
+ u_linklist_t *neighbourNodes = NULL;
+ RTMGetNeighbours(&neighbourNodes, g_routingGatewayTable);
+
+ if (0 >= u_linklist_length(neighbourNodes))
+ {
+ OC_LOG(DEBUG, TAG, "No neighbour nodes present");
+ return;
+ }
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(neighbourNodes, &iterTable);
+ while (NULL != iterTable)
+ {
+
+ OCRepPayload *payload = NULL;
+ // Created payload is freed in the OCDoResource() api.
+ OCStackResult result = RMPConstructGatewayPayload(g_GatewayID, &payload);
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(DEBUG, TAG, "RMPConstructGatewayPayload failed[%d]", result);
+ u_linklist_free(&neighbourNodes);
+ return;
+ }
+
+ RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
+ if (entry)
+ {
+ for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
+ {
+ RTMDestIntfInfo_t *dest = u_arraylist_get(entry->destination->destIntfAddr, i);
+ OCDevAddr devAddr = {.adapter = OC_DEFAULT_ADAPTER};
+ CopyEndpointToDevAddr(&(dest->destIntfAddr), &devAddr);
+ OC_LOG_V(DEBUG, TAG, "\nDestination interface addresses: %s[%d], OCDevAddr: %s[%d]",
+ dest->destIntfAddr.addr, dest->destIntfAddr.port, devAddr.addr, devAddr.port);
+ RMSendDeleteRequest(&devAddr, payload);
+ }
+ }
+ u_linklist_get_next(&iterTable);
+ }
+
+ u_linklist_free(&neighbourNodes);
+ OC_LOG(DEBUG, TAG, "RMSendDeleteToNeighbourNodes OUT");
+}
+
+uint32_t RMGetGatewayId()
+{
+ if (!g_isRMInitialized)
+ {
+ OC_LOG(ERROR, TAG, "RM not initialized");
+ return 0;
+ }
+ return g_GatewayID;
+}
+
+uint16_t RMGetMcastSeqNumber()
+{
+ if (!g_isRMInitialized)
+ {
+ OC_LOG(DEBUG, TAG, "RM not initialized");
+ return 0;
+ }
+ return ++g_mcastsequenceNumber;
+}
+
+/*
+ * This function is lifeline of packet forwarding module, hence we are going to do some serious
+ * handling here. Following are the expectations from this function:
+ * 1) If routing option is not available, forward packet to RI only. else:
+ * 2) If source is empty in routing option, packet is from end device, add an end device entry and
+ * add "GatewayId:ClientId" as source.
+ * 3) If destination is empty in routing option, its multicast packet, increase hopcount and
+ * multicast on other interfaces. Also remove routing Option and forward to RI. (Before
+ * forwarding, check last mCastSeqNumber for the source gateway otherwise we might be looping
+ * the packet.)
+ * 4) If destination is present in routing option, its unicast packet,
+ * a) If self gatewayId is present in destination and no clientId, remove routing option
+ * and forward to RI.
+ * b) If self gatewayId and a clientId is present in destination, forward to end device.
+ * 5) Drop a packet if its hop count reaches NUMBER_OF_GATEWAYS.
+ */
+
+OCStackResult RMHandlePacket(bool isRequest, void *message, const CAEndpoint_t *sender,
+ bool *selfDestination)
+{
+ RM_NULL_CHECK_WITH_RET(message, RM_TAG, "message");
+ RM_NULL_CHECK_WITH_RET(sender, RM_TAG, "sender");
+ RM_NULL_CHECK_WITH_RET(selfDestination, RM_TAG, "selfDestination");
+
+ bool forward = false;
+ CAEndpoint_t nextHop = {.adapter = CA_DEFAULT_ADAPTER};
+ CAInfo_t *info = NULL;
+ if (isRequest)
+ {
+ CARequestInfo_t *msg = message;
+ info = &(msg->info);
+ RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
+ }
+ else
+ {
+ CAResponseInfo_t *msg = message;
+ info = &(msg->info);
+ RM_NULL_CHECK_WITH_RET(info, RM_TAG, "info");
+ }
+
+ // 1. If routing option is not available, forward packet to RI only.
+ int8_t routeIndex = -1;
+ RMGetRouteOptionIndex(info->options, info->numOptions, &routeIndex);
+ if (-1 >= routeIndex)
+ {
+ OC_LOG(ERROR, RM_TAG, "No route option present. Let RI Handle");
+ // Let RI handle this packet.
+ *selfDestination = true;
+ return OC_STACK_OK;
+ }
+
+ // Get existing values in packet route option.
+ RMRouteOption_t routeOption = {.srcGw = 0};
+ OCStackResult res = RMParseRouteOption(&info->options[routeIndex], &routeOption);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG_V(ERROR, RM_TAG, "RMParseRouteOption failed");
+ return OC_STACK_ERROR;
+ }
+
+ /*
+ * 2) If source is empty in routing option, packet is from end device, add an end device entry
+ * and add "GatewayId:ClientId" as source.
+ */
+ if (g_GatewayID == routeOption.srcGw)
+ {
+ OC_LOG_V(ERROR, RM_TAG, "Packet is of its own");
+ if (0 == routeOption.destGw && g_mcastsequenceNumber < routeOption.mSeqNum)
+ {
+ g_mcastsequenceNumber = routeOption.mSeqNum;
+ }
+
+ return OC_STACK_ERROR;
+ }
+ else if (0 == routeOption.srcGw)
+ {
+ OC_LOG(INFO, RM_TAG, "Source missing in option");
+ // Packet from end device as Gateway will add source in option.
+ uint16_t endpointId = g_EndpointCount + 1;
+ OCStackResult res = RTMAddEndpointEntry(&endpointId, sender, &g_routingEndpointTable);
+ if (OC_STACK_OK == res)
+ {
+ g_EndpointCount = endpointId;
+ OC_LOG_V(INFO, RM_TAG, "New endpoint added [%d]:[%s]", g_EndpointCount, sender->addr);
+ }
+ else if (OC_STACK_DUPLICATE_REQUEST == res)
+ {
+ OC_LOG_V(INFO, RM_TAG, "Endpoint exist [%d]", endpointId);
+ }
+ else
+ {
+ OC_LOG(ERROR, RM_TAG, "Add Endpoint failed");
+ return OC_STACK_ERROR;
+ }
+
+ // add source option.
+ routeOption.srcGw = g_GatewayID;
+ routeOption.srcEp = endpointId;
+ OC_LOG_V(INFO, RM_TAG, "Added source: [%u:%u]", g_GatewayID, endpointId);
+ }
+
+ /*
+ * 3) If destination is empty in routing option, its a multicast packet, increase hopcount and
+ * multicast on other interfaces. Also remove routing Option and forward to RI (taken care by
+ * caller of this function).
+ */
+ if (0 == routeOption.destGw)
+ {
+ OC_LOG(INFO, RM_TAG, "Destination missing in option");
+ // This is a multicast packet.
+ if (g_GatewayID == routeOption.srcGw)
+ {
+ routeOption.mSeqNum = ++g_mcastsequenceNumber;
+ }
+ else
+ {
+ OCStackResult update = RTMUpdateMcastSeqNumber(routeOption.srcGw, routeOption.mSeqNum,
+ &g_routingGatewayTable);
+ if (OC_STACK_OK != update)
+ {
+ // this shouldnt have been forwarded. ignore.
+ OC_LOG_V(ERROR, RM_TAG, "Multicast Sequence number not proper: %d",
+ routeOption.mSeqNum);
+ return OC_STACK_ERROR;
+ }
+ }
+
+ // forward
+ *selfDestination = true;
+ forward = true;
+
+ // Send multicast on every adapter except the one from which packet was received
+ // TODO::: support to be added for IP hop.
+ if (sender->adapter != CA_ADAPTER_IP)
+ {
+ nextHop.adapter |= CA_ADAPTER_IP;
+ nextHop.flags |= CA_IPV4 | CA_IPV6;
+ }
+
+ if(sender->adapter != CA_ADAPTER_GATT_BTLE)
+ {
+ nextHop.adapter |= CA_ADAPTER_GATT_BTLE;
+ }
+
+ if(sender->adapter != CA_ADAPTER_RFCOMM_BTEDR)
+ {
+ nextHop.adapter |= CA_ADAPTER_RFCOMM_BTEDR;
+ }
+
+ // Only requests are sent as multicast.
+ if(isRequest)
+ {
+ CARequestInfo_t *msg = message;
+ msg->isMulticast = true;
+ }
+ goto rewriteandexit;
+ }
+ else if (g_GatewayID == routeOption.destGw)
+ {
+ OC_LOG(INFO, RM_TAG, "GatewayId found in destination");
+ /*
+ * This unicast packet either belongs to us or any of our connected end devices
+ * check if packet belongs to end device.
+ */
+ if (0 != routeOption.destEp)
+ {
+ // forward packet to the client.
+ OC_LOG_V(INFO, RM_TAG, "Forwarding packet to client id [%u]", routeOption.destEp);
+ CAEndpoint_t *clientInfo = RTMGetEndpointEntry(routeOption.destEp,
+ g_routingEndpointTable);
+ if(!clientInfo)
+ {
+ OC_LOG(ERROR, RM_TAG, "Failed to get Client info");
+ return OC_STACK_ERROR;
+ }
+
+ nextHop = *clientInfo;
+ forward = true;
+ *selfDestination = false;
+ goto rewriteandexit;
+ }
+ else
+ {
+ // packet is for us.
+ OC_LOG(INFO, RM_TAG, "Received packet for self");
+ forward = false;
+ *selfDestination = true;
+ goto rewriteandexit;
+ }
+ }
+ else
+ {
+ /*
+ * This unicast packet belongs to other gateway.
+ * we only want to print first 4 bytes of packet as readable GatewayId.
+ */
+ OC_LOG_V(INFO, RM_TAG, "Forwarding packet to Gateway: %u", routeOption.destGw);
+ RTMGatewayId_t *nextHopGw = RTMGetNextHop(routeOption.destGw, g_routingGatewayTable);
+ if(!nextHopGw)
+ {
+ OC_LOG(ERROR, RM_TAG, "Failed to get next hop");
+ return OC_STACK_ERROR;
+ }
+
+ // TODO:: check preferences among multiple interface addresses, for now sending on first one
+ RTMDestIntfInfo_t *address = u_arraylist_get(nextHopGw->destIntfAddr, 0);
+ if (!address)
+ {
+ OC_LOG(ERROR, RM_TAG, "Failed to get address for next hop");
+ return OC_STACK_ERROR;
+ }
+
+ nextHop = address->destIntfAddr;
+ forward = true;
+ *selfDestination = false;
+ goto rewriteandexit;
+ }
+
+rewriteandexit:
+
+ if (forward)
+ {
+ // Don't forward any packet meant for gateway resource.
+ if (info->resourceUri && (0 == strcmp(info->resourceUri, OC_RSRVD_GATEWAY_URI)))
+ {
+ OC_LOG(ERROR, RM_TAG, "Not forwarding gateway resource packet");
+ }
+ else if (sender->flags & CA_SECURE)
+ {
+ OC_LOG(ERROR, RM_TAG, "This is secured request. Not supported by routing manager");
+ return OC_STACK_ERROR;
+ }
+ else
+ {
+ // rewrite any changes in routing option.
+ res = RMCreateRouteOption(&routeOption, &info->options[routeIndex]);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG_V(ERROR, RM_TAG, "Rewriting RM option failed");
+ return res;
+ }
+ /*
+ * When forwarding a packet, do not attempt retransmission as its the responsibility of
+ * packet originator node.
+ */
+ info->skipRetransmission = true;
+ if(isRequest)
+ {
+ CARequestInfo_t *msg = message;
+ CAResult_t caRes = CASendRequest(&nextHop, msg);
+ if (CA_STATUS_OK != caRes)
+ {
+ OC_LOG_V(ERROR, RM_TAG, "Failed to forward request to next hop [%d][%s]", caRes,
+ nextHop.addr);
+ if(0 == routeOption.destGw)
+ {
+ /*
+ * No point going forward as unicast packet could not be forwarded
+ * not returning error for multicast as we may still let RI process
+ * this packet.
+ */
+ return OC_STACK_ERROR;
+ }
+ }
+ }
+ else
+ {
+ CAResponseInfo_t *msg = message;
+ CAResult_t caRes = CASendResponse(&nextHop, msg);
+ if (CA_STATUS_OK != caRes)
+ {
+ OC_LOG_V(ERROR, RM_TAG, "Failed to forward response to next hop [%d][%s]",
+ caRes, nextHop.addr);
+ // Since a response is always unicast, return error here.
+ return OC_STACK_ERROR;
+ }
+ }
+ }
+ }
+
+ OC_LOG_V(INFO, RM_TAG, "Sender: [%u] Destination: [%u]", routeOption.srcGw, routeOption.destGw);
+ return OC_STACK_OK;
+}
+
+OCStackResult RMHandleRequest(CARequestInfo_t *message, const CAEndpoint_t *sender,
+ bool *selfDestination)
+{
+ if (!g_isRMInitialized)
+ {
+ OC_LOG(ERROR, TAG, "RM not initialized");
+ *selfDestination = true;
+ return OC_STACK_OK;
+ }
+ OCStackResult res = RMHandlePacket(true, message, sender, selfDestination);
+ return res;
+}
+
+OCStackResult RMHandleResponse(CAResponseInfo_t *message, const CAEndpoint_t *sender,
+ bool *selfDestination)
+{
+ if (!g_isRMInitialized)
+ {
+ OC_LOG(ERROR, TAG, "RM not initialized");
+ *selfDestination = true;
+ return OC_STACK_OK;
+ }
+ OCStackResult res = RMHandlePacket(false, message, sender, selfDestination);
+ return res;
+}
--- /dev/null
+/* ****************************************************************
+ *
+ * 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 <string.h>
+#include <unistd.h>
+#include "routingmanagerinterface.h"
+#include "routingmessageparser.h"
+#include "routingutility.h"
+#include "ocobserve.h"
+#include "include/logger.h"
+#include "ocrandom.h"
+
+/**
+ * Logging tag for module name.
+ */
+#define TAG "RM_INTERFACE"
+
+/**
+ * Name of resource type.
+ */
+#define GW_RESOURCE_TYPE_NAME "core.gateway"
+
+/**
+ * Name of resource interface.
+ */
+#define GW_RESOURCE_INTF_NAME "oc.mi.def"
+
+/**
+ * URI of the resource.
+ */
+#define GW_RESOURCE_URI "/oic/gateway"
+
+/**
+ * Max Number of times to send data considering wifi packet drops.
+ */
+#define MAX_SEND_DATA 3
+
+/**
+ * Pointer to handle of the newly created gateway resource.
+ */
+static OCResourceHandle g_gateWayHandle = NULL;
+
+/**
+ * Discovery callback registered with RI for a Discover Request.
+ */
+OCStackApplicationResult RMDiscoverGatewayCallback(void* ctx, OCDoHandle handle,
+ OCClientResponse * clientResponse);
+
+/**
+ * Observe callback registered with RI for a observe Request.
+ */
+OCStackApplicationResult RMObserveRequestCallback(void* ctx, OCDoHandle handle,
+ OCClientResponse * clientResponse);
+
+OCConnectivityType RMGetConnectivityType(OCTransportAdapter adapter)
+{
+ switch(adapter)
+ {
+ case OC_ADAPTER_IP:
+ return CT_ADAPTER_IP;
+ case OC_ADAPTER_GATT_BTLE:
+ return CT_ADAPTER_GATT_BTLE;
+ case OC_ADAPTER_RFCOMM_BTEDR:
+ return CT_ADAPTER_RFCOMM_BTEDR;
+ case OC_DEFAULT_ADAPTER:
+ break;
+ default:
+ OC_LOG(DEBUG, TAG, "Default option will be selected");
+ }
+ return CT_DEFAULT;
+}
+
+OCStackResult RMInitGatewayResource()
+{
+ OC_LOG(DEBUG, TAG, "RMInitGatewayResource IN");
+
+ // Create a Gateway resource
+ OCStackResult result = OCCreateResource(&g_gateWayHandle,
+ GW_RESOURCE_TYPE_NAME,
+ GW_RESOURCE_INTF_NAME,
+ GW_RESOURCE_URI,
+ NULL,
+ NULL,
+ OC_OBSERVABLE);
+
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(ERROR, TAG, "Create resource for gateway failed[%d]", result);
+ }
+
+ OC_LOG(DEBUG, TAG, "RMInitGatewayResource OUT");
+ return result;
+}
+
+OCStackResult RMDiscoverGatewayResource()
+{
+ OC_LOG(DEBUG, TAG, "RMDiscoverGatewayResource IN");
+ OCCallbackData discoverData = {.cb = RMDiscoverGatewayCallback};
+ OCStackResult result = OC_STACK_OK;
+
+ result = OCDoResource(NULL, OC_REST_DISCOVER, GW_RESOURCE_URI, 0, 0,
+ CT_ADAPTER_IP | CT_ADAPTER_RFCOMM_BTEDR,
+ OC_LOW_QOS, &discoverData, NULL, 0);
+
+ // Temp fix for packet drops in WIFI.
+ for (int sendData = 0; sendData < MAX_SEND_DATA; sendData++)
+ {
+ result = OCDoResource(NULL, OC_REST_DISCOVER, GW_RESOURCE_URI, 0, 0,
+ CT_ADAPTER_IP, OC_LOW_QOS, &discoverData, NULL, 0);
+ usleep(100000);
+ }
+ OC_LOG(DEBUG, TAG, "RMDiscoverGatewayResource OUT");
+ return result;
+}
+
+OCStackApplicationResult RMDiscoverGatewayCallback(void* ctx, OCDoHandle handle,
+ OCClientResponse * clientResponse)
+{
+ OC_LOG(DEBUG, TAG, "RMDiscoverGatewayCallback IN");
+ (void)ctx;
+ (void)handle;
+ if (NULL == clientResponse)
+ {
+ OC_LOG(DEBUG, TAG, "clientResponse is NULL");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ OCStackResult result = RMHandleResponsePayload(&(clientResponse->devAddr),
+ (OCRepPayload *)clientResponse->payload);
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(ERROR, TAG, "RMHandleResponsePayload Failed[%d]", result);
+ }
+
+ OCRepPayload *payload = NULL;
+ // Created payload is freed in the OCDoResource() api.
+ result= RMGetGatewayPayload(&payload);
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(ERROR, TAG, "RMGetGatewayPayload Failed[%d]", result);
+ }
+
+ RMSendObserveRequest(&(clientResponse->devAddr), payload);
+
+ OC_LOG(DEBUG, TAG, "RMDiscoverGatewayCallback OUT");
+ return OC_STACK_KEEP_TRANSACTION;
+}
+
+OCStackResult RMSendObserveRequest(const OCDevAddr *devAddr, OCRepPayload *payload)
+{
+ OC_LOG(DEBUG, TAG, "RMSendObserveRequest IN");
+ OC_LOG_V(DEBUG, TAG, "Destination address is %s:%d", devAddr->addr, devAddr->port);
+ OCCallbackData observeData = {.cb = RMObserveRequestCallback};
+ OC_LOG(DEBUG, TAG, "RMSendObserveRequest OUT");
+
+ return OCDoResource(NULL, OC_REST_OBSERVE, GW_RESOURCE_URI, devAddr, (OCPayload *)payload,
+ RMGetConnectivityType(devAddr->adapter), OC_HIGH_QOS,
+ &observeData, NULL, 0);
+}
+
+OCStackResult RMSendDeleteRequest(const OCDevAddr *devAddr, OCRepPayload *payload)
+{
+ OC_LOG(DEBUG, TAG, "RMSendDeleteRequest IN");
+ RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
+ OC_LOG_V(DEBUG, TAG, "Destination address is %s:%d", devAddr->addr, devAddr->port);
+
+ OCCallbackData deleteCb = {.cb = RMDiscoverGatewayCallback};
+ OC_LOG(DEBUG, TAG, "RMSendDeleteRequest OUT");
+ return OCDoResource(NULL, OC_REST_DELETE, GW_RESOURCE_URI, devAddr, (OCPayload *)payload,
+ RMGetConnectivityType(devAddr->adapter), OC_LOW_QOS,
+ &deleteCb, NULL, 0);
+}
+
+OCStackResult RMSendResponse(const OCServerRequest *request, const OCResource *resource,
+ const OCRepPayload *payload)
+{
+ OC_LOG(DEBUG, TAG, "RMSendResponse IN");
+ OCEntityHandlerResponse response = {.ehResult = OC_EH_OK,
+ .payload = (OCPayload *)payload,
+ .persistentBufferFlag = 0,
+ .requestHandle = (OCRequestHandle) request,
+ .resourceHandle = (OCResourceHandle) resource
+ };
+ OC_LOG(DEBUG, TAG, "RMSendResponse OUT");
+
+ return OCDoResponse(&response);
+}
+
+OCStackResult RMSendNotificationForListofObservers(OCObservationId *obsId, uint8_t obsLen,
+ const OCRepPayload *payload)
+{
+ OC_LOG(DEBUG, TAG, "RMSendNotificationForListofObservers IN");
+ RM_NULL_CHECK_WITH_RET(obsId, TAG, "obsId");
+ RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
+ OCStackResult result = OCNotifyListOfObservers(g_gateWayHandle, obsId, obsLen,
+ payload, OC_LOW_QOS);
+ OC_LOG_V(DEBUG, TAG, "Result is %d", result);
+ OC_LOG(DEBUG, TAG, "RMSendNotificationForListofObservers OUT");
+ return result;
+}
+
+OCStackApplicationResult RMObserveRequestCallback(void* ctx, OCDoHandle handle,
+ OCClientResponse *clientResponse)
+{
+ OC_LOG(DEBUG, TAG, "RMObserveRequestCallback IN");
+ (void)ctx;
+ (void)handle;
+ if (NULL == clientResponse)
+ {
+ OC_LOG(DEBUG, TAG, "clientResponse is NULL");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ if (OC_STACK_COMM_ERROR == clientResponse->result)
+ {
+ OC_LOG(DEBUG, TAG, "Received TIMEOUT ERROR");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ OCStackResult result = RMHandleResponsePayload(&(clientResponse->devAddr),
+ (OCRepPayload *)clientResponse->payload);
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(ERROR, TAG, "RMHandleResponsePayload Failed[%d]", result);
+ }
+
+ OC_LOG(DEBUG, TAG, "RMObserveRequestCallback OUT");
+ return OC_STACK_KEEP_TRANSACTION;
+}
+
+OCStackResult RMAddObserverToStack(const OCServerRequest *request, OCObservationId *obsID)
+{
+ OC_LOG(DEBUG, TAG, "RMAddObserverToStack IN");
+ RM_NULL_CHECK_WITH_RET(request, TAG, "request");
+ RM_NULL_CHECK_WITH_RET(obsID, TAG, "obsID");
+
+ OCStackResult result = OC_STACK_OK;
+ while (0 == *obsID)
+ {
+ result = GenerateObserverId(obsID);
+ }
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(DEBUG, TAG, "GenerateObserverId failed[%d]", result);
+ return result;
+ }
+
+ OC_LOG_V(DEBUG, TAG, "Observer ID is %d", *obsID);
+ // Add the observer
+ result = AddObserver((const char*)(request->resourceUrl),
+ (const char *)(request->query),
+ *obsID, request->requestToken, request->tokenLength,
+ (OCResource *)g_gateWayHandle, request->qos, OC_FORMAT_CBOR,
+ &request->devAddr);
+ OC_LOG(DEBUG, TAG, "RMAddObserverToStack OUT");
+ return result;
+}
\ No newline at end of file
--- /dev/null
+/* ****************************************************************
+ *
+ * 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 <string.h>
+#include "routingmessageparser.h"
+#include "routingtablemanager.h"
+#include "routingutility.h"
+#include "ocpayload.h"
+#include "ocpayloadcbor.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "include/logger.h"
+
+/**
+ * Logging tag for module name.
+ */
+#define TAG "RPM"
+
+/**
+ * Table key to parser Payload Table.
+ */
+static const char TABLE[] = "table";
+
+/**
+ * Length key to get length Payload Array.
+ */
+static const char LENGTH_PROP[] = "len";
+
+/**
+ * Gateway key to parser Payload Table.
+ */
+static const char GATEWAY[] = "gateway";
+
+/**
+ * Route Cost key to parser Payload Table.
+ */
+static const char ROUTE_COST[] = "routecost";
+
+/**
+ * Sequence Number key to parser Payload Table.
+ */
+static const char SEQ_NUM[] = "seqnum";
+
+/**
+ * Response Type key to parser Payload Table.
+ */
+static const char UPDATE_SEQ_NUM[] = "updateseqnum";
+
+OCStackResult RMPConstructGatewayPayload(uint32_t gatewayId, OCRepPayload **payload)
+{
+ OC_LOG(DEBUG, TAG, "RMPConstructGatewayPayload IN");
+ RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
+
+ *payload = OCRepPayloadCreate();
+ if(!*payload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to allocate Payload");
+ return OC_STACK_ERROR;
+ }
+
+ (*payload)->base.type = PAYLOAD_TYPE_REPRESENTATION;
+ OCRepPayloadSetPropInt(*payload, GATEWAY, gatewayId);
+ OCRepPayloadSetPropInt(*payload, LENGTH_PROP, 0);
+
+ OC_LOG(DEBUG, TAG, "RMPConstructGatewayPayload OUT");
+
+ return OC_STACK_OK;
+}
+
+OCStackResult RMPConstructObserveResPayload(uint32_t gatewayId, uint32_t seqNum,
+ const u_linklist_t *routingtable, bool isUpdateSeqNeeded,
+ OCRepPayload **payload)
+{
+ OC_LOG(DEBUG, TAG, "RMPConstructObserveResPayload IN");
+ RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
+
+ *payload = (OCRepPayload *)OCRepPayloadCreate();
+ if(!*payload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to allocate Payload");
+ return OC_STACK_ERROR;
+ }
+
+ (*payload)->base.type = PAYLOAD_TYPE_REPRESENTATION;
+ OCRepPayloadSetPropInt(*payload, GATEWAY, gatewayId);
+ OCRepPayloadSetPropInt(*payload, SEQ_NUM, seqNum);
+ OCRepPayloadSetPropBool(*payload, UPDATE_SEQ_NUM, isUpdateSeqNeeded);
+ if (NULL == routingtable)
+ {
+ OCRepPayloadSetPropInt(*payload, LENGTH_PROP, 0);
+ OC_LOG(DEBUG, TAG, "Routing Table NULL for ObserveRes Payload");
+ return OC_STACK_OK;
+ }
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(routingtable, &iterTable);
+
+ uint32_t len = u_linklist_length(routingtable);
+ const OCRepPayload *arrayPayload[len];
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = {len, 0, 0};
+
+ int i = 0;
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+
+ OCRepPayload *add = OCRepPayloadCreate();
+ if(!add)
+ {
+ OC_LOG(ERROR, TAG, "Failed to allocate Payload");
+ return OC_STACK_ERROR;
+ }
+
+ add->base.type = PAYLOAD_TYPE_REPRESENTATION;
+ OCRepPayloadSetPropInt(add, GATEWAY, entry->destination->gatewayId);
+ OCRepPayloadSetPropInt(add, ROUTE_COST, entry->routeCost);
+ arrayPayload[i] = add;
+
+ i++;
+ u_linklist_get_next(&iterTable);
+ }
+ OCRepPayloadSetPropInt(*payload, LENGTH_PROP, i);
+ if (i > 0)
+ {
+ bool res = OCRepPayloadSetPropObjectArray(*payload, TABLE, arrayPayload, dimensions);
+ if (!res)
+ {
+ OC_LOG(ERROR, TAG, "Failed to Construct Observer response Payload");
+ return OC_STACK_ERROR;
+ }
+ }
+
+ OC_LOG(DEBUG, TAG, "RMPConstructObserveResPayload OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RMPConstructRemovalPayload(uint32_t gatewayId, uint32_t seqNum,
+ const u_linklist_t *removedGateways, bool isUpdateSeqNeeded,
+ OCRepPayload **removedPayload)
+{
+ OC_LOG(DEBUG, TAG, "RMPConstructRemovalPayload IN");
+ RM_NULL_CHECK_WITH_RET(removedGateways, TAG, "removedGateways");
+ RM_NULL_CHECK_WITH_RET(removedPayload, TAG, "removedPayload");
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(removedGateways, &iterTable);
+
+ *removedPayload = OCRepPayloadCreate();
+ if(!*removedPayload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to allocate Payload");
+ return OC_STACK_ERROR;
+ }
+
+ uint32_t len = u_linklist_length(removedGateways);
+ const OCRepPayload *arrayPayload[len];
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = {len, 0, 0};
+
+ (*removedPayload)->base.type = PAYLOAD_TYPE_REPRESENTATION;
+ OCRepPayloadSetPropInt(*removedPayload, GATEWAY, gatewayId);
+ OCRepPayloadSetPropInt(*removedPayload, SEQ_NUM, seqNum);
+ OCRepPayloadSetPropBool(*removedPayload, UPDATE_SEQ_NUM, isUpdateSeqNeeded);
+
+ int i = 0;
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
+ if (!entry)
+ {
+ u_linklist_get_next(&iterTable);
+ continue;
+ }
+ OCRepPayload *add = OCRepPayloadCreate();
+ if(!add)
+ {
+ OC_LOG(ERROR, TAG, "Failed to allocate Payload");
+ return OC_STACK_ERROR;
+ }
+
+ add->base.type = PAYLOAD_TYPE_REPRESENTATION;
+ OC_LOG_V(DEBUG, TAG, "Removing the gateway entry: %u", entry->destination->gatewayId);
+ OCRepPayloadSetPropInt(add, GATEWAY, entry->destination->gatewayId);
+ OCRepPayloadSetPropInt(add, ROUTE_COST, 0);
+ arrayPayload[i] = add;
+
+ i++;
+ u_linklist_get_next(&iterTable);
+ }
+ OCRepPayloadSetPropInt(*removedPayload, LENGTH_PROP, i);
+ bool res = OCRepPayloadSetPropObjectArray(*removedPayload, TABLE, arrayPayload, dimensions);
+ if (!res)
+ {
+ OC_LOG(ERROR, TAG, "Failed to Construct Removal Payload");
+ return OC_STACK_ERROR;
+ }
+
+ OC_LOG(DEBUG, TAG, "RMPConstructRemovalPayload OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RMPParseRequestPayload(const uint8_t* payload, size_t payloadSize,
+ uint32_t *gatewayId)
+{
+ OCPayload *ocPayload = NULL;
+ OCParsePayload(&ocPayload, payload, payloadSize);
+ OCRepPayload *repPayload = (OCRepPayload *)ocPayload;
+ OCStackResult res = RMPParseResponsePayload(repPayload, gatewayId, NULL, NULL, NULL);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(DEBUG, TAG, "ParseResponsePayload failed");
+ }
+
+ return res;
+}
+
+OCStackResult RMPParseResponsePayload(const OCRepPayload *payload, uint32_t *gatewayId,
+ uint32_t *seqNum, u_linklist_t **gatewayTable,
+ bool *isUpdateSeqNeeded)
+{
+ OC_LOG(DEBUG, TAG, "RMPParsePayload IN");
+ RM_NULL_CHECK_WITH_RET(payload, TAG, "payload");
+ RM_NULL_CHECK_WITH_RET(gatewayId, TAG, "gatewayId");
+
+ int64_t tempGateway = 0;
+ OCRepPayloadGetPropInt(payload, GATEWAY, &tempGateway);
+ *gatewayId = tempGateway;
+
+ if (NULL == gatewayId || 0 == *gatewayId)
+ {
+ return OC_STACK_COMM_ERROR;
+ }
+
+ if (NULL != seqNum)
+ {
+ int64_t tempSeq = 0;
+ OCRepPayloadGetPropInt(payload, SEQ_NUM, &tempSeq);
+ *seqNum = tempSeq;
+ }
+
+ int64_t length = 0;
+ OCRepPayloadGetPropInt(payload, LENGTH_PROP, &length);
+
+ if (NULL != isUpdateSeqNeeded)
+ {
+ OCRepPayloadGetPropBool(payload, UPDATE_SEQ_NUM, isUpdateSeqNeeded);
+ }
+
+ int len = length;
+ if (0 == len)
+ {
+ OC_LOG(DEBUG, TAG, "Parsed Gateway Payload");
+ return OC_STACK_OK;
+ }
+
+ if (NULL == gatewayTable)
+ {
+ OC_LOG(DEBUG, TAG, "Parsed Request Payload");
+ return OC_STACK_OK;
+ }
+
+ OCRepPayload **responsePayload[len];
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH];
+ OCRepPayloadGetPropObjectArray(payload, TABLE, responsePayload, dimensions);
+
+ if (NULL == *responsePayload)
+ {
+ OC_LOG(DEBUG, TAG, "RMPParsePayload OUT");
+ return OC_STACK_OK;
+ }
+
+ *gatewayTable = u_linklist_create();
+ if (NULL == *gatewayTable)
+ {
+ OC_LOG(DEBUG, TAG, "Gateway table create failed");
+ return OC_STACK_ERROR;
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *)OICCalloc(1, sizeof(RTMGatewayEntry_t));
+
+ if (NULL == entry)
+ {
+ OC_LOG(DEBUG, TAG, "RTMGatewayEntry_t Calloc failed");
+ return OC_STACK_ERROR;
+ }
+ // Filling new Entry
+ entry->destination = (RTMGatewayId_t*)OICCalloc(1, sizeof(RTMGatewayId_t));
+ if (NULL == entry->destination)
+ {
+ OC_LOG(DEBUG, TAG, "Destination Calloc failed");
+ OICFree(entry);
+ return OC_STACK_ERROR;
+ }
+ entry->nextHop = (RTMGatewayId_t*)OICCalloc(1, sizeof(RTMGatewayId_t));
+ if (NULL == entry->nextHop)
+ {
+ OC_LOG(DEBUG, TAG, "nextHop Calloc failed");
+ OICFree(entry);
+ OICFree(entry->destination);
+ return OC_STACK_ERROR;
+ }
+
+ entry->nextHop->gatewayId = *gatewayId;
+
+ int64_t gatewayBuf;
+ int64_t routeCost;
+ OCRepPayloadGetPropInt(*((*responsePayload) + i), GATEWAY, &gatewayBuf);
+ OCRepPayloadGetPropInt(*((*responsePayload) + i), ROUTE_COST, &routeCost);
+
+ entry->destination->gatewayId = gatewayBuf;
+ entry->routeCost = routeCost;
+ u_linklist_add(*gatewayTable, (void *)entry);
+ }
+ OC_LOG(DEBUG, TAG, "RMPParsePayload OUT");
+ return OC_STACK_OK;
+}
+
+void RMPFreePayload(OCRepPayload *payload)
+{
+ OC_LOG(DEBUG, TAG, "RMPFreePayload IN");
+ RM_NULL_CHECK_VOID(payload, TAG, "payload");
+ OCRepPayloadDestroy(payload);
+ OC_LOG(DEBUG, TAG, "RMPFreePayload OUT");
+}
--- /dev/null
+/* ****************************************************************
+ *
+ * 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 <string.h>
+#include "routingtablemanager.h"
+#include "routingutility.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "include/logger.h"
+
+/**
+ * Logging tag for module name.
+ */
+#define TAG "RTM"
+
+/**
+ * Tag for printing the Routing table.
+ */
+#define RM_TAG "RAP"
+
+
+/**
+ * Initial Length of observer list.
+ */
+#define MAX_OBSERVER_LIST_LENGTH 10
+
+static const uint64_t USECS_PER_SEC = 1000000;
+
+OCStackResult RTMInitialize(u_linklist_t **gatewayTable, u_linklist_t **endpointTable)
+{
+ OC_LOG(DEBUG, TAG, "RTMInitialize IN");
+ RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
+ RM_NULL_CHECK_WITH_RET(endpointTable, TAG, "endpointTable");
+ if (NULL == *gatewayTable)
+ {
+ *gatewayTable = u_linklist_create();
+ if (NULL == *gatewayTable)
+ {
+ OC_LOG(ERROR, TAG, "Creating Routing Table failed");
+ RTMTerminate(gatewayTable, endpointTable);
+ return OC_STACK_ERROR;
+ }
+ }
+
+ if (NULL == *endpointTable)
+ {
+ *endpointTable = u_linklist_create();
+ if (NULL == *endpointTable)
+ {
+ OC_LOG(ERROR, TAG, "Creating Routing Table failed");
+ RTMTerminate(gatewayTable, endpointTable);
+ return OC_STACK_ERROR;
+ }
+ }
+ OC_LOG(DEBUG, TAG, "RTMInitialize OUT");
+ return OC_STACK_OK;
+}
+
+/*
+ * Freeing every char pointer and array list of gateway entry here and frees the table.
+ */
+OCStackResult RTMFreeGatewayRouteTable(u_linklist_t **gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "RTMFreeGatewayRouteTable IN");
+ if (NULL == gatewayTable || NULL == *gatewayTable)
+ {
+ return OC_STACK_OK;
+ }
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(*gatewayTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *hop = u_linklist_get_data(iterTable);
+ if (NULL != hop && NULL != hop->destination)
+ {
+ while (u_arraylist_length(hop->destination->destIntfAddr) > 0)
+ {
+ if (NULL != hop->destination)
+ {
+ RTMDestIntfInfo_t *data = u_arraylist_remove(hop->destination->destIntfAddr, 0);
+ OICFree(data);
+ }
+ }
+ u_arraylist_free(&(hop->destination->destIntfAddr));
+ OICFree(hop->destination);
+ // No need to free next hop as it is already freed during it's gateway free
+ OICFree(hop);
+ }
+
+ OCStackResult ret = u_linklist_remove(*gatewayTable, &iterTable);
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
+ return OC_STACK_ERROR;
+ }
+ }
+ u_linklist_free(gatewayTable);
+ OC_LOG(DEBUG, TAG, "RTMFreeGatewayRouteTable OUT");
+ return OC_STACK_OK;
+}
+
+/*
+ * Freeing every char pointer of endpoint entry here frees the table.
+ */
+OCStackResult RTMFreeEndpointRouteTable(u_linklist_t **endpointTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ if (NULL == endpointTable || NULL == *endpointTable)
+ {
+ return OC_STACK_OK;
+ }
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(*endpointTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMEndpointEntry_t *hop = u_linklist_get_data(iterTable);
+ if (NULL != hop)
+ {
+ OICFree(hop);
+ }
+
+ OCStackResult ret = u_linklist_remove(*endpointTable, &iterTable);
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
+ return OC_STACK_ERROR;
+ }
+ }
+ u_linklist_free(endpointTable);
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RTMFreeGatewayIdList(u_linklist_t **gatewayIdTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ if (NULL == gatewayIdTable || NULL == *gatewayIdTable)
+ {
+ return OC_STACK_OK;
+ }
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(*gatewayIdTable, &iterTable);
+ while (iterTable != NULL)
+ {
+ RTMGatewayId_t *hop = u_linklist_get_data(iterTable);
+ if (NULL != hop)
+ {
+ while (u_arraylist_length(hop->destIntfAddr) > 0)
+ {
+ RTMDestIntfInfo_t *data = u_arraylist_remove(hop->destIntfAddr, 0);
+ OICFree(data);
+ }
+ u_arraylist_free(&(hop->destIntfAddr));
+ OICFree(hop);
+
+ OCStackResult ret = u_linklist_remove(*gatewayIdTable, &iterTable);
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
+ return OC_STACK_ERROR;
+ }
+ }
+ else
+ {
+ OCStackResult res = u_linklist_remove(*gatewayIdTable, &iterTable);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
+ return OC_STACK_ERROR;
+ }
+ }
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+/*
+ * Freeing memory first and then Freeing linked list for gateway and endpoint.
+ */
+OCStackResult RTMTerminate(u_linklist_t **gatewayTable, u_linklist_t **endpointTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+
+ OCStackResult ret = RTMFreeGatewayRouteTable(gatewayTable);
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Deleting Gateway Routing Table failed");
+ }
+ if (NULL != *gatewayTable)
+ {
+ *gatewayTable = NULL;
+ }
+
+ ret = RTMFreeEndpointRouteTable(endpointTable);
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Deleting Endpoint Routing Table failed");
+ }
+ if (NULL != *endpointTable)
+ {
+ *endpointTable = NULL;
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+/*
+ * Checks if destination gateway to be added is already present and update if present or
+ * adds new entry if not present.
+ * Adds Entry to head if route cost is 1.
+ * Adds Entry to Tail if route cost is > 1.
+ * Checks for Gateway id Memory and assigns to next hop address to achieve better memory usage.
+ */
+OCStackResult RTMAddGatewayEntry(uint32_t gatewayId, uint32_t nextHop, uint32_t routeCost,
+ const RTMDestIntfInfo_t *destInterfaces, u_linklist_t **gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
+ if (NULL == *gatewayTable)
+ {
+ *gatewayTable = u_linklist_create();
+ }
+
+ if (1 == routeCost && 0 != nextHop)
+ {
+ OC_LOG(ERROR, TAG, "Adding Gateway Failed as Next Hop should be 0 for route cost 1");
+ return OC_STACK_ERROR;
+ }
+
+ if (0 == routeCost)
+ {
+ OC_LOG(ERROR, TAG, "Adding Gateway Failed as Route cost shouldnot be less than 1");
+ return OC_STACK_ERROR;
+ }
+
+ u_linklist_iterator_t *destNode = NULL;
+ RTMGatewayId_t *gatewayNodeMap = NULL; // Gateway id ponter can be mapped to NextHop of entry.
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(*gatewayTable, &iterTable);
+ // Iterate over gateway list to find if already entry with this gatewayid is present.
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+ if (NULL == entry)
+ {
+ break;
+ }
+
+ // To save node with same gateway id (To update entry instead of add new entry).
+ if (NULL == destNode && NULL != entry->destination &&
+ (gatewayId == entry->destination->gatewayId))
+ {
+ destNode = iterTable;
+ }
+
+ // To find pointer of gateway id for a node provided next hop equals to existing gateway id.
+ if (0 != nextHop && NULL != entry->destination &&
+ nextHop == entry->destination->gatewayId)
+ {
+ gatewayNodeMap = entry->destination;
+ }
+
+ if (NULL != destNode && NULL != gatewayNodeMap)
+ {
+ break;
+ }
+
+ u_linklist_get_next(&iterTable);
+ }
+
+ if (1 < routeCost && NULL == gatewayNodeMap)
+ {
+ OC_LOG(ERROR, TAG, "Adding Gateway Failed as Next Hop is invalid");
+ return OC_STACK_ERROR;
+ }
+
+ //Logic to update entry if it is already destination present or to add new entry.
+ if (NULL != destNode)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(destNode);
+
+ if (NULL != entry && 1 == entry->routeCost && 0 == nextHop)
+ {
+ if (NULL == destInterfaces)
+ {
+ OC_LOG(ERROR, TAG, "Not Adding Gateway destInterfaces is NULL");
+ return OC_STACK_ERROR;
+ }
+ OCStackResult update = RTMUpdateDestinationIntfAdr(gatewayId, *destInterfaces, true,
+ gatewayTable);
+ if (OC_STACK_OK != update)
+ {
+ OC_LOG(ERROR, TAG, "RTMUpdateDestinationIntfAdr failed");
+ }
+ return update;
+ }
+ else if (NULL != entry && entry->routeCost >= routeCost)
+ {
+ if (entry->routeCost == routeCost && NULL != entry->nextHop &&
+ (nextHop == entry->nextHop->gatewayId))
+ {
+ OC_LOG(ERROR, TAG, "Not Adding Gateway As it is Duplicate request");
+ return OC_STACK_DUPLICATE_REQUEST;
+ }
+
+ //Mapped nextHop gateway to another entries having gateway as destination.
+ if (NULL != gatewayNodeMap)
+ {
+ entry->destination->gatewayId = gatewayId;
+ entry->nextHop = gatewayNodeMap;
+ entry->destination->destIntfAddr = NULL;
+ entry->routeCost = routeCost;
+ }
+ else if (0 == nextHop)
+ {
+ entry->routeCost = 1;
+ // Entry can't be updated if Next hop is not same as existing Destinations of Table.
+ OC_LOG(DEBUG, TAG, "Updating the gateway");
+ entry->nextHop = NULL;
+ entry->destination->destIntfAddr = u_arraylist_create();
+ if (NULL == entry->destination->destIntfAddr)
+ {
+ OC_LOG(ERROR, TAG, "Failed to create array list");
+ return OC_STACK_ERROR;
+ }
+
+ RTMDestIntfInfo_t *destAdr =
+ (RTMDestIntfInfo_t *) OICCalloc(1, sizeof(RTMDestIntfInfo_t));
+ if (NULL == destAdr)
+ {
+ OC_LOG(ERROR, TAG, "Failed to Calloc destAdr");
+ return OC_STACK_ERROR;
+ }
+
+ *destAdr = *destInterfaces;
+ destAdr->timeElapsed = RTMGetCurrentTime();
+ destAdr->isValid = true;
+ bool result =
+ u_arraylist_add(entry->destination->destIntfAddr, (void *)destAdr);
+ if (!result)
+ {
+ OC_LOG(ERROR, TAG, "Adding node to head failed");
+ OICFree(destAdr);
+ return OC_STACK_ERROR;
+ }
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Adding Gateway Failed as Next hop is invalid");
+ return OC_STACK_ERROR;
+ }
+
+ }
+ else if (NULL != entry && entry->routeCost < routeCost)
+ {
+ OC_LOG(ERROR, TAG, "Adding Gateway Failed as Route cost is more than old");
+ return OC_STACK_ERROR;
+ }
+
+ // Logic to add updated node to Head of list as route cost is 1.
+ if (1 == routeCost && NULL != entry)
+ {
+ OCStackResult res = u_linklist_remove(*gatewayTable, &destNode);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Removing node failed");
+ }
+ else
+ {
+ res = u_linklist_add_head(*gatewayTable, (void *)entry);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Adding node to head failed");
+ }
+ }
+ }
+ }
+ else
+ {
+ // Filling new Entry
+ RTMGatewayEntry_t *hopEntry = (RTMGatewayEntry_t *)OICCalloc(1, sizeof(RTMGatewayEntry_t));
+ if (NULL == hopEntry)
+ {
+ OC_LOG(ERROR, TAG, "Calloc failed for hop entry");
+ return OC_STACK_ERROR;
+ }
+
+ hopEntry->destination = (RTMGatewayId_t*)OICCalloc(1, sizeof(RTMGatewayId_t));
+ if (NULL == hopEntry->destination)
+ {
+ OC_LOG(ERROR, TAG, "Calloc failed for hop entry destination");
+ OICFree(hopEntry);
+ return OC_STACK_ERROR;
+ }
+
+ hopEntry->destination->gatewayId = gatewayId;
+ if (NULL != destInterfaces && strlen((*destInterfaces).destIntfAddr.addr) > 0)
+ {
+ hopEntry->destination->destIntfAddr = u_arraylist_create();
+ RTMDestIntfInfo_t *destAdr =
+ (RTMDestIntfInfo_t *) OICCalloc(1, sizeof(RTMDestIntfInfo_t));
+ if (NULL == destAdr)
+ {
+ OC_LOG(ERROR, TAG, "Calloc failed for destAdr");
+ u_arraylist_free(&(hopEntry->destination->destIntfAddr));
+ OICFree(hopEntry->destination);
+ OICFree(hopEntry);
+ return OC_STACK_ERROR;
+ }
+
+ *destAdr = *destInterfaces;
+ destAdr->timeElapsed = RTMGetCurrentTime();
+ destAdr->isValid = true;
+ u_arraylist_add(hopEntry->destination->destIntfAddr, (void *)destAdr);
+ }
+ else
+ {
+ hopEntry->destination->destIntfAddr = NULL;
+ }
+
+ hopEntry->routeCost = routeCost;
+ // Mapped nextHop gateway to another entries having gateway as destination.
+ if (NULL != gatewayNodeMap)
+ {
+ hopEntry->nextHop = gatewayNodeMap;
+ }
+ else if (1 == routeCost)
+ {
+ hopEntry->nextHop = NULL;
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Adding Gateway Failed as Next Hop is invalid");
+ while (u_arraylist_length(hopEntry->destination->destIntfAddr) > 0)
+ {
+ RTMDestIntfInfo_t *data =
+ u_arraylist_remove(hopEntry->destination->destIntfAddr, 0);
+ OICFree(data);
+ }
+ u_arraylist_free(&(hopEntry->destination->destIntfAddr));
+ OICFree(hopEntry->destination);
+ OICFree(hopEntry);
+
+ return OC_STACK_ERROR;
+ }
+
+ OCStackResult ret = OC_STACK_OK;
+ if (hopEntry->routeCost == 1)
+ {
+ ret = u_linklist_add_head(*gatewayTable, (void *)hopEntry);
+ }
+ else
+ {
+ ret = u_linklist_add(*gatewayTable, (void *)hopEntry);
+ }
+
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Adding Gateway Entry to Routing Table failed");
+ while (u_arraylist_length(hopEntry->destination->destIntfAddr) > 0)
+ {
+ RTMDestIntfInfo_t *data = u_arraylist_remove(hopEntry->destination->destIntfAddr, 0);
+ OICFree(data);
+ }
+ u_arraylist_free(&(hopEntry->destination->destIntfAddr));
+ OICFree(hopEntry->destination);
+ OICFree(hopEntry);
+ return OC_STACK_ERROR;
+ }
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RTMAddEndpointEntry(uint16_t *endpointId, const CAEndpoint_t *destAddr,
+ u_linklist_t **endpointTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(endpointId, TAG, "endpointId");
+ RM_NULL_CHECK_WITH_RET(destAddr, TAG, "destAddr");
+ RM_NULL_CHECK_WITH_RET(endpointTable, TAG, "endpointTable");
+ if (NULL == *endpointTable)
+ {
+ *endpointTable = u_linklist_create();
+ }
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(*endpointTable, &iterTable);
+ // Iterate over gateway list to find if already entry with this gatewayid is present.
+ while (NULL != iterTable)
+ {
+ RTMEndpointEntry_t *entry =
+ (RTMEndpointEntry_t *) u_linklist_get_data(iterTable);
+
+ if (NULL != entry && (0 == memcmp(destAddr->addr, entry->destIntfAddr.addr,
+ strlen(entry->destIntfAddr.addr)))
+ && destAddr->port == entry->destIntfAddr.port)
+ {
+ *endpointId = entry->endpointId;
+ OC_LOG(ERROR, TAG, "Adding failed as Enpoint Entry Already present in Table");
+ return OC_STACK_DUPLICATE_REQUEST;
+ }
+ u_linklist_get_next(&iterTable);
+ }
+
+ // Filling Entry.
+ RTMEndpointEntry_t *hopEntry = (RTMEndpointEntry_t *)OICCalloc(1, sizeof(RTMEndpointEntry_t));
+
+ if (NULL == hopEntry)
+ {
+ OC_LOG(ERROR, TAG, "Malloc failed for hop entry");
+ return OC_STACK_ERROR;
+ }
+
+ hopEntry->endpointId = *endpointId;
+ hopEntry->destIntfAddr = *destAddr;
+
+ OCStackResult ret = u_linklist_add(*endpointTable, (void *)hopEntry);
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Adding Enpoint Entry to Routing Table failed");
+ OICFree(hopEntry);
+ return OC_STACK_ERROR;
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RTMAddObserver(uint32_t obsID, CAEndpoint_t devAddr, u_linklist_t **gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
+ RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(*gatewayTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+
+ for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
+ {
+ RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
+ if (NULL != destCheck &&
+ (0 == memcmp(destCheck->destIntfAddr.addr, devAddr.addr, strlen(devAddr.addr)))
+ && devAddr.port == destCheck->destIntfAddr.port)
+ {
+ destCheck->observerId = obsID;
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+ }
+ }
+ u_linklist_get_next(&iterTable);
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_ERROR;
+}
+
+bool RTMIsObserverPresent(CAEndpoint_t devAddr, OCObservationId *obsID,
+ const u_linklist_t *gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ if (NULL == obsID)
+ {
+ OC_LOG(ERROR, TAG, "obsID is null");
+ return false;
+ }
+
+ if (NULL == gatewayTable)
+ {
+ OC_LOG(ERROR, TAG, "gatewayTable is null");
+ return false;
+ }
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(gatewayTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+ if (NULL == entry && NULL == entry->destination)
+ {
+ OC_LOG(ERROR, TAG, "entry is NULL");
+ return false;
+ }
+ for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
+ {
+ RTMDestIntfInfo_t *destCheck =
+ u_arraylist_get(entry->destination->destIntfAddr, i);
+ if (NULL != destCheck && (0 == memcmp(destCheck->destIntfAddr.addr, devAddr.addr,
+ strlen(devAddr.addr)))
+ && devAddr.port == destCheck->destIntfAddr.port && 0 != destCheck->observerId)
+ {
+ *obsID = destCheck->observerId;
+ OC_LOG(DEBUG, TAG, "OUT");
+ return true;
+ }
+ }
+ u_linklist_get_next(&iterTable);
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return false;
+}
+
+OCStackResult RTMRemoveGatewayEntry(uint32_t gatewayId, u_linklist_t **removedGatewayNodes,
+ u_linklist_t **gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
+ RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
+
+ u_linklist_iterator_t *iterTable = NULL;
+
+ // if link list is not null we can directly add removed nodes to it instead of creating everytime.
+ if (NULL == *removedGatewayNodes)
+ {
+ *removedGatewayNodes = u_linklist_create();
+ }
+ OCStackResult ret = OC_STACK_OK;
+ u_linklist_init_iterator(*gatewayTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+ if (NULL == entry || NULL == entry->destination)
+ {
+ u_linklist_get_next(&iterTable);
+ continue;
+ }
+
+ if (gatewayId == entry->destination->gatewayId || (NULL != entry->nextHop &&
+ (gatewayId == entry->nextHop->gatewayId)))
+ {
+ OC_LOG_V(DEBUG, TAG, "Removing the gateway entry: %u", entry->destination->gatewayId);
+ ret = u_linklist_remove(*gatewayTable, &iterTable);
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
+ return OC_STACK_ERROR;
+ }
+ else
+ {
+ u_linklist_add(*removedGatewayNodes, (void *)entry);
+ }
+ }
+ else
+ {
+ u_linklist_get_next(&iterTable);
+ }
+ }
+ OC_LOG(DEBUG, TAG, "RTMRemoveGatewayEntry OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RTMRemoveGatewayDestEntry(uint32_t gatewayId, uint32_t nextHop,
+ const RTMDestIntfInfo_t *destInfAdr,
+ RTMGatewayEntry_t **existEntry, u_linklist_t **gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
+ RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
+ RM_NULL_CHECK_WITH_RET(destInfAdr, TAG, "destInfAdr");
+
+ u_linklist_iterator_t *iterTable = NULL;
+
+ OCStackResult ret = -1;
+ u_linklist_init_iterator(*gatewayTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+ if (NULL == entry)
+ {
+ u_linklist_get_next(&iterTable);
+ continue;
+ }
+
+ // Update the time for NextHop entry.
+ if (NULL != entry->destination && nextHop == entry->destination->gatewayId)
+ {
+ for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
+ {
+ RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
+ if (0 == memcmp(destCheck->destIntfAddr.addr, destInfAdr->destIntfAddr.addr,
+ strlen(destInfAdr->destIntfAddr.addr))
+ && destInfAdr->destIntfAddr.port == destCheck->destIntfAddr.port)
+ {
+ destCheck->timeElapsed = RTMGetCurrentTime();
+ break;
+ }
+ }
+ }
+
+ // Remove node with given gatewayid and nextHop if not found update exist entry.
+ if (NULL != entry->destination && (gatewayId == entry->destination->gatewayId))
+ {
+ OC_LOG_V(INFO, TAG, "Remove the gateway ID: %u", entry->destination->gatewayId);
+ if (NULL != entry->nextHop && nextHop == entry->nextHop->gatewayId)
+ {
+ ret = u_linklist_remove(*gatewayTable, &iterTable);
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
+ return OC_STACK_ERROR;
+ }
+ OICFree(entry);
+ return OC_STACK_OK;
+ }
+
+ *existEntry = entry;
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_ERROR;
+ }
+
+ u_linklist_get_next(&iterTable);
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_ERROR;
+}
+
+OCStackResult RTMRemoveEndpointEntry(uint16_t endpointId, u_linklist_t **endpointTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(endpointTable, TAG, "endpointTable");
+ RM_NULL_CHECK_WITH_RET(*endpointTable, TAG, "*endpointTable");
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(*endpointTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMEndpointEntry_t *entry = u_linklist_get_data(iterTable);
+ if (NULL != entry && endpointId == entry->endpointId)
+ {
+ OCStackResult ret = u_linklist_remove(*endpointTable, &iterTable);
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Deleting Entry from Routing Table failed");
+ return OC_STACK_ERROR;
+ }
+ OICFree(entry);
+ }
+ else
+ {
+ u_linklist_get_next(&iterTable);
+ }
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RTMRemoveGateways(u_linklist_t **gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+
+ if (NULL == gatewayTable || NULL == *gatewayTable)
+ {
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+ }
+
+ OCStackResult ret = RTMFreeGatewayRouteTable(gatewayTable);
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Removing Gateways failed");
+ return ret;
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RTMRemoveEndpoints(u_linklist_t **endpointTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ if (NULL == endpointTable || NULL == *endpointTable)
+ {
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+ }
+
+ OCStackResult ret = RTMFreeEndpointRouteTable(endpointTable);
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Freeing Endpoints failed");
+ return OC_STACK_ERROR;
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+void RTMFreeGateway(RTMGatewayId_t *gateway, u_linklist_t **gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_VOID(gateway, TAG, "gateway");
+ RM_NULL_CHECK_VOID(gatewayTable, TAG, "gatewayTable");
+ RM_NULL_CHECK_VOID(*gatewayTable, TAG, "*gatewayTable");
+ while (0 < u_arraylist_length(gateway->destIntfAddr))
+ {
+ void *data = u_arraylist_remove(gateway->destIntfAddr, 0);
+ OICFree(data);
+ }
+ u_arraylist_free(&(gateway->destIntfAddr));
+ OICFree(gateway);
+ OC_LOG(DEBUG, TAG, "OUT");
+}
+
+void RTMGetNeighbours(u_linklist_t **neighbourNodes, const u_linklist_t *gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_VOID(neighbourNodes, TAG, "neighbourNodes");
+ RM_NULL_CHECK_VOID(gatewayTable, TAG, "gatewayTable");
+
+ *neighbourNodes = u_linklist_create();
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(gatewayTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+ if (NULL != entry && 1 == entry->routeCost)
+ {
+ u_linklist_add(*neighbourNodes, (void *)entry);
+ }
+ else if (NULL != entry && 1 < entry->routeCost)
+ {
+ OC_LOG(DEBUG, TAG, "OUT");
+ return;
+ }
+
+ u_linklist_get_next(&iterTable);
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+}
+
+RTMGatewayId_t *RTMGetNextHop(uint32_t gatewayId, const u_linklist_t *gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ if (0 == gatewayId)
+ {
+ OC_LOG(ERROR, TAG, "gatewayId is invalid");
+ return NULL;
+ }
+
+ if (NULL == gatewayTable)
+ {
+ OC_LOG(ERROR, TAG, "gatewayTable is null");
+ return NULL;
+ }
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(gatewayTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+ if (NULL != entry && gatewayId == entry->destination->gatewayId)
+ {
+ if (1 == entry->routeCost)
+ {
+ OC_LOG(DEBUG, TAG, "OUT");
+ return entry->destination;
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return entry->nextHop;
+ }
+ u_linklist_get_next(&iterTable);
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return NULL;
+}
+
+CAEndpoint_t *RTMGetEndpointEntry(uint16_t endpointId, const u_linklist_t *endpointTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ if (NULL == endpointTable)
+ {
+ OC_LOG(ERROR, TAG, "endpointTable is null");
+ return NULL;
+ }
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(endpointTable, &iterTable);
+
+ while (NULL != iterTable)
+ {
+ RTMEndpointEntry_t *entry = u_linklist_get_data(iterTable);
+ if (NULL != entry && (endpointId == entry->endpointId))
+ {
+ OC_LOG(DEBUG, TAG, "OUT");
+ return &(entry->destIntfAddr);
+ }
+ u_linklist_get_next(&iterTable);
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return NULL;
+}
+
+void RTMGetObserverList(OCObservationId **obsList, uint8_t *obsListLen,
+ const u_linklist_t *gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_VOID(gatewayTable, TAG, "gatewayTable");
+ RM_NULL_CHECK_VOID(obsList, TAG, "obsList");
+
+ *obsList = (OCObservationId *) OICCalloc(MAX_OBSERVER_LIST_LENGTH, sizeof(OCObservationId));
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(gatewayTable, &iterTable);
+ uint8_t len = 0;
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+ for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
+ {
+ RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
+ if (NULL == destCheck)
+ {
+ OC_LOG(ERROR, TAG, "destCheck is null");
+ return;
+ }
+ if (0 != destCheck->observerId)
+ {
+ OC_LOG_V(DEBUG, TAG, "Observer ID is %d", destCheck->observerId);
+ *(*obsList + len) = destCheck->observerId;
+ len++;
+ }
+ if (MAX_OBSERVER_LIST_LENGTH < len)
+ {
+ *obsList = (OCObservationId *) OICRealloc((void *)*obsList,
+ (sizeof(OCObservationId) * (len + 1)));
+ }
+ break;
+ }
+ u_linklist_get_next(&iterTable);
+ }
+
+ *obsListLen = len;
+ OC_LOG(DEBUG, TAG, "OUT");
+}
+
+OCStackResult RTMUpdateDestinationIntfAdr(uint32_t gatewayId, RTMDestIntfInfo_t destInterfaces,
+ bool addAdr, u_linklist_t **gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
+ RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(*gatewayTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+ if (NULL != entry && NULL != entry->destination &&
+ gatewayId == entry->destination->gatewayId)
+ {
+ if (addAdr)
+ {
+ for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
+ {
+ RTMDestIntfInfo_t *destCheck =
+ u_arraylist_get(entry->destination->destIntfAddr, i);
+ if (NULL == destCheck)
+ {
+ OC_LOG(ERROR, TAG, "Destination adr get failed");
+ continue;
+ }
+
+ if (0 == memcmp(destCheck->destIntfAddr.addr, destInterfaces.destIntfAddr.addr,
+ strlen(destInterfaces.destIntfAddr.addr))
+ && destInterfaces.destIntfAddr.port == destCheck->destIntfAddr.port)
+ {
+ destCheck->timeElapsed = RTMGetCurrentTime();
+ destCheck->isValid = true;
+ OC_LOG(ERROR, TAG, "destInterfaces already present");
+ return OC_STACK_ERROR;
+ }
+ }
+
+ RTMDestIntfInfo_t *destAdr =
+ (RTMDestIntfInfo_t *) OICCalloc(1, sizeof(RTMDestIntfInfo_t));
+ if (NULL == destAdr)
+ {
+ OC_LOG(ERROR, TAG, "Calloc destAdr failed");
+ return OC_STACK_ERROR;
+ }
+ *destAdr = destInterfaces;
+ destAdr->timeElapsed = RTMGetCurrentTime();
+ destAdr->isValid = true;
+ bool result =
+ u_arraylist_add(entry->destination->destIntfAddr, (void *)destAdr);
+ if (!result)
+ {
+ OC_LOG(ERROR, TAG, "Updating Destinterface address failed");
+ OICFree(destAdr);
+ return OC_STACK_ERROR;
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_DUPLICATE_REQUEST;
+ }
+
+ for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
+ {
+ RTMDestIntfInfo_t *removeAdr =
+ u_arraylist_get(entry->destination->destIntfAddr, i);
+ if (0 == memcmp(removeAdr->destIntfAddr.addr, destInterfaces.destIntfAddr.addr,
+ strlen(destInterfaces.destIntfAddr.addr))
+ && destInterfaces.destIntfAddr.port == removeAdr->destIntfAddr.port)
+ {
+ RTMDestIntfInfo_t *data =
+ u_arraylist_remove(entry->destination->destIntfAddr, i);
+ OICFree(data);
+ break;
+ }
+ }
+ }
+ u_linklist_get_next(&iterTable);
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RTMUpdateMcastSeqNumber(uint32_t gatewayId, uint16_t seqNum,
+ u_linklist_t **gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
+ RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(*gatewayTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+ if (NULL != entry && NULL != entry->destination &&
+ gatewayId == entry->destination->gatewayId)
+ {
+ if (0 == entry->mcastMessageSeqNum || entry->mcastMessageSeqNum < seqNum)
+ {
+ entry->mcastMessageSeqNum = seqNum;
+ return OC_STACK_OK;
+ }
+ else if (entry->mcastMessageSeqNum == seqNum)
+ {
+ return OC_STACK_DUPLICATE_REQUEST;
+ }
+ else
+ {
+ return OC_STACK_COMM_ERROR;
+ }
+ }
+ u_linklist_get_next(&iterTable);
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+uint64_t RTMGetCurrentTime()
+{
+ uint64_t currentTime = 0;
+
+#ifdef __ANDROID__
+ struct timespec getTs;
+
+ clock_gettime(CLOCK_MONOTONIC, &getTs);
+
+ currentTime = getTs.tv_sec;
+#elif defined __ARDUINO__
+ currentTime = millis() / 1000;
+#else
+#if _POSIX_TIMERS > 0
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ currentTime = ts.tv_sec;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ currentTime = tv.tv_sec;
+#endif
+#endif
+ return currentTime;
+}
+
+OCStackResult RTMUpdateDestAddrValidity(u_linklist_t **invalidTable, u_linklist_t **gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(invalidTable, TAG, "invalidTable");
+ RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
+ RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
+
+ *invalidTable = u_linklist_create();
+ u_linklist_iterator_t *iterTable = NULL;
+ uint64_t presentTime = RTMGetCurrentTime();
+
+ u_linklist_init_iterator(*gatewayTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
+ if (NULL == entry)
+ {
+ u_linklist_get_next(&iterTable);
+ continue;
+ }
+ else if (1 == entry->routeCost)
+ {
+ for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
+ {
+ RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
+ if (GATEWAY_ALIVE_TIMEOUT < (presentTime - destCheck->timeElapsed))
+ {
+ destCheck->isValid = false;
+ u_linklist_add(*invalidTable, (void *)destCheck);
+ }
+ }
+ }
+ else if (1 < entry->routeCost)
+ {
+ break;
+ }
+ u_linklist_get_next(&iterTable);
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RTMRemoveInvalidGateways(u_linklist_t **invalidTable, u_linklist_t **gatewayTable)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(invalidTable, TAG, "invalidTable");
+ RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
+ RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
+
+ *invalidTable = u_linklist_create();
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(*gatewayTable, &iterTable);
+ while (iterTable != NULL)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+
+ if (NULL == entry)
+ {
+ u_linklist_get_next(&iterTable);
+ continue;
+ }
+ else if (NULL != entry->destination && (1 == entry->routeCost))
+ {
+ for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
+ {
+ RTMDestIntfInfo_t *destCheck = u_arraylist_get(entry->destination->destIntfAddr, i);
+ if (!destCheck->isValid)
+ {
+ void *data = u_arraylist_remove(entry->destination->destIntfAddr, i);
+ OICFree(data);
+ i--;
+ }
+ }
+
+ if (0 == u_arraylist_length(entry->destination->destIntfAddr))
+ {
+ u_arraylist_free(&(entry->destination->destIntfAddr));
+ OCStackResult res =
+ RTMRemoveGatewayEntry(entry->destination->gatewayId, invalidTable, gatewayTable);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Removing Entries failed");
+ return OC_STACK_ERROR;
+ }
+ u_linklist_get_next(&iterTable);
+ }
+ else
+ {
+ u_linklist_get_next(&iterTable);
+ }
+ }
+ else if (1 < entry->routeCost)
+ {
+ break;
+ }
+ else
+ {
+ u_linklist_get_next(&iterTable);
+ }
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RTMUpdateEntryParameters(uint32_t gatewayId, uint32_t seqNum,
+ const RTMDestIntfInfo_t *destAdr, u_linklist_t **gatewayTable,
+ bool forceUpdate)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(gatewayTable, TAG, "gatewayTable");
+ RM_NULL_CHECK_WITH_RET(*gatewayTable, TAG, "*gatewayTable");
+ RM_NULL_CHECK_WITH_RET(destAdr, TAG, "destAdr");
+
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(*gatewayTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *entry = u_linklist_get_data(iterTable);
+
+ if (NULL == entry)
+ {
+ u_linklist_get_next(&iterTable);
+ continue;
+ }
+ if (NULL != entry->destination && gatewayId == entry->destination->gatewayId)
+ {
+ for (uint32_t i = 0; i < u_arraylist_length(entry->destination->destIntfAddr); i++)
+ {
+ RTMDestIntfInfo_t *destCheck =
+ u_arraylist_get(entry->destination->destIntfAddr, i);
+ if (NULL != destCheck &&
+ (0 == memcmp(destCheck->destIntfAddr.addr, destAdr->destIntfAddr.addr,
+ strlen(destAdr->destIntfAddr.addr)))
+ && destAdr->destIntfAddr.port == destCheck->destIntfAddr.port)
+ {
+ destCheck->timeElapsed = RTMGetCurrentTime();
+ destCheck->isValid = true;
+ }
+ }
+
+ if (0 != entry->seqNum && seqNum == entry->seqNum)
+ {
+ return OC_STACK_DUPLICATE_REQUEST;
+ }
+ else if (0 != entry->seqNum && seqNum != ((entry->seqNum) + 1) && !forceUpdate)
+ {
+ return OC_STACK_COMM_ERROR;
+ }
+ else
+ {
+ entry->seqNum = seqNum;
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+ }
+ }
+ u_linklist_get_next(&iterTable);
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+void RTMPrintTable(const u_linklist_t *gatewayTable, const u_linklist_t *endpointTable)
+{
+ RM_NULL_CHECK_VOID(gatewayTable, TAG, "gatewayTable");
+ OC_LOG(DEBUG, RM_TAG, "=================Gateway List table============================\n");
+ u_linklist_iterator_t *iterTable = NULL;
+ u_linklist_init_iterator(gatewayTable, &iterTable);
+ while (NULL != iterTable)
+ {
+ RTMGatewayEntry_t *hop =
+ (RTMGatewayEntry_t *) u_linklist_get_data(iterTable);
+ if (NULL == hop)
+ {
+ OC_LOG(ERROR, RM_TAG, "Printing Table Failed");
+ return;
+ }
+ if (NULL == hop->nextHop || 0 == hop->nextHop->gatewayId)
+ {
+ OC_LOG_V(DEBUG, RM_TAG, "\nDestination : %u\nNextHop : (null)\nHopCount : %d",
+ hop->destination->gatewayId, hop->routeCost);
+ OC_LOG_V(DEBUG, RM_TAG, "\nSequence Number :%u", hop->seqNum);
+ }
+ else
+ {
+ OC_LOG_V(DEBUG, RM_TAG, "\nDestination : %u\nNextHop : %u\nHopCount : %d",
+ hop->destination->gatewayId, hop->nextHop->gatewayId, hop->routeCost);
+ OC_LOG_V(DEBUG, RM_TAG, "\nSequence Number :%u", hop->seqNum);
+ }
+ if (1 == hop->routeCost && NULL != hop->destination &&
+ hop->destination->destIntfAddr != NULL)
+ {
+ for (uint32_t i = 0; i < u_arraylist_length(hop->destination->destIntfAddr); i++)
+ {
+ RTMDestIntfInfo_t *dest = u_arraylist_get(hop->destination->destIntfAddr, i);
+ if (NULL != dest)
+ {
+ OC_LOG_V(DEBUG, RM_TAG, "\nDestination interface addresses: %s Port : %d Obs ID: %d",
+ dest->destIntfAddr.addr, dest->destIntfAddr.port, dest->observerId);
+ OC_LOG_V(DEBUG, RM_TAG, "Validity: %d", dest->isValid);
+ }
+ }
+ }
+ OC_LOG(DEBUG, RM_TAG, "********************************************\n");
+ u_linklist_get_next(&iterTable);
+ }
+
+ OC_LOG(DEBUG, RM_TAG, "=================Endpoint List table============================\n");
+ u_linklist_iterator_t *iterEndpointTable = NULL;
+ u_linklist_init_iterator(endpointTable, &iterEndpointTable);
+
+ // Iterate over endpoint list to find if already entry for gatewayid is present.
+ while (NULL != iterEndpointTable)
+ {
+ RTMEndpointEntry_t *hop =
+ (RTMEndpointEntry_t *) u_linklist_get_data(iterEndpointTable);
+ if (NULL == hop)
+ {
+ OC_LOG(ERROR, RM_TAG, "Printing Table Failed");
+ return;
+ }
+ OC_LOG_V(DEBUG, RM_TAG, "EndpointId : %u\naddr : %s Port : %d",
+ hop->endpointId, hop->destIntfAddr.addr, hop->destIntfAddr.port);
+
+ OC_LOG(DEBUG, RM_TAG, "********************************************\n");
+ u_linklist_get_next(&iterEndpointTable);
+ }
+}
--- /dev/null
+/* ****************************************************************
+ *
+ * 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 <string.h>
+#include "routingutility.h"
+#include "routingmanager.h"
+#include "oic_malloc.h"
+#include "include/logger.h"
+
+/**
+ * Logging tag for module name.
+ */
+#define TAG "RM_UTIL"
+
+/**
+ * Tag for printing the logs of forwarding the packet.
+ */
+#define RM_TAG "RAP"
+
+/**
+ * Minimum routing option data length is
+ * length of src address(1byte) + length of destination address(1byte) + hop count(2bytes)
+ */
+#define MIN_ROUTE_OPTION_LEN 4
+
+// destination and source are <GatewayId><ClientId> here, where ClientId is optional.
+OCStackResult RMAddInfo(const char *destination, CAHeaderOption_t **options,
+ uint8_t *numOptions)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(options, TAG, "options");
+ RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
+
+ CAHeaderOption_t *optionPtr = NULL;
+ int8_t index = -1;
+
+ RMGetRouteOptionIndex(*options, *numOptions, &index);
+
+ if (-1 < index)
+ {
+ OC_LOG(INFO, TAG, "Route option is present");
+ optionPtr = *options;
+ }
+ else
+ {
+ OC_LOG(INFO, TAG, "Route option is not present");
+ index = *numOptions;
+ optionPtr = OICCalloc((*numOptions + 1), sizeof(CAHeaderOption_t));
+ if (!optionPtr)
+ {
+ OC_LOG(ERROR, TAG, "OICCalloc failed");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ memcpy(optionPtr, *options, sizeof(CAHeaderOption_t) * (*numOptions));
+ }
+
+ OCStackResult res = OC_STACK_OK;
+ RMRouteOption_t routeOption = {.destGw = 0};
+ if (*numOptions != index)
+ {
+ OC_LOG(INFO, TAG, "Route option is already present");
+ res = RMParseRouteOption(&optionPtr[index], &routeOption);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "RMParseRouteOption failed");
+ return OC_STACK_ERROR;
+ }
+ }
+
+ if(destination)
+ {
+ memcpy(&(routeOption.destGw), destination, sizeof(routeOption.destGw));
+ memcpy(&(routeOption.destEp), destination + sizeof(routeOption.destGw),
+ sizeof(routeOption.destEp));
+ }
+
+#ifdef ROUTING_GATEWAY
+ // A gateway is supposed to add its ID as source.
+ uint32_t gatewayId = RMGetGatewayId();
+ if (gatewayId)
+ {
+ memcpy(&(routeOption.srcGw), &gatewayId, sizeof(routeOption.srcGw));
+ }
+
+ if(!routeOption.destGw)
+ {
+ routeOption.mSeqNum = RMGetMcastSeqNumber();
+ }
+#endif
+
+ res = RMCreateRouteOption(&routeOption, optionPtr + index);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Creation of routing option failed");
+ OICFree(optionPtr);
+ return res;
+ }
+
+ if ((*numOptions) == index )
+ {
+ (*numOptions) = (*numOptions) + 1;
+ OICFree(*options);
+ *options = optionPtr;
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RMUpdateInfo(CAHeaderOption_t **options, uint8_t *numOptions,
+ CAEndpoint_t *endpoint)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(options, TAG, "options");
+ RM_NULL_CHECK_WITH_RET(*options, TAG, "invalid option");
+ RM_NULL_CHECK_WITH_RET(numOptions, TAG, "numOptions");
+ RM_NULL_CHECK_WITH_RET(endpoint, TAG, "endpoint");
+
+ if (0 >= *numOptions)
+ {
+ OC_LOG(ERROR, TAG, "Invalid arguement: numOptions");
+ return OC_STACK_ERROR;
+ }
+
+ int8_t routeIndex = -1;
+ RMGetRouteOptionIndex(*options, *numOptions, &routeIndex);
+
+ if (-1 >= routeIndex)
+ {
+ OC_LOG(DEBUG, TAG, "Nothing to remove.");
+ return OC_STACK_OK;
+ }
+
+ // Update Endpoint with source address from RM header option.
+ if (0 != (*options + routeIndex)->optionLength)
+ {
+ uint8_t dLen = 0;
+ uint16_t count = sizeof(dLen);
+ memcpy(&dLen, (*options + routeIndex)->optionData, sizeof(dLen));
+ count += dLen;
+ uint8_t sLen = 0;
+ memcpy(&sLen, (*options + routeIndex)->optionData + count, sizeof(sLen));
+ count += sizeof(sLen);
+ if (0 < sLen)
+ {
+ memcpy(endpoint->routeData, (*options + routeIndex)->optionData + count,
+ GATEWAY_ID_LENGTH);
+ OC_LOG_V(DEBUG, TAG, "adding srcgid: %u in endpoint [%d]",
+ *((uint32_t *)endpoint->routeData), sLen);
+
+ count += GATEWAY_ID_LENGTH;
+
+ if (GATEWAY_ID_LENGTH < sLen)
+ {
+ memcpy(endpoint->routeData + GATEWAY_ID_LENGTH,
+ (*options + routeIndex)->optionData + count, ENDPOINT_ID_LENGTH);
+ OC_LOG_V(DEBUG, TAG, "adding srceid: %u in endpoint",
+ *((uint16_t *)(endpoint->routeData + GATEWAY_ID_LENGTH)));
+ }
+ }
+ }
+
+ // Remove route option from header.
+ for (uint8_t i = routeIndex; i < (*numOptions)-1; i++)
+ {
+ memcpy((*options) + i, (*options)+i+1, sizeof(**options));
+ }
+ *numOptions = (*numOptions) - 1;
+
+ if (0 == *numOptions)
+ {
+ // Remove route option.
+ OICFree(*options);
+ *options = NULL;
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+void RMGetRouteOptionIndex(const CAHeaderOption_t *options, uint8_t numOptions, int8_t *index)
+{
+ OC_LOG(DEBUG, TAG, "IN");
+ RM_NULL_CHECK_VOID(options, TAG, "options");
+ RM_NULL_CHECK_VOID(index, TAG, "index");
+ for (uint32_t i = 0; i < numOptions; i++)
+ {
+ OC_LOG_V(DEBUG, TAG, "Request- optionID: %d", options[i].optionID);
+ if (RM_OPTION_MESSAGE_SWITCHING == options[i].optionID)
+ {
+ OC_LOG_V(INFO, TAG, "Found Option at %d", i);
+ *index = i;
+ break;
+ }
+ }
+ OC_LOG(DEBUG, TAG, "OUT");
+}
+
+OCStackResult RMCreateRouteOption(const RMRouteOption_t *optValue, CAHeaderOption_t *options)
+{
+ OC_LOG(DEBUG, RM_TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue");
+ RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options");
+
+ uint8_t dLen = (optValue->destGw ? GATEWAY_ID_LENGTH:0) +
+ (optValue->destEp ? ENDPOINT_ID_LENGTH:0);
+ uint8_t sLen = (optValue->srcGw ? GATEWAY_ID_LENGTH:0) +
+ (optValue->srcEp ? ENDPOINT_ID_LENGTH:0);
+
+ OC_LOG_V(DEBUG, RM_TAG, "createoption dlen %u slen [%u]", dLen, sLen);
+ unsigned int totalLength = MIN_ROUTE_OPTION_LEN + dLen + sLen;
+ void *tempData = OICCalloc(totalLength, sizeof(char));
+ if (NULL == tempData)
+ {
+ OC_LOG(ERROR, RM_TAG, "Calloc failed");
+ return OC_STACK_NO_MEMORY;
+ }
+ memcpy(tempData, &dLen, sizeof(dLen));
+ unsigned int count = sizeof(dLen);
+ if (0 < dLen)
+ {
+ if (optValue->destGw)
+ {
+ memcpy(tempData + count, &(optValue->destGw), GATEWAY_ID_LENGTH);
+ count += GATEWAY_ID_LENGTH;
+ }
+
+ if (optValue->destEp)
+ {
+ memcpy(tempData + count, &(optValue->destEp), ENDPOINT_ID_LENGTH);
+ count += ENDPOINT_ID_LENGTH;
+ }
+ }
+
+ memcpy(tempData + count, &sLen, sizeof(sLen));
+ count += sizeof(sLen);
+ if (0 < sLen)
+ {
+ if (optValue->srcGw)
+ {
+ memcpy(tempData + count, &(optValue->srcGw), GATEWAY_ID_LENGTH);
+ count += GATEWAY_ID_LENGTH;
+ }
+
+ if (optValue->srcEp)
+ {
+ memcpy(tempData + count, &(optValue->srcEp), ENDPOINT_ID_LENGTH);
+ count += ENDPOINT_ID_LENGTH;
+ }
+ }
+
+ memcpy(tempData + count, &optValue->mSeqNum, sizeof(optValue->mSeqNum));
+ memcpy(options->optionData, tempData, totalLength);
+
+ options->optionID = RM_OPTION_MESSAGE_SWITCHING;
+ options->optionLength = totalLength;
+
+ OC_LOG_V(INFO, RM_TAG, "Option Length is %d", options->optionLength);
+
+ OICFree(tempData);
+ OC_LOG(DEBUG, RM_TAG, "OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult RMParseRouteOption(const CAHeaderOption_t *options, RMRouteOption_t *optValue)
+{
+ OC_LOG(DEBUG, RM_TAG, "IN");
+ RM_NULL_CHECK_WITH_RET(options, RM_TAG, "options");
+ RM_NULL_CHECK_WITH_RET(optValue, RM_TAG, "optValue");
+ if (0 == options->optionLength)
+ {
+ OC_LOG(ERROR, RM_TAG, "Option data is not present");
+ return OC_STACK_ERROR;
+ }
+
+ uint8_t dLen = 0 ;
+ uint16_t count = sizeof(dLen);
+ memcpy(&dLen, options->optionData, sizeof(dLen));
+ if (0 < dLen)
+ {
+ memcpy(&(optValue->destGw), options->optionData + count, GATEWAY_ID_LENGTH);
+ count += GATEWAY_ID_LENGTH;
+
+ if (GATEWAY_ID_LENGTH < dLen)
+ {
+ memcpy(&(optValue->destEp), options->optionData + count, ENDPOINT_ID_LENGTH);
+ count += ENDPOINT_ID_LENGTH;
+ }
+ }
+
+ uint8_t sLen = 0;
+ memcpy(&sLen, options->optionData + count, sizeof(sLen));
+ count += sizeof(sLen);
+ if (0 < sLen)
+ {
+ memcpy(&(optValue->srcGw), options->optionData + count, GATEWAY_ID_LENGTH);
+ count += GATEWAY_ID_LENGTH;
+
+ if (GATEWAY_ID_LENGTH < sLen)
+ {
+ memcpy(&(optValue->srcEp), options->optionData + count, ENDPOINT_ID_LENGTH);
+ count += ENDPOINT_ID_LENGTH;
+ }
+ }
+ memcpy(&optValue->mSeqNum, options->optionData + count, sizeof(optValue->mSeqNum));
+
+ OC_LOG_V(INFO, RM_TAG, "Option hopcount is %d", optValue->mSeqNum);
+ OC_LOG_V(INFO, RM_TAG, "Option Sender Addr is [%u][%u]", optValue->srcGw, optValue->srcEp);
+ OC_LOG_V(INFO, RM_TAG, "Option Dest Addr is [%u][%u]", optValue->destGw, optValue->destEp);
+ OC_LOG(DEBUG, RM_TAG, "OUT");
+ return OC_STACK_OK;
+}
######################################################################
libocsrm_env.PrependUnique(CPPPATH = [
'../../../extlibs/cjson/',
-# '../../../extlibs/tinydtls/',
+ '../../../extlibs/tinydtls/',
'../logger/include',
'../ocrandom/include',
'../stack/include',
# Source files and Targets
######################################################################
OCSRM_SRC = 'src/'
-libocsrm_src = [
- OCSRM_SRC + 'secureresourcemanager.c',
- OCSRM_SRC + 'resourcemanager.c',
- OCSRM_SRC + 'aclresource.c',
- OCSRM_SRC + 'pstatresource.c',
- OCSRM_SRC + 'doxmresource.c',
- OCSRM_SRC + 'credresource.c',
- OCSRM_SRC + 'policyengine.c',
- OCSRM_SRC + 'psinterface.c',
- OCSRM_SRC + 'srmresourcestrings.c',
- OCSRM_SRC + 'srmutility.c',
- OCSRM_SRC + 'base64.c'
- ]
+if env.get('SECURED') == '1':
+ libocsrm_src = [
+ OCSRM_SRC + 'secureresourcemanager.c',
+ OCSRM_SRC + 'resourcemanager.c',
+ OCSRM_SRC + 'aclresource.c',
+ OCSRM_SRC + 'amaclresource.c',
+ OCSRM_SRC + 'pstatresource.c',
+ OCSRM_SRC + 'doxmresource.c',
+ OCSRM_SRC + 'credresource.c',
+ OCSRM_SRC + 'svcresource.c',
+ OCSRM_SRC + 'policyengine.c',
+ OCSRM_SRC + 'psinterface.c',
+ OCSRM_SRC + 'srmresourcestrings.c',
+ OCSRM_SRC + 'srmutility.c',
+ OCSRM_SRC + 'iotvticalendar.c',
+ OCSRM_SRC + 'oxmpincommon.c',
+ OCSRM_SRC + 'base64.c',
+ #pbkdf2.c is required to PIN based OxM only.
+ #But we did not use a separate build options to prevent the build command becomes complicated.
+ OCSRM_SRC + 'pbkdf2.c'
+ ]
+else:
+ libocsrm_src = [
+ OCSRM_SRC + 'secureresourcemanager.c',
+ OCSRM_SRC + 'resourcemanager.c',
+ OCSRM_SRC + 'aclresource.c',
+ OCSRM_SRC + 'amaclresource.c',
+ OCSRM_SRC + 'pstatresource.c',
+ OCSRM_SRC + 'doxmresource.c',
+ OCSRM_SRC + 'credresource.c',
+ OCSRM_SRC + 'svcresource.c',
+ OCSRM_SRC + 'policyengine.c',
+ OCSRM_SRC + 'psinterface.c',
+ OCSRM_SRC + 'srmresourcestrings.c',
+ OCSRM_SRC + 'srmutility.c',
+ OCSRM_SRC + 'iotvticalendar.c',
+ OCSRM_SRC + 'base64.c'
+ ]
libocsrm = libocsrm_env.StaticLibrary('libocsrm', libocsrm_src)
libocsrm_env.InstallTarget(libocsrm, 'libocsrm')
libocsrm_env.UserInstallTargetLib(libocsrm, 'libocsrm')
-if env.get('SECURED') == '1':
- SConscript('provisioning/SConscript')
+if target_os == 'linux' and env.get('SECURED') == '1':
+ SConscript('provisioning/SConscript')
*/
char* BinToAclJSON(const OicSecAcl_t * acl);
+/**
+ * This function deletes ACL data.
+ *
+ * @param acl instance of OicSecAcl_t structure.
+ */
+void DeleteACLList(OicSecAcl_t* acl);
+
#ifdef __cplusplus
}
#endif
--- /dev/null
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef IOTVT_SRM_AMACLR_H
+#define IOTVT_SRM_AMACLR_H
+
+/**
+ * @file
+ *
+ * This file contains the APIs for the /oic/sec/amacl resource is an ACL structure that
+ * specifies which resources will use an Access Manager Service (AMS) to resolve access decisions.
+ * It dynamically obtains an ACL using an AMS.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialize Amacl resource by loading data from persistent storage.
+ *
+ * @retval OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitAmaclResource();
+
+/**
+ * Perform cleanup for Amacl resources.
+ *
+ * @retval none
+ */
+void DeInitAmaclResource();
+
+/**
+ * This method is used by PolicyEngine to retrieve Amacl for a Subject.
+ *
+ * @param subjectId ID of the subject for which Amacl is required.
+ * @param savePtr is used internally by @ref GetAmaclResourceData to maintain index between
+ * successive calls for same subjectId.
+ *
+ * @retval reference to @ref OicSecAmacl_t if Amacl is found, else NULL
+ *
+ * @note On the first call to @ref GetAmaclResourceData, savePtr should point to NULL
+ */
+const OicSecAmacl_t* GetAmaclResourceData(const OicUuid_t* subjectId, OicSecAmacl_t **savePtr);
+
+/**
+ * This function converts Amacl data into JSON format.
+ * Caller needs to invoke 'free' when done using
+ * returned string.
+ * @param Amacl instance of OicSecAmacl_t structure.
+ *
+ * @retval pointer to Amacl in json format.
+ */
+char* BinToAmaclJSON(const OicSecAmacl_t * amacl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //IOTVT_SRM_AMACLR_H
+
+
*/
OCStackResult AddCredential(OicSecCred_t * cred);
+/**
+ * Function to remove the credential from SVR DB.
+ *
+ * @param credId Credential ID to be deleted.
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult RemoveCredential(const OicUuid_t* credId);
+
#if defined(__WITH_DTLS__)
/**
* This internal callback is used by lower stack (i.e. CA layer) to
* @retval none
*/
void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo);
+
+/**
+ * Add temporal PSK to PIN based OxM
+ *
+ * @param[in] tmpSubject UUID of target device
+ * @param[in] credType Type of credential to be added
+ * @param[in] pin numeric characters
+ * @param[in] pinSize length of 'pin'
+ * @param[in] ownersLen Number of owners
+ * @param[in] owners Array of owners
+ * @param[out] tmpCredSubject Generated credential's subject.
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
+ const char * pin, size_t pinSize,
+ size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject);
+
#endif /* __WITH_DTLS__ */
/**
#ifndef IOTVT_SRM_DOXM_H
#define IOTVT_SRM_DOXM_H
+#include "octypes.h"
+
#ifdef __cplusplus
extern "C" {
#endif
*/
void SRMRegisterProvisioningResponseHandler(SPResponseCallback respHandler);
+/**
+ * @brief Check the security resource URI.
+ * @param uri [IN] Pointers to security resource URI.
+ * @return true if the URI is one of security resources, otherwise false.
+ */
+bool SRMIsSecurityResourceURI(const char* uri);
+
#ifdef __cplusplus
}
#endif
extern const char * SVR_DB_FILE_NAME;
extern const char * OIC_MI_DEF;
+//AMACL
+extern const char * OIC_RSRC_TYPE_SEC_AMACL;
+extern const char * OIC_RSRC_AMACL_URI;
+extern const char * OIC_JSON_AMACL_NAME;
+
//ACL
extern const char * OIC_RSRC_TYPE_SEC_ACL;
extern const char * OIC_RSRC_ACL_URI;
extern const char * OIC_RSRC_CRED_URI;
extern const char * OIC_JSON_CRED_NAME;
+//SVC
+extern const char * OIC_RSRC_TYPE_SEC_SVC;
+extern const char * OIC_RSRC_SVC_URI;
+extern const char * OIC_JSON_SVC_NAME;
+
extern const char * OIC_JSON_SUBJECT_NAME;
extern const char * OIC_JSON_RESOURCES_NAME;
+extern const char * OIC_JSON_AMSS_NAME;
extern const char * OIC_JSON_PERMISSION_NAME;
extern const char * OIC_JSON_OWNERS_NAME;
extern const char * OIC_JSON_OWNER_NAME;
extern const char * OIC_JSON_PUBLICDATA_NAME;
extern const char * OIC_JSON_PRIVATEDATA_NAME;
extern const char * OIC_JSON_PERIOD_NAME;
+extern const char * OIC_JSON_PERIODS_NAME;
+extern const char * OIC_JSON_RECURRENCES_NAME;
extern const char * OIC_JSON_ISOP_NAME;
extern const char * OIC_JSON_COMMIT_HASH_NAME;
extern const char * OIC_JSON_DEVICE_ID_NAME;
extern const char * OIC_JSON_TM_NAME;
extern const char * OIC_JSON_OM_NAME;
extern const char * OIC_JSON_SM_NAME;
+extern const char * OIC_JSON_SERVICE_DEVICE_ID;
+extern const char * OIC_JSON_SERVICE_TYPE;
+extern const char * OIC_JSON_SUPPORTED_CRED_TYPE_NAME;
extern OicUuid_t WILDCARD_SUBJECT_ID;
extern size_t WILDCARD_SUBJECT_ID_LEN;
//Ownership Transfer Methods
extern const char * OXM_JUST_WORKS;
extern const char * OXM_MODE_SWITCH;
-extern const char * RANDOM_DEVICE_PIN;
-extern const char * PRE_PROVISIONED_DEVICE_PIN;
-extern const char * PRE_PROVISIONED_STRONG_CREDENTIAL;
+extern const char * OXM_RANDOM_DEVICE_PIN;
+extern const char * OXM_PRE_PROVISIONED_DEVICE_PIN;
+extern const char * OXM_PRE_PROVISIONED_STRONG_CREDENTIAL;
extern const char * OIC_SEC_TRUE;
extern const char * OIC_SEC_FALSE;
--- /dev/null
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef IOTVT_SRM_SVCR_H
+#define IOTVT_SRM_SVCR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialize SVC resource by loading data from persistent storage.
+ *
+ * @retval OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitSVCResource();
+
+/**
+ * Perform cleanup for SVC resources.
+ *
+ * @retval none
+ */
+void DeInitSVCResource();
+
+/**
+ * This function converts SVC data into JSON format.
+ * Caller needs to invoke 'free' when done using
+ * returned string.
+ * @param svc instance of OicSecSvc_t structure.
+ *
+ * @retval pointer to SVC in json format.
+ */
+char* BinToSvcJSON(const OicSecSvc_t * svc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //IOTVT_SRM_SVCR_H
+
+
--- /dev/null
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef IOTVT_ICALENDAR_H
+#define IOTVT_ICALENDAR_H
+
+//Not supported on Arduino due lack of absolute time need to implement iCalendar
+#ifndef WITH_ARDUINO
+
+#include <stdint.h> // for uint8_t typedef
+#include <stdbool.h>
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define FREQ_DAILY (1)
+#define MAX_BYDAY_SIZE (7) //7 days of week
+#define TM_YEAR_OFFSET (1900) //tm_year field of c-lang tm date-time struct
+ //represents number of years since 1900.
+#define TM_DST_OFFSET (1) //c-lang tm struct Daylight Saving Time offset.
+#define TOTAL_HOURS (24) //Total hours in a day.
+
+typedef struct IotvtICalRecur IotvtICalRecur_t;
+typedef struct IotvtICalPeriod IotvtICalPeriod_t;
+
+/*
+ * date-time = date "T" time
+ *
+ * date = date-value
+ * date-value = date-fullyear date-month date-mday
+ * date-fullyear = 4DIGIT
+ * date-month = 2DIGIT ;01-12
+ * date-mday = 2DIGIT ;01-28, 01-29, 01-30, 01-31
+ * ;based on month/year
+ *
+ * time = time-hour time-minute time-second [time-utc]
+ * time-hour = 2DIGIT ;00-23
+ * time-minute = 2DIGIT ;00-59
+ * time-second = 2DIGIT ;00-60
+ * ;The "60" value is used to account for "leap" seconds.
+ *
+ * Date-Time Forms:
+ * 1. Date with Local time
+ * 20150626T150000
+ */
+typedef struct tm IotvtICalDateTime_t; //c-lang tm date-time struct
+
+/*
+ * Bit mask for weekdays
+ */
+typedef enum
+{
+ NO_WEEKDAY = 0X0,
+ SUNDAY = (0x1 << 0),
+ MONDAY = (0x1 << 1),
+ TUESDAY = (0x1 << 2),
+ WEDNESDAY = (0x1 << 3),
+ THURSDAY = (0x1 << 4),
+ FRIDAY = (0x1 << 5),
+ SATURDAY = (0x1 << 6)
+}IotvtICalWeekdayBM_t;
+
+/*
+ * Result code for IotvtICalendar
+ */
+typedef enum
+{
+ IOTVTICAL_SUCCESS = 0, //successfully completed operation
+ IOTVTICAL_VALID_ACCESS, //access is within allowable time
+ IOTVTICAL_INVALID_ACCESS, //access is not within allowable time
+ IOTVTICAL_INVALID_PARAMETER, //invalid method parameter
+ IOTVTICAL_INVALID_RRULE, //rrule is not well form, missing FREQ
+ IOTVTICAL_INVALID_PERIOD, //period is not well form, start-datetime is after end-datetime
+ IOTVTICAL_ERROR //encounter error
+}IotvtICalResult_t;
+
+/*
+ * Grammar for iCalendar data type PERIOD
+ *
+ * period = date-time "/" date-time ; start-time / end-time.
+ * ;The start-time MUST be before the end-time.
+ *
+ */
+struct IotvtICalPeriod
+{
+ IotvtICalDateTime_t startDateTime;
+ IotvtICalDateTime_t endDateTime;
+};
+
+/*
+ * Grammar for iCalendar data type RECUR
+ *
+ * recur = "FREQ"=freq *(
+ * ( ";" "UNTIL" "=" enddate ) /
+ * ( ";" "BYDAY" "=" bywdaylist ) /
+ * )
+ *
+ * freq = "DAILY"
+ * enddate = date
+ * bywdaylist = weekday/ ( weekday *("," weekday) )
+ * weekday = "SU" / "MO" / "TU" / "WE" / "TH" / "FR" / "SA"
+ *
+ * Example:
+ * 1."Allow access on every Monday, Wednesday & Friday between 3pm to 5pm"
+ * PERIOD:20150626T150000/20150626T170000
+ * RRULE: FREQ=DAILY; BYDAY=MO, WE, FR
+ * 2."Allow access every Monday, Wednesday & Friday from 3pm to 5pm until
+ * July 3rd, 2015"
+ * PERIOD:20150626T150000/20150626T170000
+ * RRULE: FREQ=DAILY; UNTIL=20150703; BYDAY=MO, WE, FR
+ */
+struct IotvtICalRecur
+{
+ uint16_t freq;
+ IotvtICalDateTime_t until;
+ IotvtICalWeekdayBM_t byDay;
+};
+
+/**
+ * This API is used by policy engine to checks if the
+ * request to access resource is within valid time.
+ *
+ * @param period string representing period.
+ * @param recur string representing recurrence rule
+ *
+ * @return IOTVTICAL_VALID_ACCESS -- if the request is within valid time period
+ * IOTVTICAL_INVALID_ACCESS -- if the request is not within valid time period
+ * IOTVTICAL_INVALID_PARAMETER -- if parameter are invalid
+ * IOTVTICAL_INVALID_PERIOD -- if period string has invalid format
+ * IOTVTICAL_INVALID_RRULE -- if rrule string has invalid format
+ *
+ *Eg: if(IOTVTICAL_VALID_ACCESS == IsRequestWithinValidTime(period, recur))
+ * {
+ * //Access within allowable time
+ * }
+ * else
+ * {
+ * //Access is not within allowable time.
+ * }
+ */
+IotvtICalResult_t IsRequestWithinValidTime(char *period, char *recur);
+
+/**
+ * Parses periodStr and populate struct IotvtICalPeriod_t
+ *
+ * @param periodStr string to be parsed.
+ * @param period IotvtICalPeriod_t struct to be populated.
+ *
+ * @return IOTVTICAL_INVALID_PARAMETER -- if parameter are invalid
+ * IOTVTICAL_INVALID_PERIOD -- if period string has invalid format
+ * IOTVTICAL_INVALID_SUCCESS -- if no error while parsing
+ */
+IotvtICalResult_t ParsePeriod(const char *periodStr, IotvtICalPeriod_t *period);
+
+/**
+ * Parses recurStr and populate struct IotvtICalRecur_t
+ *
+ * @param recurStr string to be parsed.
+ * @param recur IotvtICalPeriod_t struct to be populated.
+ *
+ * @return IOTVTICAL_INVALID_PARAMETER -- if parameter are invalid
+ * IOTVTICAL_INVALID_PERIOD -- if period string has invalid format
+ * IOTVTICAL_INVALID_RRULE -- if rrule string has invalid format
+ */
+IotvtICalResult_t ParseRecur(const char *recurStr, IotvtICalRecur_t *recur);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif //IOTVT_ICALENDAR_H
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 _PBKDF2_H
+#define _PBKDF2_H
+
+#include <stdio.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * The number of iterations desired to derived key.
+ * (Recommened by RFC 2898)
+ */
+#define PBKDF_ITERATIONS 1000
+
+/**
+ * Function to derive cryptographic key from the password. (RFC 2898)
+ * In this implementation, HMAC with SHA2 is considered as a pseudorandom function
+ *
+ * @param[in] passwd is the master password from which a derived key is generated.
+ * @param[in] pLen is the byte size of the passwd.
+ * @param[in] salt is a cryptographic salt.
+ * @param[in] saltlen is the byte size of the salt.
+ * @param[in] iteration is the number of iterations desired.
+ * @param[in] keyLen is the desired byte size of the derived key. (should be the same as
+ * derivedKey size)
+ * @param[out] derivedKey is the generated derived key
+ *
+ * @return 0 on success
+ */
+int DeriveCryptoKeyFromPassword(const unsigned char* passwd, size_t pLen,
+ const uint8_t* salt, const size_t saltLen,
+ const size_t iterations,
+ const size_t keyLen, uint8_t* derivedKey);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // _PBKDF2_H
+
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 PIN_CALLBACK_DEF_H_
+#define PIN_CALLBACK_DEF_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif // __cplusplus
+
+#define OXM_RANDOM_PIN_SIZE 8
+
+/**
+ * Function pointer to print pin code
+ */
+typedef void (*GeneratePinCallback)(char* pinData, size_t pinSize);
+
+/**
+ * Function pointer to input pin code
+ */
+typedef void (*InputPinCallback)(char* pinBuf, size_t bufSize);
+
+/**
+ * Function to setting generate PIN callback from user
+ *
+ * @param[in] pinCB implementation of generate PIN callback
+ */
+void SetGeneratePinCB(GeneratePinCallback pinCB);
+
+/**
+ * Function to setting input PIN callback from user
+ *
+ * @param[in] pinCB implementation of input PIN callback
+ */
+void SetInputPinCB(InputPinCallback pinCB);
+
+/**
+ * Function to generate random PIN.
+ * This function will send generated PIN to user via callback.
+ *
+ * @param[in,out] pinBuffer Buffer to store the generated PIN data.
+ * @param[in] bufferSize Size of buffer
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize);
+
+/**
+ * Function to input PIN callback via input callback
+ *
+ * @param[in,out] pinBuffer Buffer to store the inputed PIN data.
+ * @param[in] bufferSize Size of buffer
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult InputPin(char* pinBuffer, size_t bufferSize);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //PIN_CALLBACK_DEF_H_
#define SUBJECT_NOT_FOUND_DEF (1 << 3)
#define RESOURCE_NOT_FOUND_DEF (1 << 4)
#define POLICY_ENGINE_ERROR_DEF (1 << 5)
+#define INVALID_PERIOD_DEF (1 << 6)
#define REASON_MASK_DEF (INSUFFICIENT_PERMISSION_DEF | \
+ INVALID_PERIOD_DEF | \
SUBJECT_NOT_FOUND_DEF | \
RESOURCE_NOT_FOUND_DEF | \
POLICY_ENGINE_ERROR_DEF)
{
ACCESS_GRANTED = ACCESS_GRANTED_DEF,
ACCESS_DENIED = ACCESS_DENIED_DEF,
+ ACCESS_DENIED_INVALID_PERIOD = ACCESS_DENIED_DEF
+ | INVALID_PERIOD_DEF,
ACCESS_DENIED_INSUFFICIENT_PERMISSION = ACCESS_DENIED_DEF
| INSUFFICIENT_PERMISSION_DEF,
ACCESS_DENIED_SUBJECT_NOT_FOUND = ACCESS_DENIED_DEF
typedef struct OicSecCred OicSecCred_t;
/**
- * @brief /oic/sec/credtype (Credential Type) data type.
- * Derived from OIC Security Spec /oic/sec/cred; see Spec for details.
- * 0: no security mode
- * 1: symmetric pair-wise key
- * 2: symmetric group key
- * 4: asymmetric key
- * 8: signed asymmetric key (aka certificate)
- * 16: PIN /password
- */
-typedef uint16_t OicSecCredType_t;
-
-/**
* Aid for assigning/testing vals with OicSecCredType_t.
* Example:
* OicSecCredType_t ct = PIN_PASSWORD | ASYMMETRIC_KEY;
ASYMMETRIC_KEY = (0x1 << 2),
SIGNED_ASYMMETRIC_KEY = (0x1 << 3),
PIN_PASSWORD = (0x1 << 4),
+ ASYMMETRIC_ENCRYPTION_KEY = (0x1 << 5),
} OSCTBitmask_t;
+/**
+ * @brief /oic/sec/credtype (Credential Type) data type.
+ * Derived from OIC Security Spec /oic/sec/cred; see Spec for details.
+ * 0: no security mode
+ * 1: symmetric pair-wise key
+ * 2: symmetric group key
+ * 4: asymmetric key
+ * 8: signed asymmetric key (aka certificate)
+ * 16: PIN /password
+ */
+typedef OSCTBitmask_t OicSecCredType_t;
+
typedef struct OicSecDoxm OicSecDoxm_t;
typedef enum OicSecDpm
SINGLE_SERVICE_CLIENT_DRIVEN = 0x3,
} OicSecDpom_t;
+typedef enum OicSecSvcType
+{
+ SERVICE_UNKNOWN = 0x0,
+ ACCESS_MGMT_SERVICE = 0x1, //urn:oic.sec.ams
+} OicSecSvcType_t;
+
+
//TODO: Need more clarification on deviceIDFormat field type.
#if 0
typedef enum
OIC_MODE_SWITCH = 0x1,
OIC_RANDOM_DEVICE_PIN = 0x2,
OIC_PRE_PROVISIONED_DEVICE_PIN = 0x3,
- OIC_PRE_PROVISION_STRONG_CREDENTIAL = 0x4
+ OIC_PRE_PROVISION_STRONG_CREDENTIAL = 0x4,
+ OIC_OXM_COUNT
}OicSecOxm_t;
typedef struct OicSecJwk OicSecJwk_t;
size_t resourcesLen; // the number of elts in Resources
char **resources; // 1:R:M:Y:String
uint16_t permission; // 2:R:S:Y:UINT16
- size_t periodsLen; // the number of elts in Periods
- char **periods; // 3:R:M*:N:String (<--M*; see Spec)
- char *recurrences; // 5:R:M:N:String
+ size_t prdRecrLen; // the number of elts in Periods
+ char **periods; // 3:R:M*:N:String (<--M*; see Spec)
+ char **recurrences; // 5:R:M:N:String
size_t ownersLen; // the number of elts in Owners
OicUuid_t *owners; // 8:R:M:Y:oic.uuid
// NOTE: we are using UUID for Owners instead of Svc type for mid-April
size_t resourcesLen; // the number of elts in Resources
char **resources; // 0:R:M:Y:String
size_t amssLen; // the number of elts in Amss
- OicSecSvc_t *amss; // 1:R:M:Y:acl
+ OicUuid_t *amss; // 1:R:M:Y:acl
size_t ownersLen; // the number of elts in Owners
OicUuid_t *owners; // 2:R:M:Y:oic.uuid
// NOTE: we are using UUID for Owners instead of Svc type for mid-April
// SRM version only; this will change to Svc type for full implementation.
//TODO change Owners type to oic.sec.svc
//OicSecSvc_t *Owners; // 2:R:M:Y:oic.sec.svc
+ OicSecAmacl_t *next;
};
/**
OicSecOxm_t *oxm; // 1:R:M:N:UINT16
size_t oxmLen; // the number of elts in Oxm
OicSecOxm_t oxmSel; // 2:R/W:S:Y:UINT16
- bool owned; // 3:R:S:Y:Boolean
+ OicSecCredType_t sct; // 3:R:S:Y:oic.sec.credtype
+ bool owned; // 4:R:S:Y:Boolean
//TODO: Need more clarification on deviceIDFormat field type.
- //OicSecDvcIdFrmt_t deviceIDFormat; // 4:R:S:Y:UINT8
- OicUuid_t deviceID; // 5:R:S:Y:oic.uuid
- OicUuid_t owner; // 6:R:S:Y:oic.uuid
+ //OicSecDvcIdFrmt_t deviceIDFormat; // 5:R:S:Y:UINT8
+ OicUuid_t deviceID; // 6:R:S:Y:oic.uuid
+ OicUuid_t owner; // 7:R:S:Y:oic.uuid
// NOTE: we are using UUID for Owner instead of Svc type for mid-April
// SRM version only; this will change to Svc type for full implementation.
- //OicSecSvc_t Owner; // 5:R:S:Y:oic.sec.svc
+ //OicSecSvc_t devOwner; // 7:R:S:Y:oic.sec.svc
+ //OicSecSvc_t rOwner; // 8:R:S:Y:oic.sec.svc
//TODO change Owner type to oic.sec.svc
};
struct OicSecSvc
{
// <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
- //TODO fill in from OIC Security Spec
+ OicUuid_t svcdid; //0:R:S:Y:oic.uuid
+ OicSecSvcType_t svct; //1:R:M:Y:OIC Service Type
+ size_t ownersLen; //2:the number of elts in Owners
+ OicUuid_t *owners; //3:R:M:Y:oic.uuid
+ OicSecSvc_t *next;
};
#ifdef __cplusplus
#define IOTVT_SRM_UTILITY_H
#include "ocstack.h"
+#include "cJSON.h"
+#include "securevirtualresourcetypes.h"
#ifdef __cplusplus
extern "C"
{
* @note Invoking function must define "exit:" label for goto functionality to work correctly.
*
*/
-#define VERIFY_SUCCESS(tag, op, logLevel) { if (!(op)) \
- {OC_LOG((logLevel), tag, PCF(#op " failed!!")); goto exit;} }
+#define VERIFY_SUCCESS(tag, op, logLevel) do{ if (!(op)) \
+ {OC_LOG((logLevel), tag, #op " failed!!"); goto exit; } }while(0)
/**
* @def VERIFY_NON_NULL
* @note Invoking function must define "exit:" label for goto functionality to work correctly.
*
*/
-#define VERIFY_NON_NULL(tag, arg, logLevel) { if (NULL == (arg)) \
- { OC_LOG((logLevel), tag, PCF(#arg " is NULL")); goto exit; } }
+#define VERIFY_NON_NULL(tag, arg, logLevel) do{ if (NULL == (arg)) \
+ { OC_LOG((logLevel), tag, #arg " is NULL"); goto exit; } }while(0)
/**
* This method initializes the OicParseQueryIter_t struct
*/
OicParseQueryIter_t * GetNextQuery(OicParseQueryIter_t * parseIter);
+
+
+/**
+ * This method acts as a helper funtion for JSON unmarshalling by various SVR's.
+ *
+ * @param jsonRoot - root JSON node containing the OicUuid array
+ * @param arrayItem - name of the JSON OicUuid array item
+ * @param numUuids - pointer to the number of OicUuid's available in JSON array
+ * @param uuids - pointer to the array of OicUuid's
+ *
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+OCStackResult AddUuidArray(cJSON* jsonRoot, const char* arrayItem,
+ size_t *numUuids, OicUuid_t** uuids );
+
#ifdef __cplusplus
}
#endif // __cplusplus
--- /dev/null
+Quick guide : How to make provisioning tool and servers.
+
+1. Provisioning Tool.
+
+ 1-1. Callback function registration
+ Register the callback functions of ownership transfer method(OxM) using OTMSetOwnershipTransferCallbackData API.
+ You can use default OxM callback implementation located in resource/csdk/security/provisioning/include/oxm.
+
+ [Sample code for just-works OxM]
+ OTMCallbackData_t justWorksCBData = {};
+ justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+ justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+ justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+ justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+ OTMSetOwnershipTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData);
+
+ 1-2. Find un-owned devices using OCDiscoverUnownedDevices API.
+ OCDiscoverUnownedDevices will fill the unowned device list in second parameter.
+
+ [Sample code for unowned device discovery]
+ OCProvisionDev_t* pDeviceList = NULL;
+ OCStackResult res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
+ if(OC_STACK_OK != res)
+ {
+ //error
+ }
+
+ NOTE : We also provide OCDiscoverOwnedDevices API to find owned devices.
+
+ 1-3. Performing ownership transfer
+ We provided OCDoOwnershipTransfer API to perform ownership transfer.
+ In order to perform ownership transfer, unowned device list is required generated by OCDiscoverUnownedDevices API.
+ OCDoOwnershipTransfer will require the result callback as 3rd paramter.
+ This callback function will be invoked when ownership transfer is finished.
+ You can check result of ownership transfer for each devices as array of OCProvisionResult_t.
+
+ 1-4. Find owned devices using OCDiscoverOwendDevices API.
+ 1-5. Provision credential between two owned devices.
+ If you have owned devices,
+ You can send a credential to two owned devices using OCProvisionPairwiseDevices.
+ You can also send ACL in this process.
+
+ 1-6. Free memory.
+ We provide ODDeleteDiscoverdDevices API to free list of OCProvisionDev_t.
+ Please delete your device list before the exit your application.
+
+
+2. Server.
+ The samples are resource/csdk/security/provisioning/sample
+ 2-1. Just-works OxM.
+ If you use just-works OxM to server.
+ You don't need any modification for your server.
+
Import('env')
provisioning_env = env.Clone()
+root_dir = './../../../../'
######################################################################
# Build flags
'../../ocmalloc/include',
'include',
'include/internal',
+ 'include/oxm',
'../../resource/csdk/security/include',
'../../../../extlibs/cjson/',
- '../../../../../extlibs/tinydtlsra/',
'../../connectivity/inc',
'../../connectivity/external/inc',
'../../connectivity/common/inc',
+ '../../connectivity/lib/libcoap-4.1.1',
'../../connectivity/api',
'../include',
- '../include/internal'
+ '../include/internal',
+ '../../../../extlibs/sqlite3'
])
target_os = env.get('TARGET_OS')
provisioning_env.AppendUnique(CFLAGS = ['-D__WITH_DTLS__'])
# Source files and Targets
######################################################################
provisioning_src = [
- 'src/provisioningmanager.c',
- 'src/credentialgenerator.c'
- ]
-provisioningserver = provisioning_env.StaticLibrary('ocspapi', provisioning_src)
+ 'src/pmutility.c',
+ 'src/credentialgenerator.c',
+ 'src/ownershiptransfermanager.c',
+ 'src/secureresourceprovider.c',
+ 'src/ocprovisioningmanager.c',
+ 'src/oxmjustworks.c',
+ 'src/oxmrandompin.c',
+ 'src/provisioningdatabasemanager.c',
+ root_dir+'/extlibs/sqlite3/sqlite3.c' ]
+provisioningserver = provisioning_env.StaticLibrary('ocpmapi', provisioning_src)
-provisioning_env.InstallTarget(provisioningserver, 'libocspapi')
-provisioning_env.UserInstallTargetLib(provisioningserver, 'libocspapi')
+provisioning_env.InstallTarget(provisioningserver, 'libocpmapi')
+provisioning_env.UserInstallTargetLib(provisioningserver, 'libocpmapi')
if target_os in ['linux']:
SConscript('sample/SConscript')
*
* *****************************************************************/
-#ifndef SP_CREDENTIAL_GENERATOR_H
-#define SP_CREDENTIAL_GENERATOR_H
+#ifndef PM_CREDENTIAL_GENERATOR_H
+#define PM_CREDENTIAL_GENERATOR_H
#include "ocstack.h"
#include "securevirtualresourcetypes.h"
-#include "provisioningmanager.h"
/**
* Function to generate credentials according to the type.
*
* @param[in] type Type of credential.
+ * @param[in] keysize size of key.
* @param[in] ptDeviceId Device ID of provisioning tool.
* @param[in] firstDeviceId DeviceID of the first device.
* @param[in] secondDeviceId DeviceID of the second device.
* @param[out] firstCred Generated credential for first device.
* @param[out] secondCred Generated credential for second device.
- * @return SP_SUCCESS on success
+ * @return OC_STACK_OK on success
*/
-SPResult SPGeneratePairWiseCredentials(OicSecCredType_t type, const OicUuid_t *ptDeviceId,
+OCStackResult PMGeneratePairWiseCredentials(OicSecCredType_t type, size_t keySize,
+ const OicUuid_t *ptDeviceId,
const OicUuid_t *firstDeviceId,
const OicUuid_t *secondDeviceId,
OicSecCred_t **firstCred,
#ifdef __cplusplus
}
#endif
-#endif //SP_CREDENTIAL_GENERATOR_H
+#endif //PM_CREDENTIAL_GENERATOR_H
--- /dev/null
+/* *****************************************************************\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
+#ifndef OTM_OWNERSHIPTRANSFERMANAGER_H_\r
+#define OTM_OWNERSHIPTRANSFERMANAGER_H_\r
+\r
+#include "pmtypes.h"\r
+#include "ocstack.h"\r
+#include "octypes.h"\r
+#include "securevirtualresourcetypes.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif // __cplusplus\r
+\r
+#define OXM_STRING_MAX_LENGTH 32\r
+\r
+\r
+/**\r
+ * Context for ownership transfer(OT)\r
+ */\r
+typedef struct OTMContext{\r
+ void* userCtx; /**< Context for user.*/\r
+ OCProvisionDev_t* selectedDeviceInfo; /**< Selected device info for OT. */\r
+ OicUuid_t subIdForPinOxm; /**< Subject Id which uses PIN based OTM. */\r
+ OCProvisionResultCB ctxResultCallback; /**< Function pointer to store result callback. */\r
+ OCProvisionResult_t* ctxResultArray; /**< Result array having result of all device. */\r
+ size_t ctxResultArraySize; /**< No of elements in result array. */\r
+ bool ctxHasError; /**< Does OT process have any error. */\r
+}OTMContext_t;\r
+\r
+/**\r
+ * Do ownership transfer for the unowned devices.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback\r
+ * @param[in] selectedDeviceList linked list of ownership transfer candidate devices.\r
+ * @param[in] resultCB Result callback function to be invoked when ownership transfer finished.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OTMDoOwnershipTransfer(void* ctx,\r
+ OCProvisionDev_t* selectedDeviceList, OCProvisionResultCB resultCB);\r
+\r
+/*\r
+ *Callback for load secret for temporal secure session\r
+ *\r
+ * e.g) in case of PIN based, input the pin through this callback\r
+ * in case of X.509 based, input the certificate through this callback\r
+ */\r
+typedef OCStackResult (*OTMLoadSecret)(OTMContext_t* otmCtx);\r
+\r
+\r
+/*\r
+ * Callback for create secure channel using secret inputed from OTMLoadSecret callback\r
+ */\r
+typedef OCStackResult (*OTMCreateSecureSession)(OTMContext_t* otmCtx);\r
+\r
+/*\r
+ * Callback for creating CoAP payload.\r
+ */\r
+typedef char* (*OTMCreatePayloadCallback)(OTMContext_t* otmCtx);\r
+\r
+/**\r
+ * Required callback for performing ownership transfer\r
+ */\r
+typedef struct OTMCallbackData{\r
+ OTMLoadSecret loadSecretCB;\r
+ OTMCreateSecureSession createSecureSessionCB;\r
+ OTMCreatePayloadCallback createSelectOxmPayloadCB;\r
+ OTMCreatePayloadCallback createOwnerTransferPayloadCB;\r
+}OTMCallbackData_t;\r
+\r
+/**\r
+ * Set the callbacks for ownership transfer\r
+ *\r
+ * @param[in] oxm Ownership transfer method\r
+ * @param[in] callbackData the implementation of the ownership transfer function for each step.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t* callbackData);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+#endif //OTM_OWNERSHIPTRANSFERMANAGER_H_\r
--- /dev/null
+/* *****************************************************************
+ *
+ * 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_DATABASE_MANAGER_H
+#define PROVISIONING_DATABASE_MANAGER_H
+#include "securevirtualresourcetypes.h"
+#include "ocstack.h"
+#include "pmtypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * This method is used by provisioning manager to open provisioning database.
+ *
+ * @param[in] dbPath file path of the sqlite3 db
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMInit(const char* dbPath);
+
+/**
+ * This method is used by provisioning manager to check duplication of device's Device ID with
+ * provisioning database.
+ *
+ * @param[in] uuidOfDevice information about the target device's uuid.
+ *
+ * @return false when non-duplication and true when duplication or uuidOfDevicea is NULL .
+ */
+bool PDMIsDuplicateDevice(const OicUuid_t* uuidOfDevice);
+
+/**
+ * This method is used by provisioning manager to add owned device's Device ID.
+ *
+ * @param[in] uuidOfDevice information about the owned device's uuid.
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMAddDevice(const OicUuid_t* uuidOfDevice);
+
+/**
+ * This method is used by provisioning manager to update linked status of owned devices.
+ *
+ * @param[in] uuidOfDevice1 DeviceID which is going to be linked with uuid of device 2.
+ * @param[in] uuidOfDevice2 DeviceID which is going to be linked with uuid of device 1.
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMLinkDevices(const OicUuid_t *uuidOfDevice1, const OicUuid_t *uuidOfDevice2);
+
+/**
+ * This method is used by provisioning manager to unlink pairwise devices.
+ *
+ * @param[in] uuidOfDevice1 DeviceID which is going to be unlinked with uuid of device 2.
+ * @param[in] uuidOfDevice2 DeviceID which is going to be unlinked with uuid of device 1.
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMUnlinkDevices(const OicUuid_t *uuidOfDevice1, const OicUuid_t *uuidOfDevice2);
+
+/**
+ * This method is used by provisioning manager to delete owned device's Device ID.
+ *
+ * @param[in] uuidOfDevice information about the owned device's uuid to be deleted.
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMDeleteDevice(const OicUuid_t *uuidOfDevice);
+
+/**
+ * This method is used by provisioning manager to get owned devices' Device IDs.
+ *
+ * @param[out] uuidList information about the list of owned devices' uuids.
+ * @param[out] numOfDevices total number of owned devices.
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMGetOwnedDevices(OCUuidList_t** uuidList, size_t* numOfDevices);
+
+/**
+ * This method is used by provisioning manager to get linked devices' IDs.
+ *
+ * @param[in] uuidOfDevice a target device's uuid.
+ * @param[out] uuidList information about the list of linked devices' uuids.
+ * @param[out] numOfDevices total number of linked devices.
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMGetLinkedDevices(const OicUuid_t* uuidOfDevice, OCUuidList_t** uuidList,
+ size_t* numOfDevices);
+
+/**
+ * This method is used by provisioning manager to update linked status as stale.
+ *
+ * @param[in] uuidOfDevice1 first id of stale link.
+ * @param[in] uuidOfDevice2 other id for stale link.
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMSetLinkStale(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2);
+
+/**
+ * This method is used by provisioning manager to get stale devices.
+ *
+ * @note in case of sqllite, the caller should set NULL for parameters.
+ *
+ * @param[out] staleDevices information about the list of "To be Removed" devices' uuid.
+ * @param[out] numOfDevices total number of devices to be removed.
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMGetToBeUnlinkedDevices(OCPairList_t** staleDevList, size_t* numOfDevices);
+
+/**
+ * This method is used by provisioning manager to close provisioning database.
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult PDMClose();
+
+/**
+ * This method is used by provisioning manager free memory allocated to OCUuidList_t lists.
+ *
+ * @param[in] ptr start pointer of link list.
+ */
+void PDMDestoryOicUuidLinkList(OCUuidList_t* ptr);
+
+/**
+ * This method is used by provisioning manager free memory allocated to Stalelist.
+ *
+ * @param[in] ptr start pointer of link list.
+ *
+ */
+void PDMDestoryStaleLinkList(OCPairList_t* ptr);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //PROVISIONING_DATABASE_MANAGER_H
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 SRP_SECURERESOURCEPROVIDER_H
+#define SRP_SECURERESOURCEPROVIDER_H
+
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "pmtypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * API to send ACL information to resource.
+ *
+ * @param[in] selectedDeviceInfo Selected target device.
+ * @param[in] acl ACL to provision.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * provisioning request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
+ OicSecAcl_t *acl, OCProvisionResultCB resultCallback);
+
+/**
+ * API to provision credential to devices.
+ *
+ * @param[in] type Type of credentials to be provisioned to the device.
+ * @param[in] pDev1 Pointer to PMOwnedDeviceInfo_t instance,respresenting resource to be provsioned.
+ @param[in] pDev2 Pointer to PMOwnedDeviceInfo_t instance,respresenting resource to be provsioned.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * provisioning request recieves a response from first resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult SRPProvisionCredentials(void *ctx,OicSecCredType_t type, size_t keySize,
+ const OCProvisionDev_t *pDev1,
+ const OCProvisionDev_t *pDev2,
+ OCProvisionResultCB resultCallback);
+
+/**
+ * Function to unlink devices.
+ * This function will remove the credential & relationship between the two devices.
+ *
+ * @param[in] ctx Application context would be returned in result callback
+ * @param[in] pTargetDev1 first device information to be unlinked.
+ * @param[in] pTargetDev2 second device information to be unlinked.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * device unlink is finished.
+ * when there is an error, this user callback is called immediately.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult SRPUnlinkDevices(void* ctx,
+ const OCProvisionDev_t* pTargetDev1,
+ const OCProvisionDev_t* pTargetDev2,
+ OCProvisionResultCB resultCallback);
+
+/*
+ * Function to device revocation.
+ * This function will remove credential of target device from all devices in subnet.
+ *
+ * @param[in] ctx Application context would be returned in result callback
+ * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
+ * @param[in] pTargetDev Device information to be revoked.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * credential revocation is finished.
+ * when there is an error, this user callback is called immediately.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ * If OC_STACK_OK is returned, the caller of this API should wait for callback.
+ * OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
+ */
+OCStackResult SRPRemoveDevice(void* ctx,
+ unsigned short waitTimeForOwnedDeviceDiscovery,
+ const OCProvisionDev_t* pTargetDev,
+ OCProvisionResultCB resultCallback);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //SRP_SECURERESOURCEPROVIDER_H
--- /dev/null
+/* *****************************************************************\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
+#ifndef OCPROVISIONINGMANAGER_H_\r
+#define OCPROVISIONINGMANAGER_H_\r
+\r
+#include "octypes.h"\r
+#include "pmtypes.h"\r
+#include "ownershiptransfermanager.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif // __cplusplus\r
+\r
+/**\r
+ * The function is responsible for initializaton of the provisioning manager. It will load\r
+ * provisioning database which have owned device's list and their linked status.\r
+ * TODO: In addition, if there is a device(s) which has not up-to-date credentials, this function will\r
+ * automatically try to update the deivce(s).\r
+ *\r
+ * @param[in] dbPath file path of the sqlite3 db\r
+ *\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCInitPM(const char* dbPath);\r
+\r
+/**\r
+ * The function is responsible for discovery of device is current subnet. It will list\r
+ * all the device in subnet which are not yet owned. Please call OCInit with OC_CLIENT_SERVER as\r
+ * OCMode.\r
+ *\r
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from\r
+ * client before returning the list of devices.\r
+ * @param[out] ppList List of candidate devices to be provisioned\r
+ * @return OTM_SUCCESS in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCDiscoverUnownedDevices(unsigned short waittime, OCProvisionDev_t **ppList);\r
+\r
+/**\r
+ * Do ownership transfer for un-owned device.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback\r
+ * @param[in] targetDevices List of devices to perform ownership transfer.\r
+ * @param[in] resultCallback Result callback function to be invoked when ownership transfer finished.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCDoOwnershipTransfer(void* ctx,\r
+ OCProvisionDev_t *targetDevices,\r
+ OCProvisionResultCB resultCallback);\r
+\r
+/**\r
+ * API to register for particular OxM.\r
+ *\r
+ * @param[in] Ownership transfer method.\r
+ * @param[in] Implementation of callback functions for owership transfer.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCSetOwnerTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t* callbackData);\r
+\r
+/**\r
+ * The function is responsible for discovery of owned device is current subnet. It will list\r
+ * all the device in subnet which are owned by calling provisioning client.\r
+ *\r
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from\r
+ * client before returning the list of devices.\r
+ * @param[out] ppList List of device owned by provisioning tool.\r
+ * @return OTM_SUCCESS in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList);\r
+\r
+/**\r
+ * API to provision credentials between two devices and ACLs for the devices who act as a server.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback.\r
+ * @param[in] type Type of credentials to be provisioned to the device.\r
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting device to be provisioned.\r
+ * @param[in] acl ACL for device 1. If this is not required set NULL.\r
+ * @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting device to be provisioned.\r
+ * @param[in] acl ACL for device 2. If this is not required set NULL.\r
+ * @param[in] resultCallback callback provided by API user, callback will be called when\r
+ * provisioning request recieves a response from first resource server.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCProvisionPairwiseDevices(void* ctx, OicSecCredType_t type, size_t keySize,\r
+ const OCProvisionDev_t *pDev1, OicSecAcl_t *pDev1Acl,\r
+ const OCProvisionDev_t *pDev2, OicSecAcl_t *pDev2Acl,\r
+ OCProvisionResultCB resultCallback);\r
+\r
+/**\r
+ * API to send ACL information to device.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback.\r
+ * @param[in] selectedDeviceInfo Selected target device.\r
+ * @param[in] acl ACL to provision.\r
+ * @param[in] resultCallback callback provided by API user, callback will be called when provisioning\r
+ request recieves a response from resource server.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecAcl_t *acl,\r
+ OCProvisionResultCB resultCallback);\r
+\r
+/**\r
+ * API to provision credential to devices.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback.\r
+ * @param[in] type Type of credentials to be provisioned to the device.\r
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.\r
+ @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.\r
+ * @param[in] resultCallback callback provided by API user, callback will be called when\r
+ * provisioning request recieves a response from first resource server.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,\r
+ const OCProvisionDev_t *pDev1,\r
+ const OCProvisionDev_t *pDev2,\r
+ OCProvisionResultCB resultCallback);\r
+\r
+/**\r
+ * Function to unlink devices.\r
+ * This function will remove the credential & relasionship between the two devices.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback\r
+ * @param[in] pTargetDev1 fitst device information to be unlinked.\r
+ * @param[in] pTargetDev2 second device information to be unlinked.\r
+ * @param[in] resultCallback callback provided by API user, callback will be called when\r
+ * device unlink is finished.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCUnlinkDevices(void* ctx,\r
+ const OCProvisionDev_t* pTargetDev1,\r
+ const OCProvisionDev_t* pTargetDev2,\r
+ OCProvisionResultCB resultCallback);\r
+\r
+/**\r
+ * Function for device revocation\r
+ * This function will remove credential of target device from all devices in subnet.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback\r
+ * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)\r
+ * @param[in] pTargetDev Device information to be revoked.\r
+ * @param[in] resultCallback callback provided by API user, callback will be called when\r
+ * credential revocation is finished.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ * if OC_STACK_OK is returned, the caller of this API should wait for callback.\r
+ * OC_STACK_CONTINUE means operation is success but no need to wait for callback.\r
+ */\r
+OCStackResult OCRemoveDevice(void* ctx,\r
+ unsigned short waitTimeForOwnedDeviceDiscovery,\r
+ const OCProvisionDev_t* pTargetDev,\r
+ OCProvisionResultCB resultCallback);\r
+/**
+ * API to get status of all the devices in current subnet. The status include endpoint information\r
+ * and doxm information which can be extracted duing owned and unowned discovery. Along with this\r
+ * information. The API will provide information about devices' status\r
+ * Device can have following states\r
+ * - ON/OFF: Device is switched on or off.\r
+ *\r
+ * NOTE: Caller need to call OCDeleteDiscoveredDevices to delete memory allocated by this API for out\r
+ * variables pOwnedDevList and pUnownedDevList.\r
+ *\r
+ * @param[in] waitime Wait time for the API. The wait time will be divided by 2, and half of wait time\r
+ * will be used for unowned discovery and remaining half for owned discovery.\r
+ * @param[out] pOwnedDevList list of owned devices.\r
+ * @param[out] pUnownedDevList list of unowned devices.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCGetDevInfoFromNetwork(unsigned short waittime,\r
+ OCProvisionDev_t** pOwnedDevList,\r
+ OCProvisionDev_t** pUnownedDevList);\r
+/**\r
+ * This method is used to get linked devices' IDs.\r
+ *\r
+ * @param[in] uuidOfDevice a target device's uuid.\r
+ * @param[out] uuidList information about the list of linked devices' uuids.\r
+ * @param[out] numOfDevices total number of linked devices.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCGetLinkedStatus(const OicUuid_t* uuidOfDevice,\r
+ OCUuidList_t** uuidList,\r
+ size_t* numOfDevices);\r
+\r
+/**\r
+ * API to delete memory allocated to linked list created by OCDiscover_XXX_Devices API.\r
+ *\r
+ * @param[in] pList Pointer to OCProvisionDev_t which should be deleted.\r
+ */\r
+void OCDeleteDiscoveredDevices(OCProvisionDev_t *pList);\r
+\r
+/**\r
+ * API to delete memory allocated to OicUuid_t list.\r
+ *\r
+ * @param[in] pList Pointer to OicUuid_t list which should be deleted.\r
+ */\r
+void OCDeleteUuidList(OCUuidList_t* pList);\r
+\r
+/**\r
+ * This function deletes ACL data.\r
+ *\r
+ * @param pAcl Pointer to OicSecAcl_t structure.\r
+ */\r
+void OCDeleteACLList(OicSecAcl_t* pAcl);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif // __cplusplus\r
+\r
+#endif /* OCPROVISIONINGMANAGER_H_ */\r
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 OXM_JUST_WORKS_H_
+#define OXM_JUST_WORKS_H_
+
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "ownershiptransfermanager.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+//
+//Declaration of default callback functions for just works OxM.
+//
+
+/**
+ * In case of just works OxM, no need to implement.
+ */
+OCStackResult LoadSecretJustWorksCallback(OTMContext_t* UNUSED_PARAM);
+
+/**
+ * To establish a secure channel with anonymous cipher suite
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult CreateSecureSessionJustWorksCallback(OTMContext_t* otmCtx);
+
+/**
+ * Generate payload for select OxM request.
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return DOXM JSON payload including the selected OxM.
+ * NOTE : Returned memory should be deallocated by caller.
+ */
+char* CreateJustWorksSelectOxmPayload(OTMContext_t* otmCtx);
+
+/**
+ * Generate payload for owner transfer request.
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return DOXM JSON payload including the owner information.
+ * NOTE : Returned memory should be deallocated by caller.
+ */
+char* CreateJustWorksOwnerTransferPayload(OTMContext_t* otmCtx);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //OXM_JUST_WORKS_H_
\ No newline at end of file
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 OXM_RANDOM_PIN_H_
+#define OXM_RANDOM_PIN_H_
+
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "ownershiptransfermanager.h"
+#include "pmtypes.h"
+#include "pinoxmcommon.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define OXM_PBKDF2_ITERATIONS 1000
+
+/**
+ * Callback implementation to input the PIN code from user.
+ *
+ * @otmCtx Context of OTM, It includes current device infomation.
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult InputPinCodeCallback(OTMContext_t* otmCtx);
+
+/**
+ * Callback implemenration to establish a secure channel with PSK cipher suite
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult CreateSecureSessionRandomPinCallbak(OTMContext_t* otmCtx);
+
+/**
+ * Generate payload for select OxM request.
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return DOXM JSON payload including the selected OxM.
+ * NOTE : Returned memory should be deallocated by caller.
+ */
+char* CreatePinBasedSelectOxmPayload(OTMContext_t* otmCtx);
+
+/**
+ * Generate payload for owner transfer request.
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return DOXM JSON payload including the owner information.
+ * NOTE : Returned memory should be deallocated by caller.
+ */
+char* CreatePinBasedOwnerTransferPayload(OTMContext_t* otmCtx);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //OXM_RANDOM_PIN_H_
\ No newline at end of file
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 OC_PROVISIONING_TYPES_H
+#define OC_PROVISIONING_TYPES_H
+
+#include <stdbool.h>
+#include "securevirtualresourcetypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Node to construct list of UUID pair list.
+ */
+typedef struct OCPairList OCPairList_t;
+struct OCPairList
+{
+ OicUuid_t dev;
+ OicUuid_t dev2;
+ OCPairList_t *next;
+};
+
+/**
+ * Node to construct UUID linked list.
+ */
+typedef struct OCUuidList OCUuidList_t;
+struct OCUuidList
+{
+ OicUuid_t dev;
+ OCUuidList_t *next;
+};
+
+/*
+ * Device's power on/off state.
+ */
+typedef enum {
+ DEV_STATUS_ON = (1 << 0),
+ DEV_STATUS_OFF = (1 << 1)
+}DeviceStatus;
+
+/**
+ * Device Information of discoverd unowned/owned device(s) for provisioning.
+ */
+typedef struct OCProvisionDev
+{
+ OCDevAddr endpoint; /**< target address **/
+ OicSecPstat_t *pstat; /**< Pointer to target's pstat resource. **/
+ OicSecDoxm_t *doxm; /**< Pointer to target's doxm resource. **/
+ OCConnectivityType connType; /**< Connectivity type of endpoint */
+ uint16_t securePort; /**< secure port **/
+ DeviceStatus devStatus; /**< status of device **/
+ struct OCProvisionDev *next; /**< Next pointer. **/
+}OCProvisionDev_t;
+
+/**
+ * Result information for each target device.
+ */
+typedef struct OCPMResult{
+ OicUuid_t deviceId;
+ OCStackResult res;
+}OCProvisionResult_t;
+
+/**
+ * Callback function definition of provisioning API
+ *
+ * @param[OUT] ctx - If user set his/her context, it will be returned here.
+ * @param[OUT] nOfRes - total number of results, it depends on using which provisioning API.
+ * @param[OUT] arr - Array of OCPMResult_t, each OCPMResult_t contains result for target Device.
+ * @param[OUT} hasError - If there is no error, it's returned with 'false' but if there is a single
+ * or more error is/are occured during operation, it will be 'true'.
+ */
+typedef void (*OCProvisionResultCB)(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //OC_PROVISIONING_TYPES_H
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 _PM_UTILITY_H_
+#define _PM_UTILITY_H_
+
+#include <stdbool.h>
+#include "ocstack.h"
+#include "pmtypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define DEFAULT_SECURE_PORT 5684
+
+#define COAPS_PREFIX "coaps://"
+#define COAP_PREFIX "coap://"
+#define COAPS_QUERY "coaps://%s:%d%s"
+#define COAP_QUERY "coap://%s:%d%s"
+
+/**
+ * Discover owned/unowned devices in the same IP subnet. .
+ *
+ * @param[in] waittime Timeout in seconds.
+ * @param[in] isOwned bool flag for owned / unowned discovery
+ * @param[in] ppList List of OCProvisionDev_t.
+ *
+ * @return OC_STACK_OK on success otherwise error.
+ */
+OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisionDev_t **ppList);
+
+/**
+ * This function deletes list of provision target devices
+ *
+ * @param[in] pList List of OCProvisionDev_t.
+ */
+void PMDeleteDeviceList(OCProvisionDev_t *pList);
+
+/**
+ * Timeout implementation for secure discovery. When performing secure discovery,
+ * we should wait a certain period of time for getting response of each devices.
+ *
+ * @param[in] waittime Timeout in seconds.
+ * @param[in] waitForStackResponse if true timeout function will call OCProcess while waiting.
+ * @return OC_STACK_OK on success otherwise error.
+ */
+OCStackResult PMTimeout(unsigned short waittime, bool waitForStackResponse);
+
+/**
+ * Function to clone OCProvisionDev_t
+ *
+ * @param[in] src pointer of OCProvisionDev_t to be copied.
+ *
+ * @return copied OCProvisionDev_t on success otherwise NULL.
+ */
+OCProvisionDev_t* PMCloneOCProvisionDev(const OCProvisionDev_t* src);
+
+
+/**
+ * Function to generate qurey for coap/coaps request.
+ *
+ * @param[in] isSeucre Choose whether to encrypt the payload.
+ * @param[in] address Network address of remote device
+ * @param[in] port Port number
+ * @param[in] connType Connectivity type of remote device
+ * @param[in,out] buffer A buffer to save the query.
+ * @param[in] bufferSize Size of buffer
+ * @param[in] uri The resource URI
+ *
+ * @return true on success
+ */
+bool PMGenerateQuery(bool isSecure,
+ const char* address, uint16_t port,
+ OCConnectivityType connType,
+ char* buffer, size_t bufferSize, const char* uri);
+
+/**
+ * Function to print OCProvisionDev_t for debug purpose.
+ *
+ * @param[in] pDev Pointer to OCProvisionDev_t. It's information will be printed by OC_LOG_XX
+ *
+ */
+void PMPrintOCProvisionDev(const OCProvisionDev_t* pDev);
+
+/** Function to delete matched UUID from the UUIDlist.
+ *
+ * @param[in] pUuidList a pointer to UUID list.
+ * @param[in] targetId a pointer to UUID to be deleted in the list.
+ *
+ * @return true when deletion is happened, false when no deletion is occured. In case either of
+ * two arguments is null it will return false.
+ */
+bool PMDeleteFromUUIDList(OCUuidList_t *pUuidList, OicUuid_t *targetId);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //_PM_UTILITY_H_
+++ /dev/null
-/* *****************************************************************
- *
- * 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 SP_PROVISION_API_H
-#define SP_PROVISION_API_H
-
-#include "ocstack.h"
-#include "securevirtualresourcetypes.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * Error Code.
- */
-typedef enum
-{
- SP_RESULT_SUCCESS = 0,
- SP_RESULT_INVALID_PARAM,
- SP_RESULT_MEM_ALLOCATION_FAIL,
- SP_RESULT_INTERNAL_ERROR,
- SP_RESULT_TIMEOUT,
- SP_RESULT_CONN_INVALID_PARAM,
- SP_RESULT_CONN_ADAPTER_NOT_ENABLED,
- SP_RESULT_CONN_SERVER_STARTED_ALREADY,
- SP_RESULT_CONN_SERVER_NOT_STARTED,
- SP_RESULT_CONN_DESTINATION_NOT_REACHABLE,
- SP_RESULT_CONN_SOCKET_OPERATION_FAILED,
- SP_RESULT_CONN_SEND_FAILED,
- SP_RESULT_CONN_RECEIVE_FAILED,
- SP_RESULT_CONN_MEMORY_ALLOC_FAILED,
- SP_RESULT_CONN_REQUEST_TIMEOUT,
- SP_RESULT_CONN_DESTINATION_DISCONNECTED,
- SP_RESULT_CONN_STATUS_FAILED,
- SP_RESULT_CONN_NOT_SUPPORTED
-
-} SPResult;
-
-typedef struct SPTargetDeviceInfo SPTargetDeviceInfo_t;
-typedef struct SPDevInfo SPDevInfo_t;
-
-/**
- * Device Info structure.
- */
-struct SPTargetDeviceInfo
-{
- OCDevAddr endpoint; /**< target address **/
- OicSecPstat_t *pstat; /**< Pointer to target's pstat resource. **/
- OicSecDoxm_t *doxm; /**< Pointer to target's doxm resource. **/
- uint16_t securePort; /**< Secure port **/
- SPTargetDeviceInfo_t *next; /**< Next pointer. **/
-};
-
-/**
- * Owned target device info
- */
-struct SPDevInfo
-{
- OCDevAddr endpoint; /**< target address **/
- OicUuid_t deviceId; /**< Device ID. **/
- SPDevInfo_t *next; /**< Next pointer. **/
-};
-
-/**
- * The function is responsible for discovery of device is current subnet. It will list
- * all the device in subnet which are not yet owned. Please call OCInit with OC_CLIENT_SERVER as
- * OCMode.
- *
- * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
- * client before returning the list of devices.
- * @param[out] list List of provision candidate devices.
- * @return SP_SUCCESS in case of success and other value otherwise.
- */
-SPResult SPProvisioningDiscovery(unsigned short timeout,
- SPTargetDeviceInfo_t **list);
-
-/**
- * The function is reponsible for following activities:
- * - Send post to /oic/sec/doxm resource with selected ownership transfer method
- * - Get pstat resource of target device to enumerate supported operation modes.
- * - Select and let the target device know the selected methods.
- * - Initiate anon handshake and save owner PSK
- * - Update doxm resource of target device with ownership info.
- *
- * @param[in] timeout Timeout value in secs till which call REST request will wait before
- * returning error in case of 0 function will wait till success.
- * @param[in] selectedDeviceInfo Device information.
- * @return SP_SUCCESS in case of success and other value otherwise.
- */
-SPResult SPInitProvisionContext(unsigned short timeout,
- SPTargetDeviceInfo_t *selectedDeviceInfo);
-
-/**
- * Function to send ACL information to resource.
- *
- * @param[in] timeout Timeout value in secs till which call to REST request will wait before
- * returning error in case of 0 function will wait till success.
- * @param[in] selectedDeviceInfo Selected target device.
- * @param[in] acl ACL to provision
- * @return SP_SUCCESS in case of success and other value otherwise.
- */
-SPResult SPProvisionACL(unsigned short timeout, const SPTargetDeviceInfo_t *selectedDeviceInfo,
- OicSecAcl_t *acl);
-
-/**
- * Function to send credential information to list of resources.
- *
- * @param[in] timeout Timeout value in secs till which call to REST request will wait before
- * returning error in case of 0 function will wait till success.
- * @param[in] type Type of credentials to be provisioned to the device.
- * @param[in] pDevList List of devices to be provisioned with the specified credential.
- *
- * @return SP_SUCCESS in case of success and other value otherwise.
- */
-SPResult SPProvisionCredentials(unsigned short timeout, OicSecCredType_t type,
- const SPDevInfo_t *pDevList);
-
-/**
- * Function to confirm the ACL post request to check whether its updated at
- * resource server end properly or not.
- *
- * @param[in] timeout Timeout value in seconds till which call REST request will wait
- * before returning error in case of 0 function will wait till success.
- * @param[in] context Provisioning context
- * @return SP_SUCCESS on success
- */
-SPResult SPFinalizeProvisioning(unsigned short timeout,
- SPTargetDeviceInfo_t *selectedDeviceInfo);
-
-/**
- * Function to end Provisioning session.
- *
- * @return SP_SUCCESS on success
- */
-SPResult SPTerminateProvisioning();
-
-#ifdef __cplusplus
-}
-#endif
-#endif //SP_PROVISION_API_H
'../../../logger/include',
'../../../stack/include',
'../../../security/include',
+ '../../../security/provisioning/include/internal',
'../../../../oc_logger/include',
'../include',
+ '../include/oxm',
'../../include',
'../../../../../extlibs/tinydtls',
'../../../../../extlibs/cjson',
provisioning_env.AppendUnique(CFLAGS = ['-D__WITH_DTLS__','-std=c99'])
provisioning_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread', '-fpermissive'])
provisioning_env.AppendUnique(RPATH = [env.get('BUILD_DIR')])
-provisioning_env.AppendUnique(LIBS = ['-lpthread'])
+provisioning_env.AppendUnique(LIBS = ['-lpthread','-ldl'])
provisioning_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
-provisioning_env.PrependUnique(LIBS = ['ocspapi','oc', 'oc_logger', 'ocsrm','m', 'octbstack', 'connectivity_abstraction', 'coap'])
+provisioning_env.PrependUnique(LIBS = ['ocpmapi','oc', 'oc_logger', 'ocsrm','m', 'octbstack', 'connectivity_abstraction', 'coap'])
if env.get('SECURED') == '1':
provisioning_env.AppendUnique(LIBS = ['tinydtls'])
######################################################################
provisioningclient = provisioning_env.Program('provisioningclient', 'provisioningclient.c')
+sampleserver_justworks = provisioning_env.Program('sampleserver_justworks', 'sampleserver_justworks.cpp')
+sampleserver_randompin = provisioning_env.Program('sampleserver_randompin', 'sampleserver_randompin.cpp')
-Alias("sample", [provisioningclient])
+Alias("samples", [provisioningclient, sampleserver_justworks, sampleserver_randompin])
provisioning_env.AppendTarget('samples')
sec_provisioning_build_dir = env.get('BUILD_DIR') +'/resource/csdk/security/provisioning/sample/'
provisioning_env.Alias("install", provisioning_env.Install( sec_provisioning_build_dir,
- sec_provisioning_src_dir + 'oic_svr_db_prov_tool.json'))
+ sec_provisioning_src_dir + 'oic_svr_db_client.json'))
provisioning_env.Alias("install", provisioning_env.Install( sec_provisioning_build_dir,
- sec_provisioning_src_dir + 'oic_svr_db_unowned_server.json'))
+ sec_provisioning_src_dir + 'oic_svr_db_server_justworks.json'))
+provisioning_env.Alias("install", provisioning_env.Install( sec_provisioning_build_dir,
+ sec_provisioning_src_dir + 'oic_svr_db_server_randompin.json'))
--- /dev/null
+{
+ "acl": [
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/res",
+ "/oic/d",
+ "/oic/p",
+ "/oic/res/types/d",
+ "/oic/ad",
+ "/oic/sec/amacl"
+ ],
+ "perms": 2,
+ "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+ },
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/sec/doxm",
+ "/oic/sec/pstat"
+ ],
+ "perms": 2,
+ "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+ }
+ ],
+ "pstat": {
+ "isop": true,
+ "deviceid": "YWRtaW5EZXZpY2VVVUlEMA==",
+ "ch": 0,
+ "cm": 0,
+ "tm": 0,
+ "om": 3,
+ "sm": [3]
+ },
+ "doxm": {
+ "oxm": [0],
+ "oxmsel": 0,
+ "sct": 1,
+ "owned": true,
+ "deviceid": "YWRtaW5EZXZpY2VVVUlEMA==",
+ "ownr": "YWRtaW5EZXZpY2VVVUlEMA=="
+ }
+}
"doxm": {
"oxm": [0],
"oxmsel": 0,
+ "sct": 1,
"owned": true,
"deviceid": "YWRtaW5EZXZpY2VVVUlE",
"ownr": "YWRtaW5EZXZpY2VVVUlE"
--- /dev/null
+{
+ "acl": [
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/res",
+ "/oic/res/d",
+ "/oic/res/types/d",
+ "/oic/presence"
+ ],
+ "perms": 2,
+ "ownrs" : [
+ "anVzdHdvcmtzRGV2VVVJRA=="
+ ]
+ },
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/sec/doxm",
+ "/oic/sec/pstat",
+ "/oic/sec/acl",
+ "/oic/sec/cred"
+ ],
+ "perms": 6,
+ "ownrs" : [
+ "anVzdHdvcmtzRGV2VVVJRA=="
+ ]
+ }
+ ],
+ "pstat": {
+ "isop": false,
+ "deviceid": "anVzdHdvcmtzRGV2VVVJRA==",
+ "commithash": 0,
+ "cm": 0,
+ "tm": 0,
+ "om": 3,
+ "sm": [3]
+ },
+ "doxm": {
+ "oxm": [0],
+ "oxmsel": 0,
+ "sct": 1,
+ "owned": false,
+ "deviceid": "anVzdHdvcmtzRGV2VVVJRA=="
+ }
+}
--- /dev/null
+{
+ "acl": [
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/res",
+ "/oic/res/d",
+ "/oic/res/types/d",
+ "/oic/presence"
+ ],
+ "perms": 2,
+ "ownrs" : [
+ "cmFuZG9tUGluRGV2VVVJRA=="
+ ]
+ },
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/sec/doxm",
+ "/oic/sec/pstat",
+ "/oic/sec/acl",
+ "/oic/sec/cred"
+ ],
+ "perms": 6,
+ "ownrs" : [
+ "cmFuZG9tUGluRGV2VVVJRA=="
+ ]
+ }
+ ],
+ "pstat": {
+ "isop": false,
+ "deviceid": "cmFuZG9tUGluRGV2VVVJRA==",
+ "commithash": 0,
+ "cm": 0,
+ "tm": 0,
+ "om": 3,
+ "sm": [3]
+ },
+ "doxm": {
+ "oxm": [0,2],
+ "oxmsel": 0,
+ "sct": 1,
+ "owned": false,
+ "deviceid": "cmFuZG9tUGluRGV2VVVJRA=="
+ }
+}
"doxm": {
"oxm": [0],
"oxmsel": 0,
+ "sct": 1,
"owned": false,
"deviceid": "MTExMTExMTExMTExMTExMQ=="
}
/******************************************************************
-*
-* 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.
-*
-******************************************************************/
+ *
+ * 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 <string.h>
#include <unistd.h>
-#include <getopt.h>
+
#include "logger.h"
#include "oic_malloc.h"
-#include "utlist.h"
+#include "oic_string.h"
+#include "ocprovisioningmanager.h"
+#include "oxmjustworks.h"
+#include "oxmrandompin.h"
#include "securevirtualresourcetypes.h"
-#include "provisioningmanager.h"
-
-#define MAX_URI_LENGTH (64)
-#define MAX_PERMISSION_LENGTH (5)
-#define MAX_INPUT_ID_LENGTH (16)
-#define PREDEFINED_TIMEOUT (10)
-#define CREATE (1)
-#define READ (2)
-#define UPDATE (4)
-#define DELETE (8)
-#define NOTIFY (16)
-#define DASH '-'
-#define TAG "provisioningclient"
-
-static OicSecAcl_t *gAcl = NULL;
-static char PROV_TOOL_DB_FILE[] = "oic_svr_db_prov_tool.json";
-
-/**
- * Perform cleanup for ACL list
- *
- * @param[in] ACL list
- */
-static void DeleteACLList(OicSecAcl_t *acl)
+#include "srmutility.h"
+#include "pmtypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif //__cplusplus
+
+// declaration(s) for provisioning client using C-level provisioning API
+// user input definition for main loop on provisioning client
+#define _10_DISCOV_ALL_DEVS_ 10
+#define _11_DISCOV_UNOWN_DEVS_ 11
+#define _12_DISCOV_OWN_DEVS_ 12
+#define _20_REGIST_DEVS_ 20
+#define _30_PROVIS_PAIR_DEVS_ 30
+#define _31_PROVIS_CRED_ 31
+#define _32_PROVIS_ACL_ 32
+#define _33_CHECK_LINK_STATUS_ 33
+#define _40_UNLINK_PAIR_DEVS_ 40
+#define _50_REMOVE_SELEC_DEV_ 50
+#define _99_EXIT_PRVN_CLT_ 99
+
+#define ACL_RESRC_MAX_NUM 16
+#define ACL_RESRC_MAX_LEN 128
+#define ACL_PEMISN_CNT 5
+#define DISCOVERY_TIMEOUT 10 // 10 sec
+#define CALLBACK_TIMEOUT 60 // 1 min
+#define TAG "provisioningclient"
+
+static const char* ACL_PEMISN[5] = {"CREATE", "READ", "WRITE", "DELETE", "NOTIFY"};
+static const char* SVR_DB_FILE_NAME = "oic_svr_db_client.json";
+ // '_' for separaing from the same constant variable in |srmresourcestrings.c|
+static const char* PRVN_DB_FILE_NAME = "oic_prvn_mng.db";
+// |g_ctx| means provision manager application context and
+// the following, includes |un/own_list|, could be variables, which |g_ctx| has,
+// for accessing all function(s) for these, they are declared on global domain
+static const char* g_ctx = "Provision Manager Client Application Context";
+static char* g_svr_fname;
+static char* g_prvn_fname;
+static OCProvisionDev_t* g_own_list;
+static OCProvisionDev_t* g_unown_list;
+static int g_own_cnt;
+static int g_unown_cnt;
+static bool g_doneCB;
+
+// function declaration(s) for calling them before implementing
+static OicSecAcl_t* createAcl(const int);
+static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
+static int printDevList(const OCProvisionDev_t*);
+static size_t printUuidList(const OCUuidList_t*);
+static int printResultList(const OCProvisionResult_t*, const int);
+static void printUuid(const OicUuid_t*);
+static FILE* fopen_prvnMng(const char*, const char*);
+static int waitCallbackRet(void);
+static int selectTwoDiffNum(int*, int*, const int, const char*);
+
+// callback function(s) for provisioning client using C-level provisioning API
+static void ownershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OC_LOG_V(INFO, TAG, "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OC_LOG_V(ERROR, TAG, "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
+static void provisionPairwiseCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
{
- if (acl)
+ if(!hasError)
{
- OicSecAcl_t *aclTmp1 = NULL;
- OicSecAcl_t *aclTmp2 = NULL;
- LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
+ OC_LOG_V(INFO, TAG, "Provision Pairwise SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OC_LOG_V(ERROR, TAG, "Provision Pairwise FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
+static void provisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OC_LOG_V(INFO, TAG, "Provision Credential SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OC_LOG_V(ERROR, TAG, "Provision Credential FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
+static void provisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OC_LOG_V(INFO, TAG, "Provision ACL SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OC_LOG_V(ERROR, TAG, "Provision ACL FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
+static void unlinkDevicesCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OC_LOG_V(INFO, TAG, "Unlink Devices SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OC_LOG_V(ERROR, TAG, "Unlink Devices FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
+static void removeDeviceCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OC_LOG_V(INFO, TAG, "Remove Device SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OC_LOG_V(ERROR, TAG, "Remove Device FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
+static void inputPinCB(char* pin, size_t len)
+{
+ if(!pin || OXM_RANDOM_PIN_SIZE>=len)
+ {
+ OC_LOG(ERROR, TAG, "inputPinCB invalid parameters");
+ return;
+ }
+
+ printf(" > INPUT PIN: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%8s", pin);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+}
+
+// function(s) for provisioning client using C-level provisioning API
+static int initProvisionClient(void)
+{
+ // initialize persistent storage for SVR DB
+ static OCPersistentStorage pstStr =
+ {
+ .open = fopen_prvnMng,
+ .read = fread,
+ .write = fwrite,
+ .close = fclose,
+ .unlink = unlink
+ };
+ if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&pstStr))
+ {
+ OC_LOG(ERROR, TAG, "OCRegisterPersistentStorageHandler error");
+ return -1;
+ }
+
+ // initialize OC stack and provisioning manager
+ if(OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
+ {
+ OC_LOG(ERROR, TAG, "OCStack init error");
+ return -1;
+ }
+
+ if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
+ {
+ printf("************************************************************\n");
+ printf("************Provisioning DB file already exists.************\n");
+ printf("************************************************************\n");
+ }
+ else
+ {
+ printf("*************************************************************\n");
+ printf("************No provisioning DB file, creating new************\n");
+ printf("*************************************************************\n");
+ }
+
+ if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
+ {
+ OC_LOG(ERROR, TAG, "OC_PM init error");
+ return -1;
+ }
+
+ // register callback function(s) to each OxM
+ OTMCallbackData_t otmcb =
+ {
+ .loadSecretCB = LoadSecretJustWorksCallback,
+ .createSecureSessionCB = CreateSecureSessionJustWorksCallback,
+ .createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload,
+ .createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload
+ };
+ if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_JUST_WORKS, &otmcb))
+ {
+ OC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_JUST_WORKS");
+ return -1;
+ }
+ otmcb.loadSecretCB = InputPinCodeCallback;
+ otmcb.createSecureSessionCB = CreateSecureSessionRandomPinCallbak;
+ otmcb.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
+ otmcb.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
+ if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &otmcb))
+ {
+ OC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_RANDOM_DEVICE_PIN");
+ return -1;
+ }
+ SetInputPinCB(inputPinCB);
+
+ return 0;
+}
+
+static int discoverAllDevices(void)
+{
+ // delete un/owned device lists before updating them
+ if(g_own_list)
+ {
+ OCDeleteDiscoveredDevices(g_own_list);
+ g_own_list = NULL;
+ }
+ if(g_unown_list)
+ {
+ OCDeleteDiscoveredDevices(g_unown_list);
+ g_unown_list = NULL;
+ }
+
+ // call |OCGetDevInfoFromNetwork| API actually
+ printf(" Discovering All Un/Owned Devices on Network..\n");
+ if(OC_STACK_OK != OCGetDevInfoFromNetwork(DISCOVERY_TIMEOUT, &g_own_list, &g_unown_list))
+ {
+ OC_LOG(ERROR, TAG, "OCGetDevInfoFromNetwork API error");
+ return -1;
+ }
+
+ // display the discovered un/owned lists
+ printf(" > Discovered Owned Devices\n");
+ g_own_cnt = printDevList(g_own_list);
+ printf(" > Discovered Unowned Devices\n");
+ g_unown_cnt = printDevList(g_unown_list);
+
+ return 0;
+}
+
+
+static int discoverUnownedDevices(void)
+{
+ // delete unowned device list before updating it
+ if(g_unown_list)
+ {
+ OCDeleteDiscoveredDevices(g_unown_list);
+ g_unown_list = NULL;
+ }
+
+ // call |OCDiscoverUnownedDevices| API actually
+ printf(" Discovering Only Unowned Devices on Network..\n");
+ if(OC_STACK_OK != OCDiscoverUnownedDevices(DISCOVERY_TIMEOUT, &g_unown_list))
+ {
+ OC_LOG(ERROR, TAG, "OCDiscoverUnownedDevices API error");
+ return -1;
+ }
+
+ // display the discovered unowned list
+ printf(" > Discovered Unowned Devices\n");
+ g_unown_cnt = printDevList(g_unown_list);
+
+ return 0;
+}
+
+static int discoverOwnedDevices(void)
+{
+ // delete owned device list before updating it
+ if(g_own_list)
+ {
+ OCDeleteDiscoveredDevices(g_own_list);
+ g_own_list = NULL;
+ }
+
+ // call |OCDiscoverOwnedDevices| API actually
+ printf(" Discovering Only Owned Devices on Network..\n");
+ if(OC_STACK_OK != OCDiscoverOwnedDevices(DISCOVERY_TIMEOUT, &g_own_list))
+ {
+ OC_LOG(ERROR, TAG, "OCDiscoverOwnedDevices API error");
+ return -1;
+ }
+
+ // display the discovered owned list
+ printf(" > Discovered Owned Devices\n");
+ g_own_cnt = printDevList(g_own_list);
+
+ return 0;
+}
+
+static int registerDevices(void)
+{
+ // check |unown_list| for registering devices
+ if(!g_unown_list || 0>=g_unown_cnt)
+ {
+ printf(" > Unowned Device List, to Register Devices, is Empty\n");
+ printf(" > Please Discover Unowned Devices first, with [10|11] Menu\n");
+ return 0; // normal case
+ }
+
+ // call |OCDoOwnershipTransfer| API actually
+ // calling this API with callback actually acts like blocking
+ // for error checking, the return value saved and printed
+ g_doneCB = false;
+ printf(" Registering All Discovered Unowned Devices..\n");
+ OCStackResult rst = OCDoOwnershipTransfer((void*) g_ctx, g_unown_list, ownershipTransferCB);
+ if(OC_STACK_OK != rst)
+ {
+ OC_LOG_V(ERROR, TAG, "OCDoOwnershipTransfer API error: %d", rst);
+ return -1;
+ }
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+ return -1;
+ }
+
+ // display the registered result
+ printf(" > Registered Discovered Unowned Devices\n");
+ printf(" > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
+
+ return 0;
+}
+
+static int provisionPairwise(void)
+{
+ // check |own_list| for provisioning pairwise devices
+ if(!g_own_list || 2>g_own_cnt)
+ {
+ printf(" > Owned Device List, to Provision the Pairwise, is Empty\n");
+ printf(" > Please Register Unowned Devices first, with [20] Menu\n");
+ return 0; // normal case
+ }
+
+ // select two devices for provisioning pairwise devices
+ int dev_num[2] = {0};
+ if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking Devices"))
+ {
+ OC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
+ return -1; // not need to 'goto' |ERROR| before allocating |acl|
+ }
+
+ // create ACL(s) for each selected device
+ OicSecAcl_t* acl[2] = {0};
+ for(int i=0; 2>i; ++i)
+ {
+ acl[i] = createAcl(dev_num[i]);
+ if(!acl[i])
{
- LL_DELETE(acl, aclTmp1);
+ OC_LOG(ERROR, TAG, "createAcl error return");
+ goto PVPWS_ERROR;
+ }
+ }
- /* Clean Resources */
- for (int i = 0; i < aclTmp1->resourcesLen; i++)
- {
- OICFree(aclTmp1->resources[i]);
- }
- OICFree(aclTmp1->resources);
+ // call |OCProvisionPairwiseDevices| API actually
+ // calling this API with callback actually acts like blocking
+ // for error checking, the return value saved and printed
+ g_doneCB = false;
+ printf(" Provisioning Selected Pairwise Devices..\n");
+ OCStackResult rst =
+ OCProvisionPairwiseDevices((void*) g_ctx,
+ SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
+ getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]), acl[0],
+ getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]), acl[1],
+ provisionPairwiseCB);
+ if(OC_STACK_OK != rst)
+ {
+ OC_LOG_V(ERROR, TAG, "OCProvisionPairwiseDevices API error: %d", rst);
+ goto PVPWS_ERROR;
+ }
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+ goto PVPWS_ERROR;
+ }
+ OCDeleteACLList(acl[0]);
+ OCDeleteACLList(acl[1]);
+
+ // display the pairwise-provisioned result
+ printf(" > Provisioned Selected Pairwise Devices\n");
+ printf(" > Please Check Device's Status for the Linked Result, with [33] Menu\n");
- /* Clean Owners */
- OICFree(aclTmp1->owners);
+ return 0;
+
+PVPWS_ERROR:
+ OCDeleteACLList(acl[0]);
+ OCDeleteACLList(acl[1]);
+ return -1;
+}
+
+static int provisionCred(void)
+{
+ // check |own_list| for provisioning pairwise credentials
+ if(!g_own_list || 2>g_own_cnt)
+ {
+ printf(" > Owned Device List, to Provision Credentials, is Empty\n");
+ printf(" > Please Register Unowned Devices first, with [20] Menu\n");
+ return 0; // normal case
+ }
+
+ // select two devices for provisioning pairwise credentials
+ int dev_num[2] = {0};
+ if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking CRED(s)"))
+ {
+ OC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
+ return -1;
+ }
+
+ printf(" Select PSK length..\n");
+ printf(" 1 - 128bit(Default)\n");
+ printf(" 2 - 256bit\n");
+ int sizeOption = 0;
+
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d",&sizeOption);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ size_t size = 0;
- /* Clean ACL node itself */
- OICFree(aclTmp1);
+ switch(sizeOption)
+ {
+ case 1:
+ {
+ size = OWNER_PSK_LENGTH_128;
+ break;
+ }
+ case 2:
+ {
+ size = OWNER_PSK_LENGTH_256;
+ break;
+ }
+ default:
+ {
+ size = OWNER_PSK_LENGTH_128;
+ break;
}
- acl = NULL;
}
+
+
+ // call |OCProvisionCredentials| API actually
+ // calling this API with callback actually acts like blocking
+ // for error checking, the return value saved and printed
+ g_doneCB = false;
+ printf(" Provisioning Selected Pairwise Credentials..\n");
+ OCStackResult rst =
+ OCProvisionCredentials((void*) g_ctx,
+ SYMMETRIC_PAIR_WISE_KEY, size,
+ getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
+ getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
+ provisionCredCB);
+ if(OC_STACK_OK != rst)
+ {
+ OC_LOG_V(ERROR, TAG, "OCProvisionCredentials API error: %d", rst);
+ return -1;
+ }
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+ return -1;
+ }
+
+ // display the CRED-provisioned result
+ printf(" > Provisioned Selected Pairwise Crendentials\n");
+ printf(" > Please Check Device's Status for the Linked Result, with [33] Menu\n");
+
+ return 0;
}
-/**
- * Calculate ACL permission from string to bit
- *
- * @param[in] temp_psm Input data of ACL permission string
- * @param[in,out] pms The pointer of ACL permission value
- * @return 0 on success otherwise a positive error value
- * @retval SP_RESULT_SUCCESS Successful
- * @retval SP_RESULT_INVALID_PARAM Invaild input arguments
- */
-static SPResult CalculateAclPermission(const char *temp_pms, uint16_t *pms)
+static int provisionAcl(void)
{
- int i = 0;
+ // check |own_list| for provisioning access control list
+ if(!g_own_list || 1>g_own_cnt)
+ {
+ printf(" > Owned Device List, to Provision ACL, is Empty\n");
+ printf(" > Please Register Unowned Devices first, with [20] Menu\n");
+ return 0; // normal case
+ }
+
+ // select device for provisioning access control list
+ int dev_num = 0;
+ for( ; ; )
+ {
+ printf(" > Enter Device Number, for Provisioning ACL: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &dev_num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<dev_num && g_own_cnt>=dev_num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
- if (NULL == temp_pms || NULL == pms)
+ // create ACL for selected device
+ OicSecAcl_t* acl = NULL;
+ acl = createAcl(dev_num);
+ if(!acl)
{
- return SP_RESULT_INVALID_PARAM;
+ OC_LOG(ERROR, TAG, "createAcl error return");
+ goto PVACL_ERROR;
}
- *pms = 0;
- while (temp_pms[i] != '\0')
+
+ // call |OCProvisionACL| API actually
+ // calling this API with callback actually acts like blocking
+ // for error checking, the return value saved and printed
+ g_doneCB = false;
+ printf(" Provisioning Selected ACL..\n");
+ OCStackResult rst =
+ OCProvisionACL((void*) g_ctx,
+ getDevInst((const OCProvisionDev_t*) g_own_list, dev_num),
+ acl, provisionAclCB);
+ if(OC_STACK_OK != rst)
+ {
+ OC_LOG_V(ERROR, TAG, "OCProvisionACL API error: %d", rst);
+ goto PVACL_ERROR;
+ }
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+ goto PVACL_ERROR;
+ }
+ OCDeleteACLList(acl); // after here |acl| points nothing
+
+ // display the ACL-provisioned result
+ printf(" > Provisioned Selected ACL\n");
+
+ return 0;
+
+PVACL_ERROR:
+ OCDeleteACLList(acl); // after here |acl| points nothing
+ return -1;
+}
+
+static int checkLinkedStatus(void)
+{
+ // check |own_list| for checking selected link status on PRVN DB
+ if(!g_own_list || 1>g_own_cnt)
+ {
+ printf(" > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
+ printf(" > Please Register Unowned Devices first, with [20] Menu\n");
+ return 0; // normal case
+ }
+
+ // select device for checking selected link status on PRVN DB
+ int dev_num = 0;
+ for( ; ; )
{
- switch (temp_pms[i])
+ printf(" > Enter Device Number, for Checking Linked Status on PRVN DB: ");
+ for(int ret=0; 1!=ret; )
{
- case 'C':
- {
- *pms += CREATE;
- i++;
- break;
- }
- case 'R':
- {
- *pms += READ;
- i++;
- break;
- }
- case 'U':
- {
- *pms += UPDATE;
- i++;
- break;
- }
- case 'D':
- {
- *pms += DELETE;
- i++;
- break;
- }
- case 'N':
- {
- *pms += NOTIFY;
- i++;
- break;
- }
- case '_':
- {
- i++;
- break;
- }
- default:
- {
- return SP_RESULT_INVALID_PARAM;
- }
+ ret = scanf("%d", &dev_num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
}
+ if(0<dev_num && g_own_cnt>=dev_num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ // call |OCGetLinkedStatus| API actually
+ printf(" Checking Selected Link Status on PRVN DB..\n");
+ OCUuidList_t* dvid_lst = NULL;
+ size_t dvid_cnt = 0;
+ if(OC_STACK_OK !=
+ OCGetLinkedStatus(
+ &getDevInst((const OCProvisionDev_t*) g_own_list, dev_num)->doxm->deviceID,
+ &dvid_lst, &dvid_cnt)) // allow empty list
+ {
+ OC_LOG(ERROR, TAG, "OCGetLinkedStatus API error");
+ goto CKLST_ERROR;
+ }
+
+ // display the linked status result
+ printf(" > Checked Selected Link Status on PRVN DB\n");
+ if(!dvid_lst || !dvid_cnt) // |size_t| is unsigned
+ {
+ printf(" Linked Device List is Empty..\n");
+ return 0; // normal case
+ }
+ if(dvid_cnt != printUuidList((const OCUuidList_t*) dvid_lst))
+ {
+ OC_LOG(ERROR, TAG, "printUuidList error return");
+ goto CKLST_ERROR;
}
- return SP_RESULT_SUCCESS;
+ OCDeleteUuidList(dvid_lst);
+
+ return 0;
+
+CKLST_ERROR:
+ OCDeleteUuidList(dvid_lst);
+ return -1;
}
-/**
- * Get the ACL property from user
- *
- * @param[in] ACL Datastructure to save user inputs
- * @return 0 on success otherwise a positive error value
- * @retval SP_RESULT_SUCCESS Successful
- * @retval SP_RESULT_MEM_ALLOCATION_FAIL Memmory allocation failure
- */
-static SPResult InputACL(OicSecAcl_t *acl)
+static int unlinkPairwise(void)
+{
+ // check |own_list| for unlinking pairwise devices
+ if(!g_own_list || 2>g_own_cnt)
+ {
+ printf(" > Owned Device List, to Unlink the Pairwise, is Empty\n");
+ printf(" > Please Register Unowned Devices first, with [20] Menu\n");
+ return 0; // normal case
+ }
+
+ // select two devices for unlinking pairwise devices
+ int dev_num[2] = {0};
+ if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Unlinking Devices"))
+ {
+ OC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
+ return -1;
+ }
+
+ // call |OCUnlinkDevices| API actually
+ // calling this API with callback actually acts like blocking
+ // for error checking, the return value saved and printed
+ g_doneCB = false;
+ printf(" Unlinking Selected Pairwise Devices..\n");
+ OCStackResult rst =
+ OCUnlinkDevices((void*) g_ctx,
+ getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
+ getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
+ unlinkDevicesCB);
+ if(OC_STACK_OK != rst)
+ {
+ OC_LOG_V(ERROR, TAG, "OCUnlinkDevices API error: %d", rst);
+ return -1;
+ }
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+ return -1;
+ }
+
+ // display the pairwise-unlinked result
+ printf(" > Unlinked Selected Pairwise Devices\n");
+ printf(" > Please Check Device's Status for the Unlinked Result, with [33] Menu\n");
+
+ return 0;
+}
+
+static int removeDevice(void)
+{
+ // check |own_list| for removing device
+ if(!g_own_list || 1>g_own_cnt)
+ {
+ printf(" > Owned Device List, to Remove Device, is Empty\n");
+ printf(" > Please Register Unowned Devices first, with [20] Menu\n");
+ return 0; // normal case
+ }
+
+ // select device for removing it
+ int dev_num = 0;
+ for( ; ; )
+ {
+ printf(" > Enter Device Number, for Removing Device: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &dev_num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<dev_num && g_own_cnt>=dev_num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ // call |OCRemoveDevice| API actually
+ // calling this API with callback actually acts like blocking
+ // for error checking, the return value saved and printed
+ g_doneCB = false;
+ printf(" Removing Selected Owned Device..\n");
+ OCStackResult rst =
+ OCRemoveDevice((void*) g_ctx, DISCOVERY_TIMEOUT,
+ getDevInst((const OCProvisionDev_t*) g_own_list, dev_num), removeDeviceCB);
+ if(OC_STACK_OK != rst)
+ {
+ OC_LOG_V(ERROR, TAG, "OCRemoveDevice API error: %d", rst);
+ return -1;
+ }
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+ return -1;
+ }
+
+ // display the removed result
+ printf(" > Removed Selected Owned Device\n");
+ printf(" > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
+
+ return 0;
+}
+
+static OicSecAcl_t* createAcl(const int dev_num)
{
- int unused __attribute__((unused));
- char temp_id [MAX_INPUT_ID_LENGTH + 4] = {0,};
- char temp_rsc[MAX_URI_LENGTH + 1] = {0,};
- char temp_pms[MAX_PERMISSION_LENGTH + 1] = {0,};
- printf("******************************************************************************\n");
- printf("-Set ACL policy for target device\n");
- printf("******************************************************************************\n");
- //Set Subject.
- printf("-URN identifying the subject\n");
- printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
- printf("Subject : ");
- unused = scanf("%19s", temp_id);
- int j = 0;
- for (int i = 0; temp_id[i] != '\0'; i++)
- {
- if (DASH != temp_id[i])
- acl->subject.id[j++] = temp_id[i];
- }
-
- //Set Resource.
- printf("Num. of Resource : ");
- unused = scanf("%zu", &acl->resourcesLen);
- printf("-URI of resource\n");
- printf("ex)/oic/sh/temp/0 (Max_URI_Length: 64 Byte )\n");
- acl->resources = (char **)OICMalloc(acl->resourcesLen * sizeof(char *));
- if (NULL == acl->resources)
- {
- OC_LOG(ERROR, TAG, "Error while memory allocation");
- return SP_RESULT_MEM_ALLOCATION_FAIL;
- }
- for (int i = 0; i < acl->resourcesLen; i++)
- {
- printf("[%d]Resource : ", i + 1);
- unused = scanf("%64s", temp_rsc);
- acl->resources[i] = (char *)OICMalloc((strlen(temp_rsc) + 1) * sizeof(char));
- if (NULL == acl->resources[i])
+ if(0>=dev_num || g_own_cnt<dev_num)
+ {
+ OC_LOG(ERROR, TAG, "createAcl invalid parameters");
+ return NULL; // not need to 'goto' |ERROR| before allocating |acl|
+ }
+
+ // allocate memory for |acl| struct
+ printf(" **** Create ACL for the Selected Device[%d]\n", dev_num);
+ OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
+ if(!acl)
+ {
+ OC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+ return NULL; // not need to 'goto' |ERROR| before allocating |acl|
+ }
+
+ // enter |subject| device number
+ int num = 0;
+ for( ; ; )
+ {
+ printf(" > [A] Enter Subject Device Number: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(num && g_own_cnt>=num && dev_num!=num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+ memcpy(&acl->subject,
+ &getDevInst((const OCProvisionDev_t*) g_own_list, num)->doxm->deviceID,
+ UUID_LENGTH); // not need |*sizeof(uint8_t)|
+
+ // enter number of |resources| in 'accessed' device
+ for( ; ; )
+ {
+ printf(" > [B] Enter Number of Accessed Resources (under 16): ");
+ // '16' is |ACL_RESRC_MAX_NUM|
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%zu", &acl->resourcesLen);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(acl->resourcesLen && ACL_RESRC_MAX_NUM>=acl->resourcesLen)
+ // |acl->resourcesLen| is unsigned
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter under 16 Again\n");
+ // '16' is |ACL_RESRC_MAX_NUM|
+ }
+
+ // enter actually each 'accessed' |resources| name
+ printf(" Enter Each Accessed Resource Name (each under 128 char)\n");
+ // '128' is ACL_RESRC_MAX_LEN
+ num = acl->resourcesLen;
+ acl->resources = (char**) OICCalloc(num, sizeof(char*));
+ if(!acl->resources)
+ {
+ OC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+ goto CRACL_ERROR;
+ }
+ char rsrc_in[ACL_RESRC_MAX_LEN+1] = {0}; // '1' for null termination
+ for(int i=0; num>i; ++i)
+ {
+ printf(" Enter Accessed Resource[%d] Name: ", i+1);
+ for(int ret=0; 1!=ret; )
{
- OC_LOG(ERROR, TAG, "Error while memory allocation");
- return SP_RESULT_MEM_ALLOCATION_FAIL;
+ ret = scanf("%128s", rsrc_in); // '128' is ACL_RESRC_MAX_LEN
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
}
- strncpy(acl->resources[i], temp_rsc, strlen(temp_rsc));
- acl->resources[i][strlen(temp_rsc)] = '\0';
- }
- // Set Permission
- do
- {
- printf("-Set the permission(C,R,U,D,N)\n");
- printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
- printf("Permission : ");
- unused = scanf("%5s", temp_pms);
- }
- while (SP_RESULT_SUCCESS != CalculateAclPermission(temp_pms, &(acl->permission)) );
- // Set Rowner
- printf("Num. of Rowner : ");
- unused = scanf("%zu", &acl->ownersLen);
- printf("-URN identifying the rowner\n");
- printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
- acl->owners = (OicUuid_t *)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
- if (NULL == acl->owners)
- {
- OC_LOG(ERROR, TAG, "Error while memory allocation");
- return SP_RESULT_MEM_ALLOCATION_FAIL;
- }
- for (int i = 0; i < acl->ownersLen; i++)
- {
- printf("[%d]Rowner : ", i + 1);
- unused = scanf("%19s", temp_id);
- j = 0;
- for (int k = 0; temp_id[k] != '\0'; k++)
+ size_t len = strlen(rsrc_in)+1; // '1' for null termination
+ char* rsrc = (char*) OICCalloc(len, sizeof(char));
+ if(!rsrc)
{
- if (DASH != temp_id[k])
+ OC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+ goto CRACL_ERROR;
+ }
+ OICStrcpy(rsrc, len, rsrc_in);
+ acl->resources[i] = rsrc; // after here, |rsrc| points nothing
+ }
+
+ // enter |permission| for this access
+ printf(" > [C] Enter Permission for This Access\n");
+ uint16_t pmsn = PERMISSION_FULL_CONTROL; // default full permission
+ uint16_t pmsn_msk = PERMISSION_CREATE; // default permission mask
+ for(int i=0; ACL_PEMISN_CNT>i; ++i)
+ {
+ char ans = 0;
+ for( ; ; )
+ {
+ printf(" Enter %s Permission (y/n): ", ACL_PEMISN[i]);
+ for(int ret=0; 1!=ret; )
{
- acl->owners[i].id[j++] = temp_id[k];
+ ret = scanf("%c", &ans);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
}
+ if('y'==ans || 'Y'==ans || 'n'==ans|| 'N'==ans)
+ {
+ ans &= ~0x20; // for masking lower case, 'y/n'
+ break;
+ }
+ printf(" Entered Wrong Answer. Please Enter 'y/n' Again\n");
+ }
+ if('N' == ans) // masked lower case, 'n'
+ {
+ pmsn -= pmsn_msk;
+ }
+ pmsn_msk <<= 1;
+ }
+ acl->permission = pmsn;
+
+ // enter |owner| device number
+ for( ; ; )
+ {
+ printf(" > [D] Enter Owner Device Number: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(num && g_own_cnt>=num)
+ {
+ break;
}
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+ acl->ownersLen = 1;
+ acl->owners = (OicUuid_t*) OICCalloc(1, sizeof(OicUuid_t));
+ if(!acl->owners)
+ {
+ OC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+ goto CRACL_ERROR;
}
- return SP_RESULT_SUCCESS;
+ memcpy(acl->owners,
+ &getDevInst((const OCProvisionDev_t*) g_own_list, num)->doxm->deviceID,
+ UUID_LENGTH); // not need |*sizeof(uint8_t)|
+ printf("\n");
+
+ return acl;
+
+CRACL_ERROR:
+ OCDeleteACLList(acl); // after here |acl| points nothing
+ return NULL;
}
-FILE* client_fopen(const char *path, const char *mode)
+static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
{
- (void)path;
- return fopen(PROV_TOOL_DB_FILE, mode);
+ if(!dev_lst || 0>=dev_num)
+ {
+ printf(" Device List is Empty..\n");
+ return NULL;
+ }
+
+ OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
+ for(int i=0; lst; )
+ {
+ if(dev_num == ++i)
+ {
+ return lst;
+ }
+ lst = lst->next;
+ }
+
+ return NULL; // in here |lst| is always |NULL|
}
-/**
- * Provisioning client sample using ProvisioningAPI on provisioningmanager.c
- * To change network type use command line option -w for Wifi and -e for Ethernet
- */
-int main(int argc, char **argv)
+static int printDevList(const OCProvisionDev_t* dev_lst)
{
- SPResult res = SP_RESULT_SUCCESS;
- SPTargetDeviceInfo_t *pDeviceList = NULL;
- gAcl = (OicSecAcl_t *)OICMalloc(sizeof(OicSecAcl_t));
+ if(!dev_lst)
+ {
+ printf(" Device List is Empty..\n\n");
+ return 0;
+ }
- // Initialize Persistent Storage for SVR database
- OCPersistentStorage ps = {};
- ps.open = client_fopen;
- ps.read = fread;
- ps.write = fwrite;
- ps.close = fclose;
- ps.unlink = unlink;
- OCRegisterPersistentStorageHandler(&ps);
+ OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
+ int lst_cnt = 0;
+ for( ; lst; )
+ {
+ printf(" [%d] ", ++lst_cnt);
+ printUuid((const OicUuid_t*) &lst->doxm->deviceID);
+ printf("\n");
+ lst = lst->next;
+ }
+ printf("\n");
- if (OCInit(NULL, 0, OC_CLIENT_SERVER) != OC_STACK_OK)
+ return lst_cnt;
+}
+
+static size_t printUuidList(const OCUuidList_t* uid_lst)
+{
+ if(!uid_lst)
{
- OC_LOG(ERROR, TAG, "OCStack init error");
+ printf(" Device List is Empty..\n\n");
+ return 0;
+ }
+
+ OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
+ size_t lst_cnt = 0;
+ for( ; lst; )
+ {
+ printf(" [%zu] ", ++lst_cnt);
+ printUuid((const OicUuid_t*) &lst->dev);
+ printf("\n");
+ lst = lst->next;
+ }
+ printf("\n");
+
+ return lst_cnt;
+}
+
+static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
+{
+ if(!rslt_lst || 0>=rslt_cnt)
+ {
+ printf(" Device List is Empty..\n\n");
return 0;
}
- if (NULL == gAcl)
+ int lst_cnt = 0;
+ for( ; rslt_cnt>lst_cnt; ++lst_cnt)
+ {
+ printf(" [%d] ", lst_cnt+1);
+ printUuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
+ printf(" - result: %d\n", rslt_lst[lst_cnt].res);
+ }
+ printf("\n");
+
+ return lst_cnt;
+}
+
+static void printUuid(const OicUuid_t* uid)
+{
+ for(int i=0; i<UUID_LENGTH; )
+ {
+ printf("%02X", (*uid).id[i++]);
+ if(i==4 || i==6 || i==8 || i==10) // canonical format for UUID has '8-4-4-4-12'
+ {
+ printf("-");
+ }
+ }
+}
+
+static FILE* fopen_prvnMng(const char* path, const char* mode)
+{
+ (void)path; // unused |path| parameter
+
+ // input |g_svr_db_fname| internally by force, not using |path| parameter
+ // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
+ // with its own |SVR_DB_FILE_NAME|
+ return fopen(SVR_DB_FILE_NAME, mode);
+}
+
+static int waitCallbackRet(void)
+{
+ for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
+ {
+ sleep(1);
+ if(OC_STACK_OK != OCProcess())
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int selectTwoDiffNum(int* a, int* b, const int max, const char* str)
+{
+ if(!a || !b || 2>=max || !str)
{
- OC_LOG(ERROR, TAG, "Error while memory allocation");
- return SP_RESULT_MEM_ALLOCATION_FAIL;
+ return -1;
}
- res = SPProvisioningDiscovery(PREDEFINED_TIMEOUT, &pDeviceList);
- if (SP_RESULT_SUCCESS == res)
+ for( ; ; )
{
- while (pDeviceList != NULL)
+ for(int i=0; 2>i; ++i)
{
- printf("-Provisioning device ID : ");
- for (int i = 0; i < MAX_INPUT_ID_LENGTH; i++)
+ int* num = 0==i?a:b;
+ for( ; ; )
{
- if (pDeviceList->doxm->deviceID.id[i] == '\0')
+ printf(" > Enter Device[%d] Number, %s: ", i+1, str);
+ for(int ret=0; 1!=ret; )
{
- break;
+ ret = scanf("%d", num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<*num && max>=*num)
+ {
+ break;
}
- printf("%c", pDeviceList->doxm->deviceID.id[i]);
+ printf(" Entered Wrong Number. Please Enter Again\n");
}
+ }
+ if(*a != *b)
+ {
printf("\n");
- res = SPInitProvisionContext(PREDEFINED_TIMEOUT, pDeviceList);
- if (SP_RESULT_SUCCESS != res)
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static void printMenu(void)
+{
+ printf("************************************************************\n");
+ printf("****** OIC Provisioning Client with using C-level API ******\n");
+ printf("************************************************************\n\n");
+
+ printf("** [A] DISCOVER DEVICES ON NETWORK\n");
+ printf("** 10. Discover All Un/Owned Devices on Network\n");
+ printf("** 11. Discover Only Unowned Devices on Network\n");
+ printf("** 12. Discover Only Owned Devices on Network\n\n");
+
+ printf("** [B] REGISTER/OWN ALL DISCOVERED UNOWNED DEVICES\n");
+ printf("** 20. Register/Own All Discovered Unowned Devices\n\n");
+
+ printf("** [C] PROVISION/LINK PAIRWISE THINGS\n");
+ printf("** 30. Provision/Link Pairwise Things\n");
+ printf("** 31. Provision Credentials for Pairwise Things\n");
+ printf("** 32. Provision the Selected Access Control List(ACL)\n");
+ printf("** 33. Check Linked Status of the Selected Device on PRVN DB\n\n");
+
+ printf("** [D] UNLINK PAIRWISE THINGS\n");
+ printf("** 40. Unlink Pairwise Things\n\n");
+
+ printf("** [E] REMOVE THE SELECTED DEVICE\n");
+ printf("** 50. Remove the Selected Device\n\n");
+
+ printf("** [F] EXIT PROVISIONING CLIENT\n");
+ printf("** 99. Exit Provisionong Client\n\n");
+
+ printf("************************************************************\n\n");
+}
+
+#if 0 // Code for enabling path configuration for PDB and SVR DBf
+static void printUsage(void)
+{
+ printf("\n");
+ printf("OIC Provisioning Client with using C-level API\n");
+ printf("Usage: provisioningclient [option]...\n");
+ printf("\n");
+ printf(" -h print help for this provisioning client\n");
+ printf(" -p=[prvn_db_file_path/name] input PRVN DB file path and name\n");
+ printf(" if not exists, will load default DB file\n");
+ printf(" (default: |oic_prvn_mng.db| on working dir)\n");
+ printf(" (ex. -p=oic_prvn_mng.db)\n");
+ printf(" -s=[svr_db_file_path/name] input SVR DB file path and name\n");
+ printf(" if not exists, will load default DB file\n");
+ printf(" (default: |oic_svr_db_client.json| on working dir)\n");
+ printf(" (ex. -s=oic_svr_db_client.json)\n");
+ printf("\n");
+}
+#endif
+
+// main function for provisioning client using C-level provisioning API
+int main()
+{
+ // initialize provisioning client
+ if(initProvisionClient())
+ {
+ OC_LOG(ERROR, TAG, "ProvisionClient init error");
+ goto PMCLT_ERROR;
+ }
+
+ // main loop for provisioning manager
+ int mn_num = 0;
+ for( ; ; )
+ {
+ printf("\n");
+ printMenu();
+ printf(">> Enter Menu Number: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &mn_num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ printf("\n");
+ switch(mn_num)
+ {
+ case _10_DISCOV_ALL_DEVS_:
+ if(discoverAllDevices())
+ {
+ OC_LOG(ERROR, TAG, "_10_DISCOV_ALL_DEVS_: error");
+ }
+ break;
+ case _11_DISCOV_UNOWN_DEVS_:
+ if(discoverUnownedDevices())
+ {
+ OC_LOG(ERROR, TAG, "_11_DISCOV_UNOWN_DEVS_: error");
+ }
+ break;
+ case _12_DISCOV_OWN_DEVS_:
+ if(discoverOwnedDevices())
+ {
+ OC_LOG(ERROR, TAG, "_12_DISCOV_OWN_DEVS_: error");
+ }
+ break;
+ case _20_REGIST_DEVS_:
+ if(registerDevices())
{
- OC_LOG(ERROR, TAG, "Error while init provisioning Context");
- goto error;
+ OC_LOG(ERROR, TAG, "_20_REGIST_DEVS_: error");
}
- res = InputACL(gAcl);
- if (SP_RESULT_SUCCESS != res)
+ break;
+ case _30_PROVIS_PAIR_DEVS_:
+ if(provisionPairwise())
{
- OC_LOG(ERROR, TAG, "Error while user ACL input ");
- goto error;
+ OC_LOG(ERROR, TAG, "_30_PROVIS_PAIR_DEVS_: error");
}
- res = SPProvisionACL(PREDEFINED_TIMEOUT, pDeviceList, gAcl);
- if (SP_RESULT_SUCCESS != res)
+ break;
+ case _31_PROVIS_CRED_:
+ if(provisionCred())
{
- OC_LOG(ERROR, TAG, "Error while provisioning ACL");
- goto error;
+ OC_LOG(ERROR, TAG, "_31_PROVIS_CRED_: error");
}
- res = SPFinalizeProvisioning(PREDEFINED_TIMEOUT, pDeviceList);
- if (SP_RESULT_SUCCESS == res)
+ break;
+ case _32_PROVIS_ACL_:
+ if(provisionAcl())
{
- printf("Provisioning Success~!!\n");
+ OC_LOG(ERROR, TAG, "_32_PROVIS_ACL_: error");
}
- else if (SP_RESULT_SUCCESS != res)
+ break;
+ case _33_CHECK_LINK_STATUS_:
+ if(checkLinkedStatus())
{
- OC_LOG(ERROR, TAG, "Error while Finalize Provisioning");
- goto error;
+ OC_LOG(ERROR, TAG, "_33_CHECK_LINK_STATUS_: error");
}
- pDeviceList = pDeviceList->next;
+ break;
+ case _40_UNLINK_PAIR_DEVS_:
+ if(unlinkPairwise())
+ {
+ OC_LOG(ERROR, TAG, "_40_UNLINK_PAIR_DEVS_: error");
+ }
+ break;
+ case _50_REMOVE_SELEC_DEV_:
+ if(removeDevice())
+ {
+ OC_LOG(ERROR, TAG, "_50_REMOVE_SELEC_DEV_: error");
+ }
+ break;
+ case _99_EXIT_PRVN_CLT_:
+ goto PMCLT_ERROR;
+ default:
+ printf(">> Entered Wrong Number. Please Enter Again\n\n");
+ break;
}
}
- else
+
+PMCLT_ERROR:
+ if(OC_STACK_OK != OCStop())
{
- OC_LOG(ERROR, TAG, "Error while Provisioning Discovery");
- goto error;
+ OC_LOG(ERROR, TAG, "OCStack stop error");
}
+ OCDeleteDiscoveredDevices(g_own_list); // after here |g_own_list| points nothing
+ OCDeleteDiscoveredDevices(g_unown_list); // after here |g_unown_list| points nothing
-error:
- DeleteACLList(gAcl);
- SPTerminateProvisioning();
- return 0;
+ if(g_svr_fname)
+ {
+ OICFree(g_svr_fname); // after here |g_svr_fname| points nothing
+ }
+ if(g_prvn_fname)
+ {
+ OICFree(g_prvn_fname); // after here |g_prvn_fname| points nothing
+ }
+ return 0; // always return normal case
+}
+
+#ifdef __cplusplus
}
+#endif //__cplusplus
\ No newline at end of file
--- /dev/null
+/******************************************************************
+*
+* 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.
+*
+******************************************************************/
+///////////////////////////////////////////////////////////////////////
+//NOTE : This sample server is generated based on ocserverbasicops.cpp
+///////////////////////////////////////////////////////////////////////
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include "ocstack.h"
+#include "logger.h"
+#include "ocpayload.h"
+
+#define TAG "SAMPLE_JUSTWORKS"
+
+int gQuitFlag = 0;
+
+/* Structure to represent a LED resource */
+typedef struct LEDRESOURCE{
+ OCResourceHandle handle;
+ bool state;
+ int power;
+} LEDResource;
+
+static LEDResource LED;
+// This variable determines instance number of the LED resource.
+// Used by POST method to create a new instance of LED resource.
+static int gCurrLedInstance = 0;
+#define SAMPLE_MAX_NUM_POST_INSTANCE 2
+static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
+
+char *gResourceUri= (char *)"/a/led";
+
+//Secure Virtual Resource database for Iotivity Server
+//It contains Server's Identity and the PSK credentials
+//of other devices which the server trusts
+static char CRED_FILE[] = "oic_svr_db_server_justworks.json";
+
+/* Function that creates a new LED resource by calling the
+ * OCCreateResource() method.
+ */
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower);
+
+/* This method converts the payload to JSON format */
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
+
+/* Following methods process the PUT, GET, POST
+ * requests
+ */
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+ OCRepPayload **payload);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+ OCRepPayload **payload);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+ OCEntityHandlerResponse *response,
+ OCRepPayload **payload);
+
+/* Entity Handler callback functions */
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest *entityHandlerRequest,
+ void* callbackParam);
+
+const char *getResult(OCStackResult result) {
+ switch (result) {
+ case OC_STACK_OK:
+ return "OC_STACK_OK";
+ case OC_STACK_RESOURCE_CREATED:
+ return "OC_STACK_RESOURCE_CREATED";
+ case OC_STACK_RESOURCE_DELETED:
+ return "OC_STACK_RESOURCE_DELETED";
+ case OC_STACK_INVALID_URI:
+ return "OC_STACK_INVALID_URI";
+ case OC_STACK_INVALID_QUERY:
+ return "OC_STACK_INVALID_QUERY";
+ case OC_STACK_INVALID_IP:
+ return "OC_STACK_INVALID_IP";
+ case OC_STACK_INVALID_PORT:
+ return "OC_STACK_INVALID_PORT";
+ case OC_STACK_INVALID_CALLBACK:
+ return "OC_STACK_INVALID_CALLBACK";
+ case OC_STACK_INVALID_METHOD:
+ return "OC_STACK_INVALID_METHOD";
+ case OC_STACK_NO_MEMORY:
+ return "OC_STACK_NO_MEMORY";
+ case OC_STACK_COMM_ERROR:
+ return "OC_STACK_COMM_ERROR";
+ case OC_STACK_INVALID_PARAM:
+ return "OC_STACK_INVALID_PARAM";
+ case OC_STACK_NOTIMPL:
+ return "OC_STACK_NOTIMPL";
+ case OC_STACK_NO_RESOURCE:
+ return "OC_STACK_NO_RESOURCE";
+ case OC_STACK_RESOURCE_ERROR:
+ return "OC_STACK_RESOURCE_ERROR";
+ case OC_STACK_SLOW_RESOURCE:
+ return "OC_STACK_SLOW_RESOURCE";
+ case OC_STACK_NO_OBSERVERS:
+ return "OC_STACK_NO_OBSERVERS";
+ #ifdef WITH_PRESENCE
+ case OC_STACK_PRESENCE_STOPPED:
+ return "OC_STACK_PRESENCE_STOPPED";
+ #endif
+ case OC_STACK_ERROR:
+ return "OC_STACK_ERROR";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
+{
+ OCRepPayload* payload = OCRepPayloadCreate();
+ if(!payload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to allocate Payload");
+ return NULL;
+ }
+
+ OCRepPayloadSetUri(payload, uri);
+ OCRepPayloadSetPropBool(payload, "state", state);
+ OCRepPayloadSetPropInt(payload, "power", power);
+
+ return payload;
+}
+
+//This function takes the request as an input and returns the response
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
+{
+ if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+ {
+ OC_LOG(ERROR, TAG, "Incoming payload not a representation");
+ return NULL;
+ }
+
+ OCRepPayload* input = (OCRepPayload*)(ehRequest->payload);
+
+ LEDResource *currLEDResource = &LED;
+
+ if (ehRequest->resource == gLedInstance[0].handle)
+ {
+ currLEDResource = &gLedInstance[0];
+ gResourceUri = (char *) "/a/led/0";
+ }
+ else if (ehRequest->resource == gLedInstance[1].handle)
+ {
+ currLEDResource = &gLedInstance[1];
+ gResourceUri = (char *) "/a/led/1";
+ }
+
+ if(OC_REST_PUT == ehRequest->method)
+ {
+ // Get pointer to query
+ int64_t pow;
+ if(OCRepPayloadGetPropInt(input, "power", &pow))
+ {
+ currLEDResource->power =pow;
+ }
+
+ bool state;
+ if(OCRepPayloadGetPropBool(input, "state", &state))
+ {
+ currLEDResource->state = state;
+ }
+ }
+
+ return getPayload(gResourceUri, currLEDResource->power, currLEDResource->state);
+}
+
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+ OCRepPayload **payload)
+{
+ OCEntityHandlerResult ehResult;
+
+ OCRepPayload *getResp = constructResponse(ehRequest);
+
+ if(getResp)
+ {
+ *payload = getResp;
+ ehResult = OC_EH_OK;
+ }
+ else
+ {
+ ehResult = OC_EH_ERROR;
+ }
+
+ return ehResult;
+}
+
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+ OCRepPayload **payload)
+{
+ OCEntityHandlerResult ehResult;
+
+ OCRepPayload *putResp = constructResponse(ehRequest);
+
+ if(putResp)
+ {
+ *payload = putResp;
+ ehResult = OC_EH_OK;
+ }
+ else
+ {
+ ehResult = OC_EH_ERROR;
+ }
+
+ return ehResult;
+}
+
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+ OCEntityHandlerResponse *response, OCRepPayload **payload)
+{
+ OCRepPayload *respPLPost_led = NULL;
+ OCEntityHandlerResult ehResult = OC_EH_OK;
+
+ /*
+ * The entity handler determines how to process a POST request.
+ * Per the REST paradigm, POST can also be used to update representation of existing
+ * resource or create a new resource.
+ * In the sample below, if the POST is for /a/led then a new instance of the LED
+ * resource is created with default representation (if representation is included in
+ * POST payload it can be used as initial values) as long as the instance is
+ * lesser than max new instance count. Once max instance count is reached, POST on
+ * /a/led updated the representation of /a/led (just like PUT)
+ */
+
+ if (ehRequest->resource == LED.handle)
+ {
+ if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
+ {
+ // Create new LED instance
+ char newLedUri[15] = "/a/led/";
+ int newLedUriLength = strlen(newLedUri);
+ snprintf (newLedUri + newLedUriLength, sizeof(newLedUri)-newLedUriLength, "%d", gCurrLedInstance);
+
+ respPLPost_led = OCRepPayloadCreate();
+ OCRepPayloadSetUri(respPLPost_led, gResourceUri);
+ OCRepPayloadSetPropString(respPLPost_led, "createduri", newLedUri);
+
+ if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
+ {
+ OC_LOG (INFO, TAG, "Created new LED instance");
+ gLedInstance[gCurrLedInstance].state = 0;
+ gLedInstance[gCurrLedInstance].power = 0;
+ gCurrLedInstance++;
+ strncpy ((char *)response->resourceUri, newLedUri, MAX_URI_LENGTH);
+ ehResult = OC_EH_RESOURCE_CREATED;
+ }
+ }
+ else
+ {
+ respPLPost_led = constructResponse(ehRequest);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
+ {
+ if (ehRequest->resource == gLedInstance[i].handle)
+ {
+ if (i == 0)
+ {
+ respPLPost_led = constructResponse(ehRequest);
+ break;
+ }
+ else if (i == 1)
+ {
+ respPLPost_led = constructResponse(ehRequest);
+ }
+ }
+ }
+ }
+
+ if (respPLPost_led != NULL)
+ {
+ *payload = respPLPost_led;
+ ehResult = OC_EH_OK;
+ }
+ else
+ {
+ OC_LOG_V (INFO, TAG, "Payload was NULL");
+ ehResult = OC_EH_ERROR;
+ }
+
+ return ehResult;
+}
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest *entityHandlerRequest,
+ void* callbackParam)
+{
+ OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+ (void)callbackParam;
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+ OCEntityHandlerResponse response;
+ memset(&response, 0, sizeof(response));
+
+ // Validate pointer
+ if (!entityHandlerRequest)
+ {
+ OC_LOG (ERROR, TAG, "Invalid request pointer");
+ return OC_EH_ERROR;
+ }
+
+ OCRepPayload* payload = NULL;
+
+ if (flag & OC_REQUEST_FLAG)
+ {
+ OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+ if (entityHandlerRequest)
+ {
+ if (OC_REST_GET == entityHandlerRequest->method)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+ ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
+ }
+ else if (OC_REST_PUT == entityHandlerRequest->method)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+ ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
+ }
+ else if (OC_REST_POST == entityHandlerRequest->method)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
+ ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
+ }
+ else
+ {
+ OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+ entityHandlerRequest->method);
+ ehResult = OC_EH_ERROR;
+ }
+
+ if (ehResult == OC_EH_OK && ehResult != OC_EH_FORBIDDEN)
+ {
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = entityHandlerRequest->requestHandle;
+ response.resourceHandle = entityHandlerRequest->resource;
+ response.ehResult = ehResult;
+ response.payload = (OCPayload*)(payload);
+ response.numSendVendorSpecificHeaderOptions = 0;
+ memset(response.sendVendorSpecificHeaderOptions, 0,
+ sizeof(response.sendVendorSpecificHeaderOptions));
+ memset(response.resourceUri, 0, sizeof(response.resourceUri));
+ // Indicate that response is NOT in a persistent buffer
+ response.persistentBufferFlag = 0;
+
+ // Send the response
+ if (OCDoResponse(&response) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "Error sending response");
+ ehResult = OC_EH_ERROR;
+ }
+ }
+ }
+ }
+
+ OCPayloadDestroy(response.payload);
+ return ehResult;
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+ if (signum == SIGINT)
+ {
+ gQuitFlag = 1;
+ }
+}
+
+FILE* server_fopen(const char *path, const char *mode)
+{
+ (void)path;
+ return fopen(CRED_FILE, mode);
+}
+
+int main()
+{
+ struct timespec timeout;
+
+ OC_LOG(DEBUG, TAG, "OCServer is starting...");
+
+ // Initialize Persistent Storage for SVR database
+ OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink};
+
+ OCRegisterPersistentStorageHandler(&ps);
+
+ if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack init error");
+ return 0;
+ }
+
+ /*
+ * Declare and create the example resource: LED
+ */
+ createLEDResource(gResourceUri, &LED, false, 0);
+
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 100000000L;
+
+ // Break from loop with Ctrl-C
+ OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+ signal(SIGINT, handleSigInt);
+ while (!gQuitFlag)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+ nanosleep(&timeout, NULL);
+ }
+
+ OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+ if (OCStop() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ }
+
+ return 0;
+}
+
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
+{
+ if (!uri)
+ {
+ OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+ return -1;
+ }
+
+ ledResource->state = resourceState;
+ ledResource->power= resourcePower;
+ OCStackResult res = OCCreateResource(&(ledResource->handle),
+ "core.led",
+ OC_RSRVD_INTERFACE_DEFAULT,
+ uri,
+ OCEntityHandlerCb,
+ NULL,
+ OC_DISCOVERABLE|OC_OBSERVABLE | OC_SECURE);
+ OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+
+ return 0;
+}
--- /dev/null
+/******************************************************************
+*
+* 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.
+*
+******************************************************************/
+///////////////////////////////////////////////////////////////////////
+//NOTE : This sample server is generated based on ocserverbasicops.cpp
+///////////////////////////////////////////////////////////////////////
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include "ocstack.h"
+#include "logger.h"
+#include "ocpayload.h"
+#include "pinoxmcommon.h"
+
+#define TAG "SAMPLE_RANDOMPIN"
+
+int gQuitFlag = 0;
+
+/* Structure to represent a LED resource */
+typedef struct LEDRESOURCE{
+ OCResourceHandle handle;
+ bool state;
+ int power;
+} LEDResource;
+
+static LEDResource LED;
+// This variable determines instance number of the LED resource.
+// Used by POST method to create a new instance of LED resource.
+static int gCurrLedInstance = 0;
+#define SAMPLE_MAX_NUM_POST_INSTANCE 2
+static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
+
+char *gResourceUri= (char *)"/a/led";
+
+//Secure Virtual Resource database for Iotivity Server
+//It contains Server's Identity and the PSK credentials
+//of other devices which the server trusts
+static char CRED_FILE[] = "oic_svr_db_server_randompin.json";
+
+/* Function that creates a new LED resource by calling the
+ * OCCreateResource() method.
+ */
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower);
+
+/* This method converts the payload to JSON format */
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
+
+/* Following methods process the PUT, GET, POST
+ * requests
+ */
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+ OCRepPayload **payload);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+ OCRepPayload **payload);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+ OCEntityHandlerResponse *response,
+ OCRepPayload **payload);
+
+/* Entity Handler callback functions */
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest *entityHandlerRequest,
+ void* callbackParam);
+
+const char *getResult(OCStackResult result) {
+ switch (result) {
+ case OC_STACK_OK:
+ return "OC_STACK_OK";
+ case OC_STACK_RESOURCE_CREATED:
+ return "OC_STACK_RESOURCE_CREATED";
+ case OC_STACK_RESOURCE_DELETED:
+ return "OC_STACK_RESOURCE_DELETED";
+ case OC_STACK_INVALID_URI:
+ return "OC_STACK_INVALID_URI";
+ case OC_STACK_INVALID_QUERY:
+ return "OC_STACK_INVALID_QUERY";
+ case OC_STACK_INVALID_IP:
+ return "OC_STACK_INVALID_IP";
+ case OC_STACK_INVALID_PORT:
+ return "OC_STACK_INVALID_PORT";
+ case OC_STACK_INVALID_CALLBACK:
+ return "OC_STACK_INVALID_CALLBACK";
+ case OC_STACK_INVALID_METHOD:
+ return "OC_STACK_INVALID_METHOD";
+ case OC_STACK_NO_MEMORY:
+ return "OC_STACK_NO_MEMORY";
+ case OC_STACK_COMM_ERROR:
+ return "OC_STACK_COMM_ERROR";
+ case OC_STACK_INVALID_PARAM:
+ return "OC_STACK_INVALID_PARAM";
+ case OC_STACK_NOTIMPL:
+ return "OC_STACK_NOTIMPL";
+ case OC_STACK_NO_RESOURCE:
+ return "OC_STACK_NO_RESOURCE";
+ case OC_STACK_RESOURCE_ERROR:
+ return "OC_STACK_RESOURCE_ERROR";
+ case OC_STACK_SLOW_RESOURCE:
+ return "OC_STACK_SLOW_RESOURCE";
+ case OC_STACK_NO_OBSERVERS:
+ return "OC_STACK_NO_OBSERVERS";
+ #ifdef WITH_PRESENCE
+ case OC_STACK_PRESENCE_STOPPED:
+ return "OC_STACK_PRESENCE_STOPPED";
+ #endif
+ case OC_STACK_ERROR:
+ return "OC_STACK_ERROR";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
+{
+ OCRepPayload* payload = OCRepPayloadCreate();
+ if(!payload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to allocate Payload");
+ return NULL;
+ }
+
+ OCRepPayloadSetUri(payload, uri);
+ OCRepPayloadSetPropBool(payload, "state", state);
+ OCRepPayloadSetPropInt(payload, "power", power);
+
+ return payload;
+}
+
+//This function takes the request as an input and returns the response
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
+{
+ if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+ {
+ OC_LOG(ERROR, TAG, "Incoming payload not a representation");
+ return NULL;
+ }
+
+ OCRepPayload* input = (OCRepPayload*)(ehRequest->payload);
+
+ LEDResource *currLEDResource = &LED;
+
+ if (ehRequest->resource == gLedInstance[0].handle)
+ {
+ currLEDResource = &gLedInstance[0];
+ gResourceUri = (char *) "/a/led/0";
+ }
+ else if (ehRequest->resource == gLedInstance[1].handle)
+ {
+ currLEDResource = &gLedInstance[1];
+ gResourceUri = (char *) "/a/led/1";
+ }
+
+ if(OC_REST_PUT == ehRequest->method)
+ {
+ // Get pointer to query
+ int64_t pow;
+ if(OCRepPayloadGetPropInt(input, "power", &pow))
+ {
+ currLEDResource->power =pow;
+ }
+
+ bool state;
+ if(OCRepPayloadGetPropBool(input, "state", &state))
+ {
+ currLEDResource->state = state;
+ }
+ }
+
+ return getPayload(gResourceUri, currLEDResource->power, currLEDResource->state);
+}
+
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+ OCRepPayload **payload)
+{
+ OCEntityHandlerResult ehResult;
+
+ OCRepPayload *getResp = constructResponse(ehRequest);
+
+ if(getResp)
+ {
+ *payload = getResp;
+ ehResult = OC_EH_OK;
+ }
+ else
+ {
+ ehResult = OC_EH_ERROR;
+ }
+
+ return ehResult;
+}
+
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+ OCRepPayload **payload)
+{
+ OCEntityHandlerResult ehResult;
+
+ OCRepPayload *putResp = constructResponse(ehRequest);
+
+ if(putResp)
+ {
+ *payload = putResp;
+ ehResult = OC_EH_OK;
+ }
+ else
+ {
+ ehResult = OC_EH_ERROR;
+ }
+
+ return ehResult;
+}
+
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+ OCEntityHandlerResponse *response, OCRepPayload **payload)
+{
+ OCRepPayload *respPLPost_led = NULL;
+ OCEntityHandlerResult ehResult = OC_EH_OK;
+
+ /*
+ * The entity handler determines how to process a POST request.
+ * Per the REST paradigm, POST can also be used to update representation of existing
+ * resource or create a new resource.
+ * In the sample below, if the POST is for /a/led then a new instance of the LED
+ * resource is created with default representation (if representation is included in
+ * POST payload it can be used as initial values) as long as the instance is
+ * lesser than max new instance count. Once max instance count is reached, POST on
+ * /a/led updated the representation of /a/led (just like PUT)
+ */
+
+ if (ehRequest->resource == LED.handle)
+ {
+ if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
+ {
+ // Create new LED instance
+ char newLedUri[15] = "/a/led/";
+ int newLedUriLength = strlen(newLedUri);
+ snprintf (newLedUri + newLedUriLength, sizeof(newLedUri)-newLedUriLength, "%d", gCurrLedInstance);
+
+ respPLPost_led = OCRepPayloadCreate();
+ OCRepPayloadSetUri(respPLPost_led, gResourceUri);
+ OCRepPayloadSetPropString(respPLPost_led, "createduri", newLedUri);
+
+ if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
+ {
+ OC_LOG (INFO, TAG, "Created new LED instance");
+ gLedInstance[gCurrLedInstance].state = 0;
+ gLedInstance[gCurrLedInstance].power = 0;
+ gCurrLedInstance++;
+ strncpy ((char *)response->resourceUri, newLedUri, MAX_URI_LENGTH);
+ ehResult = OC_EH_RESOURCE_CREATED;
+ }
+ }
+ else
+ {
+ respPLPost_led = constructResponse(ehRequest);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
+ {
+ if (ehRequest->resource == gLedInstance[i].handle)
+ {
+ if (i == 0)
+ {
+ respPLPost_led = constructResponse(ehRequest);
+ break;
+ }
+ else if (i == 1)
+ {
+ respPLPost_led = constructResponse(ehRequest);
+ }
+ }
+ }
+ }
+
+ if (respPLPost_led != NULL)
+ {
+ *payload = respPLPost_led;
+ ehResult = OC_EH_OK;
+ }
+ else
+ {
+ OC_LOG_V (INFO, TAG, "Payload was NULL");
+ ehResult = OC_EH_ERROR;
+ }
+
+ return ehResult;
+}
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest *entityHandlerRequest,
+ void* callbackParam)
+{
+ OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+ (void)callbackParam;
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+ OCEntityHandlerResponse response;
+ memset(&response, 0, sizeof(response));
+
+ // Validate pointer
+ if (!entityHandlerRequest)
+ {
+ OC_LOG (ERROR, TAG, "Invalid request pointer");
+ return OC_EH_ERROR;
+ }
+
+ OCRepPayload* payload = NULL;
+
+ if (flag & OC_REQUEST_FLAG)
+ {
+ OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+ if (entityHandlerRequest)
+ {
+ if (OC_REST_GET == entityHandlerRequest->method)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+ ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
+ }
+ else if (OC_REST_PUT == entityHandlerRequest->method)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+ ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
+ }
+ else if (OC_REST_POST == entityHandlerRequest->method)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
+ ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
+ }
+ else
+ {
+ OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+ entityHandlerRequest->method);
+ ehResult = OC_EH_ERROR;
+ }
+
+ if (ehResult == OC_EH_OK && ehResult != OC_EH_FORBIDDEN)
+ {
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = entityHandlerRequest->requestHandle;
+ response.resourceHandle = entityHandlerRequest->resource;
+ response.ehResult = ehResult;
+ response.payload = (OCPayload*)(payload);
+ response.numSendVendorSpecificHeaderOptions = 0;
+ memset(response.sendVendorSpecificHeaderOptions, 0,
+ sizeof(response.sendVendorSpecificHeaderOptions));
+ memset(response.resourceUri, 0, sizeof(response.resourceUri));
+ // Indicate that response is NOT in a persistent buffer
+ response.persistentBufferFlag = 0;
+
+ // Send the response
+ if (OCDoResponse(&response) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "Error sending response");
+ ehResult = OC_EH_ERROR;
+ }
+ }
+ }
+ }
+
+ OCPayloadDestroy(response.payload);
+ return ehResult;
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+ if (signum == SIGINT)
+ {
+ gQuitFlag = 1;
+ }
+}
+
+FILE* server_fopen(const char *path, const char *mode)
+{
+ (void)path;
+ return fopen(CRED_FILE, mode);
+}
+
+void GeneratePinCB(char* pin, size_t pinSize)
+{
+ if(NULL == pin || pinSize <= 0)
+ {
+ OC_LOG(INFO, TAG, "Invalid PIN");
+ return;
+ }
+
+ OC_LOG(INFO, TAG, "============================");
+ OC_LOG_V(INFO, TAG, " PIN CODE : %s", pin);
+ OC_LOG(INFO, TAG, "============================");
+}
+
+int main()
+{
+ struct timespec timeout;
+
+ OC_LOG(DEBUG, TAG, "OCServer is starting...");
+
+ // Initialize Persistent Storage for SVR database
+ OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink};
+ OCRegisterPersistentStorageHandler(&ps);
+
+ if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack init error");
+ return 0;
+ }
+
+ /**
+ * If server supported random pin based ownership transfer,
+ * callback of print PIN should be registered before runing server.
+ */
+ SetGeneratePinCB(&GeneratePinCB);
+
+ /*
+ * Declare and create the example resource: LED
+ */
+ createLEDResource(gResourceUri, &LED, false, 0);
+
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 100000000L;
+
+ // Break from loop with Ctrl-C
+ OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+ signal(SIGINT, handleSigInt);
+ while (!gQuitFlag)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+ nanosleep(&timeout, NULL);
+ }
+
+ OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+ if (OCStop() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ }
+
+ return 0;
+}
+
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
+{
+ if (!uri)
+ {
+ OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+ return -1;
+ }
+
+ ledResource->state = resourceState;
+ ledResource->power= resourcePower;
+ OCStackResult res = OCCreateResource(&(ledResource->handle),
+ "core.led",
+ OC_RSRVD_INTERFACE_DEFAULT,
+ uri,
+ OCEntityHandlerCb,
+ NULL,
+ OC_DISCOVERABLE|OC_OBSERVABLE | OC_SECURE);
+ OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+
+ return 0;
+}
*
* *****************************************************************/
#include <string.h>
-
-#include "provisioningmanager.h"
#include "credentialgenerator.h"
#include "oic_malloc.h"
#include "logger.h"
#include "credresource.h"
#include "ocrandom.h"
#include "base64.h"
-#define TAG "SPProvisionAPI"
-#define KEY_LENGTH 16
+#include "stdbool.h"
+#include "securevirtualresourcetypes.h"
-SPResult SPGeneratePairWiseCredentials(OicSecCredType_t type, const OicUuid_t *ptDeviceId,
- const OicUuid_t *firstDeviceId,
- const OicUuid_t *secondDeviceId,
- OicSecCred_t **firstCred,
- OicSecCred_t **secondCred)
-{
+#define TAG "SRPAPI-CG"
- if (NULL == ptDeviceId || NULL == firstDeviceId || NULL == secondDeviceId)
- {
- return SP_RESULT_INVALID_PARAM;
- }
- uint8_t privData[KEY_LENGTH] = {0,};
- OCFillRandomMem(privData, KEY_LENGTH);
+/**
+ * @def PM_VERIFY_SUCCESS
+ * @brief Macro to verify success of operation.
+ * eg: PM_VERIFY_SUCCESS(TAG, OC_STACK_OK == foo(), OC_STACK_ERROR, ERROR);
+ * @note Invoking function must define "bail:" label for goto functionality to work correctly and
+ * must define "OCStackResult res" for setting error code.
+ * */
+#define PM_VERIFY_SUCCESS(tag, op, errCode, logLevel) { if (!(op)) \
+ {OC_LOG((logLevel), tag, #op " failed!!"); res = errCode; goto bail;} }
+/**
+ * @def PM_VERIFY_NON_NULL
+ * @brief Macro to verify argument is not equal to NULL.
+ * eg: PM_VERIFY_NON_NULL(TAG, ptrData, ERROR);
+ * @note Invoking function must define "bail:" label for goto functionality to work correctly.
+ * */
+#define PM_VERIFY_NON_NULL(tag, arg, errCode, logLevel) { if (NULL == (arg)) \
+ { OC_LOG((logLevel), tag, #arg " is NULL"); res = errCode; goto bail;} }
- uint32_t outLen = 0;
- char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(privData)) + 1] = {};
- B64Result b64Ret = b64Encode(privData, sizeof(privData), base64Buff,
- sizeof(base64Buff), &outLen);
- if (B64_OK != b64Ret)
- {
- OC_LOG(ERROR, TAG, "Error while encoding key");
- return SP_RESULT_INTERNAL_ERROR;
- }
+OCStackResult PMGeneratePairWiseCredentials(OicSecCredType_t type, size_t keySize,
+ const OicUuid_t *ptDeviceId,
+ const OicUuid_t *firstDeviceId, const OicUuid_t *secondDeviceId,
+ OicSecCred_t **firstCred, OicSecCred_t **secondCred)
+{
- // TODO currently owner array is 1. only provisioning tool's id.
- OicSecCred_t *tempFirstCred = GenerateCredential(secondDeviceId, type, NULL, base64Buff, 1,
- ptDeviceId);
- if (NULL == tempFirstCred)
+ if (NULL == ptDeviceId || NULL == firstDeviceId || NULL != *firstCred || \
+ NULL == secondDeviceId || NULL != *secondCred)
{
- OC_LOG(ERROR, TAG, "Error while generating credential.");
- return SP_RESULT_INTERNAL_ERROR;
+ OC_LOG(INFO, TAG, "Invalid params");
+ return OC_STACK_INVALID_PARAM;
}
- // TODO currently owner array is 1. only provisioning tool's id.
- OicSecCred_t *tempSecondCred = GenerateCredential(firstDeviceId, type, NULL, base64Buff, 1,
- ptDeviceId);
- if (NULL == tempSecondCred)
+ if(!(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
{
- DeleteCredList(tempFirstCred);
- OC_LOG(ERROR, TAG, "Error while generating credential.");
- return SP_RESULT_INTERNAL_ERROR;
+ OC_LOG(INFO, TAG, "Invalid key size");
+ return OC_STACK_INVALID_PARAM;
}
+ OCStackResult res = OC_STACK_ERROR;
+ uint8_t* privData = NULL;
+ char* base64Buff = NULL;
+ OicSecCred_t *tempFirstCred = NULL;
+ OicSecCred_t *tempSecondCred = NULL;
+
+ size_t privDataKeySize = keySize;
+
+ privData = (uint8_t*) OICCalloc(privDataKeySize,sizeof(uint8_t));
+ PM_VERIFY_NON_NULL(TAG, privData, OC_STACK_NO_MEMORY, ERROR);
+
+ OCFillRandomMem(privData,privDataKeySize);
+
+ uint32_t outLen = 0;
+
+ base64Buff = (char*) OICCalloc(B64ENCODE_OUT_SAFESIZE(privDataKeySize) + 1, sizeof(char));
+ PM_VERIFY_NON_NULL(TAG, base64Buff, OC_STACK_NO_MEMORY, ERROR);
+ int memReq = (B64ENCODE_OUT_SAFESIZE(privDataKeySize) + 1) * sizeof(char);
+ B64Result b64Ret = b64Encode(privData, privDataKeySize*sizeof(uint8_t), base64Buff,
+ memReq, &outLen);
+ PM_VERIFY_SUCCESS(TAG, B64_OK == b64Ret, OC_STACK_ERROR, ERROR);
+
+ // TODO: currently owner array is 1. only provisioning tool's id.
+ tempFirstCred = GenerateCredential(secondDeviceId, type, NULL, base64Buff, 1, ptDeviceId);
+ PM_VERIFY_NON_NULL(TAG, tempFirstCred, OC_STACK_ERROR, ERROR);
+
+ // TODO: currently owner array is 1. only provisioning tool's id.
+ tempSecondCred = GenerateCredential(firstDeviceId, type, NULL, base64Buff, 1, ptDeviceId);
+ PM_VERIFY_NON_NULL(TAG, tempSecondCred, OC_STACK_ERROR, ERROR);
+
*firstCred = tempFirstCred;
*secondCred = tempSecondCred;
- return SP_RESULT_SUCCESS;
+ res = OC_STACK_OK;
+
+bail:
+ OICFree(privData);
+ OICFree(base64Buff);
+
+ if(res != OC_STACK_OK)
+ {
+ OICFree(tempFirstCred);
+ OICFree(tempSecondCred);
+ *firstCred = NULL;
+ *secondCred = NULL;
+ }
+
+ return res;
}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include "ocprovisioningmanager.h"
+#include "pmutility.h"
+#include "ownershiptransfermanager.h"
+#include "oic_malloc.h"
+#include "logger.h"
+#include "secureresourceprovider.h"
+#include "provisioningdatabasemanager.h"
+#include "credresource.h"
+#include "utlist.h"
+#include "aclresource.h" //Note: SRM internal header
+
+#define TAG "OCPMAPI"
+
+typedef struct Linkdata Linkdata_t;
+struct Linkdata
+{
+ void *ctx;
+ const OCProvisionDev_t *pDev1;
+ OicSecAcl_t *pDev1Acl;
+ const OCProvisionDev_t *pDev2;
+ OicSecAcl_t *pDev2Acl;
+ OCProvisionResult_t *resArr;
+ int numOfResults;
+ int currentCountResults;
+ OCProvisionResultCB resultCallback;
+
+};
+
+/**
+ * The function is responsible for initializaton of the provisioning manager. It will load
+ * provisioning database which have owned device's list and their linked status.
+ * TODO: In addition, if there is a device(s) which has not up-to-date credentials, this function will
+ * automatically try to update the deivce(s).
+ *
+ * @param[in] dbPath file path of the sqlite3 db
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCInitPM(const char* dbPath)
+{
+ return PDMInit(dbPath);
+}
+
+/**
+ * The function is responsible for discovery of device is current subnet. It will list
+ * all the device in subnet which are not yet owned. Please call OCInit with OC_CLIENT_SERVER as
+ * OCMode.
+ *
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
+ * client before returning the list of devices.
+ * @param[out] ppList List of candidate devices to be provisioned
+ * @return OTM_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult OCDiscoverUnownedDevices(unsigned short timeout, OCProvisionDev_t **ppList)
+{
+ if( ppList == NULL || *ppList != NULL)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ return PMDeviceDiscovery(timeout, false, ppList);
+}
+
+/**
+ * The function is responsible for discovery of owned device is current subnet. It will list
+ * all the device in subnet which are owned by calling provisioning client.
+ *
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
+ * client before returning the list of devices.
+ * @param[out] ppList List of device owned by provisioning tool.
+ * @return OTM_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList)
+{
+ if( ppList == NULL || *ppList != NULL)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ return PMDeviceDiscovery(timeout, true, ppList);
+}
+
+/**
+ * API to register for particular OxM.
+ *
+ * @param[in] Ownership transfer method.
+ * @param[in] Implementation of callback functions for owership transfer.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCSetOwnerTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t* callbackData)
+{
+ if(NULL == callbackData)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ return OTMSetOwnershipTransferCallbackData(oxm, callbackData);
+}
+
+OCStackResult OCDoOwnershipTransfer(void* ctx,
+ OCProvisionDev_t *targetDevices,
+ OCProvisionResultCB resultCallback)
+{
+ if( NULL == targetDevices )
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ return OTMDoOwnershipTransfer(ctx, targetDevices, resultCallback);
+}
+
+/**
+ * This function deletes memory allocated to linked list created by OCDiscover_XXX_Devices API.
+ *
+ * @param[in] pList Pointer to OCProvisionDev_t which should be deleted.
+ */
+void OCDeleteDiscoveredDevices(OCProvisionDev_t *pList)
+{
+ PMDeleteDeviceList(pList);
+}
+
+/**
+ * this function sends ACL information to resource.
+ *
+ * @param[in] ctx Application context would be returned in result callback.
+ * @param[in] selectedDeviceInfo Selected target device.
+ * @param[in] acl ACL to provision.
+ * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
+ request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionACL(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecAcl_t *acl,
+ OCProvisionResultCB resultCallback)
+{
+ return SRPProvisionACL(ctx, selectedDeviceInfo, acl, resultCallback);
+}
+
+/**
+ * function to provision credential to devices.
+ *
+ * @param[in] ctx Application context would be returned in result callback.
+ * @param[in] type Type of credentials to be provisioned to the device.
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
+ @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * provisioning request recieves a response from first resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
+ const OCProvisionDev_t *pDev1,
+ const OCProvisionDev_t *pDev2,
+ OCProvisionResultCB resultCallback)
+{
+ return SRPProvisionCredentials(ctx, type, keySize,
+ pDev1, pDev2, resultCallback);
+
+}
+
+/*
+* Function to unlink devices.
+* This function will remove the credential & relationship between the two devices.
+*
+* @param[in] ctx Application context would be returned in result callback
+* @param[in] pTargetDev1 first device information to be unlinked.
+* @param[in] pTargetDev2 second device information to be unlinked.
+* @param[in] resultCallback callback provided by API user, callback will be called when
+* device unlink is finished.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+*/
+OCStackResult OCUnlinkDevices(void* ctx,
+ const OCProvisionDev_t* pTargetDev1,
+ const OCProvisionDev_t* pTargetDev2,
+ OCProvisionResultCB resultCallback)
+{
+ OC_LOG(INFO, TAG, "IN OCUnlinkDevices");
+ OCUuidList_t* idList = NULL;
+ size_t numOfDev = 0;
+
+ if (!pTargetDev1 || !pTargetDev2 || !resultCallback)
+ {
+ OC_LOG(ERROR, TAG, "OCUnlinkDevices : NULL parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // Get linked devices with the first device.
+ OCStackResult res = PDMGetLinkedDevices(&(pTargetDev1->doxm->deviceID), &idList, &numOfDev);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "OCUnlinkDevices : PDMgetOwnedDevices failed");
+ goto error;
+ }
+ if (1 > numOfDev)
+ {
+ OC_LOG(DEBUG, TAG, "OCUnlinkDevices : Can not find linked devices");
+ res = OC_STACK_INVALID_PARAM; // Input devices are not linked, No request is made
+ goto error;
+ }
+
+ // Check the linked devices contains the second device. If yes send credential DELETE request.
+ OCUuidList_t* curDev = idList;
+ while (NULL != curDev)
+ {
+ if (memcmp(pTargetDev2->doxm->deviceID.id, curDev->dev.id, sizeof(curDev->dev.id)) == 0)
+ {
+ res = SRPUnlinkDevices(ctx, pTargetDev1, pTargetDev2, resultCallback);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "OCUnlinkDevices : Failed to unlink devices.");
+ }
+ goto error;
+ }
+ curDev = curDev->next;
+ }
+ OC_LOG(DEBUG, TAG, "No matched pair found from provisioning database");
+ res = OC_STACK_INVALID_PARAM; // Input devices are not linked, No request is made
+
+error:
+ OC_LOG(INFO, TAG, "OUT OCUnlinkDevices");
+
+ PDMDestoryOicUuidLinkList(idList);
+ return res;
+}
+
+/*
+* Function to device revocation
+* This function will remove credential of target device from all devices in subnet.
+*
+* @param[in] ctx Application context would be returned in result callback
+* @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
+* @param[in] pTargetDev Device information to be revoked.
+* @param[in] resultCallback callback provided by API user, callback will be called when
+* credential revocation is finished.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+*/
+OCStackResult OCRemoveDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
+ const OCProvisionDev_t* pTargetDev,
+ OCProvisionResultCB resultCallback)
+{
+ OC_LOG(INFO, TAG, "IN OCRemoveDevice");
+ OCStackResult res = OC_STACK_ERROR;
+ if (!pTargetDev || !resultCallback || 0 == waitTimeForOwnedDeviceDiscovery)
+ {
+ OC_LOG(INFO, TAG, "OCRemoveDevice : Invalied parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // Send DELETE requests to linked devices
+ OCStackResult resReq = OC_STACK_ERROR; // Check that we have to wait callback or not.
+ resReq = SRPRemoveDevice(ctx, waitTimeForOwnedDeviceDiscovery, pTargetDev, resultCallback);
+ if (OC_STACK_OK != resReq)
+ {
+ if (OC_STACK_CONTINUE == resReq)
+ {
+ OC_LOG(DEBUG, TAG, "OCRemoveDevice : Revoked device has no linked device except PT.");
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to invoke SRPRemoveDevice");
+ res = resReq;
+ goto error;
+ }
+ }
+
+ // Remove credential of revoked device from SVR database
+ const OicSecCred_t *cred = NULL;
+ cred = GetCredResourceData(&pTargetDev->doxm->deviceID);
+ if (cred == NULL)
+ {
+ OC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to get credential of remove device.");
+ goto error;
+ }
+
+ res = RemoveCredential(&cred->subject);
+ if (res != OC_STACK_RESOURCE_DELETED)
+ {
+ OC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to remove credential.");
+ goto error;
+ }
+
+ // Remove device info from prvisioning database.
+ res = PDMDeleteDevice(&pTargetDev->doxm->deviceID);
+ if (res != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to delete device in PDM.");
+ goto error;
+ }
+
+ // Check that we have to wait callback for DELETE request or not
+ res = resReq;
+
+error:
+ OC_LOG(INFO, TAG, "OUT OCRemoveDevice");
+ return res;
+}
+
+
+/**
+ * Internal Function to update result in link result array.
+ */
+static void UpdateLinkResults(Linkdata_t *link, int device, OCStackResult stackresult)
+{
+
+ OC_LOG_V(INFO,TAG,"value of link->currentCountResults is %d",link->currentCountResults);
+ if (1 == device)
+ {
+ memcpy(link->resArr[(link->currentCountResults)].deviceId.id, link->pDev1->doxm->deviceID.id,UUID_LENGTH);
+ }
+ else
+ {
+ memcpy(link->resArr[(link->currentCountResults)].deviceId.id, link->pDev2->doxm->deviceID.id,UUID_LENGTH);
+ }
+ link->resArr[(link->currentCountResults)].res = stackresult;
+ ++(link->currentCountResults);
+
+}
+
+/**
+ * Callback to handle ACL provisioning for device 2.
+ */
+static void AclProv2CB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+
+ if (NULL == ctx)
+ {
+ OC_LOG(ERROR,TAG,"Context is Null in ACLProv 2");
+ return;
+ }
+ (void)nOfRes;
+ Linkdata_t *link = (Linkdata_t*)ctx;
+ OCProvisionResultCB resultCallback = link->resultCallback;
+
+
+ if (hasError)
+ {
+ UpdateLinkResults(link, 2,arr[0].res);
+ OC_LOG(ERROR,TAG,"Error occured while ACL provisioning device 1");
+ ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+ link->resArr,
+ true);
+ OICFree(link->resArr);
+ OICFree(link) ;
+ return;
+ }
+ UpdateLinkResults(link, 2, arr[0].res);
+ ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+ link->resArr,
+ false);
+ OICFree(link->resArr);
+ OICFree(link);
+ return;
+}
+
+/**
+ * Callback to handle ACL provisioning for device 1
+ */
+static void AclProv1CB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+
+ if (NULL == ctx)
+ {
+ OC_LOG(ERROR,TAG,"Context is Null in ACLProv1");
+ return;
+ }
+ (void)nOfRes;
+ Linkdata_t *link = (Linkdata_t*)ctx;
+ OCProvisionResultCB resultCallback = link->resultCallback;
+
+ if (hasError)
+ {
+ OC_LOG(ERROR,TAG,"Error occured while ACL provisioning device 1");
+ UpdateLinkResults(link, 1, arr[0].res);
+ ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+ link->resArr,
+ true);
+ OICFree(link->resArr);
+ OICFree(link);
+ return;
+ }
+ UpdateLinkResults(link, 1, arr[0].res);
+ if (NULL != link->pDev2Acl)
+ {
+ OCStackResult res = SRPProvisionACL(ctx, link->pDev2, link->pDev2Acl, &AclProv2CB);
+ if (OC_STACK_OK!=res)
+ {
+ UpdateLinkResults(link, 2, res);
+ ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+ link->resArr,
+ true);
+
+ }
+ }
+ else
+ {
+ ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+ link->resArr,
+ false);
+ OICFree(link->resArr);
+ OICFree(link);
+ }
+
+ return;
+}
+
+/**
+ * Callback to handle credential provisioning.
+ */
+static void ProvisionCredsCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ if (NULL == ctx)
+ {
+ OC_LOG(ERROR,TAG,"Error occured while credential provisioning");
+ return;
+ }
+ Linkdata_t *link = (Linkdata_t*)ctx;
+ OCProvisionResultCB resultCallback = link->resultCallback;
+ OC_LOG_V(INFO, TAG, "has error returned %d",hasError);
+ UpdateLinkResults(link, 1, arr[0].res);
+ UpdateLinkResults(link, 2, arr[1].res);
+ if (hasError)
+ {
+ OC_LOG(ERROR,TAG,"Error occured while credential provisioning");
+ ((OCProvisionResultCB)(resultCallback))(link->ctx, nOfRes,
+ link->resArr,
+ true);
+ OICFree(link->resArr);
+ OICFree(link);
+ return;
+ }
+ if (NULL != link->pDev1Acl)
+ {
+
+ OCStackResult res = SRPProvisionACL(ctx, link->pDev1, link->pDev1Acl, &AclProv1CB);
+ if (OC_STACK_OK!=res)
+ {
+ OC_LOG(ERROR, TAG, "Error while provisioning ACL for device 1");
+ UpdateLinkResults(link, 1, res);
+ ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+ link->resArr,
+ true);
+ OICFree(link->resArr);
+ OICFree(link);
+ }
+ }
+ else if (NULL!=link->pDev2Acl)
+ {
+ OC_LOG(ERROR, TAG, "ACL for device 1 is NULL");
+ OCStackResult res = SRPProvisionACL(ctx, link->pDev2, link->pDev2Acl, &AclProv2CB);
+ if (OC_STACK_OK!=res)
+ {
+ OC_LOG(ERROR, TAG, "Error while provisioning ACL for device 2");
+ UpdateLinkResults(link, 2, res);
+ ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+ link->resArr,
+ true);
+ OICFree(link->resArr);
+ OICFree(link);
+ }
+ }
+ else
+ {
+ OC_LOG(INFO, TAG, "ACLs of both devices are NULL");
+ ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+ link->resArr,
+ false);
+ OICFree(link->resArr);
+ OICFree(link);
+ }
+ return;
+}
+/**
+ * function to provision credentials between two devices and ACLs for the devices who act as a server.
+ *
+ * @param[in] ctx Application context would be returned in result callback.
+ * @param[in] type Type of credentials to be provisioned to the device.
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
+ * @param[in] acl ACL for device 1. If this is not required set NULL.
+ * @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
+ * @param[in] acl ACL for device 2. If this is not required set NULL.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * provisioning request recieves a response from first resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionPairwiseDevices(void* ctx, OicSecCredType_t type, size_t keySize,
+ const OCProvisionDev_t *pDev1, OicSecAcl_t *pDev1Acl,
+ const OCProvisionDev_t *pDev2, OicSecAcl_t *pDev2Acl,
+ OCProvisionResultCB resultCallback)
+{
+
+ if (!pDev1 || !pDev2 || !resultCallback)
+ {
+ OC_LOG(ERROR, TAG, "OCProvisionPairwiseDevices : Invalid parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+ if (!(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
+ {
+ OC_LOG(INFO, TAG, "OCProvisionPairwiseDevices : Invalid key size");
+ return OC_STACK_INVALID_PARAM;
+ }
+ int noOfResults = 2; // Initial Value
+ if (NULL!=pDev1Acl)
+ {
+ ++noOfResults;
+ }
+ if (NULL!=pDev2Acl)
+ {
+ ++noOfResults;
+ }
+ Linkdata_t *link = (Linkdata_t*) OICMalloc(sizeof(Linkdata_t));
+ if (!link)
+ {
+ OC_LOG(ERROR, TAG, "Failed to memory allocation");
+ return OC_STACK_NO_MEMORY;
+ }
+ OC_LOG_V(INFO,TAG, "Maximum no od results %d",noOfResults);
+
+ link->pDev1 = pDev1;
+ link->pDev1Acl = pDev1Acl;
+ link->pDev2 = pDev2;
+ link->pDev2Acl = pDev2Acl;
+ link->ctx = ctx;
+ // 1 call for each device for credential provisioning. implict call by SRPProvisioning credential
+ // 1 call for ACL provisioning for device 1 and 1 call for ACL provisioning for device 2.
+ link->numOfResults = noOfResults;
+ link->resultCallback = resultCallback;
+ link->currentCountResults = 0;
+ link->resArr = (OCProvisionResult_t*) OICMalloc(sizeof(OCProvisionResult_t)*noOfResults);
+ OCStackResult res = SRPProvisionCredentials(link, type, keySize,
+ pDev1, pDev2, &ProvisionCredsCB);
+ if (res != OC_STACK_OK)
+ {
+ OICFree(link->resArr);
+ OICFree(link);
+ }
+ return res;
+
+}
+
+OCStackResult OCGetDevInfoFromNetwork(unsigned short waittime,
+ OCProvisionDev_t** pOwnedDevList,
+ OCProvisionDev_t** pUnownedDevList)
+{
+ //TODO will be replaced by more efficient logic
+ if (pOwnedDevList == NULL || *pOwnedDevList != NULL || pUnownedDevList == NULL
+ || *pUnownedDevList != NULL)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // Code for unowned discovery
+ OCProvisionDev_t *unownedDevice = NULL;
+ OCStackResult res = OCDiscoverUnownedDevices(waittime/2, &unownedDevice);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR,TAG, "Error in unowned discovery");
+ return res;
+ }
+
+ // Code for owned discovery
+ OCProvisionDev_t *ownedDevice = NULL;
+ res = OCDiscoverOwnedDevices(waittime/2, &ownedDevice);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR,TAG, "Error in owned discovery");
+ PMDeleteDeviceList(unownedDevice);
+ return res;
+ }
+
+ // Code to get list of all the owned devices.
+ OCUuidList_t *uuidList = NULL;
+ size_t numOfDevices = 0;
+ res = PDMGetOwnedDevices(&uuidList, &numOfDevices);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Error while getting info from DB");
+ PMDeleteDeviceList(unownedDevice);
+ PMDeleteDeviceList(ownedDevice);
+ return res;
+ }
+
+ // Code to compare devices in owned list and deviceid from DB.
+ OCProvisionDev_t* pCurDev = ownedDevice;
+ size_t deleteCnt = 0;
+ while (pCurDev)
+ {
+ if(true == PMDeleteFromUUIDList(uuidList, &pCurDev->doxm->deviceID))
+ {
+ deleteCnt++;
+ }
+ pCurDev = pCurDev->next;
+ }
+ // If there is no remaind device in uuidList, we have to assign NULL to prevent free.
+ if (deleteCnt == numOfDevices)
+ {
+ uuidList = NULL;
+ }
+ // Code to add information of the devices which are currently off in owned list.
+ OCUuidList_t *powerOffDeviceList = uuidList;
+ while (powerOffDeviceList)
+ {
+ OCProvisionDev_t *ptr = (OCProvisionDev_t *)OICCalloc(1, sizeof (OCProvisionDev_t));
+ if (NULL == ptr)
+ {
+ OC_LOG(ERROR,TAG,"Fail to allocate memory");
+ PMDeleteDeviceList(unownedDevice);
+ PMDeleteDeviceList(ownedDevice);
+ OCDeleteUuidList(uuidList);
+ return OC_STACK_NO_MEMORY;
+ }
+
+ ptr->doxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t));
+ if (NULL == ptr->doxm)
+ {
+ OC_LOG(ERROR,TAG,"Fail to allocate memory");
+ PMDeleteDeviceList(unownedDevice);
+ PMDeleteDeviceList(ownedDevice);
+ OCDeleteUuidList(uuidList);
+ OICFree(ptr);
+ return OC_STACK_NO_MEMORY;
+ }
+
+ memcpy(ptr->doxm->deviceID.id, powerOffDeviceList->dev.id, sizeof(ptr->doxm->deviceID.id));
+
+ ptr->devStatus = DEV_STATUS_OFF;
+ LL_PREPEND(ownedDevice, ptr);
+ powerOffDeviceList = powerOffDeviceList->next;
+
+ }
+ OCDeleteUuidList(uuidList);
+ *pOwnedDevList = ownedDevice;
+ *pUnownedDevList = unownedDevice;
+ return OC_STACK_OK;
+}
+
+OCStackResult OCGetLinkedStatus(const OicUuid_t* uuidOfDevice, OCUuidList_t** uuidList,
+ size_t* numOfDevices)
+{
+ return PDMGetLinkedDevices(uuidOfDevice, uuidList, numOfDevices);
+}
+
+void OCDeleteUuidList(OCUuidList_t* pList)
+{
+ PDMDestoryOicUuidLinkList(pList);
+}
+
+/**
+ * This function deletes ACL data.
+ *
+ * @param pAcl Pointer to OicSecAcl_t structure.
+ */
+void OCDeleteACLList(OicSecAcl_t* pAcl)
+{
+ DeleteACLList(pAcl);
+}
\ No newline at end of file
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ * *****************************************************************/
+
+// 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,
+// Refer to http://pubs.opengroup.org/stage7tc1/functions/clock_gettime.html
+// and to http://man7.org/linux/man-pages/man2/clock_gettime.2.html
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "cacommon.h"
+#include "cainterface.h"
+#include "base64.h"
+#include "cJSON.h"
+
+#include "srmresourcestrings.h"
+#include "doxmresource.h"
+#include "pstatresource.h"
+#include "credresource.h"
+#include "aclresource.h"
+#include "ownershiptransfermanager.h"
+#include "securevirtualresourcetypes.h"
+#include "oxmjustworks.h"
+#include "pmtypes.h"
+#include "pmutility.h"
+#include "srmutility.h"
+#include "provisioningdatabasemanager.h"
+#include "oxmrandompin.h"
+
+#define TAG "OTM"
+
+/**
+ * Array to store the callbacks for each owner transfer method.
+ */
+static OTMCallbackData_t g_OTMDatas[OIC_OXM_COUNT];
+
+/**
+ * Variable for storing provisioning tool's provisioning capabilities
+ * Must be in decreasing order of preference. More prefered method should
+ * have lower array index.
+ */
+static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIVEN };
+
+/**
+ * Number of supported provisioning methods
+ * current version supports only one.
+ */
+static size_t gNumOfProvisioningMethodsPT = 1;
+
+/**
+ * Function to getting string of ownership transfer method
+ */
+static const char* GetOxmString(OicSecOxm_t oxmType)
+{
+ switch(oxmType)
+ {
+ case OIC_JUST_WORKS:
+ return OXM_JUST_WORKS;
+ case OIC_MODE_SWITCH:
+ return OXM_MODE_SWITCH;
+ case OIC_RANDOM_DEVICE_PIN:
+ return OXM_RANDOM_DEVICE_PIN;
+ case OIC_PRE_PROVISIONED_DEVICE_PIN:
+ return OXM_PRE_PROVISIONED_DEVICE_PIN;
+ case OIC_PRE_PROVISION_STRONG_CREDENTIAL:
+ return OXM_PRE_PROVISIONED_STRONG_CREDENTIAL;
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * Function to select appropriate provisioning method.
+ *
+ * @param[in] supportedMethods Array of supported methods
+ * @param[in] numberOfMethods number of supported methods
+ * @param[out] selectedMethod Selected methods
+ * @return OC_STACK_OK on success
+ */
+static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
+ size_t numberOfMethods,
+ OicSecOxm_t *selectedMethod)
+{
+ OC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
+
+ if(numberOfMethods == 0 || !supportedMethods)
+ {
+ OC_LOG(WARNING, TAG, "Could not find a supported OxM.");
+ return OC_STACK_ERROR;
+ }
+
+ *selectedMethod = supportedMethods[0];
+ for(size_t i = 0; i < numberOfMethods; i++)
+ {
+ if(*selectedMethod < supportedMethods[i])
+ {
+ *selectedMethod = supportedMethods[i];
+ }
+ }
+
+ return OC_STACK_OK;
+}
+
+/**
+ * Function to select operation mode.This function will return most secure common operation mode.
+ *
+ * @param[in] selectedDeviceInfo selected device information to performing provisioning.
+ * @param[out] selectedMode selected operation mode
+ * @return OC_STACK_OK on success
+ */
+static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
+ OicSecDpom_t *selectedMode)
+{
+ OC_LOG(DEBUG, TAG, "IN SelectOperationMode");
+
+ size_t i = 0;
+ size_t j = 0;
+
+ while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
+ {
+ if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
+ {
+ i++;
+ }
+ else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
+ {
+ j++;
+ }
+ else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
+ {
+ *selectedMode = gProvisioningToolCapability[j];
+ break;
+ }
+ }
+ OC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
+}
+
+/**
+ * Function to update owner transfer mode
+ *
+ * @param[in] otmCtx Context value of ownership transfer.
+ * @return OC_STACK_OK on success
+ */
+static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
+
+/**
+ * Function to send request to resource to get its pstat resource information.
+ *
+ * @param[in] otmCtx Context value of ownership transfer.
+ * @return OC_STACK_OK on success
+ */
+static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
+
+
+/**
+ * Function to send ownerShip info. This function would update Owned as true and
+ * owner as UUID for provisioning tool
+ *
+ * @param[in] otmCtx Context value of ownership transfer.
+ * @return OC_STACK_OK on success
+ */
+static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
+
+/**
+ * Function to update the operation mode. As per the spec. Operation mode in client driven
+ * single service provisioning it will be updated to 0x3
+ *
+ * @param[in] otmCtx Context value of ownership transfer.
+ * @param[in] selectedOperationMode selected operation mode
+ * @return OC_STACK_OK on success
+ */
+static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
+ OicSecDpom_t selectedOperationMode);
+
+/**
+ * Function to start ownership transfer.
+ * This function will send the first request for provisioning,
+ * The next request message is sent from the response handler for this request.
+ *
+ * @param[in] ctx context value passed to callback from calling function.
+ * @param[in] selectedDevice selected device information to performing provisioning.
+ * @return OC_STACK_OK on success
+ */
+static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
+
+/*
+ * Function to finalize provisioning.
+ * This function will send default ACL and commit hash.
+ *
+ * @param[in] otmCtx Context value of ownership transfer.
+ * @return OC_STACK_OK on success
+ */
+static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
+
+
+static bool IsComplete(OTMContext_t* otmCtx)
+{
+ for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
+ {
+ if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Function to save the result of provisioning.
+ *
+ * @param[in,out] otmCtx Context value of ownership transfer.
+ * @param[in] res result of provisioning
+ */
+static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
+{
+ OC_LOG(DEBUG, TAG, "IN SetResult");
+
+ if(!otmCtx)
+ {
+ OC_LOG(WARNING, TAG, "OTMContext is NULL");
+ return;
+ }
+
+ if(otmCtx->selectedDeviceInfo)
+ {
+ for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
+ {
+ if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
+ otmCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
+ {
+ otmCtx->ctxResultArray[i].res = res;
+ if(OC_STACK_OK != res)
+ {
+ otmCtx->ctxHasError = true;
+ }
+ }
+ }
+
+ //If all request is completed, invoke the user callback.
+ if(IsComplete(otmCtx))
+ {
+ otmCtx->ctxResultCallback(otmCtx->userCtx, otmCtx->ctxResultArraySize,
+ otmCtx->ctxResultArray, otmCtx->ctxHasError);
+ OICFree(otmCtx->ctxResultArray);
+ OICFree(otmCtx);
+ }
+ else
+ {
+ if(OC_STACK_OK != StartOwnershipTransfer(otmCtx,
+ otmCtx->selectedDeviceInfo->next))
+ {
+ OC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
+ }
+ }
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT SetResult");
+}
+
+
+/**
+ * Function to save ownerPSK at provisioning tool end.
+ *
+ * @param[in] selectedDeviceInfo selected device information to performing provisioning.
+ * @return OC_STACK_OK on success
+ */
+static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
+{
+ OC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
+
+ OCStackResult res = OC_STACK_ERROR;
+
+ CAEndpoint_t endpoint;
+ memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
+ OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
+ endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
+ endpoint.port = selectedDeviceInfo->securePort;
+
+ OicUuid_t ptDeviceID = {.id={0}};
+ if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
+ {
+ OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+ return res;
+ }
+
+ uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
+
+ //Generating OwnerPSK
+ CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
+ (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
+ strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id,
+ sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
+ sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
+ OWNER_PSK_LENGTH_128);
+
+ if (CA_STATUS_OK == pskRet)
+ {
+ OC_LOG(INFO, TAG,"ownerPSK dump:\n");
+ OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
+ //Generating new credential for provisioning tool
+ size_t ownLen = 1;
+ uint32_t outLen = 0;
+
+ char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
+ B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
+ &outLen);
+ VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
+
+ OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
+ SYMMETRIC_PAIR_WISE_KEY, NULL,
+ base64Buff, ownLen, &ptDeviceID);
+ VERIFY_NON_NULL(TAG, cred, ERROR);
+
+ res = AddCredential(cred);
+ if(res != OC_STACK_OK)
+ {
+ DeleteCredList(cred);
+ return res;
+ }
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
+exit:
+ return res;
+}
+
+/**
+ * Callback handler for OwnerShipTransferModeHandler API.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
+
+ VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+ VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+ OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+ (void)UNUSED;
+ if(clientResponse->result == OC_STACK_OK)
+ {
+ OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
+ //Send request : GET /oic/sec/pstat
+ OCStackResult res = GetProvisioningStatusResource(otmCtx);
+ if(OC_STACK_OK != res)
+ {
+ OC_LOG(WARNING, TAG, "Failed to get pstat information");
+ SetResult(otmCtx, res);
+ }
+ }
+ else
+ {
+ OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
+ clientResponse->result);
+ SetResult(otmCtx, clientResponse->result);
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
+
+exit:
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler for ProvisioningStatusResouceHandler API.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
+
+ VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+ VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+ OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+ (void)UNUSED;
+ if (OC_STACK_OK == clientResponse->result)
+ {
+ if (NULL == clientResponse->payload)
+ {
+ OC_LOG(INFO, TAG, "Skiping Null payload");
+ SetResult(otmCtx, OC_STACK_ERROR);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
+ {
+ OC_LOG(INFO, TAG, "Unknown payload type");
+ SetResult(otmCtx, OC_STACK_ERROR);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ OicSecPstat_t* pstat = JSONToPstatBin(
+ ((OCSecurityPayload*)clientResponse->payload)->securityData);
+ if(NULL == pstat)
+ {
+ OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
+ SetResult(otmCtx, OC_STACK_ERROR);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ otmCtx->selectedDeviceInfo->pstat = pstat;
+
+ //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
+ OicSecDpom_t selectedOperationMode;
+ SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
+
+ //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
+ OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Error while updating operation mode.");
+ SetResult(otmCtx, res);
+ }
+ }
+ else
+ {
+ OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
+ clientResponse->result);
+ SetResult(otmCtx, clientResponse->result);
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
+exit:
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler for OwnershipInformationHandler API.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+ VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+ OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
+ (void)UNUSED;
+ OCStackResult res = OC_STACK_OK;
+ OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+ if (OC_STACK_OK == clientResponse->result)
+ {
+ if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
+ {
+ res = RemoveCredential(&otmCtx->subIdForPinOxm);
+ if(OC_STACK_RESOURCE_DELETED != res)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+
+ res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
+ if(OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
+ SetResult(otmCtx, res);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
+ endpoint->port = otmCtx->selectedDeviceInfo->securePort;
+ CAResult_t closeRes = CACloseDtlsSession(endpoint);
+ if(CA_STATUS_OK != closeRes)
+ {
+ OC_LOG(ERROR, TAG, "Failed to close DTLS session");
+ SetResult(otmCtx, closeRes);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
+ OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
+
+ res = FinalizeProvisioning(otmCtx);
+ if(OC_STACK_OK != res)
+ {
+ SetResult(otmCtx, res);
+ }
+ }
+ else
+ {
+ res = clientResponse->result;
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
+
+exit:
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Response handler for update operation mode.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
+
+ VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+ VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+ OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+ (void) UNUSED;
+ if (OC_STACK_OK == clientResponse->result)
+ {
+ OCStackResult res = OC_STACK_ERROR;
+ OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
+ //DTLS Handshake
+ //Load secret for temporal secure session.
+ if(g_OTMDatas[selOxm].loadSecretCB)
+ {
+ res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
+ if(OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
+ SetResult(otmCtx, res);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+
+ //Try DTLS handshake to generate secure session
+ if(g_OTMDatas[selOxm].createSecureSessionCB)
+ {
+ res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
+ if(OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
+ SetResult(otmCtx, res);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+
+ //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
+ res = PutOwnershipInformation(otmCtx);
+ if(OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
+ SetResult(otmCtx, res);
+ }
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Error while update operation mode");
+ SetResult(otmCtx, clientResponse->result);
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
+
+exit:
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
+{
+ OC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
+
+ if(!otmCtx || !otmCtx->selectedDeviceInfo)
+ {
+ OC_LOG(ERROR, TAG, "Invalid parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
+ OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+
+ if(!PMGenerateQuery(false,
+ deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
+ deviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_DOXM_URI))
+ {
+ OC_LOG(ERROR, TAG, "PutOwnerTransferModeToResource : Failed to generate query");
+ return OC_STACK_ERROR;
+ }
+ OC_LOG_V(DEBUG, TAG, "Query=%s", query);
+ OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ if(!secPayload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to memory allocation");
+ return OC_STACK_NO_MEMORY;
+ }
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+ secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
+ if (NULL == secPayload->securityData)
+ {
+ OICFree(secPayload);
+ OC_LOG(ERROR, TAG, "Error while converting bin to json");
+ return OC_STACK_ERROR;
+ }
+ OC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
+
+ OCCallbackData cbData;
+ cbData.cb = &OwnerTransferModeHandler;
+ cbData.context = (void *)otmCtx;
+ cbData.cd = NULL;
+ OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
+ &deviceInfo->endpoint, (OCPayload*)secPayload,
+ deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
+ if (res != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
+
+ return res;
+}
+
+static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
+{
+ OC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
+
+ if(!otmCtx || !otmCtx->selectedDeviceInfo)
+ {
+ OC_LOG(ERROR, TAG, "Invailed parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ if(!PMGenerateQuery(false,
+ deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
+ deviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_PSTAT_URI))
+ {
+ OC_LOG(ERROR, TAG, "GetProvisioningStatusResource : Failed to generate query");
+ return OC_STACK_ERROR;
+ }
+ OC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ OCCallbackData cbData;
+ cbData.cb = &ListMethodsHandler;
+ cbData.context = (void *)otmCtx;
+ cbData.cd = NULL;
+ OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
+ deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
+ if (res != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
+
+ return res;
+}
+
+
+static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
+{
+ OC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
+
+ if(!otmCtx || !otmCtx->selectedDeviceInfo)
+ {
+ OC_LOG(ERROR, TAG, "Invailed parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ if(!PMGenerateQuery(true,
+ deviceInfo->endpoint.addr, deviceInfo->securePort,
+ deviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_DOXM_URI))
+ {
+ OC_LOG(ERROR, TAG, "PutOwnershipInformation : Failed to generate query");
+ return OC_STACK_ERROR;
+ }
+ OC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ //OwnershipInformationHandler
+ OicSecOxm_t selOxm = deviceInfo->doxm->oxmSel;
+ OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ if(!secPayload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to memory allocation");
+ return OC_STACK_NO_MEMORY;
+ }
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+ secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
+ if (NULL == secPayload->securityData)
+ {
+ OICFree(secPayload);
+ OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCCallbackData cbData;
+ cbData.cb = &OwnershipInformationHandler;
+ cbData.context = (void *)otmCtx;
+ cbData.cd = NULL;
+ OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
+ deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
+ if (res != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
+
+ return res;
+}
+
+static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
+ OicSecDpom_t selectedOperationMode)
+{
+ OC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
+
+ if(!otmCtx || !otmCtx->selectedDeviceInfo)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ if(!PMGenerateQuery(false,
+ deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
+ deviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_PSTAT_URI))
+ {
+ OC_LOG(ERROR, TAG, "PutUpdateOperationMode : Failed to generate query");
+ return OC_STACK_ERROR;
+ }
+ OC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ deviceInfo->pstat->om = selectedOperationMode;
+
+ OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ if(!secPayload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to memory allocation");
+ return OC_STACK_NO_MEMORY;
+ }
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+ secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
+ if (NULL == secPayload->securityData)
+ {
+ OICFree(secPayload);
+ OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCCallbackData cbData;
+ cbData.cb = &OperationModeUpdateHandler;
+ cbData.context = (void *)otmCtx;
+ cbData.cd = NULL;
+ OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
+ deviceInfo->connType, OC_LOW_QOS, &cbData, NULL, 0);
+ if (res != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
+
+ return res;
+}
+
+static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
+{
+ OC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
+ OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+ otmCtx->selectedDeviceInfo = selectedDevice;
+
+ //Set to the lowest level OxM, and then find more higher level OxM.
+ OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
+ selectedDevice->doxm->oxmLen,
+ &selectedDevice->doxm->oxmSel);
+ if(OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Failed to select the provisioning method");
+ SetResult(otmCtx, res);
+ return res;
+ }
+ OC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
+
+ //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
+ res = PutOwnerTransferModeToResource(otmCtx);
+ if(OC_STACK_OK != res)
+ {
+ OC_LOG(WARNING, TAG, "Failed to select the provisioning method");
+ SetResult(otmCtx, res);
+ return res;
+ }
+
+ OC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
+
+ return res;
+
+}
+
+OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
+{
+ OC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
+
+ if(!data)
+ {
+ OC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+ if(oxmType >= OIC_OXM_COUNT)
+ {
+ OC_LOG(INFO, TAG, "Unknow ownership transfer method");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
+ g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
+ g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
+ g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
+
+ OC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
+
+ return OC_STACK_OK;
+}
+
+/**
+ * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
+ */
+OCStackResult OTMDoOwnershipTransfer(void* ctx,
+ OCProvisionDev_t *selectedDevicelist,
+ OCProvisionResultCB resultCallback)
+{
+ OC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
+
+ if (NULL == selectedDevicelist || NULL == resultCallback )
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OTMContext_t* otmCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
+ if(!otmCtx)
+ {
+ OC_LOG(ERROR, TAG, "Failed to create OTM Context");
+ return OC_STACK_NO_MEMORY;
+ }
+ otmCtx->ctxResultCallback = resultCallback;
+ otmCtx->ctxHasError = false;
+ otmCtx->userCtx = ctx;
+ OCProvisionDev_t* pCurDev = selectedDevicelist;
+
+ //Counting number of selected devices.
+ otmCtx->ctxResultArraySize = 0;
+ while(NULL != pCurDev)
+ {
+ otmCtx->ctxResultArraySize++;
+ pCurDev = pCurDev->next;
+ }
+
+ otmCtx->ctxResultArray =
+ (OCProvisionResult_t*)OICCalloc(otmCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
+ if(NULL == otmCtx->ctxResultArray)
+ {
+ OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
+ OICFree(otmCtx);
+ return OC_STACK_NO_MEMORY;
+ }
+ pCurDev = selectedDevicelist;
+
+ //Fill the device UUID for result array.
+ for(size_t devIdx = 0; devIdx < otmCtx->ctxResultArraySize; devIdx++)
+ {
+ //Checking duplication of Device ID.
+ if(true == PDMIsDuplicateDevice(&pCurDev->doxm->deviceID))
+ {
+ OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Device ID is duplicate");
+ OICFree(otmCtx->ctxResultArray);
+ OICFree(otmCtx);
+ return OC_STACK_INVALID_PARAM;
+ }
+ memcpy(otmCtx->ctxResultArray[devIdx].deviceId.id,
+ pCurDev->doxm->deviceID.id,
+ UUID_LENGTH);
+ otmCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
+ pCurDev = pCurDev->next;
+ }
+ StartOwnershipTransfer(otmCtx, selectedDevicelist);
+
+ OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
+ return OC_STACK_OK;
+}
+
+/**
+ * Callback handler of SRPFinalizeProvisioning.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
+
+ VERIFY_NON_NULL(TAG, clientResponse, ERROR);
+ VERIFY_NON_NULL(TAG, ctx, ERROR);
+
+ OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+ (void)UNUSED;
+ if(OC_STACK_OK == clientResponse->result)
+ {
+ OCStackResult res = PDMAddDevice(&otmCtx->selectedDeviceInfo->doxm->deviceID);
+
+ if (OC_STACK_OK == res)
+ {
+ OC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
+ SetResult(otmCtx, OC_STACK_OK);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Ownership transfer is complete but adding information to DB is failed.");
+ }
+ }
+exit:
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler of default ACL provisioning.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
+
+ VERIFY_NON_NULL(TAG, clientResponse, ERROR);
+ VERIFY_NON_NULL(TAG, ctx, ERROR);
+
+ OTMContext_t* otmCtx = (OTMContext_t*) ctx;
+ (void)UNUSED;
+
+ if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
+ {
+ OC_LOG_V(INFO, TAG, "Staring commit hash task.");
+ // TODO hash currently have fixed value 0.
+ uint16_t aclHash = 0;
+ otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
+ otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
+ OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ if(!secPayload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to memory allocation");
+ return OC_STACK_NO_MEMORY;
+ }
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+ secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
+ if (NULL == secPayload->securityData)
+ {
+ OICFree(secPayload);
+ SetResult(otmCtx, OC_STACK_INVALID_JSON);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
+
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ if(!PMGenerateQuery(true,
+ otmCtx->selectedDeviceInfo->endpoint.addr,
+ otmCtx->selectedDeviceInfo->securePort,
+ otmCtx->selectedDeviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_PSTAT_URI))
+ {
+ OC_LOG(ERROR, TAG, "ProvisionDefaultACLCB : Failed to generate query");
+ return OC_STACK_ERROR;
+ }
+ OC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
+ cbData.cb = &FinalizeProvisioningCB;
+ cbData.context = (void*)otmCtx;
+ cbData.cd = NULL;
+ OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
+ otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+ OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
+ if (ret != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ SetResult(otmCtx, ret);
+ }
+ }
+ else
+ {
+ OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
+ clientResponse->result);
+ SetResult(otmCtx, clientResponse->result);
+ }
+exit:
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
+{
+ OC_LOG(INFO, TAG, "IN FinalizeProvisioning");
+
+ if(!otmCtx)
+ {
+ OC_LOG(ERROR, TAG, "OTMContext is NULL");
+ return OC_STACK_INVALID_PARAM;
+ }
+ if(!otmCtx->selectedDeviceInfo)
+ {
+ OC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
+ OICFree(otmCtx);
+ return OC_STACK_INVALID_PARAM;
+ }
+ // Provision Default ACL to device
+ OicSecAcl_t defaultAcl =
+ { {.id={0}},
+ 1,
+ NULL,
+ 0x001F,
+ 0,
+ NULL,
+ NULL,
+ 1,
+ NULL,
+ NULL,
+ };
+
+ OicUuid_t provTooldeviceID = {.id={0}};
+ if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
+ {
+ OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+ SetResult(otmCtx, OC_STACK_ERROR);
+ return OC_STACK_ERROR;
+ }
+ OC_LOG(INFO, TAG, "Retieved deviceID");
+ memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
+ char *wildCardResource = "*";
+ defaultAcl.resources = &wildCardResource;
+
+ defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
+ if(!defaultAcl.owners)
+ {
+ OC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
+ SetResult(otmCtx, OC_STACK_NO_MEMORY);
+ return OC_STACK_NO_MEMORY;
+ }
+ memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
+ OC_LOG(INFO, TAG, "Provisioning default ACL");
+
+ OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ if(!secPayload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to memory allocation");
+ return OC_STACK_NO_MEMORY;
+ }
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+ secPayload->securityData = BinToAclJSON(&defaultAcl);
+ OICFree(defaultAcl.owners);
+ if(!secPayload->securityData)
+ {
+ OICFree(secPayload);
+ OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
+ SetResult(otmCtx, OC_STACK_ERROR);
+ return OC_STACK_ERROR;
+ }
+ OC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
+
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ if(!PMGenerateQuery(true,
+ otmCtx->selectedDeviceInfo->endpoint.addr,
+ otmCtx->selectedDeviceInfo->securePort,
+ otmCtx->selectedDeviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_ACL_URI))
+ {
+ OC_LOG(ERROR, TAG, "FinalizeProvisioning : Failed to generate query");
+ return OC_STACK_ERROR;
+ }
+ OC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s", query);
+
+ OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
+ cbData.cb = &ProvisionDefaultACLCB;
+ cbData.context = (void *)otmCtx;
+ cbData.cd = NULL;
+ OCStackResult ret = OCDoResource(NULL, OC_REST_POST, query,
+ &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
+ otmCtx->selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+ if (OC_STACK_OK != ret)
+ {
+ SetResult(otmCtx, ret);
+ return ret;
+ }
+
+ OC_LOG(INFO, TAG, "OUT FinalizeProvisioning");
+
+ return ret;
+
+}
+
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 <memory.h>
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "doxmresource.h"
+#include "cacommon.h"
+#include "cainterface.h"
+#include "oic_malloc.h"
+#include "logger.h"
+#include "global.h"
+#include "pmtypes.h"
+#include "ownershiptransfermanager.h"
+
+#define TAG "OXM_JustWorks"
+
+char* CreateJustWorksSelectOxmPayload(OTMContext_t* otmCtx)
+{
+ if(!otmCtx || !otmCtx->selectedDeviceInfo)
+ {
+ return NULL;
+ }
+
+ otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_JUST_WORKS;
+ return BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
+}
+
+char* CreateJustWorksOwnerTransferPayload(OTMContext_t* otmCtx)
+{
+ if(!otmCtx || !otmCtx->selectedDeviceInfo)
+ {
+ return NULL;
+ }
+
+ OicUuid_t uuidPT = {.id={0}};
+
+ if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
+ {
+ OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+ return NULL;
+ }
+ memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id , UUID_LENGTH);
+ otmCtx->selectedDeviceInfo->doxm->owned = true;
+
+ return BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
+}
+
+OCStackResult LoadSecretJustWorksCallback(OTMContext_t* UNUSED_PARAM)
+{
+ //In case of 'just works', secret data not required
+ (void)UNUSED_PARAM;
+ return OC_STACK_OK;
+}
+
+OCStackResult CreateSecureSessionJustWorksCallback(OTMContext_t* otmCtx)
+{
+ OC_LOG(INFO, TAG, "IN CreateSecureSessionJustWorksCallback");
+ if(!otmCtx || !otmCtx->selectedDeviceInfo)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ CAResult_t caresult = CAEnableAnonECDHCipherSuite(true);
+ if (CA_STATUS_OK != caresult)
+ {
+ OC_LOG_V(ERROR, TAG, "Unable to enable anon cipher suite");
+ return OC_STACK_ERROR;
+ }
+ OC_LOG(INFO, TAG, "Anonymous cipher suite Enabled.");
+
+ OCProvisionDev_t* selDevInfo = otmCtx->selectedDeviceInfo;
+ CAEndpoint_t *endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
+ if(NULL == endpoint)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+ memcpy(endpoint,&selDevInfo->endpoint,sizeof(CAEndpoint_t));
+ endpoint->port = selDevInfo->securePort;
+
+ caresult = CAInitiateHandshake(endpoint);
+ OICFree(endpoint);
+ if (CA_STATUS_OK != caresult)
+ {
+ OC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
+ return OC_STACK_ERROR;
+ }
+
+ OC_LOG(INFO, TAG, "OUT CreateSecureSessionJustWorksCallback");
+ return OC_STACK_OK;
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 <memory.h>
+
+#include "ocstack.h"
+#include "ocsecurityconfig.h"
+#include "securevirtualresourcetypes.h"
+#include "doxmresource.h"
+#include "credresource.h"
+#include "cacommon.h"
+#include "cainterface.h"
+#include "ocrandom.h"
+#include "oic_malloc.h"
+#include "logger.h"
+#include "pbkdf2.h"
+#include "global.h"
+#include "base64.h"
+#include "oxmrandompin.h"
+#include "ownershiptransfermanager.h"
+#include "pinoxmcommon.h"
+
+#define TAG "OXM_RandomPIN"
+
+char* CreatePinBasedSelectOxmPayload(OTMContext_t* otmCtx)
+{
+ if(!otmCtx || !otmCtx->selectedDeviceInfo)
+ {
+ return NULL;
+ }
+
+ otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_RANDOM_DEVICE_PIN;
+
+ OicUuid_t uuidPT = {.id={0}};
+ if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
+ {
+ OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+ return NULL;
+ }
+ memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id, UUID_LENGTH);
+
+ return BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
+}
+
+char* CreatePinBasedOwnerTransferPayload(OTMContext_t* otmCtx)
+{
+ if(!otmCtx || !otmCtx->selectedDeviceInfo)
+ {
+ return NULL;
+ }
+
+ OicUuid_t uuidPT = {.id={0}};
+
+ if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
+ {
+ OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+ return NULL;
+ }
+ memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id , UUID_LENGTH);
+ otmCtx->selectedDeviceInfo->doxm->owned = true;
+
+ return BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
+}
+
+OCStackResult InputPinCodeCallback(OTMContext_t* otmCtx)
+{
+ if(!otmCtx || !otmCtx->selectedDeviceInfo)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ uint8_t pinData[OXM_RANDOM_PIN_SIZE + 1];
+
+ OCStackResult res = InputPin((char*)pinData, OXM_RANDOM_PIN_SIZE + 1);
+ if(OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Failed to input PIN");
+ return res;
+ }
+
+ OicUuid_t deviceUUID = {.id={0}};
+ if (OC_STACK_OK != GetDoxmDeviceID(&deviceUUID))
+ {
+ OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+ return OC_STACK_ERROR;
+ }
+
+ res = AddTmpPskWithPIN(&otmCtx->selectedDeviceInfo->doxm->deviceID,
+ SYMMETRIC_PAIR_WISE_KEY,
+ (char*)pinData, OXM_RANDOM_PIN_SIZE,
+ 1, &deviceUUID, &otmCtx->subIdForPinOxm);
+ if(res != OC_STACK_OK)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed to save the temporal PSK : %d", res);
+ }
+
+ return res;
+}
+
+OCStackResult CreateSecureSessionRandomPinCallbak(OTMContext_t* otmCtx)
+{
+ OC_LOG(INFO, TAG, "IN CreateSecureSessionRandomPinCallbak");
+
+ if(!otmCtx || !otmCtx->selectedDeviceInfo)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCProvisionDev_t* selDevInfo = otmCtx->selectedDeviceInfo;
+ CAEndpoint_t *endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
+ if(NULL == endpoint)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+ memcpy(endpoint,&selDevInfo->endpoint,sizeof(CAEndpoint_t));
+ endpoint->port = selDevInfo->securePort;
+ CAResult_t caresult = CAInitiateHandshake(endpoint);
+ OICFree(endpoint);
+ if (CA_STATUS_OK != caresult)
+ {
+ OC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
+ return OC_STACK_ERROR;
+ }
+
+ OC_LOG(INFO, TAG, "OUT CreateSecureSessionRandomPinCallbak");
+
+ return OC_STACK_OK;
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200112L
+#endif
+
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "ocstack.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "logger.h"
+#include "cJSON.h"
+#include "utlist.h"
+#include "ocpayload.h"
+
+#include "securevirtualresourcetypes.h"
+#include "srmresourcestrings.h" //@note: SRM's internal header
+#include "doxmresource.h" //@note: SRM's internal header
+#include "pstatresource.h" //@note: SRM's internal header
+
+#include "pmtypes.h"
+#include "pmutility.h"
+
+#include "srmutility.h"
+
+#define TAG ("PM-UTILITY")
+
+typedef struct _DiscoveryInfo{
+ OCProvisionDev_t **ppDevicesList;
+ bool isOwnedDiscovery;
+} DiscoveryInfo;
+
+/**
+ * Function to search node in linked list that matches given IP and port.
+ *
+ * @param[in] pList List of OCProvisionDev_t.
+ * @param[in] addr address of target device.
+ * @param[in] port port of remote server.
+ *
+ * @return pointer of OCProvisionDev_t if exist, otherwise NULL
+ */
+OCProvisionDev_t* GetDevice(OCProvisionDev_t **ppDevicesList, const char* addr, const uint16_t port)
+{
+ if(NULL == addr || NULL == *ppDevicesList)
+ {
+ OC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);
+ return NULL;
+ }
+
+ OCProvisionDev_t *ptr = NULL;
+ LL_FOREACH(*ppDevicesList, ptr)
+ {
+ if( strcmp(ptr->endpoint.addr, addr) == 0 && port == ptr->endpoint.port)
+ {
+ return ptr;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Add device information to list.
+ *
+ * @param[in] pList List of OCProvisionDev_t.
+ * @param[in] addr address of target device.
+ * @param[in] port port of remote server.
+ * @param[in] adapter adapter type of endpoint.
+ * @param[in] doxm pointer to doxm instance.
+ * @param[in] connType connectivity type of endpoint
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult AddDevice(OCProvisionDev_t **ppDevicesList, const char* addr, const uint16_t port,
+ OCTransportAdapter adapter, OCConnectivityType connType, OicSecDoxm_t *doxm)
+{
+ if (NULL == addr)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCProvisionDev_t *ptr = GetDevice(ppDevicesList, addr, port);
+ if(!ptr)
+ {
+ ptr = (OCProvisionDev_t *)OICCalloc(1, sizeof (OCProvisionDev_t));
+ if (NULL == ptr)
+ {
+ OC_LOG(ERROR, TAG, "Error while allocating memory for linkedlist node !!");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ OICStrcpy(ptr->endpoint.addr, MAX_ADDR_STR_SIZE, addr);
+ ptr->endpoint.port = port;
+ ptr->doxm = doxm;
+ ptr->securePort = DEFAULT_SECURE_PORT;
+ ptr->endpoint.adapter = adapter;
+ ptr->next = NULL;
+ ptr->connType = connType;
+ ptr->devStatus = DEV_STATUS_ON; //AddDevice is called when discovery(=alive)
+
+ LL_PREPEND(*ppDevicesList, ptr);
+ }
+
+ return OC_STACK_OK;
+}
+
+/**
+ * Function to set secure port information from the given list of devices.
+ *
+ * @param[in] pList List of OCProvisionDev_t.
+ * @param[in] addr address of target device.
+ * @param[in] port port of remote server.
+ * @param[in] secureport secure port information.
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult UpdateSecurePortOfDevice(OCProvisionDev_t **ppDevicesList, const char *addr,
+ uint16_t port, uint16_t securePort)
+{
+ OCProvisionDev_t *ptr = GetDevice(ppDevicesList, addr, port);
+
+ if(!ptr)
+ {
+ OC_LOG(ERROR, TAG, "Can not find device information in the discovery device list");
+ return OC_STACK_ERROR;
+ }
+
+ ptr->securePort = securePort;
+
+ return OC_STACK_OK;
+}
+
+/**
+ * This function deletes list of provision target devices
+ *
+ * @param[in] pDevicesList List of OCProvisionDev_t.
+ */
+void PMDeleteDeviceList(OCProvisionDev_t *pDevicesList)
+{
+ if(pDevicesList)
+ {
+ OCProvisionDev_t *del = NULL, *tmp = NULL;
+ LL_FOREACH_SAFE(pDevicesList, del, tmp)
+ {
+ LL_DELETE(pDevicesList, del);
+
+ DeleteDoxmBinData(del->doxm);
+ DeletePstatBinData(del->pstat);
+ OICFree(del);
+ }
+ }
+}
+
+OCProvisionDev_t* PMCloneOCProvisionDev(const OCProvisionDev_t* src)
+{
+ OC_LOG(DEBUG, TAG, "IN PMCloneOCProvisionDev");
+
+ if (!src)
+ {
+ OC_LOG(ERROR, TAG, "PMCloneOCProvisionDev : Invalid parameter");
+ return NULL;
+ }
+
+ // TODO: Consider use VERIFY_NON_NULL instead of if ( null check ) { goto exit; }
+ OCProvisionDev_t* newDev = (OCProvisionDev_t*)OICCalloc(1, sizeof(OCProvisionDev_t));
+ VERIFY_NON_NULL(TAG, newDev, ERROR);
+
+ memcpy(&newDev->endpoint, &src->endpoint, sizeof(OCDevAddr));
+
+ if (src->pstat)
+ {
+ newDev->pstat= (OicSecPstat_t*)OICCalloc(1, sizeof(OicSecPstat_t));
+ VERIFY_NON_NULL(TAG, newDev->pstat, ERROR);
+
+ memcpy(newDev->pstat, src->pstat, sizeof(OicSecPstat_t));
+ // We have to assign NULL for not necessary information to prevent memory corruption.
+ newDev->pstat->sm = NULL;
+ }
+
+ if (src->doxm)
+ {
+ newDev->doxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t));
+ VERIFY_NON_NULL(TAG, newDev->doxm, ERROR);
+
+ memcpy(newDev->doxm, src->doxm, sizeof(OicSecDoxm_t));
+ // We have to assign NULL for not necessary information to prevent memory corruption.
+ newDev->doxm->oxmType = NULL;
+ newDev->doxm->oxm = NULL;
+ }
+
+ newDev->securePort = src->securePort;
+ newDev->devStatus = src->devStatus;
+ newDev->connType = src->connType;
+ newDev->next = NULL;
+
+ OC_LOG(DEBUG, TAG, "OUT PMCloneOCProvisionDev");
+
+ return newDev;
+
+exit:
+ OC_LOG(ERROR, TAG, "PMCloneOCProvisionDev : Failed to allocate memory");
+ if (newDev)
+ {
+ OICFree(newDev->pstat);
+ OICFree(newDev->doxm);
+ OICFree(newDev);
+ }
+ return NULL;
+}
+
+/**
+ * Timeout implementation for secure discovery. When performing secure discovery,
+ * we should wait a certain period of time for getting response of each devices.
+ *
+ * @param[in] waittime Timeout in seconds.
+ * @param[in] waitForStackResponse if true timeout function will call OCProcess while waiting.
+ * @return OC_STACK_OK on success otherwise error.
+ */
+OCStackResult PMTimeout(unsigned short waittime, bool waitForStackResponse)
+{
+ struct timespec startTime = {.tv_sec=0, .tv_nsec=0};
+ struct timespec currTime = {.tv_sec=0, .tv_nsec=0};
+
+ OCStackResult res = OC_STACK_OK;
+#ifdef _POSIX_MONOTONIC_CLOCK
+ int clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);
+#else
+ int clock_res = clock_gettime(CLOCK_REALTIME, &startTime);
+#endif
+ if (0 != clock_res)
+ {
+ return OC_STACK_ERROR;
+ }
+ while (OC_STACK_OK == res)
+ {
+#ifdef _POSIX_MONOTONIC_CLOCK
+ clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);
+#else
+ clock_res = clock_gettime(CLOCK_REALTIME, &currTime);
+#endif
+ if (0 != clock_res)
+ {
+ return OC_STACK_TIMEOUT;
+ }
+ long elapsed = (currTime.tv_sec - startTime.tv_sec);
+ if (elapsed > waittime)
+ {
+ return OC_STACK_OK;
+ }
+ if (waitForStackResponse)
+ {
+ res = OCProcess();
+ }
+ }
+ return res;
+}
+
+/**
+ * Extract secure port information from payload of discovery response.
+ *
+ * @param[in] jsonStr response payload of /oic/res discovery.
+ *
+ * @return Secure port
+ */
+uint16_t GetSecurePortFromJSON(char* jsonStr)
+{
+ // TODO: Modify error handling
+ if (NULL == jsonStr)
+ {
+ return 0;
+ }
+ cJSON *jsonProp = NULL;
+ cJSON *jsonP = NULL;
+ cJSON *jsonPort = NULL;
+
+ cJSON *jsonRoot = cJSON_Parse(jsonStr);
+ if(!jsonRoot)
+ {
+ // TODO: Add error log & return default secure port
+ return 0;
+ }
+
+ jsonProp = cJSON_GetObjectItem(jsonRoot, "prop");
+ if(!jsonProp)
+ {
+ // TODO: Add error log & return default secure port
+ return 0;
+ }
+
+ jsonP = cJSON_GetObjectItem(jsonProp, "p");
+ if(!jsonP)
+ {
+ // TODO: Add error log & return default secure port
+ return 0;
+ }
+
+ jsonPort = cJSON_GetObjectItem(jsonP, "port");
+ if(!jsonPort)
+ {
+ // TODO: Add error log & return default secure port
+ return 0;
+ }
+
+ return (uint16_t)jsonPort->valueint;
+}
+
+bool PMGenerateQuery(bool isSecure,
+ const char* address, const uint16_t port,
+ const OCConnectivityType connType,
+ char* buffer, size_t bufferSize, const char* uri)
+{
+ if(!address || !buffer || !uri)
+ {
+ OC_LOG(ERROR, TAG, "PMGenerateQuery : Invalid parameters.");
+ return false;
+ }
+
+ int snRet = 0;
+ char* prefix = (isSecure == true) ? COAPS_PREFIX : COAP_PREFIX;
+
+ switch(connType & CT_MASK_ADAPTER)
+ {
+ case CT_ADAPTER_IP:
+ switch(connType & CT_MASK_FLAGS)
+ {
+ case CT_IP_USE_V4:
+ snRet = snprintf(buffer, bufferSize, "%s%s:%d%s",
+ prefix, address, port, uri);
+ break;
+ case CT_IP_USE_V6:
+ snRet = snprintf(buffer, bufferSize, "%s[%s]:%d%s",
+ prefix, address, port, uri);
+ break;
+ default:
+ OC_LOG(ERROR, TAG, "Unknown address format.");
+ return false;
+ }
+ // snprintf return value check
+ if (snRet < 0)
+ {
+ OC_LOG_V(ERROR, TAG, "PMGenerateQuery : Error (snprintf) %d\n", snRet);
+ return false;
+ }
+ else if ((size_t)snRet >= bufferSize)
+ {
+ OC_LOG_V(ERROR, TAG, "PMGenerateQuery : Truncated (snprintf) %d\n", snRet);
+ return false;
+ }
+
+ break;
+ // TODO: We need to verify tinyDTLS in below cases
+ case CT_ADAPTER_GATT_BTLE:
+ case CT_ADAPTER_RFCOMM_BTEDR:
+ OC_LOG(ERROR, TAG, "Not supported connectivity adapter.");
+ return false;
+ break;
+ default:
+ OC_LOG(ERROR, TAG, "Unknown connectivity adapter.");
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Callback handler for getting secure port information using /oic/res discovery.
+ *
+ * @param[in] ctx user context
+ * @param[in] handle Handle for response
+ * @param[in] clientResponse Response information(It will contain payload)
+ *
+ * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
+ * OC_STACK_DELETE_TRANSACTION to delete it.
+ */
+static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ if (ctx == NULL)
+ {
+ OC_LOG(ERROR, TAG, "Lost List of device information");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ (void)UNUSED;
+ if (clientResponse)
+ {
+ if (NULL == clientResponse->payload)
+ {
+ OC_LOG(INFO, TAG, "Skiping Null payload");
+ }
+ else
+ {
+ if (PAYLOAD_TYPE_DISCOVERY != clientResponse->payload->type)
+ {
+ OC_LOG(INFO, TAG, "Wrong payload type");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ uint16_t securePort = 0;
+ OCResourcePayload* resPayload = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
+
+ if (resPayload && resPayload->secure)
+ {
+ securePort = resPayload->port;
+ }
+ else
+ {
+ OC_LOG(INFO, TAG, "Can not find secure port information.");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
+ OCProvisionDev_t **ppDevicesList = pDInfo->ppDevicesList;
+
+ OCStackResult res = UpdateSecurePortOfDevice(ppDevicesList, clientResponse->devAddr.addr,
+ clientResponse->devAddr.port, securePort);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Error while getting secure port.");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ OC_LOG(INFO, TAG, "Exiting SecurePortDiscoveryHandler.");
+ }
+
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ else
+ {
+ OC_LOG(INFO, TAG, "Skiping Null response");
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler for PMDeviceDiscovery API.
+ *
+ * @param[in] ctx User context
+ * @param[in] handle Handler for response
+ * @param[in] clientResponse Response information (It will contain payload)
+ * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
+ * OC_STACK_DELETE_TRANSACTION to delete it.
+ */
+static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ if (ctx == NULL)
+ {
+ OC_LOG(ERROR, TAG, "Lost List of device information");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ (void)UNUSED;
+ if (clientResponse)
+ {
+ if (NULL == clientResponse->payload)
+ {
+ OC_LOG(INFO, TAG, "Skiping Null payload");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ if (OC_STACK_OK != clientResponse->result)
+ {
+ OC_LOG(INFO, TAG, "Error in response");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ else
+ {
+ if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
+ {
+ OC_LOG(INFO, TAG, "Unknown payload type");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ OicSecDoxm_t *ptrDoxm = JSONToDoxmBin(
+ ((OCSecurityPayload*)clientResponse->payload)->securityData);
+ if (NULL == ptrDoxm)
+ {
+ OC_LOG(INFO, TAG, "Ignoring malformed JSON");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ else
+ {
+ OC_LOG(DEBUG, TAG, "Successfully converted doxm json to bin.");
+
+ //If this is owend device discovery we have to filter out the responses.
+ DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
+ OCProvisionDev_t **ppDevicesList = pDInfo->ppDevicesList;
+
+ // Get my device ID from doxm resource
+ OicUuid_t myId;
+ memset(&myId, 0, sizeof(myId));
+ OCStackResult res = GetDoxmDevOwnerId(&myId);
+ if(OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Error while getting my device ID.");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ // If this is owned discovery response but owner is not me then discard it.
+ if( (pDInfo->isOwnedDiscovery) &&
+ (0 != memcmp(&ptrDoxm->owner.id, &myId.id, sizeof(myId.id))) )
+ {
+ OC_LOG(DEBUG, TAG, "Discovered device is not owend by me");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ res = AddDevice(ppDevicesList, clientResponse->devAddr.addr,
+ clientResponse->devAddr.port,
+ clientResponse->devAddr.adapter,
+ clientResponse->connType, ptrDoxm);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ //Try to the unicast discovery to getting secure port
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = { 0, };
+ if(!PMGenerateQuery(false,
+ clientResponse->devAddr.addr, clientResponse->devAddr.port,
+ clientResponse->connType,
+ query, sizeof(query), OC_RSRVD_WELL_KNOWN_URI))
+ {
+ OC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ OC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ OCCallbackData cbData;
+ cbData.cb = &SecurePortDiscoveryHandler;
+ cbData.context = ctx;
+ cbData.cd = NULL;
+ OCStackResult ret = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0,
+ clientResponse->connType, OC_LOW_QOS, &cbData, NULL, 0);
+ // TODO: Should we use the default secure port in case of error?
+ if(OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "Failed to Secure Port Discovery");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ else
+ {
+ OC_LOG_V(INFO, TAG, "OCDoResource with [%s] Success", query);
+ }
+ OC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
+ }
+
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ }
+ else
+ {
+ OC_LOG(INFO, TAG, "Skiping Null response");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Discover owned/unowned devices in the same IP subnet. .
+ *
+ * @param[in] waittime Timeout in seconds.
+ * @param[in] isOwned bool flag for owned / unowned discovery
+ * @param[in] ppDevicesList List of OCProvisionDev_t.
+ *
+ * @return OC_STACK_OK on success otherwise error.
+ */
+OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisionDev_t **ppDevicesList)
+{
+ OC_LOG(DEBUG, TAG, "IN PMDeviceDiscovery");
+
+ if (NULL != *ppDevicesList)
+ {
+ OC_LOG(ERROR, TAG, "List is not null can cause memory leak");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ const char DOXM_OWNED_FALSE_MULTICAST_QUERY[] = "/oic/sec/doxm?Owned=FALSE";
+ const char DOXM_OWNED_TRUE_MULTICAST_QUERY[] = "/oic/sec/doxm?Owned=TRUE";
+
+ DiscoveryInfo *pDInfo = OICCalloc(1, sizeof(DiscoveryInfo));
+ if(NULL == pDInfo)
+ {
+ OC_LOG(ERROR, TAG, "PMDeviceDiscovery : Memory allocation failed.");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ pDInfo->ppDevicesList = ppDevicesList;
+ pDInfo->isOwnedDiscovery = isOwned;
+
+ OCCallbackData cbData;
+ cbData.cb = &DeviceDiscoveryHandler;
+ cbData.context = (void *)pDInfo;
+ cbData.cd = NULL;
+ OCStackResult res = OC_STACK_ERROR;
+
+ const char* query = isOwned ? DOXM_OWNED_TRUE_MULTICAST_QUERY :
+ DOXM_OWNED_FALSE_MULTICAST_QUERY;
+
+ res = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0,
+ CT_DEFAULT, OC_LOW_QOS, &cbData, NULL, 0);
+ if (res != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ goto exit;
+ }
+
+ //Waiting for each response.
+ res = PMTimeout(waittime, true);
+ if(OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Failed to wait response for secure discovery.");
+ goto exit;
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT PMDeviceDiscovery");
+
+exit:
+ OICFree(pDInfo);
+ return res;
+}
+
+/**
+ * Function to print OCProvisionDev_t for debug purpose.
+ *
+ * @param[in] pDev Pointer to OCProvisionDev_t. It's information will be printed by OC_LOG_XX
+ *
+ */
+void PMPrintOCProvisionDev(const OCProvisionDev_t* pDev)
+{
+ if (pDev)
+ {
+ OC_LOG(DEBUG, TAG, "+++++ OCProvisionDev_t Information +++++");
+ OC_LOG_V(DEBUG, TAG, "IP %s", pDev->endpoint.addr);
+ OC_LOG_V(DEBUG, TAG, "PORT %d", pDev->endpoint.port);
+ OC_LOG_V(DEBUG, TAG, "S-PORT %d", pDev->securePort);
+ OC_LOG(DEBUG, TAG, "++++++++++++++++++++++++++++++++++++++++");
+ }
+ else
+ {
+ OC_LOG(DEBUG, TAG, "+++++ OCProvisionDev_t is NULL +++++");
+ }
+}
+
+bool PMDeleteFromUUIDList(OCUuidList_t *pUuidList, OicUuid_t *targetId)
+{
+ if(pUuidList == NULL || targetId == NULL)
+ {
+ return false;
+ }
+ OCUuidList_t *tmp1 = NULL,*tmp2=NULL;
+ LL_FOREACH_SAFE(pUuidList, tmp1, tmp2)
+ {
+ if(0 == memcmp(tmp1->dev.id, targetId->id, sizeof(targetId->id)))
+ {
+ LL_DELETE(pUuidList, tmp1);
+ OICFree(tmp1);
+ return true;
+ }
+ }
+ return false;
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 <stdbool.h>
+#include <sqlite3.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "logger.h"
+#include "oic_malloc.h"
+#include "provisioningdatabasemanager.h"
+#include "pmutility.h"
+#include "oic_string.h"
+#include "utlist.h"
+
+
+#define DB_FILE "PDM.db"
+
+#define TAG "PDM"
+
+#define PDM_STALE_STATE 1
+#define PDM_ACTIVE_STATE 0
+
+#define PDM_FIRST_INDEX 0
+#define PDM_SECOND_INDEX 1
+
+#define PDM_BIND_INDEX_FIRST 1
+#define PDM_BIND_INDEX_SECOND 2
+#define PDM_BIND_INDEX_THIRD 3
+
+#define PDM_CREATE_T_DEVICE_LIST "create table T_DEVICE_LIST(ID INTEGER PRIMARY KEY AUTOINCREMENT,\
+ UUID BLOB NOT NULL UNIQUE);"
+
+#define PDM_CREATE_T_DEVICE_LINK "create table T_DEVICE_LINK_STATE(ID INT NOT NULL, ID2 INT NOT \
+ NULL,STATE INT NOT NULL, PRIMARY KEY (ID, ID2));"
+/**
+ * Macro to verify sqlite success.
+ * eg: VERIFY_NON_NULL(TAG, ptrData, ERROR,OC_STACK_ERROR);
+ */
+#define PDM_VERIFY_SQLITE_OK(tag, arg, logLevel, retValue) do{ if (SQLITE_OK != (arg)) \
+ { OC_LOG_V((logLevel), tag, ("Error in " #arg ", Error Message: %s"), \
+ sqlite3_errmsg(g_db)); return retValue; }}while(0)
+
+#define PDM_SQLITE_TRANSACTION_BEGIN "BEGIN TRANSACTION;"
+#define PDM_SQLITE_TRANSACTION_COMMIT "COMMIT;"
+#define PDM_SQLITE_TRANSACTION_ROLLBACK "ROLLBACK;"
+#define PDM_SQLITE_GET_STALE_INFO "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE STATE = ?"
+#define PDM_SQLITE_INSERT_T_DEVICE_LIST "INSERT INTO T_DEVICE_LIST VALUES(?,?)"
+#define PDM_SQLITE_GET_ID "SELECT ID FROM T_DEVICE_LIST WHERE UUID like ?"
+#define PDM_SQLITE_INSERT_LINK_DATA "INSERT INTO T_DEVICE_LINK_STATE VALUES(?,?,?)"
+#define PDM_SQLITE_DELETE_LINK "DELETE FROM T_DEVICE_LINK_STATE WHERE ID = ? and ID2 = ?"
+#define PDM_SQLITE_DELETE_DEVICE_LINK "DELETE FROM T_DEVICE_LINK_STATE WHERE ID = ? or ID2 = ?"
+#define PDM_SQLITE_DELETE_DEVICE "DELETE FROM T_DEVICE_LIST WHERE ID = ?"
+#define PDM_SQLITE_UPDATE_LINK "UPDATE T_DEVICE_LINK_STATE SET STATE = ? WHERE ID = ? and ID2 = ?"
+#define PDM_SQLITE_LIST_ALL_UUID "SELECT UUID FROM T_DEVICE_LIST"
+#define PDM_SQLITE_GET_UUID "SELECT UUID FROM T_DEVICE_LIST WHERE ID = ?"
+#define PDM_SQLITE_GET_LINKED_DEVICES "SELECT ID,ID2 FROM T_DEVICE_LINK_STATE WHERE ID = ? or ID2 = ?"
+
+#define ASCENDING_ORDER(id1, id2) do{if( (id1) > (id2) )\
+ { int temp; temp = id1; id1 = id2; id2 = temp; }}while(0)
+
+#define CHECK_PDM_INIT(tag) do{if(true != gInit)\
+ { OC_LOG(ERROR, (tag), "PDB is not initialized"); \
+ return OC_STACK_PDM_IS_NOT_INITIALIZED; }}while(0)
+
+static sqlite3 *g_db = NULL;
+static bool gInit = false; /* Only if we can open sqlite db successfully, gInit is true. */
+
+/**
+ * function to create DB in case DB doesn't exists
+ */
+static OCStackResult createDB(const char* path)
+{
+
+ int result = 0;
+ result = sqlite3_open_v2(path, &g_db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
+
+ result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LIST, NULL, NULL, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
+
+ OC_LOG(INFO, TAG, "Created T_DEVICE_LIST");
+ result = sqlite3_exec(g_db, PDM_CREATE_T_DEVICE_LINK, NULL, NULL, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, result, ERROR, OC_STACK_ERROR);
+
+ OC_LOG(INFO, TAG, "Created T_DEVICE_LINK_STATE");
+ gInit = true;
+ return OC_STACK_OK;
+}
+
+
+/**
+ * Function to begin any transaction
+ */
+static OCStackResult begin()
+{
+ int res = 0;
+ res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_BEGIN, NULL, NULL, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+ return OC_STACK_OK;
+}
+
+/**
+ * Function to commit any transaction
+ */
+static OCStackResult commit()
+{
+ int res = 0;
+ res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_COMMIT, NULL, NULL, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+ return OC_STACK_OK;
+}
+
+/**
+ * Function to rollback any transaction
+ */
+static OCStackResult rollback()
+{
+ int res = 0;
+ res = sqlite3_exec(g_db, PDM_SQLITE_TRANSACTION_ROLLBACK, NULL, NULL, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+ return OC_STACK_OK;
+}
+
+/**
+ * Error log callback called by SQLite stack in case of error
+ */
+void errLogCallback(void *pArg, int iErrCode, const char *zMsg)
+{
+ (void) pArg;
+ (void) iErrCode;
+ (void) zMsg;
+ OC_LOG_V(DEBUG,TAG, "(%d) %s", iErrCode, zMsg);
+}
+
+OCStackResult PDMInit(const char *path)
+{
+ int rc;
+ const char *dbPath = NULL;
+ if (SQLITE_OK != sqlite3_config(SQLITE_CONFIG_LOG, errLogCallback, NULL))
+ {
+ OC_LOG(INFO, TAG, "Unable to enable debug log of sqlite");
+ }
+
+ if (NULL == path || !*path)
+ {
+ dbPath = DB_FILE;
+ }
+ else
+ {
+ dbPath = path;
+ }
+ rc = sqlite3_open_v2(dbPath, &g_db, SQLITE_OPEN_READWRITE, NULL);
+ if (SQLITE_OK != rc)
+ {
+ OC_LOG_V(INFO, TAG, "ERROR: Can't open database: %s", sqlite3_errmsg(g_db));
+ return createDB(dbPath);
+ }
+ gInit = true;
+ return OC_STACK_OK;
+}
+
+
+OCStackResult PDMAddDevice(const OicUuid_t *UUID)
+{
+ CHECK_PDM_INIT(TAG);
+ if (NULL == UUID)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ sqlite3_stmt *stmt = 0;
+ int res =0;
+ res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_T_DEVICE_LIST,
+ strlen(PDM_SQLITE_INSERT_T_DEVICE_LIST) + 1, &stmt, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_SECOND, UUID, UUID_LENGTH, SQLITE_STATIC);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_step(stmt);
+ if (SQLITE_DONE != res)
+ {
+ if (SQLITE_CONSTRAINT == res)
+ {
+ //new OCStack result code
+ OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
+ sqlite3_finalize(stmt);
+ return OC_STACK_DUPLICATE_UUID;
+ }
+ OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
+ sqlite3_finalize(stmt);
+ return OC_STACK_ERROR;
+ }
+ sqlite3_finalize(stmt);
+ return OC_STACK_OK;
+}
+
+/**
+ *function to get Id for given UUID
+ */
+static OCStackResult getIdForUUID(const OicUuid_t *UUID , int *id)
+{
+ sqlite3_stmt *stmt = 0;
+ int res = 0;
+ res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, strlen(PDM_SQLITE_GET_ID) + 1, &stmt, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ OC_LOG(DEBUG, TAG, "Binding Done");
+ while (SQLITE_ROW == sqlite3_step(stmt))
+ {
+ int tempId = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
+ OC_LOG_V(DEBUG, TAG, "ID is %d", tempId);
+ *id = tempId;
+ sqlite3_finalize(stmt);
+ return OC_STACK_OK;
+ }
+ sqlite3_finalize(stmt);
+ return OC_STACK_INVALID_PARAM;
+}
+
+/**
+ * Function to check duplication of device's Device ID.
+ */
+bool PDMIsDuplicateDevice(const OicUuid_t* UUID)
+{
+ if(gInit)
+ {
+ if (NULL == UUID)
+ {
+ OC_LOG(ERROR, TAG, "UUID is NULL");
+ return true;
+ }
+
+ sqlite3_stmt *stmt = 0;
+ int res = 0;
+ res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_ID, strlen(PDM_SQLITE_GET_ID) + 1, &stmt, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_blob(stmt, PDM_BIND_INDEX_FIRST, UUID, UUID_LENGTH, SQLITE_STATIC);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ OC_LOG(DEBUG, TAG, "Binding Done");
+
+ while (SQLITE_ROW == sqlite3_step(stmt))
+ {
+ OC_LOG(ERROR, TAG, "UUID is duplicated");
+ sqlite3_finalize(stmt);
+ return true;
+ }
+ sqlite3_finalize(stmt);
+ return false;
+ }
+ OC_LOG(ERROR, TAG, "PDB is not initialized");
+ return true; // return true will stop futher process.
+}
+
+/**
+ * Function to add link in sqlite
+ */
+static OCStackResult addlink(int id1, int id2)
+{
+ sqlite3_stmt *stmt = 0;
+ int res = 0;
+ res = sqlite3_prepare_v2(g_db, PDM_SQLITE_INSERT_LINK_DATA,
+ strlen(PDM_SQLITE_INSERT_LINK_DATA) + 1, &stmt, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, PDM_ACTIVE_STATE);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ if (sqlite3_step(stmt) != SQLITE_DONE)
+ {
+ OC_LOG_V(ERROR, TAG, "Error Occured: %s",sqlite3_errmsg(g_db));
+ sqlite3_finalize(stmt);
+ return OC_STACK_ERROR;
+ }
+ sqlite3_finalize(stmt);
+ return OC_STACK_OK;
+}
+
+OCStackResult PDMLinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
+{
+ CHECK_PDM_INIT(TAG);
+ if (NULL == UUID1 || NULL == UUID2)
+ {
+ OC_LOG(ERROR, TAG, "Invalid PARAM");
+ return OC_STACK_INVALID_PARAM;
+ }
+ int id1 = 0;
+ if (OC_STACK_OK != getIdForUUID(UUID1, &id1))
+ {
+ OC_LOG(ERROR, TAG, "Requested value not found");
+ return OC_STACK_INVALID_PARAM;
+ }
+ int id2 = 0;
+ if (OC_STACK_OK != getIdForUUID(UUID2, &id2))
+ {
+ OC_LOG(ERROR, TAG, "Requested value not found");
+ return OC_STACK_INVALID_PARAM;
+ }
+ ASCENDING_ORDER(id1, id2);
+ return addlink(id1, id2);
+}
+
+/**
+ * Function to remove created link
+ */
+static OCStackResult removeLink(int id1, int id2)
+{
+ int res = 0;
+ sqlite3_stmt *stmt = 0;
+ res = sqlite3_prepare_v2(g_db, PDM_SQLITE_DELETE_LINK, strlen(PDM_SQLITE_DELETE_LINK) + 1, &stmt, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id1);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id2);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ if (SQLITE_DONE != sqlite3_step(stmt))
+ {
+ OC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
+ sqlite3_finalize(stmt);
+ return OC_STACK_ERROR;
+ }
+ sqlite3_finalize(stmt);
+ return OC_STACK_OK;
+}
+
+OCStackResult PDMUnlinkDevices(const OicUuid_t *UUID1, const OicUuid_t *UUID2)
+{
+ CHECK_PDM_INIT(TAG);
+ if (NULL == UUID1 || NULL == UUID2)
+ {
+ OC_LOG(ERROR, TAG, "Invalid PARAM");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ int id1 = 0;
+ if (OC_STACK_OK != getIdForUUID(UUID1, &id1))
+ {
+ OC_LOG(ERROR, TAG, "Requested value not found");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ int id2 = 0;
+ if (OC_STACK_OK != getIdForUUID(UUID2, &id2))
+ {
+ OC_LOG(ERROR, TAG, "Requested value not found");
+ return OC_STACK_INVALID_PARAM;
+ }
+ ASCENDING_ORDER(id1, id2);
+ return removeLink(id1, id2);
+}
+
+static OCStackResult removeFromDeviceList(int id)
+{
+ sqlite3_stmt *stmt = 0;
+ int res = 0;
+ res = sqlite3_prepare_v2(g_db, PDM_SQLITE_DELETE_DEVICE,
+ strlen(PDM_SQLITE_DELETE_DEVICE) + 1, &stmt, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ if (sqlite3_step(stmt) != SQLITE_DONE)
+ {
+ OC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
+ sqlite3_finalize(stmt);
+ return OC_STACK_ERROR;
+ }
+ sqlite3_finalize(stmt);
+ return OC_STACK_OK;
+}
+
+OCStackResult PDMDeleteDevice(const OicUuid_t *UUID)
+{
+ CHECK_PDM_INIT(TAG);
+ if (NULL == UUID)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+ int id = 0;
+ if (OC_STACK_OK != getIdForUUID(UUID, &id))
+ {
+ OC_LOG(ERROR, TAG, "Requested value not found");
+ return OC_STACK_INVALID_PARAM;
+ }
+ begin();
+ if(OC_STACK_OK != removeFromDeviceList(id))
+ {
+ rollback();
+ OC_LOG(ERROR, TAG, "Requested value not found");
+ return OC_STACK_ERROR;
+ }
+ commit();
+ return OC_STACK_OK;
+}
+
+
+static OCStackResult updateLinkState(int id1, int id2, int state)
+{
+ sqlite3_stmt *stmt = 0;
+ int res = 0 ;
+ res = sqlite3_prepare_v2(g_db, PDM_SQLITE_UPDATE_LINK,
+ strlen(PDM_SQLITE_UPDATE_LINK) + 1, &stmt, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, state);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id1);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_THIRD, id2);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ if (SQLITE_DONE != sqlite3_step(stmt))
+ {
+ OC_LOG_V(ERROR, TAG, "Error message: %s", sqlite3_errmsg(g_db));
+ sqlite3_finalize(stmt);
+ return OC_STACK_ERROR;
+ }
+ sqlite3_finalize(stmt);
+ return OC_STACK_OK;
+}
+
+OCStackResult PDMSetLinkStale(const OicUuid_t* uuidOfDevice1, const OicUuid_t* uuidOfDevice2)
+{
+ CHECK_PDM_INIT(TAG);
+ if (NULL == uuidOfDevice1 || NULL == uuidOfDevice2)
+ {
+ OC_LOG(ERROR, TAG, "Invalid PARAM");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ int id1 = 0;
+ if (OC_STACK_OK != getIdForUUID(uuidOfDevice1, &id1))
+ {
+ OC_LOG(ERROR, TAG, "Requested value not found");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ int id2 = 0;
+ if (OC_STACK_OK != getIdForUUID(uuidOfDevice2, &id2))
+ {
+ OC_LOG(ERROR, TAG, "Requested value not found");
+ return OC_STACK_INVALID_PARAM;
+ }
+ ASCENDING_ORDER(id1, id2);
+ return updateLinkState(id1, id2, PDM_STALE_STATE);
+
+}
+
+OCStackResult PDMGetOwnedDevices(OCUuidList_t **uuidList, size_t *numOfDevices)
+{
+ CHECK_PDM_INIT(TAG);
+ if (NULL != *uuidList)
+ {
+ OC_LOG(ERROR, TAG, "Not null list will cause memory leak");
+ return OC_STACK_INVALID_PARAM;
+ }
+ sqlite3_stmt *stmt = 0;
+ int res = 0;
+ res = sqlite3_prepare_v2(g_db, PDM_SQLITE_LIST_ALL_UUID,
+ strlen(PDM_SQLITE_LIST_ALL_UUID) + 1, &stmt, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ int counter = 0;
+ while (SQLITE_ROW == sqlite3_step(stmt))
+ {
+
+ const void *ptr = sqlite3_column_blob(stmt, PDM_FIRST_INDEX);
+ OicUuid_t *uid = (OicUuid_t *)ptr;
+ OCUuidList_t *temp = (OCUuidList_t *) OICCalloc(1,sizeof(OCUuidList_t));
+ if (NULL == temp)
+ {
+ OC_LOG_V(ERROR, TAG, "Memory allocation problem");
+ sqlite3_finalize(stmt);
+ return OC_STACK_NO_MEMORY;
+ }
+ memcpy(&temp->dev.id, uid->id, UUID_LENGTH);
+ LL_PREPEND(*uuidList,temp);
+ ++counter;
+ }
+ *numOfDevices = counter;
+ sqlite3_finalize(stmt);
+ return OC_STACK_OK;
+}
+
+static OCStackResult getUUIDforId(int id, OicUuid_t *uid)
+{
+ sqlite3_stmt *stmt = 0;
+ int res = 0;
+ res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_UUID,
+ strlen(PDM_SQLITE_GET_UUID) + 1, &stmt, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ while (SQLITE_ROW == sqlite3_step(stmt))
+ {
+ const void *ptr = sqlite3_column_blob(stmt, PDM_FIRST_INDEX);
+ memcpy(uid, ptr, sizeof(OicUuid_t));
+ }
+ sqlite3_finalize(stmt);
+ return OC_STACK_OK;
+}
+
+OCStackResult PDMGetLinkedDevices(const OicUuid_t *UUID, OCUuidList_t **UUIDLIST, size_t *numOfDevices)
+{
+ CHECK_PDM_INIT(TAG);
+ if (NULL != *UUIDLIST)
+ {
+ OC_LOG(ERROR, TAG, "Not null list will cause memory leak");
+ return OC_STACK_INVALID_PARAM;
+ }
+ if (NULL == UUID)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+ int id = 0;
+ if (OC_STACK_OK != getIdForUUID(UUID, &id))
+ {
+ OC_LOG(ERROR, TAG, "Requested value not found");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ sqlite3_stmt *stmt = 0;
+ int res = 0;
+ res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_LINKED_DEVICES,
+ strlen(PDM_SQLITE_GET_LINKED_DEVICES) + 1, &stmt, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, id);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_SECOND, id);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ int counter = 0;
+ while (SQLITE_ROW == sqlite3_step(stmt))
+ {
+ int i1 = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
+ int i2 = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
+
+ OicUuid_t temp = {{0,}};
+ if (i1 != id)
+ {
+ getUUIDforId(i1, &temp);
+ }
+ if (i2 != id)
+ {
+ getUUIDforId(i2, &temp);
+ }
+
+ OCUuidList_t *tempNode = (OCUuidList_t *) OICCalloc(1,sizeof(OCUuidList_t));
+ if (NULL == tempNode)
+ {
+ OC_LOG(ERROR, TAG, "No Memory");
+ sqlite3_finalize(stmt);
+ return OC_STACK_NO_MEMORY;
+ }
+ memcpy(&tempNode->dev.id, &temp.id, UUID_LENGTH);
+ LL_PREPEND(*UUIDLIST,tempNode);
+ ++counter;
+ }
+ *numOfDevices = counter;
+ sqlite3_finalize(stmt);
+ return OC_STACK_OK;
+}
+
+OCStackResult PDMGetToBeUnlinkedDevices(OCPairList_t **staleDevList, size_t *numOfDevices)
+{
+ CHECK_PDM_INIT(TAG);
+ if (NULL != *staleDevList)
+ {
+ OC_LOG(ERROR, TAG, "Not null list will cause memory leak");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ sqlite3_stmt *stmt = 0;
+ int res = 0;
+ res = sqlite3_prepare_v2(g_db, PDM_SQLITE_GET_STALE_INFO,
+ strlen(PDM_SQLITE_GET_STALE_INFO) + 1, &stmt, NULL);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ res = sqlite3_bind_int(stmt, PDM_BIND_INDEX_FIRST, PDM_STALE_STATE);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+
+ int counter = 0;
+ while (SQLITE_ROW == sqlite3_step(stmt))
+ {
+ int i1 = sqlite3_column_int(stmt, PDM_FIRST_INDEX);
+ int i2 = sqlite3_column_int(stmt, PDM_SECOND_INDEX);
+ OicUuid_t temp1 = {{0,}};
+ OicUuid_t temp2 = {{0,}};;
+ getUUIDforId(i1, &temp1);
+ getUUIDforId(i2, &temp2);
+
+ OCPairList_t *tempNode = (OCPairList_t *) OICCalloc(1, sizeof(OCPairList_t));
+ if (NULL == tempNode)
+ {
+ OC_LOG(ERROR, TAG, "No Memory");
+ sqlite3_finalize(stmt);
+ return OC_STACK_NO_MEMORY;
+ }
+ memcpy(&tempNode->dev.id, &temp1.id, UUID_LENGTH);
+ memcpy(&tempNode->dev2.id, &temp2.id, UUID_LENGTH);
+ LL_PREPEND(*staleDevList, tempNode);
+ ++counter;
+ }
+ *numOfDevices = counter;
+ sqlite3_finalize(stmt);
+ return OC_STACK_OK;
+}
+
+OCStackResult PDMClose()
+{
+ CHECK_PDM_INIT(TAG);
+ int res = 0;
+ res = sqlite3_close(g_db);
+ PDM_VERIFY_SQLITE_OK(TAG, res, ERROR, OC_STACK_ERROR);
+ return OC_STACK_OK;
+}
+
+void PDMDestoryOicUuidLinkList(OCUuidList_t* ptr)
+{
+ if(ptr)
+ {
+ OCUuidList_t *tmp1 = NULL,*tmp2=NULL;
+ LL_FOREACH_SAFE(ptr, tmp1, tmp2)
+ {
+ LL_DELETE(ptr, tmp1);
+ OICFree(tmp1);
+ }
+ }
+}
+
+void PDMDestoryStaleLinkList(OCPairList_t* ptr)
+{
+ if(ptr)
+ {
+ OCPairList_t *tmp1 = NULL,*tmp2=NULL;
+ LL_FOREACH_SAFE(ptr, tmp1, tmp2)
+ {
+ LL_DELETE(ptr, tmp1);
+ OICFree(tmp1);
+ }
+ }
+}
+++ /dev/null
-/* *****************************************************************
- *
- * 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.
- *
- * *****************************************************************/
-
-// 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,
-// Refer to http://pubs.opengroup.org/stage7tc1/functions/clock_gettime.html
-// and to http://man7.org/linux/man-pages/man2/clock_gettime.2.html
-
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 200809L
-#endif
-
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <stdbool.h>
-
-#include "cJSON.h"
-#include "ocpayload.h"
-#include "ocpayloadcbor.h"
-#include "oic_malloc.h"
-#include "logger.h"
-#include "cacommon.h"
-#include "cainterface.h"
-#include "provisioningmanager.h"
-#include "credentialgenerator.h"
-#include "global.h"
-#include "base64.h"
-#include "aclresource.h"
-#include "doxmresource.h"
-#include "pstatresource.h"
-#include "srmresourcestrings.h"
-#include "credresource.h"
-#include "oic_string.h"
-#include "secureresourcemanager.h"
-
-typedef enum
-{
- SP_NO_MASK = (0 ),
- SP_DISCOVERY_STARTED = (0x1 << 1),
- SP_DISCOVERY_ERROR = (0x1 << 2),
- SP_DISCOVERY_DONE = (0x1 << 3),
- SP_SEC_RES_INFO_STARTED = (0x1 << 4),
- SP_SEC_RES_INFO_ERROR = (0x1 << 5),
- SP_SEC_RES_INFO_DONE = (0x1 << 6),
- SP_UP_OWN_TR_METH_STARTED = (0x1 << 7),
- SP_UP_OWN_TR_METH_ERROR = (0x1 << 8),
- SP_UP_OWN_TR_METH_DONE = (0x1 << 9),
- SP_LIST_METHODS_STARTED = (0x1 << 10),
- SP_LIST_METHODS_ERROR = (0x1 << 11),
- SP_LIST_METHODS_DONE = (0x1 << 12),
- SP_UPDATE_OP_MODE_STARTED = (0x1 << 13),
- SP_UPDATE_OP_MODE_ERROR = (0x1 << 14),
- SP_UPDATE_OP_MODE_DONE = (0x1 << 15),
- SP_UPDATE_OWNER_STARTED = (0x1 << 16),
- SP_UPDATE_OWNER_ERROR = (0x1 << 17),
- SP_UPDATE_OWNER_DONE = (0x1 << 18),
- SP_PROV_ACL_STARTED = (0x1 << 19),
- SP_PROV_ACL_ERROR = (0x1 << 20),
- SP_PROV_ACL_DONE = (0x1 << 21),
- SP_UP_HASH_STARTED = (0x1 << 22),
- SP_UP_HASH_ERROR = (0x1 << 23),
- SP_UP_HASH_DONE = (0x1 << 24),
- SP_PROV_CRED_STARTED = (0x1 << 25),
- SP_PROV_CRED_ERROR = (0x1 << 26),
- SP_PROV_CRED_DONE = (0x1 << 27)
-} SPProvisioningStates;
-
-#define SP_MAX_BUF_LEN 1024
-#define TAG "SPProvisionAPI"
-#define COAP_QUERY "coap://%s:%d%s"
-#define COAPS_QUERY "coaps://%s:%d%s"
-
-bool (*handler)(const CAEndpoint_t *, const CAResponseInfo_t *);
-
-/**
- * CA token to keep track of response.
- */
-static CAToken_t gToken = NULL;
-
-/**
- * start pointer for discovered device linked list.
- */
-static SPTargetDeviceInfo_t *gStartOfDiscoveredDevices = NULL;
-
-/**
- * current pointer of device linked list.
- */
-static SPTargetDeviceInfo_t *gCurrent = NULL;
-
-/**
- * Variable to keep track of various request.
- */
-static uint32_t gStateManager = 0;
-
-/**
- * Variable for storing provisioning tool's provisioning capabilities
- * Must be in decreasing order of preference. More prefered method should
- * have lower array index.
- */
-static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIVEN };
-
-/**
- * Number of supported provisioning methods
- * current version supports only one.
- */
-static int gNumOfProvisioningMethodsPT = 1;
-
-/**
- * Global variable to save pstat.
- */
-static OicSecPstat_t *gPstat = NULL;
-
-/**
- * Secure String copy function
- * @param[in] destination Pointer to destination string.
- * @param[in] source Pointer to source string.
- * @return pointer to destination string, NULL in case of error.
- */
-static inline char *SPStringCopy(char *destination, const char *source, size_t num)
-{
- if (strncpy(destination, source, num))
- {
- destination[num - 1] = '\0';
- return destination;
- }
- return NULL;
-}
-
-/**
- * Function to convert CA result code to SP result code.
- *
- * @return result code of SP corresponding to that of CA.
- */
-static SPResult convertCAResultToSPResult(CAResult_t caResult)
-{
- switch (caResult)
- {
- case CA_STATUS_OK:
- {
- return SP_RESULT_SUCCESS;
- }
- case CA_STATUS_INVALID_PARAM:
- {
- return SP_RESULT_CONN_INVALID_PARAM;
- }
- case CA_ADAPTER_NOT_ENABLED:
- {
- return SP_RESULT_CONN_SERVER_STARTED_ALREADY;
- }
- case CA_SERVER_STARTED_ALREADY:
- {
- return SP_RESULT_CONN_SERVER_STARTED_ALREADY;
- }
- case CA_SERVER_NOT_STARTED:
- {
- return SP_RESULT_CONN_SERVER_NOT_STARTED;
- }
- case CA_DESTINATION_NOT_REACHABLE:
- {
- return SP_RESULT_CONN_DESTINATION_NOT_REACHABLE;
- }
- case CA_SOCKET_OPERATION_FAILED:
- {
- return SP_RESULT_CONN_SOCKET_OPERATION_FAILED;
- }
- case CA_SEND_FAILED:
- {
- return SP_RESULT_CONN_SEND_FAILED;
- }
- case CA_RECEIVE_FAILED:
- {
- return SP_RESULT_CONN_RECEIVE_FAILED;
- }
- case CA_MEMORY_ALLOC_FAILED:
- {
- return SP_RESULT_CONN_MEMORY_ALLOC_FAILED;
- }
- case CA_REQUEST_TIMEOUT:
- {
- return SP_RESULT_CONN_REQUEST_TIMEOUT;
- }
- case CA_DESTINATION_DISCONNECTED:
- {
- return SP_RESULT_CONN_DESTINATION_DISCONNECTED;
- }
- case CA_STATUS_FAILED:
- {
- return SP_RESULT_CONN_STATUS_FAILED;
- }
- case CA_NOT_SUPPORTED:
- {
- return SP_RESULT_CONN_NOT_SUPPORTED;
- }
- default:
- {
- return SP_RESULT_INTERNAL_ERROR;
- }
- }
-}
-
-/**
- * Function to delete memory allocated to linked list.
- *
- */
-static void deleteList()
-{
- SPTargetDeviceInfo_t *current = gStartOfDiscoveredDevices;
-
- while (current)
- {
- SPTargetDeviceInfo_t *next = current->next;
- DeleteDoxmBinData(current->doxm);
- DeletePstatBinData(current->pstat);
- OICFree(current);
- current = next;
- }
- gStartOfDiscoveredDevices = NULL;
-}
-
-/**
- * Timeout implementation.
- * @param[in] timeout Timeout in seconds. with 0 it will wait forever for success.
- * @param[in] mask Mask of operation and 0 for no mask.
- * @return SP_RESULT_SUCCESS on success otherwise error.
- */
-static SPResult SPTimeout(unsigned short timeout, uint32_t mask)
-{
- struct timespec startTime = {};
- struct timespec currTime = {};
-
- CAResult_t res = SP_RESULT_SUCCESS;
-#ifdef _POSIX_MONOTONIC_CLOCK
- int clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);
-#else
- int clock_res = clock_gettime(CLOCK_REALTIME, &startTime);
-#endif
- if (0 != clock_res)
- {
- return SP_RESULT_INTERNAL_ERROR;
- }
- while (CA_STATUS_OK == res)
- {
- res = CAHandleRequestResponse();
-#ifdef _POSIX_MONOTONIC_CLOCK
- clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);
-#else
- clock_res = clock_gettime(CLOCK_REALTIME, &currTime);
-#endif
- if (0 != clock_res)
- {
- return SP_RESULT_INTERNAL_ERROR;
- }
- long elapsed = (currTime.tv_sec - startTime.tv_sec);
- if (SP_NO_MASK == mask)
- {
- if (elapsed > timeout)
- {
- return SP_RESULT_SUCCESS;
- }
- }
- else
- {
- if (gStateManager & mask)
- {
- return SP_RESULT_SUCCESS;
- }
- if ((elapsed > timeout) && timeout)
- {
- return SP_RESULT_INTERNAL_ERROR;
- }
- }
- }
- return convertCAResultToSPResult(res);
-}
-
-/**
- * Function to send request to resource server.
- * @param[in] method method to be used for sending rquest.
- * @param[in] endpoint endpoint address
- * @param[in] secure use secure connection
- * @param[in] resourceUri resourceUri token.
- * @param[in] payload Payload to be sent with data. NULL is case message
- * doesn't have payload.
- * @param[in] payloadLen Size of data to be sent.
- * @return CA_STATUS_OK on success, otherwise error code.
- */
-static CAResult_t sendCARequest(CAMethod_t method,
- const OCDevAddr *devAddr,
- OCTransportFlags secure,
- const char *resourceUri,
- char *payload, int payloadLen)
-{
- if (payload && '\0' != (*(payload + payloadLen)))
- {
- OC_LOG(ERROR, TAG, "Payload not properly terminated.");
- return CA_STATUS_INVALID_PARAM;
- }
-
- if (CA_STATUS_OK != CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN))
- {
- OC_LOG(ERROR, TAG, "Error while generating token");
- return CA_MEMORY_ALLOC_FAILED;
- }
-
- CAEndpoint_t *endpoint = NULL;
- if (CA_STATUS_OK != CACreateEndpoint(devAddr->flags | (CATransportFlags_t)secure,
- devAddr->adapter, devAddr->addr,
- devAddr->port, &endpoint))
- {
- OC_LOG(ERROR, TAG, "Failed to create remote endpoint");
- CADestroyEndpoint(endpoint);
- return CA_STATUS_FAILED;
- }
-
- OCSecurityPayload secPayload = {};
- secPayload.securityData = payload;
- secPayload.base.type = PAYLOAD_TYPE_SECURITY;
-
- CARequestInfo_t requestInfo = {};
- requestInfo.method = method;
- requestInfo.isMulticast = false;
- OCConvertPayload((OCPayload*)(&secPayload), &requestInfo.info.payload,
- &requestInfo.info.payloadSize);
-
- requestInfo.info.type = CA_MSG_CONFIRM;
- requestInfo.info.token = gToken;
- requestInfo.info.tokenLength = CA_MAX_TOKEN_LEN;
- requestInfo.info.resourceUri = (CAURI_t)resourceUri;
-
- CAResult_t caResult = CA_STATUS_OK;
- caResult = CASendRequest(endpoint, &requestInfo);
- if (CA_STATUS_OK != caResult)
- {
- OC_LOG(ERROR, TAG, "Send Request Error !!");
- }
- CADestroyEndpoint(endpoint);
- return caResult;
-}
-
-/**
- * addDevice to list.
- *
- * @param[in] endpoint Endpoint information
- * @param[in] doxm pointer to doxm instance.
- * @return SP_RESULT_SUCCESS for success and errorcode otherwise.
- */
-static SPResult addDevice(const CAEndpoint_t *endpoint, OicSecDoxm_t* doxm)
-{
- if (NULL == endpoint)
- {
- return SP_RESULT_INVALID_PARAM;
- }
- SPTargetDeviceInfo_t *ptr = (SPTargetDeviceInfo_t *)OICCalloc(1, sizeof (SPTargetDeviceInfo_t));
- if (NULL == ptr)
- {
- OC_LOG(ERROR, TAG, "Error while allocating memory for linkedlist node !!");
- return SP_RESULT_MEM_ALLOCATION_FAIL;
- }
-
- memcpy(&(ptr->endpoint), endpoint, sizeof(CAEndpoint_t));
- ptr->doxm = doxm;
-
- ptr->next = NULL;
-
- if (NULL == gStartOfDiscoveredDevices)
- {
- gStartOfDiscoveredDevices = ptr;
- gCurrent = ptr;
- }
- else
- {
- gCurrent->next = ptr;
- gCurrent = ptr;
- }
- return SP_RESULT_SUCCESS;
-}
-
-/**
- * updateDevice to update resource info for the endpoint.
- *
- * @param[in] endpoint Endpoint information
- * @param[in] port secure port.
- * @return SP_RESULT_SUCCESS for success and errorcode otherwise.
- */
-
-static SPResult updateDevice(const CAEndpoint_t *endpoint, uint16_t port)
-{
- if (NULL == endpoint)
- {
- return SP_RESULT_INVALID_PARAM;
- }
- SPTargetDeviceInfo_t *ptr = gStartOfDiscoveredDevices;
- while(ptr)
- {
- if(0 == strcmp(ptr->endpoint.addr, endpoint->addr) &&
- ptr->endpoint.port == endpoint->port)
- {
- ptr->securePort = port;
- return SP_RESULT_SUCCESS;
- }
- ptr = ptr->next;
- }
- return SP_RESULT_INTERNAL_ERROR;
-}
-
-/**
- * Function to provide timeframe in which response can be received.
- *
- * @param[in] timeout Timeout in seconds.
- * @return SP_RESULT_SUCCESS on success , otherwise error code.
- */
-static SPResult SPWaitForResponse(unsigned short timeout)
-{
- return SPTimeout(timeout, SP_NO_MASK);
-}
-
-/**
- * Function to select appropriate provisioning method.
- *
- * @param[in] supportedMethodsList List of supported methods
- * @param[out] selectedMethod Selected methods
- * @return SP_SUCCESS on success
- */
-static SPResult selectProvisioningMethod(OicSecOxm_t *supportedMethods, size_t numberOfMethods,
- OicSecOxm_t *selectedMethod)
-{
- /*
- TODO Logic to find appropiate method and assign it to out param
- for beachhead release method at index 0 will be returned.
- */
- *selectedMethod = supportedMethods[0];
- return SP_RESULT_SUCCESS;
-}
-
-/**
- * Response handler for discovery.
- *
- * @param[in] object Remote endpoint object
- * @param[in] requestInfo Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool ProvisionDiscoveryHandler(const CAEndpoint_t *object,
- const CAResponseInfo_t *responseInfo)
-{
- if ((gStateManager & SP_DISCOVERY_STARTED) && gToken)
- {
- // Response handler for discovery.
- if (0 == memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength))
- {
- OC_LOG(INFO, TAG, "Inside ProvisionDiscoveryHandler.");
- if (NULL == responseInfo->info.payload)
- {
- OC_LOG(INFO, TAG, "Skiping Null payload");
- }
- else
- {
- OCPayload* payload = NULL;
- OCStackResult result = OCParsePayload(&payload, responseInfo->info.payload,
- responseInfo->info.payloadSize);
-
- OicSecDoxm_t *ptrDoxm = NULL;
-
- if(result == OC_STACK_OK && payload->type == PAYLOAD_TYPE_SECURITY)
- {
- ptrDoxm = JSONToDoxmBin(((OCSecurityPayload*)payload)->securityData);
- }
-
- OCPayloadDestroy(payload);
-
- if (NULL == ptrDoxm)
- {
- OC_LOG(INFO, TAG, "Ignoring malformed JSON");
- }
- else
- {
- OC_LOG(DEBUG, TAG, "Successfully converted doxm json to bin.");
-
- SPResult res = addDevice(object, ptrDoxm);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
- gStateManager = gStateManager | SP_DISCOVERY_ERROR;
- DeleteDoxmBinData(ptrDoxm);
- return true;
- }
- OC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
- gStateManager |= SP_DISCOVERY_DONE;
- }
- }
- return true;
- }
- }
- return false;
-}
-
-/**
- * Response handler for discovery.
- *
- * @param[in] object Remote endpoint object
- * @param[in] requestInfo Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-
-static bool ProvisionSecureResourceInfoHandler(const CAEndpoint_t *object,
- const CAResponseInfo_t *responseInfo)
-{
- if (!object || !responseInfo)
- {
- return false;
- }
-
- if ((gStateManager & SP_SEC_RES_INFO_STARTED) && gToken)
- {
- // Response handler for discovery.
- if (0 == memcmp(gToken, responseInfo->info.token, CA_MAX_TOKEN_LEN))
- {
- OC_LOG(INFO, TAG, "Inside ProvisionSecureResourceInfoHandler.");
- if (NULL == responseInfo->info.payload)
- {
- OC_LOG(ERROR, TAG, "Exiting ProvisionSecureResourceInfoHandler.");
- gStateManager |= SP_SEC_RES_INFO_ERROR;
- }
- else
- {
- OCPayload* payload = NULL;
- OCStackResult result = OCParsePayload(&payload, responseInfo->info.payload,
- responseInfo->info.payloadSize);
-
- OCDiscoveryPayload* discover = (OCDiscoveryPayload*) payload;
- // Discovered secure resource payload contains secure port; update the device
- // with the secure port using endpoint.
- if (result == OC_STACK_OK && discover)
- {
- if (updateDevice(object, discover->resources->port) == SP_RESULT_SUCCESS)
- {
- gStateManager |= SP_SEC_RES_INFO_DONE;
- }
- else
- {
- gStateManager |= SP_SEC_RES_INFO_ERROR;
- }
- OC_LOG(INFO, TAG, "Exiting ProvisionSecureResourceInfoHandler.");
- }
-
- OCPayloadDestroy(payload);
- }
- return true;
- }
- else
- {
- OC_LOG(ERROR, TAG, "Error in ProvisionSecureResourceInfoHandler.");
- gStateManager |= SP_SEC_RES_INFO_ERROR;
- return false;
- }
- }
- return false;
-}
-
-/**
- * Response handler ownership transfer.
- *
- * @param[in] object Remote endpoint object
- * @param[in] requestInfo Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool OwnerShipTransferModeHandler(const CAEndpoint_t *object,
- const CAResponseInfo_t *responseInfo)
-{
- if ((gStateManager & SP_UP_OWN_TR_METH_STARTED) && gToken)
- {
- // response handler for ownership tranfer
- OC_LOG(INFO, TAG, "Inside OwnerShipTransferModeHandler.");
- if (memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength) == 0)
- {
- OC_LOG_V(DEBUG, TAG, "Response result for OwnerShipTransferMode: %d", responseInfo->result);
- if (CA_SUCCESS == responseInfo->result)
- {
- gStateManager |= SP_UP_OWN_TR_METH_DONE;
- OC_LOG(INFO, TAG, "Exiting OwnerShipTransferModeHandler.");
- }
- else
- {
- gStateManager |= SP_UP_OWN_TR_METH_ERROR;
- OC_LOG(ERROR, TAG, "Error in OwnerShipTransferModeHandler.");
- }
- return true;
- }
- }
- return false;
-}
-
-/**
- * Response handler list methods.
- *
- * @param[in] object Remote endpoint object
- * @param[in] requestInfo Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool ListMethodsHandler(const CAEndpoint_t *object,
- const CAResponseInfo_t *responseInfo)
-{
- if ((gStateManager & SP_LIST_METHODS_STARTED) && gToken)
- {
- OC_LOG(INFO, TAG, "Inside ListMethodsHandler.");
- if (memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength) == 0)
- {
- OC_LOG_V(DEBUG, TAG, "Response result for ListMethodsHandler: %d", responseInfo->result);
- if (CA_SUCCESS == responseInfo->result)
- {
- OC_LOG_V (DEBUG, TAG, "Response Payload: %s", responseInfo->info.payload);
- // Temp logic to trim oc attribute from json
- // JSONToPstatBin should handle OC in JSON.
- if (NULL == responseInfo->info.payload)
- {
- OC_LOG(ERROR, TAG, "response payload is null.");
- gStateManager |= SP_LIST_METHODS_ERROR;
- return true;
- }
-
- OCPayload* payload = NULL;
- OCStackResult result = OCParsePayload(&payload, responseInfo->info.payload,
- responseInfo->info.payloadSize);
-
- OicSecPstat_t *pstat = NULL;
-
- if(result == OC_STACK_OK && payload->type == PAYLOAD_TYPE_SECURITY)
- {
- pstat = JSONToPstatBin(((OCSecurityPayload*)payload)->securityData);
- }
-
- OCPayloadDestroy(payload);
-
- if (NULL == pstat)
- {
- OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
- gStateManager |= SP_LIST_METHODS_ERROR;
- return true;
- }
- DeletePstatBinData(gPstat);
-
- gPstat = pstat;
- gStateManager |= SP_LIST_METHODS_DONE;
-
- OC_LOG(INFO, TAG, "Exiting ListMethodsHandler.");
- }
- return true;
- }
- }
- return false;
-}
-
-/**
- * Response handler for update operation mode.
- *
- * @param[in] object Remote endpoint object
- * @param[in] requestInfo Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool OperationModeUpdateHandler(const CAEndpoint_t *object,
- const CAResponseInfo_t *responseInfo)
-{
- if ((gStateManager & SP_UPDATE_OP_MODE_STARTED) && gToken)
- {
- if (0 == memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength))
- {
- OC_LOG(INFO, TAG, "Inside OperationModeUpdateHandler.");
- OC_LOG_V(DEBUG, TAG, "Response result for OperationModeUpdateHandler: %d", responseInfo->result);
- if (CA_SUCCESS == responseInfo->result)
- {
- gStateManager |= SP_UPDATE_OP_MODE_DONE;
- OC_LOG(INFO, TAG, "Exiting OperationModeUpdateHandler.");
- }
- else
- {
- gStateManager |= SP_UPDATE_OP_MODE_ERROR;
- OC_LOG(ERROR, TAG, "Error in OperationModeUpdateHandler.");
- }
- return true;
- }
- }
- return false;
-}
-
-/**
- * Response handler for ownership transfer.
- *
- * @param[in] object Remote endpoint object
- * @param[in] requestInfo Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool OwnerShipUpdateHandler(const CAEndpoint_t *object,
- const CAResponseInfo_t *responseInfo)
-{
- if ((gStateManager & SP_UPDATE_OWNER_STARTED) && gToken)
- {
- // response handler for ownership tranfer
- if (0 == memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength))
- {
- OC_LOG(INFO, TAG, "Inside OwnerShipUpdateHandler.");
- OC_LOG_V(DEBUG, TAG, "Response result for OwnerShipUpdateHandler: %d", responseInfo->result);
- if (CA_SUCCESS == responseInfo->result)
- {
- gStateManager |= SP_UPDATE_OWNER_DONE;
- OC_LOG(INFO, TAG, "Exiting OwnerShipUpdateHandler.");
- }
- else
- {
- gStateManager |= SP_UPDATE_OWNER_ERROR;
- OC_LOG(ERROR, TAG, "Error in OwnerShipUpdateHandler.");
- }
- return true;
- }
- }
- return false;
-}
-
-/**
- * Response handler for ACL provisioning.
- *
- * @param[in] object Remote endpoint object
- * @param[in] requestInfo Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool ACLProvisioningHandler(const CAEndpoint_t *object,
- const CAResponseInfo_t *responseInfo)
-{
- if ((gStateManager & SP_PROV_ACL_STARTED) && gToken)
- {
-
- // response handler for ACL provisioning.
- if (0 == memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength))
- {
- OC_LOG(INFO, TAG, "Inside ACLProvisioningHandler.");
- OC_LOG_V(DEBUG, TAG, "Response result for ACLProvisioningHandler: %d", responseInfo->result);
- if (CA_CREATED == responseInfo->result)
- {
- OC_LOG(INFO, TAG, "Exiting ACLProvisioningHandler.");
- gStateManager |= SP_PROV_ACL_DONE;
- }
- else
- {
- OC_LOG(ERROR, TAG, "Error in ACLProvisioningHandler.");
- gStateManager |= SP_PROV_ACL_ERROR;
- }
- return true;
- }
- }
- return false;
-}
-
-/**
- * Response handler for provisioning finalization.
- *
- * @param[in] object Remote endpoint object
- * @param[in] requestInfo Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool FinalizeProvisioningHandler(const CAEndpoint_t *object,
- const CAResponseInfo_t *responseInfo)
-{
- if ((gStateManager & SP_UP_HASH_STARTED) && gToken)
- {
- // response handler for finalize provisioning.
- if (0 == memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength))
- {
- OC_LOG(INFO, TAG, "Inside FinalizeProvisioningHandler.");
- OC_LOG_V(DEBUG, TAG, "Response result for FinalizeProvisioningHandler: %d", responseInfo->result);
- if (CA_SUCCESS == responseInfo->result)
- {
- gStateManager |= SP_UP_HASH_DONE;
- OC_LOG(INFO, TAG, "Exiting FinalizeProvisioningHandler.");
- }
- else
- {
- gStateManager |= SP_UP_HASH_ERROR;
- OC_LOG(ERROR, TAG, "Error in FinalizeProvisioningHandler.");
- }
- return true;
- }
- }
- return false;
-}
-
-/**
- * Response handler for Credential provisioning.
- *
- * @param[in] object Remote endpoint object
- * @param[in] requestInfo Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool CredProvisioningHandler(const CAEndpoint_t *object,
- const CAResponseInfo_t *responseInfo)
-{
- if ((gStateManager & SP_PROV_CRED_STARTED) && gToken)
- {
- // response handler for CRED provisioning.
- OC_LOG(INFO, TAG, "Inside CredProvisioningHandler.");
- OC_LOG_V(DEBUG, TAG, "Response result for CredProvisioningHandler: %d", responseInfo->result);
- if (0 == memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength))
- {
- if (CA_CREATED == responseInfo->result)
- {
- gStateManager |= SP_PROV_CRED_DONE;
- OC_LOG(INFO, TAG, "Exiting CredProvisioningHandler.");
- }
- else
- {
- gStateManager |= SP_PROV_CRED_ERROR;
- OC_LOG(ERROR, TAG, "Error in CredProvisioningHandler.");
- }
- return true;
- }
- }
- return false;
-}
-
-/**
- * Response Handler
- *
- * @param[in] object Remote endpoint object
- * @param[in] responseInfo Datastructure containing response information.
- * @return true if received response is for provisioning API false otherwise.
- */
-static bool SPResponseHandler(const CAEndpoint_t *object,
- const CAResponseInfo_t *responseInfo)
-{
- bool isProvResponse = false;
- if ((NULL != responseInfo) && (NULL != responseInfo->info.token))
- {
- isProvResponse = handler(object, responseInfo);
- }
- return isProvResponse;
-}
-
-/**
- * Function to find the resources using multicast discovery.
- *
- * @param[in] timeout timeout in secs
- * @return SP_RESULT_SUCCESS normally otherwise error code.
- */
-static SPResult findResource(unsigned short timeout)
-{
- static char DOXM_OWNED_FALSE_MULTICAST_QUERY[] = "/oic/sec/doxm?Owned=FALSE";
- CAResult_t res = CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN);
- if (CA_STATUS_OK != res)
- {
- OC_LOG(ERROR, TAG, "Error while generating token.");
- return SP_RESULT_INTERNAL_ERROR;
- }
-
- CAEndpoint_t endpoint = {};
-
- // Only IP is supported currently for provisioning and ownership transfer
- endpoint.adapter = CA_ADAPTER_IP;
- endpoint.flags = CA_IPV4 | CA_IPV6 | CA_SCOPE_LINK;
-
- CAMessageType_t msgType = CA_MSG_NONCONFIRM;
- CAInfo_t requestData = { 0 };
- requestData.token = gToken;
- requestData.tokenLength = CA_MAX_TOKEN_LEN;
- requestData.payload = NULL;
- requestData.payloadSize = 0;
- requestData.type = msgType;
- requestData.resourceUri = DOXM_OWNED_FALSE_MULTICAST_QUERY;
- CARequestInfo_t requestInfo = { 0 };
- requestInfo.method = CA_GET;
- requestInfo.info = requestData;
- requestInfo.isMulticast = true;
- res = CASendRequest(&endpoint, &requestInfo);
-
- handler = &ProvisionDiscoveryHandler;
- gStateManager |= SP_DISCOVERY_STARTED;
- if (CA_STATUS_OK != res)
- {
- OC_LOG(ERROR, TAG, "Error while finding resource.");
- return convertCAResultToSPResult(res);
- }
- else
- {
- OC_LOG(INFO, TAG, "Discovery Request sent successfully");
- }
- return SPWaitForResponse(timeout);
-}
-
-/**
- * Function to get the secure resource info.
- *
- * @param[in] devAddr Device address for the destination
- * @param[in] timeout timeout in secs
- * @return SP_RESULT_SUCCESS normally otherwise error code.
- */
-static SPResult getSecureResourceInfo(OCDevAddr *devAddr, unsigned short timeout)
-{
- char OIC_UNICAST_SEC_QUERY[] = "/oic/res?rt=oic.sec.doxm";
- CAResult_t res = CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN);
- if (CA_STATUS_OK != res)
- {
- OC_LOG(ERROR, TAG, "Error while generating token.");
- return SP_RESULT_INTERNAL_ERROR;
- }
-
- CAInfo_t requestData = {};
- requestData.token = gToken;
- requestData.tokenLength = CA_MAX_TOKEN_LEN;
- requestData.payload = NULL;
- requestData.payloadSize = 0;
- requestData.type = CA_MSG_NONCONFIRM;
- requestData.resourceUri = OIC_UNICAST_SEC_QUERY;
- CARequestInfo_t requestInfo = { 0 };
- requestInfo.method = CA_GET;
- requestInfo.info = requestData;
- requestInfo.isMulticast = false;
- handler = &ProvisionSecureResourceInfoHandler;
- res = CASendRequest((CAEndpoint_t*)devAddr, &requestInfo);
-
- gStateManager |= SP_SEC_RES_INFO_STARTED;
- if (CA_STATUS_OK != res)
- {
- OC_LOG(ERROR, TAG, "Error while finding secure resource.");
- return convertCAResultToSPResult(res);
- }
- else
- {
- OC_LOG(INFO, TAG, "Secure resource info request sent successfully");
- }
- return SPWaitForResponse(timeout);
-}
-
-/**
- * Function to update the operation mode. As per the spec. Operation mode in client driven
- * single service provisioning it will be updated to 0x3
- *
- * @param[in] timeout timeout for operation.
- * @param[in] deviceInfo Device Info.
- * @return SP_SUCCESS on success
- */
-static SPResult updateOwnerTransferModeToResource(unsigned short timeout,
- SPTargetDeviceInfo_t *deviceInfo, OicSecOxm_t selectedMethod)
-{
- SPResult res = SP_RESULT_INTERNAL_ERROR;
-
- deviceInfo->doxm->oxmSel = selectedMethod;
- char *payload = BinToDoxmJSON(deviceInfo->doxm);
- if (NULL == payload)
- {
- OC_LOG(ERROR, TAG, "Error while converting bin to json");
- return SP_RESULT_INTERNAL_ERROR;
- }
- OC_LOG_V(DEBUG, TAG, "Payload: %s", payload);
- int payloadLen = strlen(payload);
-
- handler = &OwnerShipTransferModeHandler;
- gStateManager |= SP_UP_OWN_TR_METH_STARTED;
-
- CAResult_t result = sendCARequest(CA_PUT,
- &deviceInfo->endpoint,
- OC_DEFAULT_FLAGS,
- OIC_RSRC_DOXM_URI,
- payload, payloadLen);
- OICFree(payload);
- if (CA_STATUS_OK != result)
- {
- OC_LOG(ERROR, TAG, "Error while sending request.");
- CADestroyToken(gToken);
- return convertCAResultToSPResult(result);
- }
- res = SPTimeout(timeout, SP_UP_OWN_TR_METH_DONE);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Internal Error occured");
- CADestroyToken(gToken);
- return SP_RESULT_TIMEOUT;
- }
- CADestroyToken(gToken);
- return SP_RESULT_SUCCESS;
-}
-
-/**
- * Function to send request to resource to get its pstat resource information.
- *
- * @param[in] timeout timeout for operation.
- * @param[in] deviceInfo Device Info.
- * @return SP_SUCCESS on success
- */
-static SPResult getProvisioningStatusResource(unsigned short timeout,
- SPTargetDeviceInfo_t *deviceInfo)
-{
- handler = &ListMethodsHandler;
- gStateManager |= SP_LIST_METHODS_STARTED;
-
- CAResult_t result = sendCARequest(CA_GET,
- &deviceInfo->endpoint,
- OC_DEFAULT_FLAGS,
- OIC_RSRC_PSTAT_URI,
- NULL, 0);
- if (CA_STATUS_OK != result)
- {
- OC_LOG(ERROR, TAG, "Failure while sending request.");
- CADestroyToken(gToken);
- return convertCAResultToSPResult(result);
- }
- SPResult res = SPTimeout(timeout, SP_LIST_METHODS_DONE);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Timeout while getting method list.");
- CADestroyToken(gToken);
- return SP_RESULT_TIMEOUT;
- }
- if (gStateManager && SP_LIST_METHODS_DONE)
- {
- deviceInfo->pstat = gPstat;
- CADestroyToken(gToken);
- OC_LOG(DEBUG, TAG, "getProvisioningStatusResource completed.");
- return SP_RESULT_SUCCESS;
- }
- CADestroyToken(gToken);
- return SP_RESULT_INTERNAL_ERROR;
-}
-
-/**
- * Function to update the operation mode. As per the spec. Operation mode in client driven
- * single service provisioning it will be updated to 0x3
- *
- * @param[in] timeout timeout for operation.
- * @param[in] deviceInfo Device Info.
- * @return SP_SUCCESS on success
- */
-static SPResult updateOperationMode(unsigned short timeout,
- SPTargetDeviceInfo_t *deviceInfo,
- OicSecDpom_t selectedOperationMode)
-{
-
- SPResult res = SP_RESULT_INTERNAL_ERROR;
-
- deviceInfo->pstat->om = selectedOperationMode;
-
- char *payloadBuffer = BinToPstatJSON(deviceInfo->pstat);
- if (NULL == payloadBuffer)
- {
- OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
- return SP_RESULT_INTERNAL_ERROR;
- }
-
- size_t payloadLen = strlen(payloadBuffer);
- handler = &OperationModeUpdateHandler;
- gStateManager |= SP_UPDATE_OP_MODE_STARTED;
-
- CAResult_t result = sendCARequest(CA_PUT,
- &deviceInfo->endpoint,
- OC_DEFAULT_FLAGS,
- OIC_RSRC_PSTAT_URI,
- payloadBuffer, payloadLen);
- if (CA_STATUS_OK != result)
- {
- OC_LOG(ERROR, TAG, "Error while sending request.");
- CADestroyToken(gToken);
- OICFree(payloadBuffer);
- return convertCAResultToSPResult(result);
- }
- res = SPTimeout(timeout, SP_UPDATE_OP_MODE_DONE);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Internal Error occured");
- CADestroyToken(gToken);
- OICFree(payloadBuffer);
- return SP_RESULT_TIMEOUT;
- }
- CADestroyToken(gToken);
- OICFree(payloadBuffer);
-
- if (gStateManager & SP_UPDATE_OP_MODE_DONE)
- {
- return SP_RESULT_SUCCESS;
- }
- return SP_RESULT_INTERNAL_ERROR;
-}
-
-/**
- * Function to initiate DTLS handshake.
- *
- * @param[in] deviceInfo Provisioning context
- * @return SP_SUCCESS on success
- */
-static SPResult initiateDtlsHandshake(const CAEndpoint_t *endpoint)
-{
- CAResult_t caresult = CAEnableAnonECDHCipherSuite(true);
- if (CA_STATUS_OK != caresult)
- {
- OC_LOG_V(ERROR, TAG, "Unable to enable anon cipher suite");
- return SP_RESULT_INTERNAL_ERROR;
- }
- OC_LOG(INFO, TAG, "Anonymous cipher suite Enabled.");
-
- caresult = CAInitiateHandshake(endpoint);
- if (CA_STATUS_OK != caresult)
- {
- OC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
- }
-
- return SP_RESULT_SUCCESS;
-}
-
-/**
- * Function to send ownerShip info. This function would update Owned as true and
- * owner as UUID for provisioning tool
- *
- * @param[in] timeout timeout value for the operation.
- * @param[in] deviceInfo provisioning context.
- * @return SP_SUCCESS on success
- */
-static SPResult sendOwnershipInfo(unsigned short timeout,
- SPTargetDeviceInfo_t *selectedDeviceInfo)
-{
- OicUuid_t provTooldeviceID = {};
-
- if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
- {
- OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
- return SP_RESULT_INTERNAL_ERROR;
- }
- memcpy(selectedDeviceInfo->doxm->owner.id, provTooldeviceID.id , UUID_LENGTH);
-
- selectedDeviceInfo->doxm->owned = true;
-
- char *payloadBuffer = BinToDoxmJSON(selectedDeviceInfo->doxm);
- if (NULL == payloadBuffer)
- {
- OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
- return SP_RESULT_INTERNAL_ERROR;
- }
- int payloadLen = strlen(payloadBuffer);
-
- handler = &OwnerShipUpdateHandler;
- gStateManager |= SP_UPDATE_OWNER_STARTED;
-
- CAResult_t result = sendCARequest(CA_PUT,
- &selectedDeviceInfo->endpoint,
- OC_FLAG_SECURE,
- OIC_RSRC_DOXM_URI,
- payloadBuffer, payloadLen);
- if (CA_STATUS_OK != result)
- {
- OC_LOG(ERROR, TAG, "Error while sending request.");
- CADestroyToken(gToken);
- OICFree(payloadBuffer);
- return convertCAResultToSPResult(result);
- }
- SPResult res = SPTimeout(timeout, SP_UPDATE_OWNER_DONE);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Internal Error occured");
- CADestroyToken(gToken);
- OICFree(payloadBuffer);
- return SP_RESULT_TIMEOUT;
- }
- CADestroyToken(gToken);
- OICFree(payloadBuffer);
- return SP_RESULT_SUCCESS;
-}
-
-/**
- * Function to save ownerPSK at provisioning tool end.
- *
- * @return SP_SUCCESS on success
- */
-static SPResult saveOwnerPSK(SPTargetDeviceInfo_t *selectedDeviceInfo)
-{
- SPResult result = SP_RESULT_INTERNAL_ERROR;
-
- CAEndpoint_t endpoint = {};
- OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
- endpoint.port = selectedDeviceInfo->securePort;
-
- OicUuid_t provTooldeviceID = {};
- if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
- {
- OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
- return result;
- }
-
- uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
-
- //Generating OwnerPSK
- CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
- (uint8_t *)OXM_JUST_WORKS, strlen(OXM_JUST_WORKS), provTooldeviceID.id,
- sizeof(provTooldeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
- sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
- OWNER_PSK_LENGTH_128);
-
- if (CA_STATUS_OK == pskRet)
- {
- OC_LOG(INFO, TAG,"ownerPSK dump:\n");
- OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
- //Generating new credential for provisioning tool
- size_t ownLen = 1;
- uint32_t outLen = 0;
-
- char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
- B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
- &outLen);
- if (B64_OK == b64Ret)
- {
- OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
- SYMMETRIC_PAIR_WISE_KEY, NULL,
- base64Buff, ownLen, &provTooldeviceID);
- if (cred)
- {
- //Update the SVR database.
- if (OC_STACK_OK == AddCredential(cred))
- {
- result = SP_RESULT_SUCCESS;
- }
- else
- {
- OC_LOG(ERROR, TAG, "AddCredential failed");
- }
- }
- else
- {
- OC_LOG(ERROR, TAG, "GenerateCredential failed");
- }
- }
- else
- {
- OC_LOG(ERROR, TAG, "b64Encode failed");
- }
- }
- else
- {
- OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
- }
- return result;
-}
-
-/**
- * Function to select operation mode.This function will return most secure common operation mode.
- *
- * @param[out] selectedMode selected operation mode
- * @return SP_SUCCESS on success
- */
-static void selectOperationMode(const SPTargetDeviceInfo_t *selectedDeviceInfo,
- OicSecDpom_t **selectedMode)
-{
- int i = 0;
- int j = 0;
- while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
- {
- if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
- {
- i++;
- }
- else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
- {
- j++;
- }
- else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
- {
- *selectedMode = &(gProvisioningToolCapability[j]);
- break;
- }
- }
-}
-
-/**
- * Function to perform onwership tranfer based to ownership transfer mode.
- *
- * @param[in] timeout timeout in secs to perform operation. 0 timeout means
- function will wait forever.
- * @param[in] selectedDeviceInfo instance of SPTargetDeviceInfo_t structure.
- * @return SP_SUCCESS on success
- */
-static SPResult doOwnerShipTransfer(unsigned short timeout,
- SPTargetDeviceInfo_t *selectedDeviceInfo)
-{
- OicSecDpom_t *selectedOperationMode = NULL;
- selectOperationMode(selectedDeviceInfo, &selectedOperationMode);
-
- SPResult res = updateOperationMode(timeout, selectedDeviceInfo, *selectedOperationMode);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Error while updating operation mode.");
- return SP_RESULT_INTERNAL_ERROR;
- }
- if (*selectedOperationMode == SINGLE_SERVICE_CLIENT_DRIVEN)
- {
- CAEndpoint_t endpoint = {0};
- OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
- endpoint.port = selectedDeviceInfo->securePort;
-
- res = initiateDtlsHandshake(&endpoint);
- if (SP_RESULT_SUCCESS == res)
- {
- selectedDeviceInfo->endpoint.port = selectedDeviceInfo->securePort;
- res = sendOwnershipInfo(timeout, selectedDeviceInfo);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Error while updating ownership information.");
- }
- res = saveOwnerPSK(selectedDeviceInfo);
-
- //Close temporal DTLS session
- if(CA_STATUS_OK != CACloseDtlsSession(&endpoint))
- {
- OC_LOG(WARNING, TAG, "doOwnerShipTransfer() : failed to close the dtls session");
- }
- }
- else
- {
- OC_LOG(ERROR, TAG, "Error during initiating DTLS handshake.");
- }
-
- //Disable Anonymous ECDH cipher suite before leaving this method
- if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
- {
- OC_LOG(WARNING, TAG, "doOwnerShipTransfer() : failed to disable Anon ECDH cipher suite");
- }
- }
- return (res != SP_RESULT_SUCCESS) ? SP_RESULT_INTERNAL_ERROR : SP_RESULT_SUCCESS;
-
-}
-/**
- * The function is responsible for discovering secure resources(such as, /oic/sec/doxm etc) with
- * OC_EXPLICIT_DISCOVERABLE on a OIC device which needs to be provisioned.
- *
- * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
- * client before returning the list of devices.
- * @param[in] selectedDeviceInfo Device information.
- * @return SP_SUCCESS in case of success and other value otherwise.
- */
-static SPResult discoverSecureResource(unsigned short timeout,
- SPTargetDeviceInfo_t *selectedDeviceInfo)
-{
- if (NULL == selectedDeviceInfo)
- {
- OC_LOG(ERROR, TAG, "List is not null can cause memory leak");
- return SP_RESULT_INVALID_PARAM;
- }
- SPResult smResponse = SP_RESULT_SUCCESS;
- smResponse = getSecureResourceInfo(&selectedDeviceInfo->endpoint, timeout);
- if (SP_RESULT_SUCCESS != smResponse)
- {
- return SP_RESULT_INTERNAL_ERROR;
- }
- if (gStateManager & SP_SEC_RES_INFO_DONE)
- {
- if (gStateManager & SP_SEC_RES_INFO_ERROR)
- {
- return SP_RESULT_INTERNAL_ERROR;
- }
- return SP_RESULT_SUCCESS;
- }
- return SP_RESULT_INTERNAL_ERROR;
-}
-
-/**
- * Function to provision credentials to specific device.
- *
- * @param[in] timeout timeout in secs to perform operation. 0 timeout means function will
- wait till success.
- * @param[in] cred credential to be provisioned.
- * @param[in] deviceInfo Instance of SPDevInfo_t structure. Representing a selected device for
- provisioning.
- * @return SP_SUCCESS on success
- */
-SPResult provisionCredentials(unsigned short timeout, const OicSecCred_t *cred,
- const SPDevInfo_t *deviceInfo)
-{
- char *credJson = NULL;
- credJson = BinToCredJSON(cred);
- if (NULL == credJson)
- {
- OC_LOG(ERROR, TAG, "Memory allocation problem");
- return SP_RESULT_MEM_ALLOCATION_FAIL;
- }
-
- int payloadLen = strlen(credJson);
- handler = &CredProvisioningHandler;
- gStateManager |= SP_PROV_CRED_STARTED;
-
- CAResult_t result = sendCARequest(CA_POST,
- &deviceInfo->endpoint,
- OC_FLAG_SECURE,
- OIC_RSRC_CRED_URI,
- credJson, payloadLen);
- OICFree(credJson);
- if (CA_STATUS_OK != result)
- {
- OC_LOG(ERROR, TAG, "Internal Error while sending Credentials.");
- CADestroyToken(gToken);
- return convertCAResultToSPResult(result);
- }
-
- SPResult res = SPTimeout(timeout, SP_PROV_CRED_DONE);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Internal Error occured");
- CADestroyToken(gToken);
- return SP_RESULT_TIMEOUT;
- }
- CADestroyToken(gToken);
- gStateManager = 0;
- return res;
-}
-
-SPResult SPProvisioningDiscovery(unsigned short timeout,
- SPTargetDeviceInfo_t **list)
-{
- if (NULL != *list)
- {
- OC_LOG(ERROR, TAG, "List is not null can cause memory leak");
- return SP_RESULT_INVALID_PARAM;
- }
- SRMRegisterProvisioningResponseHandler(SPResponseHandler);
- SPResult smResponse = SP_RESULT_SUCCESS;
- smResponse = findResource(timeout);
- if (SP_RESULT_SUCCESS != smResponse)
- {
- return SP_RESULT_INTERNAL_ERROR;
- }
- if (gStateManager & SP_DISCOVERY_DONE)
- {
- if (gStateManager & SP_DISCOVERY_ERROR)
- {
- return SP_RESULT_INTERNAL_ERROR;
- }
- *list = gStartOfDiscoveredDevices;
- return SP_RESULT_SUCCESS;
- }
- return SP_RESULT_INTERNAL_ERROR;
-}
-
-SPResult SPInitProvisionContext(unsigned short timeout,
- SPTargetDeviceInfo_t *selectedDeviceInfo)
-{
- if (NULL == selectedDeviceInfo )
- {
- return SP_RESULT_INVALID_PARAM;
- }
- SPResult res = SP_RESULT_SUCCESS;
-
- //Discover secure resource and update the device info.
- res = discoverSecureResource(timeout, selectedDeviceInfo);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Error in discoverSecureResource");
- return SP_RESULT_INTERNAL_ERROR;
- }
-
- OicSecOxm_t selectedMethod = OIC_JUST_WORKS;
-
- selectProvisioningMethod(selectedDeviceInfo->doxm->oxm, selectedDeviceInfo->doxm->oxmLen,
- &selectedMethod);
- OC_LOG_V(DEBUG, TAG, "Selected method %d:", selectedMethod);
- res = updateOwnerTransferModeToResource(timeout, selectedDeviceInfo, selectedMethod);
-
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Error while updating owner transfer mode.");
- return SP_RESULT_INTERNAL_ERROR;
- }
-
- res = getProvisioningStatusResource(timeout, selectedDeviceInfo);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Error while getting provisioning status.");
- return SP_RESULT_INTERNAL_ERROR;
- }
- OC_LOG(INFO, TAG, "Starting ownership transfer");
- return doOwnerShipTransfer(timeout, selectedDeviceInfo);
-
-}
-
-SPResult SPProvisionACL(unsigned short timeout, const SPTargetDeviceInfo_t *selectedDeviceInfo,
- OicSecAcl_t *acl)
-{
- if (NULL == selectedDeviceInfo || NULL == acl)
- {
- return SP_RESULT_INVALID_PARAM;
- }
- char *aclString = NULL;
- aclString = BinToAclJSON(acl);
-
- if (NULL == aclString)
- {
- OC_LOG(ERROR, TAG, "Memory allocation problem");
- return SP_RESULT_MEM_ALLOCATION_FAIL;
- }
-
- int payloadLen = strlen(aclString);
- handler = &ACLProvisioningHandler;
- gStateManager |= SP_PROV_ACL_STARTED;
-
- CAResult_t result = sendCARequest(CA_POST,
- &selectedDeviceInfo->endpoint,
- OC_FLAG_SECURE,
- OIC_RSRC_ACL_URI,
- aclString, payloadLen);
- OICFree(aclString);
- if (CA_STATUS_OK != result)
- {
- OC_LOG(ERROR, TAG, "Internal Error while sending ACL.");
- CADestroyToken(gToken);
- return convertCAResultToSPResult(result);
- }
-
- SPResult res = SPTimeout(timeout, SP_PROV_ACL_DONE);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Internal Error occured");
- CADestroyToken(gToken);
- return SP_RESULT_TIMEOUT;
- }
- CADestroyToken(gToken);
- return res;
-}
-
-SPResult SPProvisionCredentials(unsigned short timeout, OicSecCredType_t type,
- const SPDevInfo_t *pDevList)
-{
- if (NULL == pDevList)
- {
- return SP_RESULT_INVALID_PARAM;
- }
- const SPDevInfo_t *curr = pDevList;
- OicUuid_t provTooldeviceID = {};
- if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
- {
- OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
- return SP_RESULT_INTERNAL_ERROR;
- }
- //TODO Need to support other key types in future.
- switch (type)
- {
- case SYMMETRIC_PAIR_WISE_KEY:
- {
- if (NULL == curr->next)
- {
- return SP_RESULT_INVALID_PARAM;
- }
- // Devices if present after second node will not be considered.
- // in scenario-2. 2 devices are provisioned with credentials.
- const SPDevInfo_t *firstDevice = curr;
- const SPDevInfo_t *secondDevice = curr->next;
-
- OicSecCred_t *firstCred = NULL;
- OicSecCred_t *secondCred = NULL;
-
- SPResult res = SPGeneratePairWiseCredentials(type, &provTooldeviceID,
- &firstDevice->deviceId, &secondDevice->deviceId,
- &firstCred, &secondCred);
- if (res != SP_RESULT_SUCCESS)
- {
- OC_LOG(ERROR, TAG, "error while generating credentials");
- return SP_RESULT_INTERNAL_ERROR;
- }
- res = provisionCredentials(timeout, firstCred, firstDevice);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG_V(ERROR, TAG, "Credentials provisioning Error");
- DeleteCredList(firstCred);
- DeleteCredList(secondCred);
- return SP_RESULT_INTERNAL_ERROR;
- }
- res = provisionCredentials(timeout, secondCred, secondDevice);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG_V(ERROR, TAG, "Credentials provisioning Error");
- DeleteCredList(firstCred);
- DeleteCredList(secondCred);
- return SP_RESULT_INTERNAL_ERROR;
- }
- DeleteCredList(firstCred);
- DeleteCredList(secondCred);
- return SP_RESULT_SUCCESS;
- }
- default:
- {
- OC_LOG(ERROR, TAG, "Invalid option.");
- return SP_RESULT_INVALID_PARAM;
- }
- return SP_RESULT_INTERNAL_ERROR;
- }
-}
-
-SPResult SPFinalizeProvisioning(unsigned short timeout,
- SPTargetDeviceInfo_t *selectedDeviceInfo)
-{
- // TODO
- if (NULL == selectedDeviceInfo)
- {
- OC_LOG(ERROR, TAG, "Target device Info is NULL.");
- return SP_RESULT_INVALID_PARAM;
- }
-
- uint16_t aclHash = 0; // value for beachhead version.
- selectedDeviceInfo->pstat->commitHash = aclHash;
- selectedDeviceInfo->pstat->tm = NORMAL;
- char *payloadBuffer = BinToPstatJSON(selectedDeviceInfo->pstat);
- if (NULL == payloadBuffer)
- {
- OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
- return SP_RESULT_INTERNAL_ERROR;
- }
- int payloadLen = strlen(payloadBuffer);
-
- handler = &FinalizeProvisioningHandler;
- gStateManager |= SP_UP_HASH_STARTED;
-
- CAResult_t result = sendCARequest(CA_PUT,
- &selectedDeviceInfo->endpoint,
- OC_FLAG_SECURE,
- OIC_RSRC_PSTAT_URI,
- payloadBuffer, payloadLen);
- OICFree(payloadBuffer);
- if (CA_STATUS_OK != result)
- {
- OC_LOG(ERROR, TAG, "Internal Error occured");
- CADestroyToken(gToken);
- return convertCAResultToSPResult(result);
- }
-
- SPResult res = SPTimeout(timeout, SP_UP_HASH_DONE);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Internal Error occured");
- CADestroyToken(gToken);
- return SP_RESULT_TIMEOUT;
- }
-
- result = CACloseDtlsSession((CAEndpoint_t*)&selectedDeviceInfo->endpoint);
- if (CA_STATUS_OK != result)
- {
- OC_LOG(WARNING, TAG, "Failed to close the DTLS session.");
- }
-
- CADestroyToken(gToken);
- gStateManager = 0;
- gPstat = NULL;
- return res;
-}
-
-SPResult SPTerminateProvisioning()
-{
- deleteList();
- return SP_RESULT_SUCCESS;;
-}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 <string.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "ocprovisioningmanager.h"
+#include "secureresourceprovider.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "aclresource.h"
+#include "pstatresource.h"
+#include "srmresourcestrings.h"
+#include "credresource.h"
+#include "doxmresource.h"
+#include "credentialgenerator.h"
+#include "cainterface.h"
+#include "cJSON.h"
+#include "pmtypes.h"
+#include "pmutility.h"
+#include "provisioningdatabasemanager.h"
+#include "base64.h"
+#include "utlist.h"
+
+#define TAG "SRPAPI"
+
+/**
+ * Macro to verify argument is not equal to NULL.
+ * eg: VERIFY_NON_NULL(TAG, ptrData, ERROR,OC_STACK_ERROR);
+ */
+#define VERIFY_NON_NULL(tag, arg, logLevel, retValue) { if (NULL == (arg)) \
+ { OC_LOG((logLevel), tag, (#arg " is NULL")); return retValue; } }
+
+/**
+ * Macro to verify success of operation.
+ * eg: VERIFY_SUCCESS(TAG, OC_STACK_OK == foo(), ERROR, OC_STACK_ERROR);
+ */
+#define VERIFY_SUCCESS(tag, op, logLevel, retValue) { if (!(op)) \
+ {OC_LOG((logLevel), tag, (#op " failed!!")); return retValue;} }
+
+/**
+ * Structure to carry credential data to callback.
+ */
+typedef struct CredentialData CredentialData_t;
+struct CredentialData
+{
+ void *ctx; /**< Pointer to user context.**/
+ const OCProvisionDev_t *deviceInfo1; /**< Pointer to OCProvisionDev_t.**/
+ const OCProvisionDev_t *deviceInfo2; /**< Pointer to OCProvisionDev_t.**/
+ OicSecCred_t *credInfo; /**< Pointer to OicSecCred_t.**/
+ OicSecCred_t *credInfoFirst; /**< Pointer to OicSecCred_t.**/
+ OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
+ OCProvisionResult_t *resArr; /**< Result array.**/
+ int numOfResults; /**< Number of results in result array.**/
+};
+
+/**
+ * Structure to carry ACL provision API data to callback.
+ */
+typedef struct ACLData ACLData_t;
+struct ACLData
+{
+ void *ctx; /**< Pointer to user context.**/
+ const OCProvisionDev_t *deviceInfo; /**< Pointer to PMDevInfo_t.**/
+ OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
+ OCProvisionResult_t *resArr; /**< Result array.**/
+ int numOfResults; /**< Number of results in result array.**/
+};
+
+// Enum type index for unlink callback.
+typedef enum {
+ IDX_FIRST_DEVICE_RES = 0, // index for resulf of the first device
+ IDX_SECOND_DEVICE_RES, // index for result of the second device
+ IDX_DB_UPDATE_RES // index for result of updating provisioning database.
+} IdxUnlinkRes_t;
+
+// Structure to carry unlink APIs data to callback.
+typedef struct UnlinkData UnlinkData_t;
+struct UnlinkData {
+ void *ctx;
+ OCProvisionDev_t* unlinkDev; /**< Pointer to OCProvisionDev_t to be unlinked.**/
+ OCProvisionResult_t* unlinkRes; /**< Result array.**/
+ OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
+ int numOfResults; /**< Number of results in result array.**/
+};
+
+//Example of DELETE cred request -> coaps://0.0.0.0:5684/oic/sec/cred?sub=(BASE64 ENCODED UUID)
+const char * SRP_FORM_DELETE_CREDENTIAL = "coaps://[%s]:%d%s?%s=%s";
+
+// Structure to carry remove APIs data to callback.
+typedef struct RemoveData RemoveData_t;
+struct RemoveData {
+ void *ctx;
+ OCProvisionDev_t* revokeTargetDev; /**< Device which is going to be revoked..**/
+ OCProvisionDev_t* linkedDevList; /**< A list of devices which have invalid credential.**/
+ OCProvisionResult_t* removeRes; /**< Result array.**/
+ OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
+ size_t numOfResults; /**< Number of results in result array.**/
+ size_t sizeOfResArray;
+ bool hasError;
+};
+
+/**
+ * Function prototype
+ */
+static OCStackResult provisionCredentials(const OicSecCred_t *cred,
+ const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
+ OCClientResponseHandler responseHandler);
+
+
+/**
+ * Internal function to update result in result array.
+ */
+static void registerResultForCredProvisioning(CredentialData_t *credData,
+ OCStackResult stackresult, int cause)
+{
+
+ OC_LOG_V(INFO,TAG,"value of credData->numOfResults is %d",credData->numOfResults);
+ if(1 == cause)
+ {
+ memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
+ credData->deviceInfo1->doxm->deviceID.id,UUID_LENGTH);
+ }
+ else
+ {
+ memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
+ credData->deviceInfo2->doxm->deviceID.id,UUID_LENGTH);
+ }
+ credData->resArr[(credData->numOfResults)].res = stackresult;
+ ++(credData->numOfResults);
+}
+
+/**
+ * Callback handler for handling callback of provisioning device 2.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult provisionCredentialCB2(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+ CredentialData_t *credData = (CredentialData_t *) ctx;
+ (void)UNUSED;
+
+ OCProvisionResultCB resultCallback = credData->resultCallback;
+ OC_LOG(INFO, TAG, "provisionCredentialCB2 called");
+ if (clientResponse)
+ {
+ if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+ {
+ registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CREATED, 2);
+ OCStackResult res = PDMLinkDevices(&credData->deviceInfo1->doxm->deviceID,
+ &credData->deviceInfo2->doxm->deviceID);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Error occured on PDMLinkDevices");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ OC_LOG(INFO, TAG, "Link created successfully");
+
+ ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+ credData->resArr,
+ false);
+ OICFree(credData->resArr);
+ OICFree(credData);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ }
+ OC_LOG(INFO, TAG, "provisionCredentialCB2 received Null clientResponse");
+ registerResultForCredProvisioning(credData, OC_STACK_ERROR, 2);
+ ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+ credData->resArr,
+ true);
+ OICFree(credData->resArr);
+ OICFree(credData);
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler for handling callback of provisioning device 1.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult provisionCredentialCB1(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+ (void)UNUSED;
+ CredentialData_t* credData = (CredentialData_t*) ctx;
+ OICFree(credData->credInfoFirst);
+ const OCProvisionDev_t *deviceInfo = credData->deviceInfo2;
+ OicSecCred_t *credInfo = credData->credInfo;
+ const OCProvisionResultCB resultCallback = credData->resultCallback;
+ if (clientResponse)
+ {
+ if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
+ {
+ // send credentials to second device
+ registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CREATED,1);
+ OCStackResult res = provisionCredentials(credInfo, deviceInfo, credData,
+ provisionCredentialCB2);
+ DeleteCredList(credInfo);
+ if (OC_STACK_OK != res)
+ {
+ registerResultForCredProvisioning(credData, res,2);
+ ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+ credData->resArr,
+ true);
+ OICFree(credData->resArr);
+ OICFree(credData);
+ credData = NULL;
+ }
+ }
+ else
+ {
+ registerResultForCredProvisioning(credData, OC_STACK_ERROR,1);
+ ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+ credData->resArr,
+ true);
+ OICFree(credData->resArr);
+ OICFree(credData);
+ credData = NULL;
+ }
+ }
+ else
+ {
+ OC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
+ registerResultForCredProvisioning(credData, OC_STACK_ERROR,1);
+ ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+ credData->resArr,
+ true);
+ DeleteCredList(credInfo);
+ OICFree(credData->resArr);
+ OICFree(credData);
+ credData = NULL;
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+
+/**
+ * Internal function for handling credential generation and sending credential to resource server.
+ *
+ * @param[in] cred Instance of cred resource.
+ * @param[in] deviceInfo information about device to which credential is to be provisioned.
+ * @param[in] responseHandler callbak called by OC stack when request API receives response.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+static OCStackResult provisionCredentials(const OicSecCred_t *cred,
+ const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
+ OCClientResponseHandler responseHandler)
+{
+ OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ if(!secPayload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to memory allocation");
+ return OC_STACK_NO_MEMORY;
+ }
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+ secPayload->securityData = BinToCredJSON(cred);
+ if(NULL == secPayload->securityData)
+ {
+ OICFree(secPayload);
+ OC_LOG(ERROR, TAG, "Failed to BinToCredJSON");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ OC_LOG_V(INFO, TAG, "Credential for provisioning : %s",secPayload->securityData);
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ if(!PMGenerateQuery(true,
+ deviceInfo->endpoint.addr,
+ deviceInfo->securePort,
+ deviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_CRED_URI))
+ {
+ OC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
+ return OC_STACK_ERROR;
+ }
+ OC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
+ cbData.cb = responseHandler;
+ cbData.context = (void *) credData;
+ cbData.cd = NULL;
+
+ OCDoHandle handle = NULL;
+ OCMethod method = OC_REST_POST;
+ OCStackResult ret = OCDoResource(&handle, method, query, 0, (OCPayload*)secPayload,
+ deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+ OC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d",ret);
+ if (ret != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ return ret;
+ }
+ return OC_STACK_OK;
+}
+
+OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
+ const OCProvisionDev_t *pDev1,
+ const OCProvisionDev_t *pDev2,
+ OCProvisionResultCB resultCallback)
+{
+ VERIFY_NON_NULL(TAG, pDev1, ERROR, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(TAG, pDev2, ERROR, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK);
+
+ if (!(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
+ {
+ OC_LOG(INFO, TAG, "Invalid key size");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OC_LOG(INFO, TAG, "In SRPProvisionCredentials");
+
+ OicUuid_t provTooldeviceID = {{0,}};
+ if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
+ {
+ OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+ return OC_STACK_ERROR;
+ }
+ OC_LOG(INFO, TAG, "retrieved deviceid");
+ switch (type)
+ {
+ case SYMMETRIC_PAIR_WISE_KEY:
+ {
+ const OCProvisionDev_t *firstDevice = pDev1;
+ const OCProvisionDev_t *secondDevice = pDev2;
+
+ OicSecCred_t *firstCred = NULL;
+ OicSecCred_t *secondCred = NULL;
+ OCStackResult res = PMGeneratePairWiseCredentials(type, keySize, &provTooldeviceID,
+ &firstDevice->doxm->deviceID, &secondDevice->doxm->deviceID,
+ &firstCred, &secondCred);
+ VERIFY_SUCCESS(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
+ OC_LOG(INFO, TAG, "Credentials generated successfully");
+ CredentialData_t *credData = (CredentialData_t *) OICMalloc(sizeof(CredentialData_t));
+ if (NULL == credData)
+ {
+ OC_LOG(ERROR, TAG, "Memory allocation problem");
+ return OC_STACK_NO_MEMORY;
+ }
+ memset(credData, 0x00, sizeof(CredentialData_t));
+ credData->deviceInfo1 = firstDevice;
+ credData->deviceInfo2 = secondDevice;
+ credData->credInfo = secondCred;
+ credData->ctx = ctx;
+ credData->credInfoFirst = firstCred;
+ credData->numOfResults = 0;
+ credData->resultCallback = resultCallback;
+ // first call to provision creds to device1.
+ // second call to provision creds to device2.
+ int noOfRiCalls = 2;
+ credData->resArr =
+ (OCProvisionResult_t*)OICMalloc(sizeof(OCProvisionResult_t) * noOfRiCalls);
+ if (NULL == credData->resArr)
+ {
+ OC_LOG(ERROR, TAG, "Memory allocation problem");
+ return OC_STACK_NO_MEMORY;
+ }
+ memset(credData->resArr, 0x00, sizeof(sizeof(OCProvisionResult_t)*noOfRiCalls));
+ res = provisionCredentials(firstCred, firstDevice, credData, &provisionCredentialCB1);
+ if (OC_STACK_OK != res)
+ {
+ DeleteCredList(firstCred);
+ DeleteCredList(secondCred);
+ OICFree(credData->resArr);
+ OICFree(credData);
+ }
+ OC_LOG_V(INFO, TAG, "provisionCredentials returned: %d",res);
+ VERIFY_SUCCESS(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
+ return res;
+ }
+ default:
+ {
+ OC_LOG(ERROR, TAG, "Invalid option.");
+ return OC_STACK_INVALID_PARAM;
+ }
+ }
+ return OC_STACK_ERROR;
+}
+
+/**
+ * Internal Function to store results in result array during ACL provisioning.
+ */
+static void registerResultForACLProvisioning(ACLData_t *aclData,
+ OCStackResult stackresult)
+{
+ OC_LOG_V(INFO, TAG, "Inside registerResultForACLProvisioning aclData->numOfResults is %d\n",
+ aclData->numOfResults);
+ memcpy(aclData->resArr[(aclData->numOfResults)].deviceId.id,
+ aclData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
+ aclData->resArr[(aclData->numOfResults)].res = stackresult;
+ ++(aclData->numOfResults);
+}
+
+/**
+ * Callback handler of SRPProvisionACL.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult SRPProvisionACLCB(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ OC_LOG_V(INFO, TAG, "Inside SRPProvisionACLCB.");
+ (void)UNUSED;
+ VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+ ACLData_t *aclData = (ACLData_t*)ctx;
+ OCProvisionResultCB resultCallback = aclData->resultCallback;
+
+ if (clientResponse)
+ {
+ if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+ {
+ registerResultForACLProvisioning(aclData, OC_STACK_RESOURCE_CREATED);
+ ((OCProvisionResultCB)(resultCallback))(aclData->ctx, aclData->numOfResults,
+ aclData->resArr,
+ false);
+ OICFree(aclData->resArr);
+ OICFree(aclData);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+ registerResultForACLProvisioning(aclData, OC_STACK_ERROR);
+ ((OCProvisionResultCB)(resultCallback))(aclData->ctx, aclData->numOfResults,
+ aclData->resArr,
+ true);
+ OC_LOG_V(ERROR, TAG, "SRPProvisionACLCB received Null clientResponse");
+ OICFree(aclData->resArr);
+ OICFree(aclData);
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
+ OicSecAcl_t *acl, OCProvisionResultCB resultCallback)
+{
+ VERIFY_NON_NULL(TAG, selectedDeviceInfo, ERROR, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(TAG, acl, ERROR, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(TAG, resultCallback, ERROR, OC_STACK_INVALID_CALLBACK);
+
+ OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ if(!secPayload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to memory allocation");
+ return OC_STACK_NO_MEMORY;
+ }
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+ secPayload->securityData = BinToAclJSON(acl);
+ if(NULL == secPayload->securityData)
+ {
+ OICFree(secPayload);
+ OC_LOG(ERROR, TAG, "Failed to BinToAclJSON");
+ return OC_STACK_NO_MEMORY;
+ }
+ OC_LOG_V(INFO, TAG, "ACL : %s", secPayload->securityData);
+
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ if(!PMGenerateQuery(true,
+ selectedDeviceInfo->endpoint.addr,
+ selectedDeviceInfo->securePort,
+ selectedDeviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_ACL_URI))
+ {
+ OC_LOG(ERROR, TAG, "DeviceDiscoveryHandler : Failed to generate query");
+ return OC_STACK_ERROR;
+ }
+ OC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
+ cbData.cb = &SRPProvisionACLCB;
+ ACLData_t *aclData = (ACLData_t *) OICMalloc(sizeof(ACLData_t));
+ if (aclData == NULL)
+ {
+ OICFree(secPayload);
+ OC_LOG(ERROR, TAG, "Unable to allocate memory");
+ return OC_STACK_NO_MEMORY;
+ }
+ memset(aclData, 0x00, sizeof(ACLData_t));
+ aclData->deviceInfo = selectedDeviceInfo;
+ aclData->resultCallback = resultCallback;
+ aclData->numOfResults=0;
+ aclData->ctx = ctx;
+ // call to provision ACL to device1.
+ int noOfRiCalls = 1;
+ aclData->resArr = (OCProvisionResult_t*)OICMalloc(sizeof(OCProvisionResult_t)*noOfRiCalls);
+ if (aclData->resArr == NULL)
+ {
+ OICFree(secPayload);
+ OC_LOG(ERROR, TAG, "Unable to allocate memory");
+ return OC_STACK_NO_MEMORY;
+ }
+ memset(aclData->resArr, 0x00, sizeof(sizeof(OCProvisionResult_t)*noOfRiCalls));
+ cbData.context = (void *)aclData;
+ cbData.cd = NULL;
+ OCMethod method = OC_REST_POST;
+ OCDoHandle handle = NULL;
+ OC_LOG(DEBUG, TAG, "Sending ACL info to resource server");
+ OCStackResult ret = OCDoResource(&handle, method, query,
+ &selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
+ selectedDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+ if (ret != OC_STACK_OK)
+ {
+ OICFree(aclData->resArr);
+ OICFree(aclData);
+ }
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
+ return OC_STACK_OK;
+}
+
+static void DeleteUnlinkData_t(UnlinkData_t *unlinkData)
+{
+ if (unlinkData)
+ {
+ OICFree(unlinkData->unlinkDev);
+ OICFree(unlinkData->unlinkRes);
+ OICFree(unlinkData);
+ }
+}
+
+static void registerResultForUnlinkDevices(UnlinkData_t *unlinkData, OCStackResult stackresult,
+ IdxUnlinkRes_t idx)
+{
+ if (NULL != unlinkData)
+ {
+ OC_LOG_V(INFO, TAG, "Inside registerResultForUnlinkDevices unlinkData->numOfResults is %d\n",
+ unlinkData->numOfResults);
+ OC_LOG_V(INFO, TAG, "Stack result :: %d", stackresult);
+
+ OicUuid_t *pUuid = &unlinkData->unlinkRes[(unlinkData->numOfResults)].deviceId;
+
+ // Set result in the result array according to the position (devNum).
+ if (idx != IDX_DB_UPDATE_RES)
+ {
+ memcpy(pUuid->id, unlinkData->unlinkDev[idx].doxm->deviceID.id, sizeof(pUuid->id));
+ }
+ else
+ { // When deivce ID is 000... this means it's the result of database update.
+ memset(pUuid->id, 0, sizeof(pUuid->id));
+ }
+ unlinkData->unlinkRes[(unlinkData->numOfResults)].res = stackresult;
+ ++(unlinkData->numOfResults);
+ OC_LOG (INFO, TAG, "Out registerResultForUnlinkDevices");
+ }
+}
+
+static OCStackResult SendDeleteCredentialRequest(void* ctx,
+ OCClientResponseHandler respHandler,
+ const OCProvisionDev_t* revokedDev,
+ const OCProvisionDev_t* destDev)
+{
+ OC_LOG(DEBUG, TAG, "IN SendDeleteCredentialRequest");
+
+ if (NULL == ctx || NULL == respHandler || NULL == revokedDev || NULL == destDev)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(revokedDev->doxm->deviceID.id)) + 1] = {};
+ uint32_t base64Len = 0;
+ if (B64_OK != b64Encode(revokedDev->doxm->deviceID.id, sizeof(revokedDev->doxm->deviceID.id),
+ base64Buff, sizeof(base64Buff), &base64Len))
+ {
+ OC_LOG(ERROR, TAG, "SendDeleteCredentialRequest : Failed to base64 encoding");
+ return OC_STACK_ERROR;
+ }
+
+ char reqBuf[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ int snRet = 0;
+ //coaps://0.0.0.0:5684/oic/sec/cred?sub=(BASE64 ENCODED UUID)
+ snRet = snprintf(reqBuf, sizeof(reqBuf), SRP_FORM_DELETE_CREDENTIAL, destDev->endpoint.addr,
+ destDev->securePort, OIC_RSRC_CRED_URI, OIC_JSON_SUBJECT_NAME, base64Buff);
+ if (snRet < 0)
+ {
+ OC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Error (snprintf) %d\n", snRet);
+ return OC_STACK_ERROR;
+ }
+ else if ((size_t)snRet >= sizeof(reqBuf))
+ {
+ OC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Truncated (snprintf) %d\n", snRet);
+ return OC_STACK_ERROR;
+ }
+
+ OCCallbackData cbData;
+ memset(&cbData, 0, sizeof(cbData));
+ cbData.context = ctx;
+ cbData.cb = respHandler;
+ cbData.cd = NULL;
+ OC_LOG_V(INFO, TAG, "URI: %s",reqBuf);
+
+ OC_LOG(DEBUG, TAG, "Sending remove credential request to resource server");
+
+ OCStackResult ret = OCDoResource(NULL, OC_REST_DELETE, reqBuf,
+ &destDev->endpoint, NULL,
+ CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG_V(ERROR, TAG, "SendDeleteCredentialRequest : Error in OCDoResource %d", ret);
+ }
+ OC_LOG(DEBUG, TAG, "OUT SendDeleteCredentialRequest");
+
+ return ret;
+}
+
+/**
+ * Callback handler of unlink second device.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] handle handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction and
+ * OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult SRPUnlinkDevice2CB(void *unlinkCtx, OCDoHandle handle,
+ OCClientResponse *clientResponse)
+{
+ (void) handle;
+ OC_LOG(DEBUG, TAG, "IN SRPUnlinkDevice2CB");
+ VERIFY_NON_NULL(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
+ UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
+
+ if (clientResponse)
+ {
+ OC_LOG(DEBUG, TAG, "Valid client response for device 2");
+ registerResultForUnlinkDevices(unlinkData, clientResponse->result, IDX_SECOND_DEVICE_RES);
+
+ if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
+ {
+ OC_LOG(DEBUG, TAG, "Credential of device2 revoked");
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Unable to delete credential information from device 2");
+ unlinkData->resultCallback(unlinkData->ctx,
+ unlinkData->numOfResults, unlinkData->unlinkRes, true);
+ goto error;
+ }
+ }
+ else
+ {
+ registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
+ IDX_SECOND_DEVICE_RES);
+ unlinkData->resultCallback(unlinkData->ctx,
+ unlinkData->numOfResults, unlinkData->unlinkRes, true);
+ OC_LOG(ERROR, TAG, "SRPUnlinkDevice2CB received Null clientResponse");
+ goto error;
+ }
+
+ //Update provisioning DB when succes case.
+ if (OC_STACK_OK != PDMUnlinkDevices(&unlinkData->unlinkDev[0].doxm->deviceID,
+ &unlinkData->unlinkDev[1].doxm->deviceID))
+ {
+ OC_LOG(FATAL, TAG, "All requests are successfully done but update provisioning DB FAILED.");
+ registerResultForUnlinkDevices(unlinkData, OC_STACK_INCONSISTENT_DB, IDX_DB_UPDATE_RES);
+ unlinkData->resultCallback(unlinkData->ctx,
+ unlinkData->numOfResults, unlinkData->unlinkRes, true);
+ goto error;
+ }
+ unlinkData->resultCallback(unlinkData->ctx, unlinkData->numOfResults, unlinkData->unlinkRes,
+ false);
+
+error:
+ DeleteUnlinkData_t(unlinkData);
+ OC_LOG(DEBUG, TAG, "OUT SRPUnlinkDevice2CB");
+ return OC_STACK_DELETE_TRANSACTION;
+
+}
+
+/**
+ * Callback handler of unlink first device.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] handle handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction and
+ * OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult SRPUnlinkDevice1CB(void *unlinkCtx, OCDoHandle handle,
+ OCClientResponse *clientResponse)
+{
+ OC_LOG_V(INFO, TAG, "Inside SRPUnlinkDevice1CB ");
+ VERIFY_NON_NULL(TAG, unlinkCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
+ UnlinkData_t* unlinkData = (UnlinkData_t*)unlinkCtx;
+ (void) handle;
+
+ if (clientResponse)
+ {
+ OC_LOG(DEBUG, TAG, "Valid client response for device 1");
+ registerResultForUnlinkDevices(unlinkData, clientResponse->result, IDX_FIRST_DEVICE_RES);
+
+ if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
+ {
+ OC_LOG(DEBUG, TAG, "Credential of device 1 is revoked");
+
+ // Second revocation request to second device.
+ OCStackResult res = SendDeleteCredentialRequest((void*)unlinkData, &SRPUnlinkDevice2CB,
+ &unlinkData->unlinkDev[0],
+ &unlinkData->unlinkDev[1] /*Dest*/);
+ OC_LOG_V(DEBUG, TAG, "Credential revocation request device 2, result :: %d",res);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "Error while sending revocation request for device 2");
+ registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
+ IDX_SECOND_DEVICE_RES);
+ unlinkData->resultCallback(unlinkData->ctx,
+ unlinkData->numOfResults, unlinkData->unlinkRes, true);
+ goto error;
+ }
+ else
+ {
+ OC_LOG(DEBUG, TAG, "Request for credential revocation successfully sent");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Unable to delete credential information from device 1");
+
+ unlinkData->resultCallback(unlinkData->ctx, unlinkData->numOfResults,
+ unlinkData->unlinkRes, true);
+ goto error;
+ }
+ }
+ else
+ {
+ OC_LOG(DEBUG, TAG, "Invalid response from server");
+ registerResultForUnlinkDevices(unlinkData, OC_STACK_INVALID_REQUEST_HANDLE,
+ IDX_FIRST_DEVICE_RES );
+ unlinkData->resultCallback(unlinkData->ctx,
+ unlinkData->numOfResults, unlinkData->unlinkRes,
+ true);
+ OC_LOG(ERROR, TAG, "SRPUnlinkDevice1CB received Null clientResponse");
+ }
+
+error:
+ OC_LOG_V(INFO, TAG, "Out SRPUnlinkDevice1CB");
+ DeleteUnlinkData_t(unlinkData);
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/*
+* Function to unlink devices.
+* This function will remove the credential & relationship between the two devices.
+*
+* @param[in] ctx Application context would be returned in result callback
+* @param[in] pTargetDev1 first device information to be unlinked.
+* @param[in] pTargetDev2 second device information to be unlinked.
+* @param[in] resultCallback callback provided by API user, callback will be called when
+* device unlink is finished.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+*/
+OCStackResult SRPUnlinkDevices(void* ctx,
+ const OCProvisionDev_t* pTargetDev1,
+ const OCProvisionDev_t* pTargetDev2,
+ OCProvisionResultCB resultCallback)
+{
+ OC_LOG(INFO, TAG, "IN SRPUnlinkDevices");
+
+ if (!pTargetDev1 || !pTargetDev2 || !resultCallback)
+ {
+ OC_LOG(INFO, TAG, "SRPUnlinkDevices : NULL parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+ OC_LOG(INFO, TAG, "Unlinking following devices: ");
+ PMPrintOCProvisionDev(pTargetDev1);
+ PMPrintOCProvisionDev(pTargetDev2);
+
+ // Mark the link status stale
+ OCStackResult res = PDMSetLinkStale(&pTargetDev1->doxm->deviceID, &pTargetDev2->doxm->deviceID);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(FATAL, TAG, "unable to update DB. Try again.");
+ return res;
+ }
+
+ UnlinkData_t* unlinkData = (UnlinkData_t*)OICCalloc(1, sizeof(UnlinkData_t));
+ VERIFY_NON_NULL(TAG, unlinkData, ERROR, OC_STACK_NO_MEMORY);
+
+ //Initialize unlink data
+ unlinkData->ctx = ctx;
+ unlinkData->unlinkDev = (OCProvisionDev_t*)OICCalloc(2, sizeof(OCProvisionDev_t));
+ if (NULL == unlinkData->unlinkDev)
+ {
+ OC_LOG(ERROR, TAG, "Memory allocation failed");
+ res = OC_STACK_NO_MEMORY;
+ goto error;
+ }
+
+ unlinkData->unlinkRes = (OCProvisionResult_t*)OICCalloc(3, sizeof(OCProvisionResult_t));
+ if (NULL == unlinkData->unlinkRes)
+ {
+ OC_LOG(ERROR, TAG, "Memory allocation failed");
+ res = OC_STACK_NO_MEMORY;
+ goto error;
+ }
+
+ memcpy(&unlinkData->unlinkDev[0], pTargetDev1, sizeof(OCProvisionDev_t));
+ memcpy(&unlinkData->unlinkDev[1], pTargetDev2, sizeof(OCProvisionDev_t));
+
+ unlinkData->numOfResults = 0;
+ unlinkData->resultCallback = resultCallback;
+
+ res = SendDeleteCredentialRequest((void*)unlinkData, &SRPUnlinkDevice1CB,
+ &unlinkData->unlinkDev[1], &unlinkData->unlinkDev[0]);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "SRPUnlinkDevices : SendDeleteCredentialRequest failed");
+ goto error;
+ }
+
+ return res;
+
+error:
+ OC_LOG(INFO, TAG, "OUT SRPUnlinkDevices");
+ DeleteUnlinkData_t(unlinkData);
+ return res;
+}
+
+static void DeleteRemoveData_t(RemoveData_t* pRemoveData)
+{
+ if (pRemoveData)
+ {
+ OICFree(pRemoveData->revokeTargetDev);
+ OCDeleteDiscoveredDevices(pRemoveData->linkedDevList);
+ OICFree(pRemoveData->removeRes);
+ OICFree(pRemoveData);
+ }
+}
+
+static void registerResultForRemoveDevice(RemoveData_t *removeData, OicUuid_t *pLinkedDevId,
+ OCStackResult stackresult, bool hasError)
+{
+ OC_LOG_V(INFO, TAG, "Inside registerResultForRemoveDevice removeData->numOfResults is %d\n",
+ removeData->numOfResults + 1);
+ if (pLinkedDevId)
+ {
+ memcpy(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
+ &pLinkedDevId->id, sizeof(pLinkedDevId->id));
+ }
+ else
+ {
+ memset(removeData->removeRes[(removeData->numOfResults)].deviceId.id,
+ 0, sizeof(pLinkedDevId->id) );
+ }
+ removeData->removeRes[(removeData->numOfResults)].res = stackresult;
+ removeData->hasError = hasError;
+ ++(removeData->numOfResults);
+
+ // If we get suffcient result from linked devices, we have to call user callback and do free
+ if (removeData->sizeOfResArray == removeData->numOfResults)
+ {
+ removeData->resultCallback(removeData->ctx, removeData->numOfResults, removeData->removeRes,
+ removeData->hasError);
+ DeleteRemoveData_t(removeData);
+ }
+ }
+
+/**
+ * Callback handler of unlink first device.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] handle handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult SRPRemoveDeviceCB(void *delDevCtx, OCDoHandle handle,
+ OCClientResponse *clientResponse)
+{
+ //Update the delete credential into delete device context
+ //Save the deleted status in delDevCtx
+ (void)handle;
+ OC_LOG_V(INFO, TAG, "Inside SRPRemoveDeviceCB.");
+ VERIFY_NON_NULL(TAG, delDevCtx, ERROR, OC_STACK_DELETE_TRANSACTION);
+ OCStackResult res = OC_STACK_ERROR;
+
+ RemoveData_t* removeData = (RemoveData_t*)delDevCtx;
+ if (clientResponse)
+ {
+ // If we can get device's UUID from OCClientResponse, it'd be good to use it in here
+ // but OCIdentity in OCClientResponse is emtpy now.
+ // It seems that we can set identity to CAData_t *cadata in CAPrepareSendData() API
+ // but CA doesn't have deviceID yet.
+ //
+ //TODO: Get OCIdentity from OCClientResponse and use it for 'registerResultForRemoveDevice'
+ // If we can't complete this task, Provisioning Database has always stale link status
+ // when Remove device is called.
+
+ if (OC_STACK_RESOURCE_DELETED == clientResponse->result)
+ {
+ res = PDMUnlinkDevices(&removeData->revokeTargetDev->doxm->deviceID,
+ NULL /*TODO: Replace NULL to uuid from OCClientResponse*/);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(FATAL, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
+ registerResultForRemoveDevice(removeData,
+ NULL /*TODO: Replace NULL to uuid from OCClientResponse*/,
+ OC_STACK_INCONSISTENT_DB, true);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ registerResultForRemoveDevice(removeData,
+ NULL /*TODO: Replace NULL to uuid from OCClientResponse*/,
+ OC_STACK_RESOURCE_DELETED, false);
+ }
+ else
+ {
+ registerResultForRemoveDevice(removeData,
+ NULL /*TODO: Replace NULL to uuid from OCClientResponse*/,
+ clientResponse->result, true);
+ OC_LOG(ERROR, TAG, "Unexpected result from DELETE credential request!");
+ }
+ }
+ else
+ {
+ registerResultForRemoveDevice(removeData, NULL, OC_STACK_ERROR, true);
+ OC_LOG(ERROR, TAG, "SRPRemoveDevices received Null clientResponse");
+ }
+
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+static OCStackResult GetListofDevToReqDeleteCred(const OCProvisionDev_t* pRevokeTargetDev,
+ OCProvisionDev_t* pOwnedDevList,
+ OCUuidList_t* pLinkedUuidList,
+ OCProvisionDev_t** ppLinkedDevList,
+ size_t *numOfLinkedDev)
+{
+ // pOwnedDevList could be NULL. It means no alived and owned device now.
+ if (pRevokeTargetDev == NULL || pLinkedUuidList == NULL ||\
+ ppLinkedDevList == NULL || numOfLinkedDev == NULL)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ size_t cnt = 0;
+ OCUuidList_t *curUuid = NULL, *tmpUuid = NULL;
+ LL_FOREACH_SAFE(pLinkedUuidList, curUuid, tmpUuid)
+ {
+ // Mark the link status stale.
+ OCStackResult res = PDMSetLinkStale(&curUuid->dev, &pRevokeTargetDev->doxm->deviceID);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(FATAL, TAG, "PDMSetLinkStale() FAIL: PDB is an obsolete one.");
+ return OC_STACK_INCONSISTENT_DB;
+ }
+
+ if (pOwnedDevList)
+ {
+ // If this linked device is alive (power-on), add the deivce to the list.
+ OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
+ LL_FOREACH_SAFE(pOwnedDevList, curDev, tmpDev)
+ {
+ if (memcmp(curDev->doxm->deviceID.id, curUuid->dev.id, sizeof(curUuid->dev.id)) == 0)
+ {
+ OCProvisionDev_t* targetDev = PMCloneOCProvisionDev(curDev);
+ if (NULL == targetDev)
+ {
+ OC_LOG(ERROR, TAG, "SRPRemoveDevice : Cloning OCProvisionDev_t Failed.");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ LL_PREPEND(*ppLinkedDevList, targetDev);
+ cnt++;
+ break;
+ }
+ }
+ }
+ }
+ *numOfLinkedDev = cnt;
+ return OC_STACK_OK;
+}
+
+/*
+* Function to device revocation
+* This function will remove credential of target device from all devices in subnet.
+*
+* @param[in] ctx Application context would be returned in result callback
+* @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
+* @param[in] pTargetDev Device information to be revoked.
+* @param[in] resultCallback callback provided by API user, callback will be called when
+* credential revocation is finished.
+* @return OC_STACK_OK in case of success and other value otherwise.
+* If OC_STACK_OK is returned, the caller of this API should wait for callback.
+* OC_STACK_CONTINUE means operation is success but no request is need to be initiated.
+*/
+OCStackResult SRPRemoveDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
+ const OCProvisionDev_t* pTargetDev, OCProvisionResultCB resultCallback)
+{
+ OC_LOG(INFO, TAG, "IN SRPRemoveDevice");
+
+ if (!pTargetDev || !resultCallback || 0 == waitTimeForOwnedDeviceDiscovery)
+ {
+ OC_LOG(INFO, TAG, "SRPRemoveDevice : NULL parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // Declare variables in here to handle error cases with goto statement.
+ OCProvisionDev_t* pOwnedDevList = NULL;
+ OCProvisionDev_t* pLinkedDevList = NULL;
+ RemoveData_t* removeData = NULL;
+
+ //1. Find all devices that has a credential of the revoked device
+ OCUuidList_t* pLinkedUuidList = NULL;
+ size_t numOfDevices = 0;
+ OCStackResult res = OC_STACK_ERROR;
+ res = PDMGetLinkedDevices(&pTargetDev->doxm->deviceID, &pLinkedUuidList, &numOfDevices);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "SRPRemoveDevice : Failed to get linked devices information");
+ return res;
+ }
+ // if there is no related device, we can skip further process.
+ if (0 == numOfDevices)
+ {
+ OC_LOG(DEBUG, TAG, "SRPRemoveDevice : No linked device found.");
+ res = OC_STACK_CONTINUE;
+ goto error;
+ }
+
+ //2. Find owned device from the network
+ res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "SRPRemoveDevice : Failed to PMDeviceDiscovery");
+ goto error;
+ }
+
+ //3. Make a list of devices to send DELETE credential request
+ // by comparing owned devices from provisioning database with mutlicast discovery result.
+ size_t numOfLinkedDev = 0;
+ res = GetListofDevToReqDeleteCred(pTargetDev, pOwnedDevList, pLinkedUuidList,
+ &pLinkedDevList, &numOfLinkedDev);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG(ERROR, TAG, "SRPRemoveDevice : GetListofDevToReqDeleteCred() failed");
+ goto error;
+ }
+ if (0 == numOfLinkedDev) // This case means, there is linked device but it's not alive now.
+ { // So we don't have to send request message.
+ OC_LOG(DEBUG, TAG, "SRPRemoveDevice : No alived & linked device found.");
+ res = OC_STACK_CONTINUE;
+ goto error;
+ }
+
+ // 4. Prepare RemoveData Context data.
+ removeData = (RemoveData_t*)OICCalloc(1, sizeof(RemoveData_t));
+ if (!removeData)
+ {
+ OC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to memory allocation");
+ res = OC_STACK_NO_MEMORY;
+ goto error;
+ }
+
+ removeData->revokeTargetDev = PMCloneOCProvisionDev(pTargetDev);
+ if (!removeData->revokeTargetDev)
+ {
+ OC_LOG(ERROR, TAG, "SRPRemoveDevices : PMCloneOCProvisionDev Failed");
+ res = OC_STACK_NO_MEMORY;
+ goto error;
+ }
+
+ removeData->removeRes =
+ (OCProvisionResult_t*)OICCalloc(numOfLinkedDev, sizeof(OCProvisionResult_t));
+ if (!removeData->removeRes)
+ {
+ OC_LOG(ERROR, TAG, "SRPRemoveDevices : Failed to memory allocation");
+ res = OC_STACK_NO_MEMORY;
+ goto error;
+ }
+
+ removeData->ctx = ctx;
+ removeData->linkedDevList = pLinkedDevList;
+ removeData->resultCallback = resultCallback;
+ removeData->numOfResults = 0;
+ removeData->sizeOfResArray = numOfLinkedDev;
+ removeData->hasError = false;
+
+ // 5. Send DELETE credential request to linked devices.
+ OCProvisionDev_t *curDev = NULL, *tmpDev = NULL;
+ OCStackResult totalRes = OC_STACK_ERROR; /* variable for checking request is sent or not */
+ LL_FOREACH_SAFE(pLinkedDevList, curDev, tmpDev)
+ {
+ res = SendDeleteCredentialRequest((void*)removeData, &SRPRemoveDeviceCB,
+ removeData->revokeTargetDev, curDev);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG_V(ERROR, TAG, "SRPRemoveDevice : Fail to send the DELETE credential request to\
+ %s:%u", curDev->endpoint.addr, curDev->endpoint.port);
+ }
+ else
+ {
+ totalRes = OC_STACK_OK; // This means at least one request is successfully sent.
+ }
+ }
+
+ PDMDestoryOicUuidLinkList(pLinkedUuidList); //TODO: Modify API name to have unified convention.
+ PMDeleteDeviceList(pOwnedDevList);
+ OC_LOG(INFO, TAG, "OUT SRPRemoveDevice");
+
+ return totalRes; // Caller of this API should wait callback if totalRes == OC_STACK_OK.
+
+error:
+ PDMDestoryOicUuidLinkList(pLinkedUuidList);
+ PMDeleteDeviceList(pOwnedDevList);
+ PMDeleteDeviceList(pLinkedDevList);
+ if (removeData)
+ {
+ OICFree(removeData->revokeTargetDev);
+ OICFree(removeData->removeRes);
+ OICFree(removeData);
+ }
+ OC_LOG(INFO, TAG, "OUT ERROR case SRPRemoveDevice");
+ return res;
+}
'../../include',
'../../../../../extlibs/tinydtls',
'../include/internal',
+ '../include/oxm',
'../../../logger/include',
'../../../stack/include',
'../../../../oc_logger/include',
'../../../../../extlibs/gtest/gtest-1.7.0/include',
- '../include'
+ '../include',
+ '../include/internal'
])
sptest_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
-sptest_env.AppendUnique(LIBS = ['-lpthread'])
+sptest_env.AppendUnique(LIBS = ['-lpthread','-ldl'])
sptest_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
sptest_env.AppendUnique(LIBPATH = [src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs'])
-sptest_env.PrependUnique(LIBS = [ 'ocspapi',
+sptest_env.PrependUnique(LIBS = [ 'ocpmapi',
'ocsrm',
'octbstack',
'oc_logger',
######################################################################
# Source files and Targets
######################################################################
-unittest = sptest_env.Program('unittest', ['provisioningmanager.cpp'])
+unittest = sptest_env.Program('unittest', ['pmutilitytest.cpp', 'otmunittest.cpp',
+ 'secureresourceprovider.cpp',
+ 'provisioningdatabasemanager.cpp',
+ 'ocprovisioningmanager.cpp' ])
Alias("test", [unittest])
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "gtest/gtest.h"
+#include "ocprovisioningmanager.h"
+
+static void provisioningCB (void* UNUSED1, int UNUSED2, OCProvisionResult_t *UNUSED3, bool UNUSED4)
+{
+ //dummy callback
+ (void) UNUSED1;
+ (void) UNUSED2;
+ (void) UNUSED3;
+ (void) UNUSED4;
+}
+
+TEST(OCUnlinkDevicesTest, NullDevice1)
+{
+ OCProvisionDev_t dev2;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCUnlinkDevices(NULL, NULL, &dev2, provisioningCB));
+}
+
+TEST(OCUnlinkDevicesTest, NullDevice2)
+{
+ OCProvisionDev_t dev1;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCUnlinkDevices(NULL, &dev1, NULL, provisioningCB));
+}
+
+TEST(OCUnlinkDevicesTest, NullCallback)
+{
+ OCProvisionDev_t dev1;
+ OCProvisionDev_t dev2;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCUnlinkDevices(NULL, &dev1, &dev2, NULL));
+}
+
+TEST(OCRemoveDeviceTest, NullTargetDevice)
+{
+ unsigned short waitTime = 10 ;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCRemoveDevice(NULL, waitTime, NULL, provisioningCB));
+}
+
+TEST(OCRemoveDeviceTest, NullResultCallback)
+{
+ unsigned short waitTime = 10;
+ OCProvisionDev_t dev1;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCRemoveDevice(NULL, waitTime, &dev1, NULL));
+}
+
+TEST(OCRemoveDeviceTest, ZeroWaitTime)
+{
+ unsigned short waitTime = 0;
+ OCProvisionDev_t dev1;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCRemoveDevice(NULL, waitTime, &dev1, NULL));
+}
+
+TEST(OCGetDevInfoFromNetworkTest, NullUnOwnedDeviceInfo)
+{
+ OCProvisionDev_t *ownedList = NULL;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCGetDevInfoFromNetwork(0, &ownedList, NULL));
+}
+
+TEST(OCGetDevInfoFromNetworkTest, NullOwnedDeviceInfo)
+{
+ OCProvisionDev_t *unownedList = NULL;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCGetDevInfoFromNetwork(0, NULL, &unownedList));
+}
+
+TEST(OCGetLinkedStatusTest, NULLDeviceID)
+{
+ OCUuidList_t *list = NULL;
+ size_t noOfDevices = 0;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCGetLinkedStatus(NULL, &list, &noOfDevices));
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "gtest/gtest.h"
+#include "oxmjustworks.h"
+#include "oxmrandompin.h"
+#include "ownershiptransfermanager.h"
+#include "ocstack.h"
+#include "utlist.h"
+
+using namespace std;
+
+TEST(JustWorksOxMTest, NullParam)
+{
+
+ OTMContext_t* otmCtx = NULL;
+ OCStackResult res = OC_STACK_ERROR;
+ char* payloadRes;
+
+ //LoadSecretJustWorksCallback always returns OC_STACK_OK.
+ res = LoadSecretJustWorksCallback(otmCtx);
+ EXPECT_TRUE(OC_STACK_OK == res);
+
+ res = CreateSecureSessionJustWorksCallback(otmCtx);
+ EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+ payloadRes = CreateJustWorksSelectOxmPayload(otmCtx);
+ EXPECT_TRUE(NULL == payloadRes);
+
+ payloadRes = CreateJustWorksOwnerTransferPayload(otmCtx);
+ EXPECT_TRUE(NULL == payloadRes);
+
+ OTMContext_t otmCtx2;
+ otmCtx2.selectedDeviceInfo = NULL;
+
+ //LoadSecretJustWorksCallback always returns OC_STACK_OK.
+ res = LoadSecretJustWorksCallback(&otmCtx2);
+ EXPECT_TRUE(OC_STACK_OK == res);
+
+ res = CreateSecureSessionJustWorksCallback(&otmCtx2);
+ EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+ payloadRes = CreateJustWorksSelectOxmPayload(&otmCtx2);
+ EXPECT_TRUE(NULL == payloadRes);
+
+ payloadRes = CreateJustWorksOwnerTransferPayload(&otmCtx2);
+ EXPECT_TRUE(NULL == payloadRes);
+}
+
+TEST(RandomPinOxMTest, NullParam)
+{
+ OTMContext_t* otmCtx = NULL;
+ OCStackResult res = OC_STACK_ERROR;
+ char* payloadRes;
+
+ //LoadSecretJustWorksCallback always returns OC_STACK_OK.
+ res = InputPinCodeCallback(otmCtx);
+ EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+ res = CreateSecureSessionRandomPinCallbak(otmCtx);
+ EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+ payloadRes = CreatePinBasedSelectOxmPayload(otmCtx);
+ EXPECT_TRUE(NULL == payloadRes);
+
+ payloadRes = CreatePinBasedOwnerTransferPayload(otmCtx);
+ EXPECT_TRUE(NULL == payloadRes);
+
+ OTMContext_t otmCtx2;
+ otmCtx2.selectedDeviceInfo = NULL;
+
+ //LoadSecretJustWorksCallback always returns OC_STACK_OK.
+ res = InputPinCodeCallback(&otmCtx2);
+ EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+ res = CreateSecureSessionRandomPinCallbak(&otmCtx2);
+ EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+ payloadRes = CreatePinBasedSelectOxmPayload(&otmCtx2);
+ EXPECT_TRUE(NULL == payloadRes);
+
+ payloadRes = CreatePinBasedOwnerTransferPayload(&otmCtx2);
+ EXPECT_TRUE(NULL == payloadRes);
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "gtest/gtest.h"
+#include "pmutility.h"
+#include "ocstack.h"
+#include "utlist.h"
+
+using namespace std;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern OCStackResult AddDevice(OCProvisionDev_t **ppDevicesList, const char* addr,
+ const uint16_t port, OCTransportAdapter adapter,
+ OCConnectivityType connType, OicSecDoxm_t *doxm);
+#ifdef __cplusplus
+}
+#endif
+
+OCProvisionDev_t* gList = NULL;
+
+// List add Tests
+TEST(ProvisionListTest, Addition)
+{
+ OCProvisionDev_t* el = NULL;
+ OCStackResult res = OC_STACK_ERROR;
+ OicSecDoxm_t* pDoxm = NULL;
+ int cnt =0;
+
+ // The first addition
+ res = AddDevice(&gList, "10.20.30.40", 5684, OC_DEFAULT_ADAPTER, CT_IP_USE_V4, pDoxm);
+ EXPECT_TRUE(OC_STACK_OK == res);
+ EXPECT_TRUE(NULL != gList);
+
+ LL_FOREACH(gList,el){ ++cnt; };
+ EXPECT_TRUE(1 == cnt);
+
+ // Same node must not be inserted
+ res = AddDevice(&gList, "10.20.30.40", 5684, OC_ADAPTER_IP, CT_IP_USE_V4, pDoxm);
+ EXPECT_TRUE(OC_STACK_OK == res);
+ EXPECT_TRUE(NULL != gList);
+
+ cnt = 0;
+ LL_FOREACH(gList,el){ ++cnt; };
+ EXPECT_TRUE(1 == cnt);
+
+ // Differnet node must be inserted
+ res = AddDevice(&gList, "110.120.130.140", 6789, OC_DEFAULT_ADAPTER, CT_IP_USE_V4, pDoxm);
+ EXPECT_TRUE(OC_STACK_OK == res);
+ EXPECT_TRUE(NULL != gList);
+
+ cnt = 0;
+ LL_FOREACH(gList,el){ ++cnt; };
+ EXPECT_TRUE(2 == cnt);
+}
+
+// List Delete Tests
+TEST(ProvisionListTest, Deletion)
+{
+ OCProvisionDev_t* el = NULL;
+ int cnt =0;
+
+ // Delete whole
+ PMDeleteDeviceList(gList);
+ gList = NULL;
+
+ LL_FOREACH(gList,el){ ++cnt; };
+ EXPECT_TRUE(0 == cnt);
+}
\ No newline at end of file
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "gtest/gtest.h"
+#include "provisioningdatabasemanager.h"
+
+const char ID_1[] = "1111111111111111";
+const char ID_2[] = "2111111111111111";
+const char ID_3[] = "3111111111111111";
+const char ID_4[] = "4111111111111111";
+const char ID_5[] = "5111111111111111";
+const char ID_6[] = "6111111111111111";
+
+TEST(CallPDMAPIbeforeInit, BeforeInit)
+{
+ EXPECT_EQ(OC_STACK_PDM_IS_NOT_INITIALIZED, PDMAddDevice(NULL));
+ EXPECT_EQ(true, PDMIsDuplicateDevice(NULL)); // return type is not OCStackResult
+ EXPECT_EQ(OC_STACK_PDM_IS_NOT_INITIALIZED, PDMLinkDevices(NULL, NULL));
+ EXPECT_EQ(OC_STACK_PDM_IS_NOT_INITIALIZED, PDMUnlinkDevices(NULL, NULL));
+ EXPECT_EQ(OC_STACK_PDM_IS_NOT_INITIALIZED, PDMDeleteDevice(NULL));
+ EXPECT_EQ(OC_STACK_PDM_IS_NOT_INITIALIZED, PDMGetOwnedDevices(NULL, NULL));
+ EXPECT_EQ(OC_STACK_PDM_IS_NOT_INITIALIZED, PDMGetLinkedDevices(NULL, NULL, NULL));
+ EXPECT_EQ(OC_STACK_PDM_IS_NOT_INITIALIZED, PDMSetLinkStale(NULL, NULL));
+ EXPECT_EQ(OC_STACK_PDM_IS_NOT_INITIALIZED, PDMGetToBeUnlinkedDevices(NULL, NULL));
+}
+
+TEST(PDMInitTest, PDMInitWithNULL)
+{
+ EXPECT_EQ(OC_STACK_OK, PDMInit(NULL));
+}
+
+TEST(PDMAddDeviceTest, NullUUID)
+{
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMAddDevice(NULL));
+}
+
+TEST(PDMIsDuplicateDeviceTest, NullUUID)
+{
+ EXPECT_TRUE(PDMIsDuplicateDevice(NULL));
+}
+
+
+TEST(PDMIsDuplicateDeviceTest, ValidUUID)
+{
+ OicUuid_t uid1 = {{0,}};
+ memcpy(&uid1.id, ID_1, sizeof(uid1.id));
+ PDMAddDevice(&uid1);
+ OicUuid_t uid2 = {{0,}};
+ memcpy(&uid2.id, ID_2, sizeof(uid2.id));
+ PDMAddDevice(&uid2);
+ OicUuid_t uid3 = {{0,}};
+ memcpy(&uid3.id, ID_3, sizeof(uid3.id));
+
+ EXPECT_TRUE(PDMIsDuplicateDevice(&uid1));
+ EXPECT_FALSE(PDMIsDuplicateDevice(&uid3));
+}
+
+TEST(PDMAddDeviceTest, ValidUUID)
+{
+ OicUuid_t uid = {{0,}};
+
+ uint8_t id[UUID_LENGTH] = {0,};
+ for (size_t i = 0 ; i < sizeof(id) ; i++)
+ {
+ int tem = rand() % 25;
+
+ id[i] = tem + 65;
+ }
+
+ memcpy(&uid.id, &id, UUID_LENGTH);
+
+ EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid));
+ PDMDeleteDevice(&uid);
+}
+
+TEST(PDMLinkDevicesTest, NULLDevice1)
+{
+ OicUuid_t uid = {{0,}};
+ memcpy(&uid.id, ID_2, sizeof(uid.id));
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMLinkDevices(NULL, &uid));
+}
+
+TEST(PDMLinkDevicesTest, NULLDevice2)
+{
+ OicUuid_t uid = {{0,}};
+ memcpy(&uid.id, ID_3, sizeof(uid.id));
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMLinkDevices(&uid, NULL));
+}
+
+TEST(PDMLinkDevicesTest, ValidCase)
+{
+ OicUuid_t uid1 = {{0,}};
+ memcpy(&uid1.id, ID_4, sizeof(uid1.id));
+ PDMAddDevice(&uid1);
+ OicUuid_t uid2 = {{0,}};
+ memcpy(&uid2.id, ID_5, sizeof(uid2.id));
+ PDMAddDevice(&uid2);
+ EXPECT_EQ(OC_STACK_OK, PDMLinkDevices(&uid1, &uid2));
+}
+
+TEST(PDMUnlinkDevicesTest, NULLDevice1)
+{
+ OicUuid_t uid = {{0,}};
+ memcpy(&uid.id, ID_3, sizeof(uid.id));
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMUnlinkDevices(NULL, &uid));
+}
+
+TEST(PDMUnlinkDevicesTest, NULLDevice2)
+{
+ OicUuid_t uid = {{0,}};
+ memcpy(&uid.id, ID_3, sizeof(uid.id));
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMUnlinkDevices(&uid, NULL));
+}
+
+TEST(PDMUnlinkDevices, ValidCase)
+{
+ OicUuid_t uid1 = {{0,}};
+ memcpy(&uid1.id, ID_4, sizeof(uid1.id));
+ OicUuid_t uid2 = {{0,}};
+ memcpy(&uid2.id, ID_5, sizeof(uid2.id));
+ EXPECT_EQ(OC_STACK_OK, PDMUnlinkDevices(&uid1, &uid2));
+}
+
+
+TEST (PDMDeleteDevice, NULLDeviceID)
+{
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMDeleteDevice(NULL));
+}
+
+TEST (PDMDeleteDevice, ValidButNonExistDeviceID)
+{
+
+ OicUuid_t uid = {{0,}};
+ uint8_t id[UUID_LENGTH] = {0,};
+ for (size_t i = 0 ; i < sizeof(id) ; i++)
+ {
+ int tem = rand() % 25;
+
+ id[i] = tem + 65;
+ }
+
+ memcpy(&uid.id, &id, sizeof(uid.id));
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMDeleteDevice(&uid));
+}
+
+TEST(PDMGetOwnedDevices, ValidCase)
+{
+ OCUuidList_t *list = NULL;
+ size_t noOfDevcies = 0;
+ EXPECT_EQ(OC_STACK_OK, PDMGetOwnedDevices(&list, &noOfDevcies));
+}
+
+TEST(PDMGetLinkedDevices, NULLDeviceID)
+{
+ OCUuidList_t *list = NULL;
+ size_t noOfDevices = 0;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMGetLinkedDevices(NULL, &list, &noOfDevices));
+}
+
+TEST(PDMGetLinkedDevices, ValidCase)
+{
+ OicUuid_t uid = {{0,}};
+ memcpy(&uid.id, ID_1, sizeof(uid.id));
+ OCUuidList_t *list = NULL;
+ size_t noOfDevices = 0;
+ EXPECT_EQ(OC_STACK_OK, PDMGetLinkedDevices(&uid, &list, &noOfDevices));
+}
+
+TEST(PDMGetLinkedDevices, InvalidCase)
+{
+ OicUuid_t uid = {{0,}};
+ memcpy(&uid.id, ID_6, sizeof(uid.id));
+ OCUuidList_t *list = NULL;
+ size_t noOfDevices = 0;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMGetLinkedDevices(&uid, &list, &noOfDevices));
+}
+
+TEST(PDMSetLinkStale, NULLDeviceID1)
+{
+ OicUuid_t uid = {{0,}};
+ memcpy(&uid.id, ID_1, sizeof(uid.id));
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMSetLinkStale(NULL, &uid));
+}
+
+TEST(PDMSetLinkStale, NULLDeviceID2)
+{
+ OicUuid_t uid = {{0,}};
+ memcpy(&uid.id, ID_1, sizeof(uid.id));
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMSetLinkStale(&uid, NULL));
+}
+
+TEST(PDMSetLinkStale, ValidCase)
+{
+ OicUuid_t uid1 = {{0,}};
+ memcpy(&uid1.id, ID_6, sizeof(uid1.id));
+ OicUuid_t uid2 = {{0,}};
+ memcpy(&uid2.id, ID_1, sizeof(uid2.id));
+
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, PDMSetLinkStale(&uid1, &uid2));
+
+ EXPECT_EQ(OC_STACK_OK, PDMAddDevice(&uid1));
+
+ EXPECT_EQ(OC_STACK_OK, PDMLinkDevices(&uid1, &uid2));
+
+ EXPECT_EQ(OC_STACK_OK, PDMSetLinkStale(&uid1, &uid2));
+}
+
+TEST(PDMGetToBeUnlinkedDevices, ValidCase)
+{
+ OCPairList_t *list = NULL;
+ size_t noOfDevices = 0;
+ EXPECT_EQ(OC_STACK_OK, PDMGetToBeUnlinkedDevices(&list, &noOfDevices));
+}
+
+TEST(PDMClose, ValidCase)
+{
+ EXPECT_EQ(OC_STACK_OK, PDMClose());
+}
+
+TEST(PDMDestoryOicUuidLinkList, NULLParam)
+{
+ PDMDestoryOicUuidLinkList(NULL);
+}
+
+TEST(PDMDestoryStaleLinkList, NULLParam)
+{
+ PDMDestoryStaleLinkList(NULL);
+}
+++ /dev/null
-/* *****************************************************************
- *
- * 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 "gtest/gtest.h"
-
-#include "provisioningmanager.h"
-
-
-static OicSecAcl_t acl;
-SPTargetDeviceInfo_t list;
-SPTargetDeviceInfo_t *ptr = &list;
-
-TEST(SPProvisioningDiscoveryTest, NotNullList)
-{
- EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPProvisioningDiscovery(0, &ptr));
-}
-
-TEST(SPInitProvisionContextTest, NullDeviceInfo)
-{
- EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPInitProvisionContext(0, NULL));
-}
-
-TEST(SPProvisionACLTest, NullDeviceInfo)
-{
- EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPProvisionACL(0, NULL, &acl));
-}
-
-TEST(SPFinalizeProvisioningTest, NullDeviceInfo)
-{
- EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPFinalizeProvisioning(0, NULL));
-}
-
-TEST(SPTerminateProvisioningTest, ValidCase)
-{
- EXPECT_EQ(SP_RESULT_SUCCESS, SPTerminateProvisioning());
-}
-
-TEST(SPProvisionCredentialsTest, NullList)
-{
- EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPProvisionCredentials(0, 0, NULL));
-}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "gtest/gtest.h"
+#include "secureresourceprovider.h"
+
+
+static OicSecAcl_t acl;
+static OCProvisionDev_t pDev1;
+static OCProvisionDev_t pDev2;
+static OicSecCredType_t credType;
+
+static void provisioningCB (void* UNUSED1, int UNUSED2, OCProvisionResult_t *UNUSED3, bool UNUSED4)
+{
+ //dummy callback
+ (void) UNUSED1;
+ (void) UNUSED2;
+ (void) UNUSED3;
+ (void) UNUSED4;
+}
+
+TEST(SRPProvisionACLTest, NullDeviceInfo)
+{
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionACL(NULL, NULL, &acl, &provisioningCB));
+}
+
+TEST(SRPProvisionACLTest, NullCallback)
+{
+ EXPECT_EQ(OC_STACK_INVALID_CALLBACK, SRPProvisionACL(NULL, &pDev1, &acl, NULL));
+}
+
+TEST(SRPProvisionACLTest, NullACL)
+{
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionACL(NULL, &pDev1, NULL, &provisioningCB));
+}
+
+TEST(SRPProvisionCredentialsTest, NullDevice1)
+{
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionCredentials(NULL, credType,
+ OWNER_PSK_LENGTH_128, NULL,
+ &pDev2, &provisioningCB));
+}
+
+TEST(SRPProvisionCredentialsTest, NullCallback)
+{
+ EXPECT_EQ(OC_STACK_INVALID_CALLBACK, SRPProvisionCredentials(NULL, credType,
+ OWNER_PSK_LENGTH_128,
+ &pDev1, &pDev2, NULL));
+}
+
+TEST(SRPProvisionCredentialsTest, InvalidKeySize)
+{
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionCredentials(NULL, credType,
+ 0, &pDev1, &pDev2,
+ &provisioningCB));
+}
+
+TEST(SRPUnlinkDevicesTest, NullDevice1)
+{
+ OCProvisionDev_t dev2;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPUnlinkDevices(NULL, NULL, &dev2, provisioningCB));
+}
+
+TEST(SRPUnlinkDevicesTest, NullDevice2)
+{
+ OCProvisionDev_t dev1;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPUnlinkDevices(NULL, &dev1, NULL, provisioningCB));
+}
+
+TEST(SRPUnlinkDevicesTest, NullCallback)
+{
+ OCProvisionDev_t dev1;
+ OCProvisionDev_t dev2;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPUnlinkDevices(NULL, &dev1, &dev2, NULL));
+}
+
+TEST(SRPRemoveDeviceTest, NullTargetDevice)
+{
+ unsigned short waitTime = 10 ;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPRemoveDevice(NULL, waitTime, NULL, provisioningCB));
+}
+
+TEST(SRPRemoveDeviceTest, NullResultCallback)
+{
+ unsigned short waitTime = 10;
+ OCProvisionDev_t dev1;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPRemoveDevice(NULL, waitTime, &dev1, NULL));
+}
+
+TEST(SRPRemoveDeviceTest, ZeroWaitTime)
+{
+ OCProvisionDev_t dev1;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPRemoveDevice(NULL, 0, &dev1, NULL));
+}
#include "ocstack.h"
#include "logger.h"
#include "oic_malloc.h"
+#include "oic_string.h"
#include "cJSON.h"
#include "base64.h"
#include "resourcemanager.h"
#include "srmresourcestrings.h"
#include "doxmresource.h"
#include "srmutility.h"
+#include "ocserverrequest.h"
#include <stdlib.h>
+#ifdef WITH_ARDUINO
#include <string.h>
+#else
+#include <strings.h>
+#endif
-#define TAG PCF("SRM-ACL")
+#define TAG "SRM-ACL"
-OicSecAcl_t *gAcl = NULL;
+OicSecAcl_t *gAcl = NULL;
static OCResourceHandle gAclHandle = NULL;
+/**
+ * This function frees OicSecAcl_t object's fields and object itself.
+ */
+static void FreeACE(OicSecAcl_t *ace)
+{
+ size_t i;
+ if(NULL == ace)
+ {
+ OC_LOG (INFO, TAG, "Invalid Parameter");
+ return;
+ }
+
+ // Clean Resources
+ for (i = 0; i < ace->resourcesLen; i++)
+ {
+ OICFree(ace->resources[i]);
+ }
+ OICFree(ace->resources);
+
+ //Clean Period & Recurrence
+ for(i = 0; i < ace->prdRecrLen; i++)
+ {
+ OICFree(ace->periods[i]);
+ OICFree(ace->recurrences[i]);
+ }
+ OICFree(ace->periods);
+ OICFree(ace->recurrences);
+
+ // Clean Owners
+ OICFree(ace->owners);
+
+ // Clean ACL node itself
+ OICFree(ace);
+}
+
void DeleteACLList(OicSecAcl_t* acl)
{
if (acl)
LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
{
LL_DELETE(acl, aclTmp1);
-
- // Clean Resources
- for (size_t i = 0; i < aclTmp1->resourcesLen; i++)
- {
- OICFree(aclTmp1->resources[i]);
- }
- OICFree(aclTmp1->resources);
-
- // Clean Owners
- OICFree(aclTmp1->owners);
-
- // Clean ACL node itself
- OICFree(aclTmp1);
+ FreeACE(aclTmp1);
}
}
}
// Permissions -- Mandatory
cJSON_AddNumberToObject (jsonAcl, OIC_JSON_PERMISSION_NAME, acl->permission);
+ //Period & Recurrence -- Not Mandatory
+ if(0 != acl->prdRecrLen)
+ {
+ cJSON *jsonPeriodArray = NULL;
+ cJSON_AddItemToObject (jsonAcl, OIC_JSON_PERIODS_NAME,
+ jsonPeriodArray = cJSON_CreateArray());
+ VERIFY_NON_NULL(TAG, jsonPeriodArray, ERROR);
+ for (size_t i = 0; i < acl->prdRecrLen; i++)
+ {
+ cJSON_AddItemToArray (jsonPeriodArray,
+ cJSON_CreateString(acl->periods[i]));
+ }
+ }
+
+ //Recurrence -- Not Mandatory
+ if(0 != acl->prdRecrLen && acl->recurrences)
+ {
+ cJSON *jsonRecurArray = NULL;
+ cJSON_AddItemToObject (jsonAcl, OIC_JSON_RECURRENCES_NAME,
+ jsonRecurArray = cJSON_CreateArray());
+ VERIFY_NON_NULL(TAG, jsonRecurArray, ERROR);
+ for (size_t i = 0; i < acl->prdRecrLen; i++)
+ {
+ cJSON_AddItemToArray (jsonRecurArray,
+ cJSON_CreateString(acl->recurrences[i]));
+ }
+ }
+
// Owners -- Mandatory
cJSON *jsonOwnrArray = NULL;
cJSON_AddItemToObject (jsonAcl, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray());
jsonObjLen = strlen(jsonRsrc->valuestring) + 1;
acl->resources[idxx] = (char*)OICMalloc(jsonObjLen);
VERIFY_NON_NULL(TAG, (acl->resources[idxx]), ERROR);
- strncpy(acl->resources[idxx], jsonRsrc->valuestring, jsonObjLen);
+ OICStrcpy(acl->resources[idxx], jsonObjLen, jsonRsrc->valuestring);
} while ( ++idxx < acl->resourcesLen);
// Permissions -- Mandatory
- jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_PERMISSION_NAME);
+ jsonObj = cJSON_GetObjectItem(jsonAcl,
+ OIC_JSON_PERMISSION_NAME);
VERIFY_NON_NULL(TAG, jsonObj, ERROR);
VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
acl->permission = jsonObj->valueint;
+ //Period -- Not Mandatory
+ cJSON *jsonPeriodObj = cJSON_GetObjectItem(jsonAcl,
+ OIC_JSON_PERIODS_NAME);
+ if(jsonPeriodObj)
+ {
+ VERIFY_SUCCESS(TAG, cJSON_Array == jsonPeriodObj->type,
+ ERROR);
+ acl->prdRecrLen = cJSON_GetArraySize(jsonPeriodObj);
+ if(acl->prdRecrLen > 0)
+ {
+ acl->periods = (char**)OICCalloc(acl->prdRecrLen,
+ sizeof(char*));
+ VERIFY_NON_NULL(TAG, acl->periods, ERROR);
+
+ cJSON *jsonPeriod = NULL;
+ for(size_t i = 0; i < acl->prdRecrLen; i++)
+ {
+ jsonPeriod = cJSON_GetArrayItem(jsonPeriodObj, i);
+ VERIFY_NON_NULL(TAG, jsonPeriod, ERROR);
+
+ jsonObjLen = strlen(jsonPeriod->valuestring) + 1;
+ acl->periods[i] = (char*)OICMalloc(jsonObjLen);
+ VERIFY_NON_NULL(TAG, acl->periods[i], ERROR);
+ OICStrcpy(acl->periods[i], jsonObjLen,
+ jsonPeriod->valuestring);
+ }
+ }
+ }
+
+ //Recurrence -- Not mandatory
+ cJSON *jsonRecurObj = cJSON_GetObjectItem(jsonAcl,
+ OIC_JSON_RECURRENCES_NAME);
+ if(jsonRecurObj)
+ {
+ VERIFY_SUCCESS(TAG, cJSON_Array == jsonRecurObj->type,
+ ERROR);
+ if(acl->prdRecrLen > 0)
+ {
+ acl->recurrences = (char**)OICCalloc(acl->prdRecrLen,
+ sizeof(char*));
+ VERIFY_NON_NULL(TAG, acl->recurrences, ERROR);
+
+ cJSON *jsonRecur = NULL;
+ for(size_t i = 0; i < acl->prdRecrLen; i++)
+ {
+ jsonRecur = cJSON_GetArrayItem(jsonRecurObj, i);
+ jsonObjLen = strlen(jsonRecur->valuestring) + 1;
+ acl->recurrences[i] = (char*)OICMalloc(jsonObjLen);
+ VERIFY_NON_NULL(TAG, acl->recurrences[i], ERROR);
+ OICStrcpy(acl->recurrences[i], jsonObjLen,
+ jsonRecur->valuestring);
+ }
+ }
+ }
+
// Owners -- Mandatory
jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_OWNERS_NAME);
VERIFY_NON_NULL(TAG, jsonObj, ERROR);
return headAcl;
}
+static bool UpdatePersistentStorage(const OicSecAcl_t *acl)
+{
+ // Convert ACL data into JSON for update to persistent storage
+ char *jsonStr = BinToAclJSON(acl);
+ if (jsonStr)
+ {
+ cJSON *jsonAcl = cJSON_Parse(jsonStr);
+ OICFree(jsonStr);
+
+ if ((jsonAcl) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl)))
+ {
+ return true;
+ }
+ cJSON_Delete(jsonAcl);
+ }
+ return false;
+}
+/*
+ * This method removes ACE for the subject and resource from the ACL
+ *
+ * @param subject - subject of the ACE
+ * @param resource - resource of the ACE
+ *
+ * @return
+ * OC_STACK_RESOURCE_DELETED on success
+ * OC_STACK_NO_RESOURC on failure to find the appropriate ACE
+ * OC_STACK_INVALID_PARAM on invalid parameter
+ */
+static OCStackResult RemoveACE(const OicUuid_t * subject,
+ const char * resource)
+{
+ OC_LOG(INFO, TAG, "IN RemoveACE");
+
+ OicSecAcl_t *acl = NULL;
+ OicSecAcl_t *tempAcl = NULL;
+ bool deleteFlag = false;
+ OCStackResult ret = OC_STACK_NO_RESOURCE;
+
+ if(memcmp(subject->id, &WILDCARD_SUBJECT_ID, sizeof(subject->id)) == 0)
+ {
+ OC_LOG_V (INFO, TAG, "%s received invalid parameter", __func__ );
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ //If resource is NULL then delete all the ACE for the subject.
+ if(NULL == resource || resource[0] == '\0')
+ {
+ LL_FOREACH_SAFE(gAcl, acl, tempAcl)
+ {
+ if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
+ {
+ LL_DELETE(gAcl, acl);
+ FreeACE(acl);
+ deleteFlag = true;
+ }
+ }
+ }
+ else
+ {
+ //Looping through ACL to find the right ACE to delete. If the required resource is the only
+ //resource in the ACE for the subject then delete the whole ACE. If there are more resources
+ //than the required resource in the ACE, for the subject then just delete the resource from
+ //the resource array
+ LL_FOREACH_SAFE(gAcl, acl, tempAcl)
+ {
+ if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
+ {
+ if(1 == acl->resourcesLen && strcmp(acl->resources[0], resource) == 0)
+ {
+ LL_DELETE(gAcl, acl);
+ FreeACE(acl);
+ deleteFlag = true;
+ break;
+ }
+ else
+ {
+ int resPos = -1;
+ size_t i;
+ for(i = 0; i < acl->resourcesLen; i++)
+ {
+ if(strcmp(acl->resources[i], resource) == 0)
+ {
+ resPos = i;
+ break;
+ }
+ }
+ if((0 <= resPos))
+ {
+ OICFree(acl->resources[resPos]);
+ acl->resources[resPos] = NULL;
+ acl->resourcesLen -= 1;
+ for(i = resPos; i < acl->resourcesLen; i++)
+ {
+ acl->resources[i] = acl->resources[i+1];
+ }
+ deleteFlag = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if(deleteFlag)
+ {
+ if(UpdatePersistentStorage(gAcl))
+ {
+ ret = OC_STACK_RESOURCE_DELETED;
+ }
+ }
+ return ret;
+}
+
+/*
+ * This method parses the query string received for REST requests and
+ * retrieves the 'subject' field.
+ *
+ * @param query querystring passed in REST request
+ * @param subject subject UUID parsed from query string
+ *
+ * @return true if query parsed successfully and found 'subject', else false.
+ */
+static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject)
+{
+ OicParseQueryIter_t parseIter = {.attrPos=NULL};
+
+ ParseQueryIterInit((unsigned char *)query, &parseIter);
+
+ while(GetNextQuery(&parseIter))
+ {
+ if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0)
+ {
+ VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
+ unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+ uint32_t outLen = 0;
+ B64Result b64Ret = B64_OK;
+ b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
+ sizeof(base64Buff), &outLen);
+ VERIFY_SUCCESS(TAG, (B64_OK == b64Ret && outLen <= sizeof(subject->id)), ERROR);
+ memcpy(subject->id, base64Buff, outLen);
+
+ return true;
+ }
+ }
+
+exit:
+ return false;
+}
+
+/*
+ * This method parses the query string received for REST requests and
+ * retrieves the 'resource' field.
+ *
+ * @param query querystring passed in REST request
+ * @param resource resource parsed from query string
+ * @param resourceSize size of the memory pointed to resource
+ *
+ * @return true if query parsed successfully and found 'resource', else false.
+ */
+static bool GetResourceFromQueryString(const char *query, char *resource, size_t resourceSize)
+{
+ OicParseQueryIter_t parseIter = {.attrPos=NULL};
+
+ ParseQueryIterInit((unsigned char *)query, &parseIter);
+
+ while(GetNextQuery(&parseIter))
+ {
+ if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen) == 0)
+ {
+ VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
+ OICStrcpy(resource, resourceSize, (char *)parseIter.valPos);
+
+ return true;
+ }
+ }
+
+exit:
+ return false;
+}
+
+
+
static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest)
{
- // Convert ACL data into JSON for transmission
- char* jsonStr = BinToAclJSON(gAcl);
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+ char* jsonStr = NULL;
- /*
- * A device should 'always' have a default ACL. Therefore,
- * jsonStr should never be NULL.
- */
- OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
+ // Process the REST querystring parameters
+ if(ehRequest->query)
+ {
+ OC_LOG (INFO, TAG, "HandleACLGetRequest processing query");
+
+ OicUuid_t subject = {.id={0}};
+ char resource[MAX_URI_LENGTH] = {0};
+
+ OicSecAcl_t *savePtr = NULL;
+ const OicSecAcl_t *currentAce = NULL;
+
+ // 'Subject' field is MUST for processing a querystring in REST request.
+ VERIFY_SUCCESS(TAG,
+ true == GetSubjectFromQueryString(ehRequest->query, &subject),
+ ERROR);
+
+ GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
+
+ /*
+ * TODO : Currently, this code only provides one ACE for a Subject.
+ * Below code needs to be updated for scenarios when Subject have
+ * multiple ACE's in ACL resource.
+ */
+ while((currentAce = GetACLResourceData(&subject, &savePtr)))
+ {
+ /*
+ * If REST querystring contains a specific resource, we need
+ * to search for that resource in ACE.
+ */
+ if (resource[0] != '\0')
+ {
+ for(size_t n = 0; n < currentAce->resourcesLen; n++)
+ {
+ if((currentAce->resources[n]) &&
+ (0 == strcmp(resource, currentAce->resources[n]) ||
+ 0 == strcmp(WILDCARD_RESOURCE_URI, currentAce->resources[n])))
+ {
+ // Convert ACL data into JSON for transmission
+ jsonStr = BinToAclJSON(currentAce);
+ goto exit;
+ }
+ }
+ }
+ else
+ {
+ // Convert ACL data into JSON for transmission
+ jsonStr = BinToAclJSON(currentAce);
+ goto exit;
+ }
+ }
+ }
+ else
+ {
+ // Convert ACL data into JSON for transmission
+ jsonStr = BinToAclJSON(gAcl);
+ }
+
+exit:
+ ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
// Send response payload to request originator
SendSRMResponse(ehRequest, ehRet, jsonStr);
OICFree(jsonStr);
- OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ehRet);
+ OC_LOG_V (INFO, TAG, "%s RetVal %d", __func__ , ehRet);
return ehRet;
}
// Append the new ACL to existing ACL
LL_APPEND(gAcl, newAcl);
- // Convert ACL data into JSON for update to persistent storage
- char *jsonStr = BinToAclJSON(gAcl);
- if (jsonStr)
+ if(UpdatePersistentStorage(gAcl))
{
- cJSON *jsonAcl = cJSON_Parse(jsonStr);
- OICFree(jsonStr);
-
- if ((jsonAcl) &&
- (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl)))
- {
- ehRet = OC_EH_RESOURCE_CREATED;
- }
- cJSON_Delete(jsonAcl);
+ ehRet = OC_EH_RESOURCE_CREATED;
}
}
// Send payload to request originator
SendSRMResponse(ehRequest, ehRet, NULL);
- OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ehRet);
+ OC_LOG_V (INFO, TAG, "%s RetVal %d", __func__ , ehRet);
+ return ehRet;
+}
+
+static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest)
+{
+ OC_LOG (INFO, TAG, "Processing ACLDeleteRequest");
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+ OicUuid_t subject = {.id={0}};
+ char resource[MAX_URI_LENGTH] = {0};
+
+ VERIFY_NON_NULL(TAG, ehRequest->query, ERROR);
+
+ // 'Subject' field is MUST for processing a querystring in REST request.
+ VERIFY_SUCCESS(TAG,
+ true == GetSubjectFromQueryString(ehRequest->query, &subject),
+ ERROR);
+
+ GetResourceFromQueryString(ehRequest->query, resource, sizeof(resource));
+
+ if(OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
+ {
+ ehRet = OC_EH_RESOURCE_DELETED;
+ }
+
+exit:
+ // Send payload to request originator
+ SendSRMResponse(ehRequest, ehRet, NULL);
+
return ehRet;
}
OCEntityHandlerRequest * ehRequest,
void* callbackParameter)
{
+ OC_LOG(INFO, TAG, "Received request ACLEntityHandler");
(void)callbackParameter;
OCEntityHandlerResult ehRet = OC_EH_ERROR;
if (flag & OC_REQUEST_FLAG)
{
- // TODO : Handle PUT and DEL methods
- OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+ // TODO : Handle PUT method
+ OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
switch (ehRequest->method)
{
case OC_REST_GET:
ehRet = HandleACLPostRequest(ehRequest);
break;
+ case OC_REST_DELETE:
+ ehRet = HandleACLDeleteRequest(ehRequest);
+ break;
+
default:
ehRet = OC_EH_ERROR;
SendSRMResponse(ehRequest, ehRet, NULL);
if (OC_STACK_OK != ret)
{
- OC_LOG (FATAL, TAG, PCF("Unable to instantiate ACL resource"));
+ OC_LOG (FATAL, TAG, "Unable to instantiate ACL resource");
DeInitACLResource();
}
return ret;
size_t len = strlen(rsrcs[i]) + 1;
acl->resources[i] = (char*)OICMalloc(len * sizeof(char));
VERIFY_NON_NULL(TAG, (acl->resources[i]), ERROR);
- strncpy(acl->resources[i], rsrcs[i], len);
+ OICStrcpy(acl->resources[i], len, rsrcs[i]);
}
acl->permission = PERMISSION_READ;
- acl->periodsLen = 0;
+ acl->prdRecrLen = 0;
acl->periods = NULL;
acl->recurrences = NULL;
--- /dev/null
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "ocstack.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "cJSON.h"
+#include "base64.h"
+#include "resourcemanager.h"
+#include "psinterface.h"
+#include "utlist.h"
+#include "srmresourcestrings.h"
+#include "amaclresource.h"
+#include "srmutility.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define TAG "SRM-AMACL"
+
+OicSecAmacl_t *gAmacl = NULL;
+static OCResourceHandle gAmaclHandle = NULL;
+
+void DeleteAmaclList(OicSecAmacl_t* amacl)
+{
+ if (amacl)
+ {
+ OicSecAmacl_t *amaclTmp1 = NULL, *amaclTmp2 = NULL;
+ LL_FOREACH_SAFE(amacl, amaclTmp1, amaclTmp2)
+ {
+ unsigned int i = 0;
+
+ LL_DELETE(amacl, amaclTmp1);
+
+ // Clean Resources
+ for (i = 0; i < amaclTmp1->resourcesLen; i++)
+ {
+ OICFree(amaclTmp1->resources[i]);
+ }
+ OICFree(amaclTmp1->resources);
+
+ // Clean Amss
+ OICFree(amaclTmp1->amss);
+
+ // Clean Owners
+ OICFree(amaclTmp1->owners);
+
+ // Clean Amacl node itself
+ OICFree(amaclTmp1);
+ }
+ }
+}
+
+/*
+ * This internal method converts AMACL data into JSON format.
+ *
+ * Note: Caller needs to invoke 'free' when finished using the return string.
+ */
+char * BinToAmaclJSON(const OicSecAmacl_t * amacl)
+{
+ cJSON *jsonRoot = NULL;
+ char *jsonStr = NULL;
+
+ if (amacl)
+ {
+ jsonRoot = cJSON_CreateObject();
+ VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+ cJSON *jsonAmaclArray = NULL;
+ cJSON_AddItemToObject (jsonRoot, OIC_JSON_AMACL_NAME, jsonAmaclArray = cJSON_CreateArray());
+ VERIFY_NON_NULL(TAG, jsonAmaclArray, ERROR);
+
+ while(amacl)
+ {
+ char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
+ uint32_t outLen = 0;
+ B64Result b64Ret = B64_OK;
+
+ cJSON *jsonAmacl = cJSON_CreateObject();
+
+ // Resources -- Mandatory
+ cJSON *jsonRsrcArray = NULL;
+ cJSON_AddItemToObject(jsonAmacl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray =
+ cJSON_CreateArray());
+ VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);
+ for (unsigned int i = 0; i < amacl->resourcesLen; i++)
+ {
+ cJSON_AddItemToArray(jsonRsrcArray, cJSON_CreateString(amacl->resources[i]));
+ }
+
+ // Amss -- Mandatory
+ cJSON *jsonAmsArray = NULL;
+ cJSON_AddItemToObject(jsonAmacl, OIC_JSON_AMSS_NAME, jsonAmsArray =
+ cJSON_CreateArray());
+ VERIFY_NON_NULL(TAG, jsonAmsArray, ERROR);
+ for (unsigned int i = 0; i < amacl->amssLen; i++)
+ {
+ outLen = 0;
+
+ b64Ret = b64Encode(amacl->amss[i].id, sizeof(((OicUuid_t*) 0)->id), base64Buff,
+ sizeof(base64Buff), &outLen);
+ VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+
+ cJSON_AddItemToArray(jsonAmsArray, cJSON_CreateString(base64Buff));
+ }
+
+ // Owners -- Mandatory
+ cJSON *jsonOwnrArray = NULL;
+ cJSON_AddItemToObject(jsonAmacl, OIC_JSON_OWNERS_NAME, jsonOwnrArray =
+ cJSON_CreateArray());
+ VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
+ for (unsigned int i = 0; i < amacl->ownersLen; i++)
+ {
+ outLen = 0;
+
+ b64Ret = b64Encode(amacl->owners[i].id, sizeof(((OicUuid_t*) 0)->id), base64Buff,
+ sizeof(base64Buff), &outLen);
+ VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+
+ cJSON_AddItemToArray(jsonOwnrArray, cJSON_CreateString(base64Buff));
+ }
+
+ // Attach current amacl node to Amacl Array
+ cJSON_AddItemToArray(jsonAmaclArray, jsonAmacl);
+ amacl = amacl->next;
+ }
+
+ jsonStr = cJSON_PrintUnformatted(jsonRoot);
+ }
+
+exit:
+ if (jsonRoot)
+ {
+ cJSON_Delete(jsonRoot);
+ }
+ return jsonStr;
+}
+
+
+
+
+/*
+ * This internal method converts JSON AMACL into binary AMACL.
+ */
+OicSecAmacl_t * JSONToAmaclBin(const char * jsonStr)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ OicSecAmacl_t * headAmacl = NULL;
+ OicSecAmacl_t * prevAmacl = NULL;
+ cJSON *jsonRoot = NULL;
+ cJSON *jsonAmaclArray = NULL;
+
+ VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+ jsonRoot = cJSON_Parse(jsonStr);
+ VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+ jsonAmaclArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_AMACL_NAME);
+ VERIFY_NON_NULL(TAG, jsonAmaclArray, INFO);
+
+ if (cJSON_Array == jsonAmaclArray->type)
+ {
+ int numAmacl = cJSON_GetArraySize(jsonAmaclArray);
+ int idx = 0;
+
+ VERIFY_SUCCESS(TAG, numAmacl > 0, INFO);
+ do
+ {
+ cJSON *jsonAmacl = cJSON_GetArrayItem(jsonAmaclArray, idx);
+ VERIFY_NON_NULL(TAG, jsonAmacl, ERROR);
+
+ OicSecAmacl_t *amacl = (OicSecAmacl_t*)OICCalloc(1, sizeof(OicSecAmacl_t));
+ VERIFY_NON_NULL(TAG, amacl, ERROR);
+
+ headAmacl = (headAmacl) ? headAmacl : amacl;
+ if (prevAmacl)
+ {
+ prevAmacl->next = amacl;
+ }
+
+ size_t jsonObjLen = 0;
+ cJSON *jsonObj = NULL;
+
+ // Resources -- Mandatory
+ jsonObj = cJSON_GetObjectItem(jsonAmacl, OIC_JSON_RESOURCES_NAME);
+ VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+ VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
+
+ amacl->resourcesLen = cJSON_GetArraySize(jsonObj);
+ VERIFY_SUCCESS(TAG, amacl->resourcesLen > 0, ERROR);
+ amacl->resources = (char**)OICCalloc(amacl->resourcesLen, sizeof(char*));
+ VERIFY_NON_NULL(TAG, (amacl->resources), ERROR);
+
+ size_t idxx = 0;
+ do
+ {
+ cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx);
+ VERIFY_NON_NULL(TAG, jsonRsrc, ERROR);
+
+ jsonObjLen = strlen(jsonRsrc->valuestring) + 1;
+ amacl->resources[idxx] = (char*)OICMalloc(jsonObjLen);
+ VERIFY_NON_NULL(TAG, (amacl->resources[idxx]), ERROR);
+ OICStrcpy(amacl->resources[idxx], jsonObjLen, jsonRsrc->valuestring);
+ } while ( ++idxx < amacl->resourcesLen);
+
+ // Amss -- Mandatory
+ VERIFY_SUCCESS( TAG, OC_STACK_OK == AddUuidArray(jsonAmacl, OIC_JSON_AMSS_NAME,
+ &(amacl->amssLen), &(amacl->amss)), ERROR);
+
+ // Owners -- Mandatory
+ VERIFY_SUCCESS( TAG, OC_STACK_OK == AddUuidArray(jsonAmacl, OIC_JSON_OWNERS_NAME,
+ &(amacl->ownersLen), &(amacl->owners)), ERROR);
+
+ prevAmacl = amacl;
+ } while( ++idx < numAmacl);
+ }
+
+ ret = OC_STACK_OK;
+
+exit:
+ cJSON_Delete(jsonRoot);
+ if (OC_STACK_OK != ret)
+ {
+ DeleteAmaclList(headAmacl);
+ headAmacl = NULL;
+ }
+ return headAmacl;
+}
+
+static OCEntityHandlerResult HandleAmaclGetRequest (const OCEntityHandlerRequest * ehRequest)
+{
+ // Convert Amacl data into JSON for transmission
+ char* jsonStr = BinToAmaclJSON(gAmacl);
+
+ OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
+
+ // Send response payload to request originator
+ SendSRMResponse(ehRequest, ehRet, jsonStr);
+
+ OICFree(jsonStr);
+
+ OC_LOG_V (INFO, TAG, "%s RetVal %d", __func__ , ehRet);
+ return ehRet;
+}
+
+static OCEntityHandlerResult HandleAmaclPostRequest (const OCEntityHandlerRequest * ehRequest)
+{
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+ // Convert JSON Amacl data into binary. This will also validate the Amacl data received.
+ OicSecAmacl_t* newAmacl = JSONToAmaclBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
+
+ if (newAmacl)
+ {
+ // Append the new Amacl to existing Amacl
+ LL_APPEND(gAmacl, newAmacl);
+
+ // Convert Amacl data into JSON for update to persistent storage
+ char *jsonStr = BinToAmaclJSON(gAmacl);
+ if (jsonStr)
+ {
+ cJSON *jsonAmacl = cJSON_Parse(jsonStr);
+ OICFree(jsonStr);
+
+ if ((jsonAmacl) &&
+ (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_AMACL_NAME, jsonAmacl)))
+ {
+ ehRet = OC_EH_RESOURCE_CREATED;
+ }
+ cJSON_Delete(jsonAmacl);
+ }
+ }
+
+ // Send payload to request originator
+ SendSRMResponse(ehRequest, ehRet, NULL);
+
+ OC_LOG_V (INFO, TAG, "%s RetVal %d", __func__ , ehRet);
+ return ehRet;
+}
+
+/*
+ * This internal method is the entity handler for Amacl resources and
+ * will handle REST request (GET/PUT/POST/DEL) for them.
+ */
+OCEntityHandlerResult AmaclEntityHandler (OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest * ehRequest,
+ void* callbackParameter)
+{
+ (void) callbackParameter;
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+ if (!ehRequest)
+ {
+ return ehRet;
+ }
+
+ if (flag & OC_REQUEST_FLAG)
+ {
+ OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+ switch (ehRequest->method)
+ {
+ case OC_REST_GET:
+ ehRet = HandleAmaclGetRequest(ehRequest);
+ break;
+
+ case OC_REST_POST:
+ ehRet = HandleAmaclPostRequest(ehRequest);
+ break;
+
+ default:
+ ehRet = OC_EH_ERROR;
+ SendSRMResponse(ehRequest, ehRet, NULL);
+ }
+ }
+
+ return ehRet;
+}
+
+/*
+ * This internal method is used to create '/oic/sec/amacl' resource.
+ */
+OCStackResult CreateAmaclResource()
+{
+ OCStackResult ret;
+
+ ret = OCCreateResource(&gAmaclHandle,
+ OIC_RSRC_TYPE_SEC_AMACL,
+ OIC_MI_DEF,
+ OIC_RSRC_AMACL_URI,
+ AmaclEntityHandler,
+ NULL,
+ OC_OBSERVABLE);
+
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG (FATAL, TAG, "Unable to instantiate Amacl resource");
+ DeInitAmaclResource();
+ }
+ return ret;
+}
+
+/**
+ * Initialize Amacl resource by loading data from persistent storage.
+ *
+ * @retval OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitAmaclResource()
+{
+ OCStackResult ret = OC_STACK_ERROR;
+
+ // Read Amacl resource from PS
+ char* jsonSVRDatabase = GetSVRDatabase();
+
+ if (jsonSVRDatabase)
+ {
+ // Convert JSON Amacl into binary format
+ gAmacl = JSONToAmaclBin(jsonSVRDatabase);
+ OICFree(jsonSVRDatabase);
+ }
+
+ // Instantiate 'oic/sec/amacl' resource
+ ret = CreateAmaclResource();
+
+ if (OC_STACK_OK != ret)
+ {
+ DeInitAmaclResource();
+ }
+ return ret;
+}
+
+/**
+ * Perform cleanup for Amacl resources.
+ *
+ * @retval none
+ */
+void DeInitAmaclResource()
+{
+ OCDeleteResource(gAmaclHandle);
+ gAmaclHandle = NULL;
+
+ DeleteAmaclList(gAmacl);
+ gAmacl = NULL;
+}
#include "base64.h"
#include "srmutility.h"
#include "cainterface.h"
+#include "pbkdf2.h"
#include <stdlib.h>
+#ifdef WITH_ARDUINO
#include <string.h>
+#else
+#include <strings.h>
+#endif
#include <stdint.h>
+#define TAG "SRM-CREDL"
-#define TAG PCF("SRM-CREDL")
static OicSecCred_t *gCred = NULL;
static OCResourceHandle gCredHandle = NULL;
-void DeleteCredList(OicSecCred_t* cred)
+/**
+ * This function frees OicSecCred_t object's fields and object itself.
+ */
+static void FreeCred(OicSecCred_t *cred)
{
- if (cred)
+ if(NULL == cred)
{
- OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
- LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
- {
- LL_DELETE(cred, credTmp1);
-
- //Note: Need further clarification on roleID data type
+ OC_LOG (INFO, TAG, "Invalid Parameter");
+ return;
+ }
+ //Note: Need further clarification on roleID data type
#if 0
- //Clean roleIds
- OICFree(credTmp1->roleIds);
+ //Clean roleIds
+ OICFree(cred->roleIds);
#endif
- //Clean PublicData
- OICFree(credTmp1->publicData.data);
+ //Clean PublicData
+ OICFree(cred->publicData.data);
+
+ //Clean PrivateData
+ OICFree(cred->privateData.data);
- //Clean PrivateData
- OICFree(credTmp1->privateData.data);
+ //Clean Period
+ OICFree(cred->period);
- //Clean Period
- OICFree(credTmp1->period);
+ //Clean Owners
+ OICFree(cred->owners);
- //Clean Owners
- OICFree(credTmp1->owners);
+ //Clean Cred node itself
+ OICFree(cred);
+}
- //Clean Cred node itself
- OICFree(credTmp1);
+void DeleteCredList(OicSecCred_t* cred)
+{
+ if (cred)
+ {
+ OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
+ LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
+ {
+ LL_DELETE(cred, credTmp1);
+ FreeCred(credTmp1);
}
}
}
jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDTYPE_NAME);
VERIFY_NON_NULL(TAG, jsonObj, ERROR);
VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
- cred->credType = jsonObj->valueint;
+ cred->credType = (OicSecCredType_t)jsonObj->valueint;
//PrivateData is mandatory for some of the credential types listed below.
jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PRIVATEDATA_NAME);
//Owners -- Mandatory
jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_OWNERS_NAME);
VERIFY_NON_NULL(TAG, jsonObj, ERROR);
- VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR)
+ VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
cred->ownersLen = cJSON_GetArraySize(jsonObj);
VERIFY_SUCCESS(TAG, cred->ownersLen > 0, ERROR);
cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
return cred;
}
-/*
+static bool UpdatePersistentStorage(const OicSecCred_t *cred)
+{
+ bool ret = false;
+
+ // Convert Cred data into JSON for update to persistent storage
+ char *jsonStr = BinToCredJSON(cred);
+ if (jsonStr)
+ {
+ cJSON *jsonCred = cJSON_Parse(jsonStr);
+ OICFree(jsonStr);
+
+ if ((jsonCred) &&
+ (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
+ {
+ ret = true;
+ }
+ cJSON_Delete(jsonCred );
+ }
+ else //Empty cred list
+ {
+ if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, NULL))
+ {
+ ret = true;
+ }
+ }
+ return ret;
+}
+
+/**
* Compare function used LL_SORT for sorting credentials
*
* @param first pointer to OicSecCred_t struct
exit:
return 0;
}
+
+
/**
* This function adds the new cred to the credential list.
*
OCStackResult AddCredential(OicSecCred_t * newCred)
{
OCStackResult ret = OC_STACK_ERROR;
- char * jsonStr = NULL;
VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
//Append the new Cred to existing list
LL_APPEND(gCred, newCred);
- //Convert CredList to JSON and update the persistent Storage
- jsonStr = BinToCredJSON(gCred);
-
- if(jsonStr)
+ if(UpdatePersistentStorage(gCred))
{
- cJSON *jsonCred = cJSON_Parse(jsonStr);
- OICFree(jsonStr);
+ ret = OC_STACK_OK;
+ }
+
+exit:
+ return ret;
+}
+
+OCStackResult RemoveCredential(const OicUuid_t *subject)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ OicSecCred_t *cred = NULL;
+ OicSecCred_t *tempCred = NULL;
+ bool deleteFlag = false;
- if((jsonCred) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
+ LL_FOREACH_SAFE(gCred, cred, tempCred)
+ {
+ if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
{
- ret = OC_STACK_OK;
+ LL_DELETE(gCred, cred);
+ FreeCred(cred);
+ deleteFlag = 1;
}
- cJSON_Delete(jsonCred);
}
-exit:
+ if(deleteFlag)
+ {
+ if(UpdatePersistentStorage(gCred))
+ {
+ ret = OC_STACK_RESOURCE_DELETED;
+ }
+ }
return ret;
+
}
static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
return ret;
}
+static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
+{
+ OC_LOG(INFO, TAG, "Processing CredDeleteRequest");
+
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+ if(NULL == ehRequest->query)
+ {
+ return ehRet;
+ }
+
+ OicParseQueryIter_t parseIter = {.attrPos=NULL};
+ OicUuid_t subject = {.id={0}};
+
+ //Parsing REST query to get the subject
+ ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
+ while(GetNextQuery(&parseIter))
+ {
+ if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME,
+ parseIter.attrLen) == 0)
+ {
+ unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+ uint32_t outLen = 0;
+ B64Result b64Ret = B64_OK;
+
+ b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen,
+ base64Buff, sizeof(base64Buff), &outLen);
+
+ VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
+ memcpy(subject.id, base64Buff, outLen);
+ }
+ }
+
+ if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
+ {
+ ehRet = OC_EH_RESOURCE_DELETED;
+ }
+
+exit:
+ return ehRet;
+}
+
+
/*
* This internal method is the entity handler for Cred resources
* to handle REST request (PUT/POST/DEL)
}
if (flag & OC_REQUEST_FLAG)
{
- OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+ OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
//TODO : Handle PUT/DEL methods
switch(ehRequest->method)
{
case OC_REST_POST:
ret = HandlePostRequest(ehRequest);
break;
+ case OC_REST_DELETE:
+ ret = HandleDeleteRequest(ehRequest);
+ break;
default:
ret = OC_EH_ERROR;
break;
if (OC_STACK_OK != ret)
{
- OC_LOG (FATAL, TAG, PCF("Unable to instantiate Cred resource"));
+ OC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
DeInitCredResource();
}
return ret;
{
OicSecCred_t *cred = NULL;
- if ( NULL == subject)
+ if ( NULL == subject)
{
- return NULL;
+ return NULL;
}
LL_FOREACH(gCred, cred)
{
if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
{
- return cred;
+ return cred;
}
}
return NULL;
caBlob = (CADtlsPskCredsBlob_t *)OICCalloc(sizeof(CADtlsPskCredsBlob_t), 1);
if (caBlob)
{
- OicUuid_t deviceID = {};
+ OicUuid_t deviceID = {.id={}};
// Retrieve Device ID from doxm resource and copy in PSK creds blob
VERIFY_SUCCESS(TAG, GetDoxmDeviceID(&deviceID) == OC_STACK_OK, ERROR);
}
OICFree(caBlob);
}
+
+/**
+ * Add temporal PSK to PIN based OxM
+ *
+ * @param[in] tmpSubject UUID of target device
+ * @param[in] credType Type of credential to be added
+ * @param[in] pin numeric characters
+ * @param[in] pinSize length of 'pin'
+ * @param[in] ownersLen Number of owners
+ * @param[in] owners Array of owners
+ * @param[out] tmpCredSubject Generated credential's subject.
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
+ const char * pin, size_t pinSize,
+ size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+
+ if(tmpSubject == NULL || pin == NULL || pinSize == 0 || tmpCredSubject == NULL)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
+ int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, owners->id,
+ UUID_LENGTH, PBKDF_ITERATIONS,
+ OWNER_PSK_LENGTH_128, privData);
+ VERIFY_SUCCESS(TAG, (dtlsRes == 0) , ERROR);
+
+ uint32_t outLen = 0;
+ char base64Buff[B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128) + 1] = {};
+ B64Result b64Ret = b64Encode(privData, OWNER_PSK_LENGTH_128, base64Buff,
+ sizeof(base64Buff), &outLen);
+ VERIFY_SUCCESS(TAG, (B64_OK == b64Ret), ERROR);
+
+ OicSecCred_t* cred = GenerateCredential(tmpSubject, credType, NULL,
+ base64Buff, ownersLen, owners);
+ if(NULL == cred)
+ {
+ OC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
+ return OC_STACK_ERROR;
+ }
+
+ memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
+
+ ret = AddCredential(cred);
+ if( OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
+ }
+
+exit:
+ return ret;
+}
+
#endif /* __WITH_DTLS__ */
#include "credresource.h"
#include "ocserverrequest.h"
#include "srmutility.h"
+#include "pinoxmcommon.h"
+
+#ifdef __WITH_DTLS__
+#include "global.h"
+#endif
+
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#endif
-#define TAG PCF("SRM-DOXM")
+#define TAG "SRM-DOXM"
static OicSecDoxm_t *gDoxm = NULL;
static OCResourceHandle gDoxmHandle = NULL;
&gOicSecDoxmJustWorks, /* uint16_t *oxm */
1, /* size_t oxmLen */
OIC_JUST_WORKS, /* uint16_t oxmSel */
+ SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
false, /* bool owned */
{.id = {0}}, /* OicUuid_t deviceID */
{.id = {0}}, /* OicUuid_t owner */
//OxmSel -- Mandatory
cJSON_AddNumberToObject(jsonDoxm, OIC_JSON_OXM_SEL_NAME, (int)doxm->oxmSel);
+ //sct -- Mandatory
+ cJSON_AddNumberToObject(jsonDoxm, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, (int)doxm->sct);
+
//Owned -- Mandatory
cJSON_AddBoolToObject(jsonDoxm, OIC_JSON_OWNED_NAME, doxm->owned);
jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_SEL_NAME);
if(jsonObj)
{
- VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR)
+ VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
doxm->oxmSel = (OicSecOxm_t)jsonObj->valueint;
}
else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
doxm->oxmSel = gDoxm->oxmSel;
}
+ //sct -- Mandatory
+ jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_SUPPORTED_CRED_TYPE_NAME);
+ if(jsonObj)
+ {
+ VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
+ doxm->sct = (OicSecCredType_t)jsonObj->valueint;
+ }
+ else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
+ {
+ VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+ doxm->sct = gDoxm->sct;
+ }
+
//Owned -- Mandatory
jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNED_NAME);
if(jsonObj)
{
- VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR)
+ VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR);
doxm->owned = jsonObj->valueint;
}
else // PUT/POST JSON may not have owned so set it to the gDomx->owned
else // PUT/POST JSON will not have deviceID so set it to the gDoxm->deviceID.id
{
VERIFY_NON_NULL(TAG, gDoxm, ERROR);
- VERIFY_SUCCESS(TAG, strcmp((char *)gDoxm->deviceID.id, "") != 0, ERROR);
- strncpy((char *)doxm->deviceID.id, (char *)gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
+ memcpy((char *)doxm->deviceID.id, (char *)gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
}
- // Owner -- will be empty when device state is unowned.
- if (true == doxm->owned)
+ //Owner -- will be empty when device status is unowned.
+ jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNER_NAME);
+ if(true == doxm->owned)
{
- jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNER_NAME);
VERIFY_NON_NULL(TAG, jsonObj, ERROR);
- VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR)
- outLen = 0;
+ }
+ if(jsonObj)
+ {
+ VERIFY_SUCCESS(TAG, (cJSON_String == jsonObj->type), ERROR);
+ outLen = 0;
b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
sizeof(base64Buff), &outLen);
- VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(doxm->owner.id)), ERROR);
+ VERIFY_SUCCESS(TAG, ((b64Ret == B64_OK) && (outLen <= sizeof(doxm->owner.id))), ERROR);
memcpy(doxm->owner.id, base64Buff, outLen);
}
return bRet;
}
-static bool ValidateQuery(unsigned char * query)
+static bool ValidateQuery(const char * query)
{
// Send doxm resource data if the state of doxm resource
// matches with the query parameters.
// access rules. Eventually, the PE and PM code will
// not send a request to the /doxm Entity Handler at all
// if it should not respond.
- OC_LOG (INFO, TAG, PCF("In ValidateQuery"));
+ OC_LOG (INFO, TAG, "In ValidateQuery");
if(NULL == gDoxm)
{
return false;
}
- OicParseQueryIter_t parseIter = {0};
+ bool bOwnedQry = false; // does querystring contains 'owned' query ?
+ bool bOwnedMatch = false; // does 'owned' query value matches with doxm.owned status?
+ bool bDeviceIDQry = false; // does querystring contains 'deviceid' query ?
+ bool bDeviceIDMatch = false; // does 'deviceid' query matches with doxm.deviceid ?
- ParseQueryIterInit(query, &parseIter);
+ OicParseQueryIter_t parseIter = {.attrPos = NULL};
+
+ ParseQueryIterInit((unsigned char*)query, &parseIter);
while(GetNextQuery(&parseIter))
{
if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
{
+ bOwnedQry = true;
if((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
(gDoxm->owned))
{
- return true;
+ bOwnedMatch = true;
}
else if((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
&& (!gDoxm->owned))
{
- return true;
+ bOwnedMatch = true;
+ }
+ }
+
+ if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
+ {
+ bDeviceIDQry = true;
+ OicUuid_t subject = {.id={0}};
+ unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+ uint32_t outLen = 0;
+ B64Result b64Ret = B64_OK;
+
+ b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
+ sizeof(base64Buff), &outLen);
+
+ VERIFY_SUCCESS(TAG, (B64_OK == b64Ret && outLen <= sizeof(subject.id)), ERROR);
+ memcpy(subject.id, base64Buff, outLen);
+ if(0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
+ {
+ bDeviceIDMatch = true;
}
}
}
- return false;
+
+exit:
+ return ((bOwnedQry ? bOwnedMatch : true) && (bDeviceIDQry ? bDeviceIDMatch : true));
}
static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
char* jsonStr = NULL;
OCEntityHandlerResult ehRet = OC_EH_OK;
- OC_LOG (INFO, TAG, PCF("Doxm EntityHandle processing GET request"));
+ OC_LOG (INFO, TAG, "Doxm EntityHandle processing GET request");
//Checking if Get request is a query.
if(ehRequest->query)
{
- OC_LOG (INFO, TAG, PCF("HandleDoxmGetRequest processing query"));
- if(!ValidateQuery((unsigned char *)ehRequest->query))
+ OC_LOG (INFO, TAG, "HandleDoxmGetRequest processing query");
+ if(!ValidateQuery(ehRequest->query))
{
ehRet = OC_EH_ERROR;
}
// Send response payload to request originator
if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, jsonStr))
{
- OC_LOG (ERROR, TAG, PCF("SendSRMResponse failed in HandleDoxmGetRequest"));
+ OC_LOG (ERROR, TAG, "SendSRMResponse failed in HandleDoxmGetRequest");
}
OICFree(jsonStr);
return ehRet;
}
+#ifdef __WITH_DTLS__
+/*
+ * Generating new credential for provisioning tool
+ *
+ * PSK generated by
+ */
+static OCEntityHandlerResult AddOwnerPSK(const CAEndpoint_t* endpoint,
+ OicSecDoxm_t* ptDoxm,
+ const uint8_t* label, const size_t labelLen)
+{
+ size_t ownLen = 1;
+ uint32_t outLen = 0;
+ OicSecCred_t *cred = NULL;
+ uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
+
+ CAResult_t pskRet = CAGenerateOwnerPSK(endpoint,
+ label, labelLen,
+ ptDoxm->owner.id, sizeof(ptDoxm->owner.id),
+ gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
+ ownerPSK, OWNER_PSK_LENGTH_128);
+
+ VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
+
+ char base64Buff[B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128) + 1] = {};
+ B64Result b64Ret = b64Encode(ownerPSK, OWNER_PSK_LENGTH_128, base64Buff,
+ sizeof(base64Buff), &outLen);
+ VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+
+ OC_LOG (INFO, TAG, "Doxm EntityHandle generating Credential");
+ cred = GenerateCredential(&ptDoxm->owner, SYMMETRIC_PAIR_WISE_KEY,
+ NULL, base64Buff, ownLen, &ptDoxm->owner);
+ VERIFY_NON_NULL(TAG, cred, ERROR);
+
+ //Adding provisioning tool credential to cred Resource.
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == AddCredential(cred), ERROR);
+
+ gDoxm->owned = true;
+ gDoxm->oxmSel = ptDoxm->oxmSel;
+ memcpy(&(gDoxm->owner), &(ptDoxm->owner), sizeof(OicUuid_t));
+
+ return OC_EH_OK;
+
+exit:
+ return OC_EH_ERROR;
+}
+#endif //__WITH_DTLS__
static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest * ehRequest)
{
- OC_LOG (INFO, TAG, PCF("Doxm EntityHandle processing PUT request"));
+ OC_LOG (INFO, TAG, "Doxm EntityHandle processing PUT request");
OCEntityHandlerResult ehRet = OC_EH_ERROR;
OicUuid_t emptyOwner = {.id = {0}};
*/
if ((false == gDoxm->owned) && (false == newDoxm->owned))
{
- OC_LOG (INFO, TAG, PCF("Doxm EntityHandle enabling AnonECDHCipherSuite"));
+ OC_LOG (INFO, TAG, "Doxm EntityHandle enabling AnonECDHCipherSuite");
#ifdef __WITH_DTLS__
ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
#endif //__WITH_DTLS__
*
*/
#ifdef __WITH_DTLS__
- CAResult_t pskRet;
-
OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
- uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
//Generating OwnerPSK
- OC_LOG (INFO, TAG, PCF("Doxm EntityHandle generating OwnerPSK"));
- pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
- (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS),
- newDoxm->owner.id, sizeof(newDoxm->owner.id),
- gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
- ownerPSK, OWNER_PSK_LENGTH_128);
-
- VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
+ OC_LOG (INFO, TAG, "Doxm EntityHandle generating OwnerPSK");
- //Generating new credential for provisioning tool
- size_t ownLen = 1;
- uint32_t outLen = 0;
+ //Generate new credential for provisioning tool
+ ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm,
+ (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS));
- char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
- B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff,
- sizeof(base64Buff), &outLen);
- VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
-
- OC_LOG (INFO, TAG, PCF("Doxm EntityHandle generating Credential"));
- OicSecCred_t *cred = GenerateCredential(&newDoxm->owner, SYMMETRIC_PAIR_WISE_KEY,
- NULL, base64Buff, ownLen, &newDoxm->owner);
- VERIFY_NON_NULL(TAG, cred, ERROR);
-
- //Adding provisioning tool credential to cred Resource.
- VERIFY_SUCCESS(TAG, OC_STACK_OK == AddCredential(cred), ERROR);
-
- gDoxm->owned = true;
- memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
+ VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
// Update new state in persistent storage
if (true == UpdatePersistentStorage(gDoxm))
* for global variable.
*/
gDoxm->owned = false;
+ gDoxm->oxmSel = 0;
memset(&(gDoxm->owner), 0, sizeof(OicUuid_t));
}
#endif //__WITH_DTLS__
}
}
+ else if(OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
+ {
+ //this temp Credential ID is used to track temporal Cred Id
+ static OicUuid_t tmpCredId = {.id={0}};
+ static bool tmpCredGenFlag = false;
+
+ if ((false == gDoxm->owned) && (false == newDoxm->owned))
+ {
+#ifdef __WITH_DTLS__
+ CAEnableAnonECDHCipherSuite(false);
+ OC_LOG(DEBUG, TAG, "ECDH_ANON CipherSuite is DISABLED");
+ CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
+
+ char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
+ if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
+ {
+ if(tmpCredGenFlag)
+ {
+ OC_LOG(DEBUG, TAG, "Corrupted PSK is detected!!!");
+ VERIFY_SUCCESS(TAG,
+ OC_STACK_RESOURCE_DELETED == RemoveCredential(&tmpCredId),
+ ERROR);
+ }
+
+ OCStackResult res = AddTmpPskWithPIN( &(newDoxm->owner), SYMMETRIC_PAIR_WISE_KEY,
+ ranPin, OXM_RANDOM_PIN_SIZE, 1, &(newDoxm->owner), &tmpCredId);
+ VERIFY_SUCCESS(TAG, res == OC_STACK_OK, ERROR);
+ tmpCredGenFlag = true;
+ ehRet = OC_EH_OK;
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Failed to generate random PIN");
+ ehRet = OC_EH_ERROR;
+ }
+
+#endif //__WITH_DTLS__
+ }
+
+ /*
+ * When current state of the device is un-owned and Provisioning
+ * Tool is attempting to change the state to 'Owned' with a
+ * qualified value for the field 'Owner'
+ */
+ if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
+ (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0))
+ {
+#ifdef __WITH_DTLS__
+ OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;
+
+ //Remove Temporal Credential resource
+ if(tmpCredGenFlag)
+ {
+ VERIFY_SUCCESS(TAG,
+ OC_STACK_RESOURCE_DELETED == RemoveCredential(&tmpCredId),
+ ERROR);
+ tmpCredGenFlag = false;
+ }
+
+ //Generate new credential for provisioning tool
+ ehRet = AddOwnerPSK((CAEndpoint_t*)(&request->devAddr), newDoxm,
+ (uint8_t*)OXM_RANDOM_DEVICE_PIN, strlen(OXM_RANDOM_DEVICE_PIN));
+ VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
+
+ //Update new state in persistent storage
+ if((UpdatePersistentStorage(gDoxm) == true))
+ {
+ ehRet = OC_EH_OK;
+ }
+ else
+ {
+ /*
+ * If persistent storage update failed, revert back the state
+ * for global variable.
+ */
+ gDoxm->owned = false;
+ gDoxm->oxmSel = 0;
+ memset(&(gDoxm->owner), 0, sizeof(OicUuid_t));
+ ehRet = OC_EH_ERROR;
+
+ }
+#endif
+ }
+ }
}
exit:
//Send payload to request originator
if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))
{
- OC_LOG (ERROR, TAG, PCF("SendSRMResponse failed in HandlePstatPostRequest"));
+ OC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
}
DeleteDoxmBinData(newDoxm);
if (flag & OC_REQUEST_FLAG)
{
- OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+ OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
switch (ehRequest->method)
{
case OC_REST_GET:
if (OC_STACK_OK != ret)
{
- OC_LOG (FATAL, TAG, PCF("Unable to instantiate Doxm resource"));
+ OC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
DeInitDoxmResource();
}
return ret;
* Once DeviceID is assigned to the device it does not change for the lifetime of the device.
*
*/
-void CheckDeviceID()
+static OCStackResult CheckDeviceID()
{
- if(strcmp((char *)gDoxm->deviceID.id, "") == 0 )
+ OCStackResult ret = OC_STACK_ERROR;
+ bool validId = false;
+ for (uint8_t i = 0; i < UUID_LENGTH; i++)
+ {
+ if (gDoxm->deviceID.id[i] != 0)
+ {
+ validId = true;
+ break;
+ }
+ }
+
+ if (!validId)
{
- OCFillRandomMem(gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id));
- UpdatePersistentStorage(gDoxm);
+ if (OCGenerateUuid(gDoxm->deviceID.id) != RAND_UUID_OK)
+ {
+ OC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
+ return ret;
+ }
+ ret = OC_STACK_OK;
+
+ if (UpdatePersistentStorage(gDoxm))
+ {
+ //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
+ OC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
+ }
+ }
+ else
+ {
+ ret = OC_STACK_OK;
}
+ return ret;
}
/**
*/
static OicSecDoxm_t* GetDoxmDefault()
{
- OC_LOG (INFO, TAG, PCF("GetDoxmToDefault"));
+ OC_LOG (INFO, TAG, "GetDoxmToDefault");
return &gDefaultDoxm;
}
{
gDoxm = GetDoxmDefault();
}
- CheckDeviceID();
- //Instantiate 'oic.sec.doxm'
- ret = CreateDoxmResource();
+ ret = CheckDeviceID();
+ if (ret == OC_STACK_OK)
+ {
+ //Instantiate 'oic.sec.doxm'
+ ret = CreateDoxmResource();
+ }
+ else
+ {
+ OC_LOG (ERROR, TAG, "CheckDeviceID failed");
+ }
OICFree(jsonSVRDatabase);
return ret;
}
--- /dev/null
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+//Not supported on Arduino due lack of absolute time need to implement iCalendar
+#ifndef WITH_ARDUINO
+
+#define _XOPEN_SOURCE //Needed by strptime
+#include <string.h>
+#include "iotvticalendar.h"
+#include "oic_string.h"
+
+static char dtFormat[] = "%Y%m%dT%H%M%S"; //date-time format
+static char dFormat[] = "%Y%m%d"; // date format
+
+static const char FREQ[] = "FREQ";
+static const char UNTIL[] = "UNTIL";
+static const char BYDAY[] = "BYDAY";
+static const char DAILY[] = "DAILY";
+
+
+/**
+ * Parses periodStr and populate struct IotvtICalPeriod_t
+ *
+ * @param periodStr string to be parsed.
+ * @param period IotvtICalPeriod_t struct to be populated.
+ *
+ * @return IOTVTICAL_INVALID_PARAMETER -- if parameter are invalid
+ * IOTVTICAL_INVALID_PERIOD -- if period string has invalid format
+ * IOTVTICAL_INVALID_SUCCESS -- if no error while parsing
+ */
+IotvtICalResult_t ParsePeriod(const char *periodStr, IotvtICalPeriod_t *period)
+{
+ if((NULL == periodStr) || (NULL == period))
+ {
+ return IOTVTICAL_INVALID_PARAMETER;
+ }
+
+ char *endDTPos;
+ char *fmt = "";
+ int startDTLen;
+ int endDTLen;
+
+ //Finding length of startDateTime and endDateTime in period
+ //startDateTime and endDateTime can have form YYYYmmdd or YYYYmmddTHHMMSS
+ //startDateTime and endDateTime must be same form
+ //Eg: periodStr = "20150629T153050/20150630T203055"
+ // periodStr = "20150629/20150630"
+ if(NULL == (endDTPos = strchr(periodStr, '/')))
+ {
+ return IOTVTICAL_INVALID_PERIOD;
+ }
+ endDTPos += 1;
+ startDTLen = endDTPos - periodStr - 1;
+ endDTLen = strlen(endDTPos);
+
+ //Checking if both startDateTime and endDateTime are of same form
+ if(startDTLen == endDTLen)
+ {
+ if(8 == startDTLen) //YYYYmmdd
+ {
+ fmt = dFormat;
+ }
+ else if(15 == startDTLen) //YYYYmmddTHHMMSS
+ {
+ fmt = dtFormat;
+ }
+ else
+ {
+ return IOTVTICAL_INVALID_PERIOD;
+ }
+ }
+ else
+ {
+ return IOTVTICAL_INVALID_PERIOD;
+ }
+
+ //Checking if startDateTime has right format
+ if(NULL != strptime(periodStr, fmt, &period->startDateTime))
+ {
+ //Checking if endDateTime has right format
+ if(NULL != strptime(endDTPos, fmt, &period->endDateTime))
+ {
+ //Checking if endDateTime is after startDateTime
+ if(difftime(mktime(&period->endDateTime),
+ mktime(&period->startDateTime)) > 0)
+ {
+ //mktime increases value of tm_hour by 1 if tm_isdst is set.
+ //The tm_hour value in period's startDateTime and endDatetime
+ //should remain same irrespective of daylight saving time.
+ if(period->startDateTime.tm_isdst)
+ {
+ period->startDateTime.tm_hour =
+ (period->startDateTime.tm_hour + TOTAL_HOURS - TM_DST_OFFSET) % TOTAL_HOURS;
+ }
+ if(period->endDateTime.tm_isdst)
+ {
+ period->endDateTime.tm_hour =
+ (period->endDateTime.tm_hour + TOTAL_HOURS - TM_DST_OFFSET) % TOTAL_HOURS;
+ }
+ return IOTVTICAL_SUCCESS;
+ }
+ }
+ }
+ return IOTVTICAL_INVALID_PERIOD;
+}
+
+
+/**
+ * Parses untilRule and populate "until" field of struct IotvtICalRecur_t
+ *
+ * @param untilRule string to be parsed.
+ * @param recur IotvtICalRecur_t struct to be populated.
+ *
+ * @return IOTVTICAL_ERRRO -- if untilRule has invalid format
+ * IOTVTICAL_INVALID_SUCCESS -- if no error while parsing
+ */
+static IotvtICalResult_t ParseDate(char *untilRule, IotvtICalRecur_t *recur)
+{
+ char *date = strchr(untilRule, '=');
+
+ if(NULL == date)
+ {
+ return IOTVTICAL_ERROR;
+ }
+ date += 1;
+
+ if(strlen(date) == 8) //YYYYmmdd
+ {
+ if(NULL != strptime(date, dFormat, &recur->until))
+ {
+ return IOTVTICAL_SUCCESS;
+ }
+ }
+ return IOTVTICAL_ERROR;
+}
+
+
+/**
+ * Parses bydayRule and populate "byDay" field of struct IotvtICalRecur_t
+ *
+ * @param bydayRule string to be parsed.
+ * @param recur IotvtICalRecur_t struct to be populated.
+ *
+ * @return IOTVTICAL_ERRRO -- if bydayRule has empty weekday list or invalid weekdays
+ * IOTVTICAL_INVALID_SUCCESS -- if no error while parsing
+ */
+static IotvtICalResult_t ParseByday(char *bydayRule, IotvtICalRecur_t *recur)
+{
+ if(strstr(bydayRule, "SU"))
+ {
+ recur->byDay = recur->byDay | SUNDAY;
+ }
+ if(strstr(bydayRule, "MO"))
+ {
+ recur->byDay = recur->byDay | MONDAY;
+ }
+ if(strstr(bydayRule, "TU"))
+ {
+ recur->byDay = recur->byDay | TUESDAY;
+ }
+ if(strstr(bydayRule, "WE"))
+ {
+ recur->byDay = recur->byDay | WEDNESDAY;
+ }
+ if(strstr(bydayRule, "TH"))
+ {
+ recur->byDay = recur->byDay | THURSDAY;
+ }
+ if(strstr(bydayRule, "FR"))
+ {
+ recur->byDay = recur->byDay | FRIDAY;
+ }
+ if(strstr(bydayRule, "SA"))
+ {
+ recur->byDay = recur->byDay | SATURDAY;
+ }
+
+ //Checking if byDay list is empty or has inValid weekdays
+ if(recur->byDay == NO_WEEKDAY)
+ {
+ return IOTVTICAL_ERROR;
+ }
+
+ return IOTVTICAL_SUCCESS;
+}
+
+
+/**
+ * Parses recurStr and populate struct IotvtICalRecur_t
+ *
+ * @param recurStr string to be parsed.
+ * @param recur IotvtICalPeriod_t struct to be populated.
+ *
+ * @return IOTVTICAL_INVALID_PARAMETER -- if parameter are invalid
+ * IOTVTICAL_INVALID_PERIOD -- if period string has invalid format
+ * IOTVTICAL_INVALID_RRULE -- if rrule string has invalid format
+ */
+IotvtICalResult_t ParseRecur(const char *recurStr, IotvtICalRecur_t *recur)
+{
+
+ if((NULL == recurStr) || (NULL == recur))
+ {
+ return IOTVTICAL_INVALID_PARAMETER;
+ }
+
+ const char *startPos="";
+ const char *endPos="";
+ char buf[50];
+ int freqFlag = 0; //valid RRULE must have "FREQ" parameter.
+ //flag to track if RRULE has "FREQ" or not
+
+ startPos = recurStr;
+ //Iterates though recurrence rule
+ //Eg, RRULE: FREQ=DAILY; UNTIL=20150703; BYDAY=MO, WE, FR
+ while('\0' != startPos)
+ {
+ endPos = strchr(startPos, ';');
+ if(endPos)
+ {
+ endPos += 1;
+ }
+ OICStrcpy(buf, (endPos - startPos), startPos);
+ if(NULL != strstr(buf, FREQ))
+ {
+ if(NULL != strstr(buf, DAILY))
+ {
+ recur->freq = FREQ_DAILY;
+ freqFlag = 1;
+ }
+ else
+ {
+ return IOTVTICAL_INVALID_RRULE;
+ }
+ }
+ else if(NULL != strstr(buf, UNTIL))
+ {
+ if(IOTVTICAL_SUCCESS != ParseDate(buf, recur))
+ {
+ return IOTVTICAL_INVALID_RRULE;
+ }
+ }
+ else if(NULL != strstr(buf, BYDAY))
+ {
+ if(IOTVTICAL_SUCCESS != ParseByday(buf, recur))
+ {
+ return IOTVTICAL_INVALID_RRULE;
+ };
+ }
+ startPos = endPos;
+ }
+
+ if(1 != freqFlag)
+ {
+ return IOTVTICAL_INVALID_RRULE;
+ }
+
+ return IOTVTICAL_SUCCESS;
+}
+
+/**
+ * Computes number of days between two dates.
+ *
+ * @param date1 earlier date.
+ * @param date2 later date.
+ *
+ * @return number of days between date1 & date2.
+ */
+static int DiffDays(IotvtICalDateTime_t *date1, IotvtICalDateTime_t *date2)
+{
+ int days;
+ int leapDays=0;
+
+ if(date2->tm_year > date1->tm_year)
+ {
+ for(int y = date1->tm_year; y < date2->tm_year; y++)
+ {
+ y += TM_YEAR_OFFSET;
+ if(y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
+ {
+ leapDays += 1;
+ }
+ }
+ }
+
+ days = (365 * date2->tm_year + date2->tm_yday + leapDays) -
+ (365 * date1->tm_year + date1->tm_yday);
+
+ return days;
+}
+
+
+/**
+ * Computes number of seconds between two time.
+ *
+ * @param time1 earlier time.
+ * @param date2 later time.
+ *
+ * @return number of seconds between time1 and time2.
+ */
+static int DiffSecs(IotvtICalDateTime_t *time1, IotvtICalDateTime_t *time2)
+{
+ return (3600 * time2->tm_hour + 60 * time2->tm_min + time2->tm_sec) -
+ (3600 * time1->tm_hour + 60 * time1->tm_min + time1->tm_sec);
+}
+
+
+/**
+ * This API is used by policy engine to checks if the
+ * request to access resource is within valid time.
+ *
+ * @param period string representing period.
+ * @param recur string representing recurrence rule
+ *
+ * @return IOTVTICAL_VALID_ACCESS -- if the request is within valid time period
+ * IOTVTICAL_INVALID_ACCESS -- if the request is not within valid time period
+ * IOTVTICAL_INVALID_PARAMETER -- if parameter are invalid
+ * IOTVTICAL_INVALID_PERIOD -- if period string has invalid format
+ * IOTVTICAL_INVALID_RRULE -- if rrule string has invalid format
+ */
+
+IotvtICalResult_t IsRequestWithinValidTime(char *periodStr, char *recurStr)
+{
+ //NULL recur rule means no recurring patter exist.
+ //Period can't be null. Period is used with or without
+ //recur rule to compute allowable access time.
+ if(NULL == periodStr)
+ {
+ return IOTVTICAL_INVALID_PARAMETER;
+ }
+
+ IotvtICalPeriod_t period = {.startDateTime={.tm_sec=0}};
+ IotvtICalRecur_t recur = {.freq=0};
+ IotvtICalResult_t ret = IOTVTICAL_INVALID_ACCESS;
+
+ time_t rawTime = time(0);
+ IotvtICalDateTime_t *currentTime = localtime(&rawTime);
+
+ ret = ParsePeriod(periodStr, &period);
+ if(ret != IOTVTICAL_SUCCESS)
+ {
+ return ret;
+ }
+
+ //If recur is NULL then the access time is between period's startDate and endDate
+ if(NULL == recurStr)
+ {
+ if((0 <= DiffDays(&period.startDateTime, currentTime)) &&
+ (0 <= DiffDays(currentTime, &period.endDateTime)))
+ {
+ ret = IOTVTICAL_VALID_ACCESS;
+ }
+ }
+
+ //If recur is not NULL then the access time is between period's startTime and
+ //endTime on days specified in "BYDAY" list. The first instance of recurrence
+ //is computed from period's startDate and the last instance is computed from
+ //"UNTIL". If "UNTIL" is not specified then the recurrence goes for forever.
+ //Eg, RRULE: FREQ=DAILY; UNTIL=20150703; BYDAY=MO, WE, FR
+ if(NULL != recurStr)
+ {
+ ret = ParseRecur(recurStr, &recur);
+ if(ret != IOTVTICAL_SUCCESS)
+ {
+ return ret;
+ }
+
+ if((0 <= DiffSecs(&period.startDateTime, currentTime))&&
+ (0 <= DiffSecs(currentTime, &period.endDateTime)) &&
+ (0 <= DiffDays(&period.startDateTime, currentTime)))
+ {
+ IotvtICalDateTime_t emptyDT = {.tm_sec=0};
+ ret = IOTVTICAL_VALID_ACCESS;
+
+ //"UNTIL" is an optional parameter of RRULE, checking if until present in recur
+ if(0 != memcmp(&recur.until, &emptyDT, sizeof(IotvtICalDateTime_t)))
+ {
+ if(0 > DiffDays(currentTime, &recur.until))
+ {
+ ret = IOTVTICAL_INVALID_ACCESS;
+ }
+ }
+
+ //"BYDAY" is an optional parameter of RRULE, checking if byday present in recur
+ if(NO_WEEKDAY != recur.byDay)
+ {
+
+ int isValidWD = (0x1 << currentTime->tm_wday) & recur.byDay; //Valid weekdays
+ if(!isValidWD)
+ {
+ ret = IOTVTICAL_INVALID_ACCESS;
+ }
+ }
+ }
+ else
+ {
+ ret = IOTVTICAL_INVALID_ACCESS;
+ }
+ }
+ return ret;
+}
+#endif
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "ocstack.h"
+#include "ocrandom.h"
+#include "logger.h"
+#include "pinoxmcommon.h"
+
+#define TAG "PIN_OXM_COMMON"
+
+static GeneratePinCallback gGenPinCallback = NULL;
+static InputPinCallback gInputPinCallback = NULL;
+
+void SetInputPinCB(InputPinCallback pinCB)
+{
+ if(NULL == pinCB)
+ {
+ OC_LOG(ERROR, TAG, "Failed to set callback for input pin.");
+ return;
+ }
+
+ gInputPinCallback = pinCB;
+}
+
+void SetGeneratePinCB(GeneratePinCallback pinCB)
+{
+ if(NULL == pinCB)
+ {
+ OC_LOG(ERROR, TAG, "Failed to set callback for generate pin.");
+ return;
+ }
+
+ gGenPinCallback = pinCB;
+}
+
+OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
+{
+ if(!pinBuffer)
+ {
+ OC_LOG(ERROR, TAG, "PIN buffer is NULL");
+ return OC_STACK_INVALID_PARAM;
+ }
+ if(OXM_RANDOM_PIN_SIZE + 1 > bufferSize)
+ {
+ OC_LOG(ERROR, TAG, "PIN buffer size is too small");
+ return OC_STACK_INVALID_PARAM;
+ }
+ for(size_t i = 0; i < OXM_RANDOM_PIN_SIZE; i++)
+ {
+ pinBuffer[i] = OCGetRandomRange((uint32_t)'0', (uint32_t)'9');
+ }
+ pinBuffer[OXM_RANDOM_PIN_SIZE] = '\0';
+
+ if(gGenPinCallback)
+ {
+ gGenPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE);
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
+ OC_LOG(ERROR, TAG, "Callback for genrate PIN should be registered to use PIN based OxM.");
+ return OC_STACK_ERROR;
+ }
+
+ return OC_STACK_OK;
+}
+
+
+OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
+{
+ if(!pinBuffer)
+ {
+ OC_LOG(ERROR, TAG, "PIN buffer is NULL");
+ return OC_STACK_INVALID_PARAM;
+ }
+ if(OXM_RANDOM_PIN_SIZE + 1 > bufferSize)
+ {
+ OC_LOG(ERROR, TAG, "PIN buffer size is too small");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ if(gInputPinCallback)
+ {
+ gInputPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE + 1);
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
+ OC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use PIN based OxM.");
+ return OC_STACK_ERROR;
+ }
+
+ return OC_STACK_OK;
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 <string.h>
+#include <math.h>
+#include "pbkdf2.h"
+#include "hmac.h"
+#include "debug.h"
+#include "logger.h"
+
+#define TAG "PBDKF2"
+#define XOR_BUF(in, out, bufSize)\
+do{\
+ size_t i=0;\
+ for(i=0; i< (bufSize); i++)\
+ {\
+ (out)[i] = (in)[i] ^ (out)[i];\
+ }\
+}while(0)\
+
+
+static int isLittle()
+{
+ static int a = 1;
+ static int flag = -1;
+ if (flag == -1)
+ {
+ if ( ((uint8_t *)&a)[0] == 0x1) // little
+ flag = 1;
+ else
+ flag = 0;
+ }
+ return flag;
+}
+
+static void GetBigEndianBuf(uint8_t *buf, int num)
+{
+ uint8_t *nBuf = (uint8_t *)#
+ if ( isLittle() == 1 )
+ {
+ size_t i = 0;
+ for (i = 0; i < sizeof(int); i++)
+ {
+ buf[i] = nBuf[ sizeof(int) - i - 1];
+ }
+ }
+ else
+ {
+ memcpy(buf, nBuf, sizeof(int));
+ }
+}
+
+// TODO: Add comments to explain implementation.
+int DeriveCryptoKeyFromPassword(const unsigned char *passwd, size_t pLen,
+ const uint8_t *salt, const size_t saltLen,
+ const size_t iterations,
+ const size_t keyLen, uint8_t *derivedKey)
+{
+ int res = 0;
+ uint8_t buf[DTLS_HMAC_DIGEST_SIZE];
+ uint8_t uBuf[DTLS_HMAC_DIGEST_SIZE];
+
+ size_t nBlocks = 0;
+ size_t nOctetInLastBlock = 0;
+
+ nBlocks = (size_t)ceil ((double)keyLen / (double)DTLS_HMAC_DIGEST_SIZE);
+ nOctetInLastBlock = keyLen - (nBlocks - 1) * DTLS_HMAC_DIGEST_SIZE;
+
+ dtls_hmac_context_t *ctx = NULL;
+ ctx = dtls_hmac_new( (const unsigned char *)passwd, pLen);
+ if (NULL == ctx)
+ {
+ OC_LOG(ERROR, TAG, "DTLS HMAC Context is NULL");
+ goto bail;
+ }
+
+ size_t i = 1;
+ size_t idx = 0; //index for buffer
+ size_t counter = 0;
+ while (i != nBlocks + 1)
+ {
+ counter = 0 ;
+ dtls_hmac_init(ctx, (const unsigned char *)passwd, pLen);
+ while (counter != iterations)
+ {
+ if (counter == 0)
+ {
+ uint8_t intBuf[4] = {0x00, 0x00, 0x00, 0x00};
+ dtls_hmac_update(ctx, salt, saltLen);
+ GetBigEndianBuf(intBuf, i);
+ dtls_hmac_update(ctx, intBuf, 4);
+
+ int len = dtls_hmac_finalize(ctx, buf);
+ if (DTLS_HMAC_DIGEST_SIZE != len)
+ {
+ OC_LOG(ERROR, TAG, "DTLS HMAC is failed");
+ res = -1;
+ }
+ memcpy(uBuf, buf, DTLS_HMAC_DIGEST_SIZE);
+ }
+ else
+ {
+ dtls_hmac_init(ctx, (const unsigned char *)passwd, pLen);
+ dtls_hmac_update(ctx, buf, DTLS_HMAC_DIGEST_SIZE);
+ int len = dtls_hmac_finalize(ctx, buf);
+ if (DTLS_HMAC_DIGEST_SIZE != len)
+ {
+ OC_LOG(ERROR, TAG, "DTLS HMAC is failed");
+ res = -1;
+ }
+ XOR_BUF(buf, uBuf, DTLS_HMAC_DIGEST_SIZE);
+ }
+ counter++;
+ }
+
+
+ if (i == nBlocks)
+ {
+ memcpy(derivedKey + idx, uBuf, nOctetInLastBlock);
+ }
+ else
+ {
+ memcpy(derivedKey + idx, uBuf, DTLS_HMAC_DIGEST_SIZE);
+ idx += DTLS_HMAC_DIGEST_SIZE;
+ }
+ i++;
+ }
+
+bail:
+ dtls_hmac_free(ctx);
+ return res;
+}
+
#include "aclresource.h"
#include "srmutility.h"
#include "doxmresource.h"
+#include "iotvticalendar.h"
#include <string.h>
-#define TAG PCF("SRM-PE")
+#define TAG "SRM-PE"
/**
* Return the uint16_t CRUDN permission corresponding to passed CAMethod_t.
}
/**
- * Check whether 'resource' is in the passed ACL.
- * @param resource The resource to search for.
+ * Check whether 'resource' is getting accessed within the valid time period.
* @param acl The ACL to check.
- * @return true if 'resource' found, otherwise false.
+ * @return
+ * true if access is within valid time period or if the period or recurrence is not present.
+ * false if period and recurrence present and the access is not within valid time period.
*/
- bool IsResourceInAcl(const char *resource, const OicSecAcl_t *acl)
- {
- for(size_t n = 0; n < acl->resourcesLen; n++)
+static bool IsAccessWithinValidTime(const OicSecAcl_t *acl)
+{
+#ifndef WITH_ARDUINO //Period & Recurrence not supported on Arduino due
+ //lack of absolute time
+ if(NULL== acl || NULL == acl->periods || 0 == acl->prdRecrLen)
+ {
+ return true;
+ }
+
+ for(size_t i = 0; i < acl->prdRecrLen; i++)
{
- if(0 == strcmp(resource, acl->resources[n]) || // TODO null terms?
- 0 == strcmp(WILDCARD_RESOURCE_URI, acl->resources[n]))
+ if(IOTVTICAL_VALID_ACCESS == IsRequestWithinValidTime(acl->periods[i],
+ acl->recurrences[i]))
{
+ OC_LOG(INFO, TAG, "Access request is in allowed time period");
return true;
}
}
+ OC_LOG(INFO, TAG, "Access request is in invalid time period");
return false;
- }
+
+#else
+ return true;
+#endif
+}
+
+/**
+ * Check whether 'resource' is in the passed ACL.
+ * @param resource The resource to search for.
+ * @param acl The ACL to check.
+ * @return true if 'resource' found, otherwise false.
+ */
+ bool IsResourceInAcl(const char *resource, const OicSecAcl_t *acl)
+{
+ for(size_t n = 0; n < acl->resourcesLen; n++)
+ {
+ if(0 == strcmp(resource, acl->resources[n]) || // TODO null terms?
+ 0 == strcmp(WILDCARD_RESOURCE_URI, acl->resources[n]))
+ {
+ return true;
+ }
+ }
+ return false;
+}
/**
* Find ACLs containing context->subject.
*/
void ProcessAccessRequest(PEContext_t *context)
{
- OC_LOG(INFO, TAG, PCF("Entering ProcessAccessRequest()"));
+ OC_LOG(INFO, TAG, "Entering ProcessAccessRequest()");
if(NULL != context)
{
const OicSecAcl_t *currentAcl = NULL;
context->retVal = ACCESS_DENIED_SUBJECT_NOT_FOUND;
do
{
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): getting ACL..."));
+ OC_LOG(INFO, TAG, "ProcessAccessRequest(): getting ACL...");
currentAcl = GetACLResourceData(context->subject, &savePtr);
if(NULL != currentAcl)
{
// Found the subject, so how about resource?
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- found ACL matching subject."));
+ OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
+ found ACL matching subject.");
context->retVal = ACCESS_DENIED_RESOURCE_NOT_FOUND;
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- Searching for resource..."));
+ OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
+ Searching for resource...");
if(IsResourceInAcl(context->resource, currentAcl))
{
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- found matching resource in ACL."));
+ OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
+ found matching resource in ACL.");
context->matchingAclFound = true;
- // Found the resource, so it's down to permission.
- context->retVal = ACCESS_DENIED_INSUFFICIENT_PERMISSION;
- if(IsPermissionAllowingRequest(currentAcl->permission, \
- context->permission))
+
+ // Found the resource, so it's down to valid period & permission.
+ context->retVal = ACCESS_DENIED_INVALID_PERIOD;
+ if(IsAccessWithinValidTime(currentAcl))
{
- context->retVal = ACCESS_GRANTED;
+ context->retVal = ACCESS_DENIED_INSUFFICIENT_PERMISSION;
+ if(IsPermissionAllowingRequest(currentAcl->permission, \
+ context->permission))
+ {
+ context->retVal = ACCESS_GRANTED;
+ }
}
}
}
else
{
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- no ACL found matching subject ."));
+ OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
+ no ACL found matching subject .");
}
}
while((NULL != currentAcl) && (false == context->matchingAclFound));
if(IsAccessGranted(context->retVal))
{
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- Leaving ProcessAccessRequest(ACCESS_GRANTED)"));
+ OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
+ Leaving ProcessAccessRequest(ACCESS_GRANTED)");
}
else
{
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- Leaving ProcessAccessRequest(ACCESS_DENIED)"));
+ OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
+ Leaving ProcessAccessRequest(ACCESS_DENIED)");
}
}
else
{
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- Leaving ProcessAccessRequest(context is NULL)"));
+ OC_LOG(INFO, TAG, "ProcessAccessRequest(): \
+ Leaving ProcessAccessRequest(context is NULL)");
}
}
#include <stdlib.h>
#include <string.h>
-#define TAG PCF("SRM-PSI")
+#define TAG "SRM-PSI"
//SVR database buffer block size
const size_t DB_FILE_SIZE_BLOCK = 1023;
int size = GetSVRDatabaseSize(ps);
if (0 == size)
{
- OC_LOG (ERROR, TAG, PCF("FindSVRDatabaseSize failed"));
+ OC_LOG (ERROR, TAG, "FindSVRDatabaseSize failed");
return NULL;
}
size_t bytesRead = ps->read(jsonStr, 1, size, fp);
jsonStr[bytesRead] = '\0';
- OC_LOG_V(INFO, TAG, PCF("Read %d bytes from SVR database file"), bytesRead);
+ OC_LOG_V(INFO, TAG, "Read %d bytes from SVR database file", bytesRead);
ps->close(fp);
fp = NULL;
}
else
{
- OC_LOG (ERROR, TAG, PCF("Unable to open SVR database file!!"));
+ OC_LOG (ERROR, TAG, "Unable to open SVR database file!!");
}
}
{
OCStackResult ret = OC_STACK_ERROR;
cJSON *jsonSVRDb = NULL;
+ OCPersistentStorage* ps = NULL;
// Read SVR database from PS
char* jsonSVRDbStr = GetSVRDatabase();
OICFree(jsonSVRDbStr);
jsonSVRDbStr = NULL;
- if (jsonObj->child )
+ //If Cred resource gets updated with empty list then delete the Cred
+ //object from database.
+ if(NULL == jsonObj && (0 == strcmp(rsrcName, OIC_JSON_CRED_NAME)))
+ {
+ cJSON_DeleteItemFromObject(jsonSVRDb, rsrcName);
+ }
+ else if (jsonObj->child )
{
// Create a duplicate of the JSON object which was passed.
cJSON* jsonDuplicateObj = cJSON_Duplicate(jsonObj, 1);
// Replace the modified json object in existing SVR database json
cJSON_ReplaceItemInObject(jsonSVRDb, rsrcName, jsonDuplicateObj->child);
}
+ }
- // Generate string representation of updated SVR database json object
- jsonSVRDbStr = cJSON_PrintUnformatted(jsonSVRDb);
- VERIFY_NON_NULL(TAG,jsonSVRDbStr, ERROR);
+ // Generate string representation of updated SVR database json object
+ jsonSVRDbStr = cJSON_PrintUnformatted(jsonSVRDb);
+ VERIFY_NON_NULL(TAG,jsonSVRDbStr, ERROR);
- // Update the persistent storage with new SVR database
- OCPersistentStorage* ps = SRMGetPersistentStorageHandler();
- if (ps && ps->open)
+ // Update the persistent storage with new SVR database
+ ps = SRMGetPersistentStorageHandler();
+ if (ps && ps->open)
+ {
+ FILE* fp = ps->open(SVR_DB_FILE_NAME, "w");
+ if (fp)
{
- FILE* fp = ps->open(SVR_DB_FILE_NAME, "w");
- if (fp)
+ size_t bytesWritten = ps->write(jsonSVRDbStr, 1, strlen(jsonSVRDbStr), fp);
+ if (bytesWritten == strlen(jsonSVRDbStr))
{
- size_t bytesWritten = ps->write(jsonSVRDbStr, 1, strlen(jsonSVRDbStr), fp);
- if (bytesWritten == strlen(jsonSVRDbStr))
- {
- ret = OC_STACK_OK;
- }
- OC_LOG_V(INFO, TAG, PCF("Written %d bytes into SVR database file"), bytesWritten);
- ps->close(fp);
- fp = NULL;
- }
- else
- {
- OC_LOG (ERROR, TAG, PCF("Unable to open SVR database file!! "));
+ ret = OC_STACK_OK;
}
+ OC_LOG_V(INFO, TAG, "Written %d bytes into SVR database file", bytesWritten);
+ ps->close(fp);
+ fp = NULL;
+ }
+ else
+ {
+ OC_LOG (ERROR, TAG, "Unable to open SVR database file!! ");
}
}
#include <stdlib.h>
#include <string.h>
-#define TAG PCF("SRM-PSTAT")
+#define TAG "SRM-PSTAT"
static OicSecDpom_t gSm = SINGLE_SERVICE_CLIENT_DRIVEN;
static OicSecPstat_t gDefaultPstat =
cJSON_Delete(jsonRoot);
if (OC_STACK_OK != ret)
{
- OC_LOG (ERROR, TAG, PCF("JSONToPstatBin failed"));
+ OC_LOG (ERROR, TAG, "JSONToPstatBin failed");
DeletePstatBinData(pstat);
pstat = NULL;
}
*/
static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest * ehRequest)
{
- // Convert ACL data into JSON for transmission
+ OC_LOG (INFO, TAG, "HandlePstatGetRequest processing GET request");
+ // Convert ACL data into JSON for transmission
char* jsonStr = BinToPstatJSON(gPstat);
// A device should always have a default pstat. Therefore, jsonStr should never be NULL.
{
OCEntityHandlerResult ehRet = OC_EH_ERROR;
cJSON *postJson = NULL;
+ OC_LOG (INFO, TAG, "HandlePstatPutRequest processing PUT request");
if (ehRequest->resource)
{
{
gPstat->isOp = true;
gPstat->cm = NORMAL;
- OC_LOG (INFO, TAG, PCF("CommitHash is valid and isOp is TRUE"));
+ OC_LOG (INFO, TAG, "CommitHash is valid and isOp is TRUE");
}
else
{
- OC_LOG (INFO, TAG, PCF("CommitHash is not valid"));
+ OC_LOG (INFO, TAG, "CommitHash is not valid");
}
}
cJSON *omJson = cJSON_GetObjectItem(jsonPstat, OIC_JSON_OM_NAME);
*/
for(size_t i=0; i< gPstat->smLen; i++)
{
- if(gPstat->sm[i] == omJson->valueint)
+ if(gPstat->sm[i] == (unsigned int)omJson->valueint)
{
gPstat->om = (OicSecDpom_t)omJson->valueint;
break;
//Send payload to request originator
if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))
{
- OC_LOG (ERROR, TAG, PCF("SendSRMResponse failed in HandlePstatPostRequest"));
+ OC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
}
cJSON_Delete(postJson);
return ehRet;
// This method will handle REST request (GET/POST) for /oic/sec/pstat
if (flag & OC_REQUEST_FLAG)
{
- OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+ OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
switch (ehRequest->method)
{
case OC_REST_GET:
if (ret != OC_STACK_OK)
{
- OC_LOG (FATAL, TAG, PCF("Unable to instantiate pstat resource"));
+ OC_LOG (FATAL, TAG, "Unable to instantiate pstat resource");
DeInitPstatResource();
}
return ret;
#include "pstatresource.h"
#include "doxmresource.h"
#include "credresource.h"
+#include "svcresource.h"
+#include "amaclresource.h"
#include "oic_malloc.h"
#include "oic_string.h"
#include "logger.h"
#include "utlist.h"
#include <string.h>
-#define TAG PCF("SRM-RM")
+#define TAG "SRM-RM"
/**
* This method is used by all secure resource modules to send responses to REST queries.
OCStackResult SendSRMResponse(const OCEntityHandlerRequest *ehRequest,
OCEntityHandlerResult ehRet, const char *rspPayload)
{
- OC_LOG (INFO, TAG, PCF("SRM sending SRM response"));
- OCEntityHandlerResponse response = {0};
+ OC_LOG (INFO, TAG, "SRM sending SRM response");
+ OCEntityHandlerResponse response = {.requestHandle = NULL};
if (ehRequest)
{
OCSecurityPayload ocPayload = {.base = {.type = PAYLOAD_TYPE_INVALID}};
{
ret = InitCredResource();
}
+ if(OC_STACK_OK == ret)
+ {
+ ret = InitSVCResource();
+ }
+ if(OC_STACK_OK == ret)
+ {
+ ret = InitAmaclResource();
+ }
if(OC_STACK_OK != ret)
{
//TODO: Update the default behavior if one of the SVR fails
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <string.h>
#include "ocstack.h"
#include "logger.h"
#include "cainterface.h"
#include "credresource.h"
#include "policyengine.h"
#include "oic_string.h"
-#include <string.h>
+#include "srmresourcestrings.h"
-#define TAG PCF("SRM")
+#define TAG "SRM"
//Request Callback handler
static CARequestCallback gRequestHandler = NULL;
*/
void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requestInfo)
{
- OC_LOG(INFO, TAG, PCF("Received request from remote device"));
+ OC_LOG(INFO, TAG, "Received request from remote device");
if (!endPoint || !requestInfo)
{
- OC_LOG(ERROR, TAG, PCF("Invalid arguments"));
+ OC_LOG(ERROR, TAG, "Invalid arguments");
return;
}
// Copy the subjectID
OicUuid_t subjectId = {.id = {0}};
- memcpy(subjectId.id, endPoint->identity.id, sizeof(subjectId.id));
+ memcpy(subjectId.id, requestInfo->info.identity.id, sizeof(subjectId.id));
//Check the URI has the query and skip it before checking the permission
char *uri = strstr(requestInfo->info.resourceUri, "?");
}
if (position > MAX_URI_LENGTH)
{
- OC_LOG(ERROR, TAG, PCF("URI length is too long"));
+ OC_LOG(ERROR, TAG, "URI length is too long");
return;
}
SRMAccessResponse_t response = ACCESS_DENIED;
if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
{
- OC_LOG(ERROR, TAG, PCF("Failed in sending response to a unauthorized request!"));
+ OC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
}
}
*/
void SRMResponseHandler(const CAEndpoint_t *endPoint, const CAResponseInfo_t *responseInfo)
{
- OC_LOG(INFO, TAG, PCF("Received response from remote device"));
+ OC_LOG(INFO, TAG, "Received response from remote device");
// isProvResponse flag is to check whether response is catered by provisioning APIs or not.
// When token sent by CA response matches with token generated by provisioning request,
*/
void SRMErrorHandler(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo)
{
- OC_LOG(INFO, TAG, PCF("Received error from remote device"));
+ OC_LOG(INFO, TAG, "Received error from remote device");
if (gErrorHandler)
{
gErrorHandler(endPoint, errorInfo);
CAResponseCallback respHandler,
CAErrorCallback errHandler)
{
- OC_LOG(INFO, TAG, PCF("SRMRegisterHandler !!"));
+ OC_LOG(INFO, TAG, "SRMRegisterHandler !!");
if( !reqHandler || !respHandler || !errHandler)
{
- OC_LOG(ERROR, TAG, PCF("Callback handlers are invalid"));
+ OC_LOG(ERROR, TAG, "Callback handlers are invalid");
return OC_STACK_INVALID_PARAM;
}
gRequestHandler = reqHandler;
*/
OCStackResult SRMRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
{
- OC_LOG(INFO, TAG, PCF("SRMRegisterPersistentStorageHandler !!"));
+ OC_LOG(INFO, TAG, "SRMRegisterPersistentStorageHandler !!");
if(!persistentStorageHandler)
{
- OC_LOG(ERROR, TAG, PCF("The persistent storage handler is invalid"));
+ OC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
return OC_STACK_INVALID_PARAM;
}
gPersistentStorageHandler = persistentStorageHandler;
OCPersistentStorage* SRMGetPersistentStorageHandler()
{
- OC_LOG(INFO, TAG, PCF("SRMGetPersistentStorageHandler !!"));
return gPersistentStorageHandler;
}
{
return DeInitPolicyEngine(&g_policyEngineContext);
}
+
+/**
+ * @brief Check the security resource URI.
+ * @param uri [IN] Pointers to security resource URI.
+ * @return true if the URI is one of security resources, otherwise false.
+ */
+bool SRMIsSecurityResourceURI(const char* uri)
+{
+ bool result = false;
+ if (!uri)
+ {
+ return result;
+ }
+
+ if (strcmp(uri, OIC_RSRC_AMACL_URI) == 0 || strcmp(uri, OIC_RSRC_ACL_URI) == 0
+ || strcmp(uri, OIC_RSRC_PSTAT_URI) == 0
+ || strncmp(OIC_RSRC_DOXM_URI, uri, sizeof(OIC_RSRC_DOXM_URI) - 1) == 0
+ || strcmp(uri, OIC_RSRC_CRED_URI) == 0 || strcmp(uri, OIC_RSRC_SVC_URI) == 0)
+ {
+ result = true;
+ }
+ return result;
+}
const char * SVR_DB_FILE_NAME = "oic_svr_db.json";
const char * OIC_MI_DEF = "oic.mi.def";
+//AMACL
+const char * OIC_RSRC_TYPE_SEC_AMACL = "oic.sec.amacl";
+const char * OIC_RSRC_AMACL_URI = "/oic/sec/amacl";
+const char * OIC_JSON_AMACL_NAME = "amacl";
+
//ACL
const char * OIC_RSRC_TYPE_SEC_ACL = "oic.sec.acl";
const char * OIC_RSRC_ACL_URI = "/oic/sec/acl";
const char * OIC_RSRC_CRED_URI = "/oic/sec/cred";
const char * OIC_JSON_CRED_NAME = "cred";
+//svc
+const char * OIC_RSRC_TYPE_SEC_SVC = "oic.sec.svc";
+const char * OIC_RSRC_SVC_URI = "/oic/sec/svc";
+const char * OIC_JSON_SVC_NAME = "svc";
+
+
const char * OIC_JSON_SUBJECT_NAME = "sub";
const char * OIC_JSON_RESOURCES_NAME = "rsrc";
+const char * OIC_JSON_AMSS_NAME = "amss";
const char * OIC_JSON_PERMISSION_NAME = "perms";
const char * OIC_JSON_OWNERS_NAME = "ownrs";
const char * OIC_JSON_OWNER_NAME = "ownr";
const char * OIC_JSON_CREDTYPE_NAME = "credtyp";
const char * OIC_JSON_PUBLICDATA_NAME = "pbdata";
const char * OIC_JSON_PRIVATEDATA_NAME = "pvdata";
-const char * OIC_JSON_PERIOD_NAME = "period";
+const char * OIC_JSON_SERVICE_DEVICE_ID = "svcdid";
+const char * OIC_JSON_SERVICE_TYPE = "svct";
+const char * OIC_JSON_PERIOD_NAME = "prd";
+const char * OIC_JSON_PERIODS_NAME = "prds";
+const char * OIC_JSON_RECURRENCES_NAME = "recurs";
+const char * OIC_JSON_SUPPORTED_CRED_TYPE_NAME = "sct";
OicUuid_t WILDCARD_SUBJECT_ID = {"*"};
size_t WILDCARD_SUBJECT_ID_LEN = 1;
const char * OIC_SEC_TRUE = "true";
const char * OIC_SEC_FALSE = "false";
-const char * OIC_SEC_REST_QUERY_SEPARATOR = "&";
+const char * OIC_SEC_REST_QUERY_SEPARATOR = ";";
char OIC_SEC_REST_QUERY_DELIMETER = '=';
+
#include "srmutility.h"
#include "srmresourcestrings.h"
#include "logger.h"
+#include "oic_malloc.h"
+#include "base64.h"
-#define TAG PCF("SRM-UTILITY")
+#define TAG "SRM-UTILITY"
/**
* This method initializes the OicParseQueryIter_t struct
*/
void ParseQueryIterInit(unsigned char * query, OicParseQueryIter_t * parseIter)
{
- OC_LOG (INFO, TAG, PCF("Initializing coap iterator"));
+ OC_LOG (INFO, TAG, "Initializing coap iterator");
if((NULL == query) || (NULL == parseIter))
return;
(unsigned char *)OIC_SEC_REST_QUERY_SEPARATOR, (unsigned char *) "", 0, &parseIter->pi);
}
-
/**
* This method fills the OicParseQueryIter_t struct with next REST query's
* attribute's and value's information
*/
OicParseQueryIter_t * GetNextQuery(OicParseQueryIter_t * parseIter)
{
- OC_LOG (INFO, TAG, PCF("Getting Next Query"));
+ OC_LOG (INFO, TAG, "Getting Next Query");
if(NULL == parseIter)
return NULL;
}
return NULL;
}
+
+
+// TODO This functionality is replicated in all SVR's and therefore we need
+// to encapsulate it in a common method. However, this may not be the right
+// file for this method.
+OCStackResult AddUuidArray(cJSON* jsonRoot, const char* arrayItem,
+ size_t *numUuids, OicUuid_t** uuids )
+{
+ size_t idxx = 0;
+ cJSON* jsonObj = cJSON_GetObjectItem(jsonRoot, arrayItem);
+ VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+ VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
+
+ *numUuids = cJSON_GetArraySize(jsonObj);
+ VERIFY_SUCCESS(TAG, *numUuids > 0, ERROR);
+ *uuids = (OicUuid_t*)OICCalloc(*numUuids, sizeof(OicUuid_t));
+ VERIFY_NON_NULL(TAG, *uuids, ERROR);
+
+ do
+ {
+ unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+ uint32_t outLen = 0;
+ B64Result b64Ret = B64_OK;
+
+ cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx);
+ VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
+ VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
+
+ outLen = 0;
+ b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff,
+ sizeof(base64Buff), &outLen);
+
+ VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof((*uuids)[idxx].id)),
+ ERROR);
+ memcpy((*uuids)[idxx].id, base64Buff, outLen);
+ } while ( ++idxx < *numUuids);
+
+ return OC_STACK_OK;
+
+exit:
+ return OC_STACK_ERROR;
+
+}
--- /dev/null
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "ocstack.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "cJSON.h"
+#include "base64.h"
+#include "resourcemanager.h"
+#include "psinterface.h"
+#include "svcresource.h"
+#include "utlist.h"
+#include "srmresourcestrings.h"
+#include "srmutility.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define TAG "SRM-SVC"
+
+OicSecSvc_t *gSvc = NULL;
+static OCResourceHandle gSvcHandle = NULL;
+
+void DeleteSVCList(OicSecSvc_t* svc)
+{
+ if (svc)
+ {
+ OicSecSvc_t *svcTmp1 = NULL, *svcTmp2 = NULL;
+ LL_FOREACH_SAFE(svc, svcTmp1, svcTmp2)
+ {
+ LL_DELETE(svc, svcTmp1);
+
+ // Clean Owners
+ OICFree(svcTmp1->owners);
+
+ // Clean SVC node itself
+ OICFree(svcTmp1);
+ }
+ }
+}
+
+/*
+ * This internal method converts SVC data into JSON format.
+ *
+ * Note: Caller needs to invoke 'free' when finished done using
+ * return string.
+ */
+char * BinToSvcJSON(const OicSecSvc_t * svc)
+{
+ cJSON *jsonRoot = NULL;
+ char *jsonStr = NULL;
+
+ if (svc)
+ {
+ jsonRoot = cJSON_CreateObject();
+ VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+ cJSON *jsonSvcArray = NULL;
+ cJSON_AddItemToObject (jsonRoot, OIC_JSON_SVC_NAME, jsonSvcArray = cJSON_CreateArray());
+ VERIFY_NON_NULL(TAG, jsonSvcArray, ERROR);
+
+ while(svc)
+ {
+ char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
+ uint32_t outLen = 0;
+ B64Result b64Ret = B64_OK;
+
+ cJSON *jsonSvc = cJSON_CreateObject();
+
+ // Service Device Identity
+ outLen = 0;
+ b64Ret = b64Encode(svc->svcdid.id, sizeof(OicUuid_t), base64Buff,
+ sizeof(base64Buff), &outLen);
+ VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+ cJSON_AddStringToObject(jsonSvc, OIC_JSON_SERVICE_DEVICE_ID, base64Buff );
+
+ // Service Type
+ cJSON_AddNumberToObject (jsonSvc, OIC_JSON_SERVICE_TYPE, svc->svct);
+
+ // Owners
+ cJSON *jsonOwnrArray = NULL;
+ cJSON_AddItemToObject (jsonSvc, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray());
+ VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
+ for (unsigned int i = 0; i < svc->ownersLen; i++)
+ {
+ outLen = 0;
+
+ b64Ret = b64Encode(svc->owners[i].id, sizeof(((OicUuid_t*)0)->id), base64Buff,
+ sizeof(base64Buff), &outLen);
+ VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+
+ cJSON_AddItemToArray (jsonOwnrArray, cJSON_CreateString(base64Buff));
+ }
+
+ // Attach current svc node to Svc Array
+ cJSON_AddItemToArray(jsonSvcArray, jsonSvc);
+ svc = svc->next;
+ }
+
+ jsonStr = cJSON_PrintUnformatted(jsonRoot);
+ }
+
+exit:
+ if (jsonRoot)
+ {
+ cJSON_Delete(jsonRoot);
+ }
+ return jsonStr;
+}
+
+/*
+ * This internal method converts JSON SVC into binary SVC.
+ */
+OicSecSvc_t * JSONToSvcBin(const char * jsonStr)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ OicSecSvc_t * headSvc = NULL;
+ OicSecSvc_t * prevSvc = NULL;
+ cJSON *jsonRoot = NULL;
+ cJSON *jsonSvcArray = NULL;
+
+ VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+ jsonRoot = cJSON_Parse(jsonStr);
+ VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+ jsonSvcArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_SVC_NAME);
+ VERIFY_NON_NULL(TAG, jsonSvcArray, INFO);
+
+ if (cJSON_Array == jsonSvcArray->type)
+ {
+ int numSvc = cJSON_GetArraySize(jsonSvcArray);
+ int idx = 0;
+
+ VERIFY_SUCCESS(TAG, numSvc > 0, INFO);
+ do
+ {
+ cJSON *jsonSvc = cJSON_GetArrayItem(jsonSvcArray, idx);
+ VERIFY_NON_NULL(TAG, jsonSvc, ERROR);
+
+ OicSecSvc_t *svc = (OicSecSvc_t*)OICCalloc(1, sizeof(OicSecSvc_t));
+ VERIFY_NON_NULL(TAG, svc, ERROR);
+
+ headSvc = (headSvc) ? headSvc : svc;
+ if (prevSvc)
+ {
+ prevSvc->next = svc;
+ }
+
+ cJSON *jsonObj = NULL;
+
+ unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+ uint32_t outLen = 0;
+ B64Result b64Ret = B64_OK;
+
+ // Service Device Identity
+ jsonObj = cJSON_GetObjectItem(jsonSvc, OIC_JSON_SERVICE_DEVICE_ID);
+ VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+ VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
+ outLen = 0;
+ b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
+ sizeof(base64Buff), &outLen);
+ VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(svc->svcdid.id)), ERROR);
+ memcpy(svc->svcdid.id, base64Buff, outLen);
+
+ // Service Type
+ jsonObj = cJSON_GetObjectItem(jsonSvc, OIC_JSON_SERVICE_TYPE);
+ VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+ VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
+ svc->svct = (OicSecSvcType_t)jsonObj->valueint;
+
+ // Resource Owners
+ jsonObj = cJSON_GetObjectItem(jsonSvc, OIC_JSON_OWNERS_NAME);
+ VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+ VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
+
+ svc->ownersLen = cJSON_GetArraySize(jsonObj);
+ VERIFY_SUCCESS(TAG, svc->ownersLen > 0, ERROR);
+ svc->owners = (OicUuid_t*)OICCalloc(svc->ownersLen, sizeof(OicUuid_t));
+ VERIFY_NON_NULL(TAG, (svc->owners), ERROR);
+
+ size_t idxx = 0;
+ do
+ {
+ cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx);
+ VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
+ VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
+
+ outLen = 0;
+ b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff,
+ sizeof(base64Buff), &outLen);
+
+ VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(svc->owners[idxx].id)),
+ ERROR);
+ memcpy(svc->owners[idxx].id, base64Buff, outLen);
+ } while ( ++idxx < svc->ownersLen);
+
+ prevSvc = svc;
+ } while( ++idx < numSvc);
+ }
+
+ ret = OC_STACK_OK;
+
+exit:
+ cJSON_Delete(jsonRoot);
+ if (OC_STACK_OK != ret)
+ {
+ DeleteSVCList(headSvc);
+ headSvc = NULL;
+ }
+ return headSvc;
+}
+
+static OCEntityHandlerResult HandleSVCGetRequest (const OCEntityHandlerRequest * ehRequest)
+{
+ // Convert SVC data into JSON for transmission
+ char* jsonStr = BinToSvcJSON(gSvc);
+
+ OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
+
+ // Send response payload to request originator
+ SendSRMResponse(ehRequest, ehRet, jsonStr);
+
+ OICFree(jsonStr);
+
+ OC_LOG_V (INFO, TAG, "%s RetVal %d", __func__ , ehRet);
+ return ehRet;
+}
+
+static OCEntityHandlerResult HandleSVCPostRequest (const OCEntityHandlerRequest * ehRequest)
+{
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+ // Convert JSON SVC data into binary. This will also validate the SVC data received.
+ OicSecSvc_t* newSvc = JSONToSvcBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
+
+ if (newSvc)
+ {
+ // Append the new SVC to existing SVC
+ LL_APPEND(gSvc, newSvc);
+
+ // Convert SVC data into JSON for update to persistent storage
+ char *jsonStr = BinToSvcJSON(gSvc);
+ if (jsonStr)
+ {
+ cJSON *jsonSvc = cJSON_Parse(jsonStr);
+ OICFree(jsonStr);
+
+ if ((jsonSvc) &&
+ (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_SVC_NAME, jsonSvc)))
+ {
+ ehRet = OC_EH_RESOURCE_CREATED;
+ }
+ cJSON_Delete(jsonSvc);
+ }
+ }
+
+ // Send payload to request originator
+ SendSRMResponse(ehRequest, ehRet, NULL);
+
+ OC_LOG_V (INFO, TAG, "%s RetVal %d", __func__ , ehRet);
+ return ehRet;
+}
+
+/*
+ * This internal method is the entity handler for SVC resources and
+ * will handle REST request (GET/PUT/POST/DEL) for them.
+ */
+OCEntityHandlerResult SVCEntityHandler (OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest * ehRequest,
+ void* callbackParameter)
+{
+ (void) callbackParameter;
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+ if (!ehRequest)
+ {
+ return ehRet;
+ }
+
+ if (flag & OC_REQUEST_FLAG)
+ {
+ switch (ehRequest->method)
+ {
+ case OC_REST_GET:
+ ehRet = HandleSVCGetRequest(ehRequest);
+ break;
+
+ case OC_REST_POST:
+ ehRet = HandleSVCPostRequest(ehRequest);
+ break;
+
+ default:
+ ehRet = OC_EH_ERROR;
+ SendSRMResponse(ehRequest, ehRet, NULL);
+ }
+ }
+
+ return ehRet;
+}
+
+/*
+ * This internal method is used to create '/oic/sec/svc' resource.
+ */
+OCStackResult CreateSVCResource()
+{
+ OCStackResult ret;
+
+ ret = OCCreateResource(&gSvcHandle,
+ OIC_RSRC_TYPE_SEC_SVC,
+ OIC_MI_DEF,
+ OIC_RSRC_SVC_URI,
+ SVCEntityHandler,
+ NULL,
+ OC_OBSERVABLE);
+
+ if (OC_STACK_OK != ret)
+ {
+ OC_LOG (FATAL, TAG, "Unable to instantiate SVC resource");
+ DeInitSVCResource();
+ }
+ return ret;
+}
+
+
+OCStackResult InitSVCResource()
+{
+ OCStackResult ret = OC_STACK_ERROR;
+
+ OC_LOG_V (INFO, TAG, "Begin %s ", __func__ );
+
+ // Read SVC resource from PS
+ char* jsonSVRDatabase = GetSVRDatabase();
+
+ if (jsonSVRDatabase)
+ {
+ // Convert JSON SVC into binary format
+ gSvc = JSONToSvcBin(jsonSVRDatabase);
+ OICFree(jsonSVRDatabase);
+ }
+
+ // Instantiate 'oic.sec.svc'
+ ret = CreateSVCResource();
+
+ if (OC_STACK_OK != ret)
+ {
+ DeInitSVCResource();
+ }
+
+ OC_LOG_V (INFO, TAG, "%s RetVal %d", __func__ , ret);
+ return ret;
+}
+
+/**
+ * Perform cleanup for SVC resources.
+ *
+ * @retval none
+ */
+void DeInitSVCResource()
+{
+ OCDeleteResource(gSvcHandle);
+ gSvcHandle = NULL;
+
+ DeleteSVCList(gSvc);
+ gSvc = NULL;
+}
+
'securityresourcemanager.cpp',
'credentialresource.cpp',
'srmutility.cpp',
- 'base64tests.cpp'])
+ 'iotvticalendartest.cpp',
+ 'base64tests.cpp',
+ 'svcresourcetest.cpp',
+ 'srmtestcommon.cpp'])
Alias("test", [unittest])
#include "ocstack.h"
#include "ocpayload.h"
#include "oic_malloc.h"
+#include "oic_string.h"
#include "cJSON.h"
#include "cainterface.h"
#include "secureresourcemanager.h"
#include "securevirtualresourcetypes.h"
#include "srmresourcestrings.h"
#include "aclresource.h"
+#include "srmtestcommon.h"
+#include "srmutility.h"
+#include "logger.h"
using namespace std;
+#define TAG "SRM-ACL-UT"
+
#ifdef __cplusplus
extern "C" {
#endif
+
extern char * BinToAclJSON(const OicSecAcl_t * acl);
extern OicSecAcl_t * JSONToAclBin(const char * jsonStr);
-char* ReadFile(const char* filename);
extern void DeleteACLList(OicSecAcl_t* acl);
OCStackResult GetDefaultACL(OicSecAcl_t** defaultAcl);
OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
#define NUM_ACE_FOR_WILDCARD_IN_ACL1_JSON (2)
-char* ReadFile(const char* filename)
-{
-
- FILE *fp = NULL;
- char *data = NULL;
- struct stat st;
- // TODO: Find the location of the executable and concatenate the SVR file name
- // before opening it.
- fp = fopen(filename, "r");
- if (fp)
- {
- if (stat(filename, &st) == 0)
- {
- data = (char*)OICMalloc(st.st_size);
- if (data)
- {
- if (fread(data, 1, st.st_size, fp) != (size_t)st.st_size)
- {
- printf("Error in reading file %s", filename);
- }
- }
- }
- fclose(fp);
- }
- else
- {
- printf("Unable to open %s file", filename);
- }
-
- return data;
-}
-
-void SetPersistentHandler(OCPersistentStorage *ps, bool set)
-{
- if (set)
- {
- ps->open = fopen;
- ps->read = fread;
- ps->write = fwrite;
- ps->close = fclose;
- ps->unlink = unlink;
- }
- else
- {
- memset(ps, 0, sizeof(OCPersistentStorage));
- }
- EXPECT_EQ(OC_STACK_OK,
- OCRegisterPersistentStorageHandler(ps));
-}
-
// JSON Marshalling Tests
TEST(ACLResourceTest, JSONMarshallingTests)
{
// 'POST' ACL tests
TEST(ACLResourceTest, ACLPostTest)
{
- OCEntityHandlerRequest ehReq = {};
+ OCEntityHandlerRequest ehReq = OCEntityHandlerRequest();
// Read an ACL from the file
char *jsonStr = ReadFile(ACL1_JSON_FILE_NAME);
if (jsonStr)
{
- static OCPersistentStorage ps =
- { };
+ static OCPersistentStorage ps = OCPersistentStorage();
+
SetPersistentHandler(&ps, true);
// Create Entity Handler POST request payload
}
}
+static OCStackResult populateAcl(OicSecAcl_t *acl, int numRsrc)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ memcpy(acl->subject.id, "2222222222222222", sizeof(acl->subject.id));
+ acl->resourcesLen = numRsrc;
+ acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
+ VERIFY_NON_NULL(TAG, acl->resources, ERROR);
+ acl->resources[0] = (char*)OICMalloc(strlen("/a/led")+1);
+ VERIFY_NON_NULL(TAG, acl->resources[0], ERROR);
+ OICStrcpy(acl->resources[0], sizeof(acl->resources[0]), "/a/led");
+ if(numRsrc == 2)
+ {
+ acl->resources[1] = (char*)OICMalloc(strlen("/a/fan")+1);
+ VERIFY_NON_NULL(TAG, acl->resources[1], ERROR);
+ OICStrcpy(acl->resources[1], sizeof(acl->resources[1]), "/a/fan");
+ }
+ acl->permission = 6;
+ acl->ownersLen = 1;
+ acl->owners = (OicUuid_t*)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
+ VERIFY_NON_NULL(TAG, acl->owners, ERROR);
+ memcpy(acl->owners->id, "1111111111111111", sizeof(acl->owners->id));
+
+ ret = OC_STACK_OK;
+exit:
+ return ret;
+
+}
+
+//'DELETE' ACL test
+TEST(ACLResourceTest, ACLDeleteWithSingleResourceTest)
+{
+ OCEntityHandlerRequest ehReq = OCEntityHandlerRequest();
+ static OCPersistentStorage ps = OCPersistentStorage();
+ char *jsonStr = NULL;
+ OicSecAcl_t acl = OicSecAcl_t();
+ OicSecAcl_t* savePtr = NULL;
+ const OicSecAcl_t* subjectAcl1 = NULL;
+ const OicSecAcl_t* subjectAcl2 = NULL;
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+ char query[] = "sub=MjIyMjIyMjIyMjIyMjIyMg==;rsrc=/a/led";
+
+ SetPersistentHandler(&ps, true);
+
+ //Populate ACL
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == populateAcl(&acl, 1)), ERROR);
+
+ //GET json POST payload
+ jsonStr = BinToAclJSON(&acl);
+ VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+ // Create Entity Handler POST request payload
+ ehReq.method = OC_REST_POST;
+ ehReq.payload = (OCPayload*)OCSecurityPayloadCreate(jsonStr);
+ ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+ EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+ // Verify if SRM contains ACE for the subject
+ savePtr = NULL;
+ subjectAcl1 = GetACLResourceData(&acl.subject, &savePtr);
+ EXPECT_TRUE(NULL != subjectAcl1);
+
+ // Create Entity Handler DELETE request
+ ehReq.method = OC_REST_DELETE;
+ ehReq.query = (char*)OICMalloc(strlen(query)+1);
+ VERIFY_NON_NULL(TAG, ehReq.query, ERROR);
+ OICStrcpy(ehReq.query, strlen(query)+1, query);
+ ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+ EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+ // Verify if SRM has deleted ACE for the subject
+ savePtr = NULL;
+ subjectAcl2 = GetACLResourceData(&acl.subject, &savePtr);
+ EXPECT_TRUE(NULL == subjectAcl2);
+
+exit:
+ // Perform cleanup
+ if(NULL != subjectAcl1)
+ {
+ DeInitACLResource();
+ }
+ OCPayloadDestroy(ehReq.payload);
+ OICFree(ehReq.query);
+ OICFree(jsonStr);
+
+}
+
+TEST(ACLResourceTest, ACLDeleteWithMultiResourceTest)
+{
+ OCEntityHandlerRequest ehReq = OCEntityHandlerRequest();
+ static OCPersistentStorage ps = OCPersistentStorage();
+ OicSecAcl_t acl = OicSecAcl_t();
+ char *jsonStr = NULL;
+ OicSecAcl_t* savePtr = NULL;
+ const OicSecAcl_t* subjectAcl1 = NULL;
+ const OicSecAcl_t* subjectAcl2 = NULL;
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+ char query[] = "sub=MjIyMjIyMjIyMjIyMjIyMg==;rsrc=/a/led";
+
+ SetPersistentHandler(&ps, true);
+
+ //Populate ACL
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == populateAcl(&acl, 2)), ERROR);
+
+ //GET json POST payload
+ jsonStr = BinToAclJSON(&acl);
+ VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+ // Create Entity Handler POST request payload
+ ehReq.method = OC_REST_POST;
+ ehReq.payload = (OCPayload*)OCSecurityPayloadCreate(jsonStr);
+ ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+ EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+ // Verify if SRM contains ACE for the subject with two resources
+ savePtr = NULL;
+ subjectAcl1 = GetACLResourceData(&acl.subject, &savePtr);
+ EXPECT_TRUE(NULL != subjectAcl1);
+ EXPECT_TRUE(subjectAcl1->resourcesLen == 2);
+
+ // Create Entity Handler DELETE request
+ ehReq.method = OC_REST_DELETE;
+ ehReq.query = (char*)OICMalloc(strlen(query)+1);
+ VERIFY_NON_NULL(TAG, ehReq.query, ERROR);
+ OICStrcpy(ehReq.query, strlen(query)+1, query);
+
+ ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+ EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+ // Verify if SRM contains ACL for the subject but only with one resource
+ savePtr = NULL;
+ subjectAcl2 = GetACLResourceData(&acl.subject, &savePtr);
+ EXPECT_TRUE(NULL != subjectAcl2);
+ EXPECT_TRUE(subjectAcl2->resourcesLen == 1);
+
+exit:
+ // Perform cleanup
+ if(NULL != subjectAcl1)
+ {
+ DeInitACLResource();
+ }
+ OCPayloadDestroy(ehReq.payload);
+ OICFree(ehReq.query);
+ OICFree(jsonStr);
+}
+
+//'GET' with query ACL test
+
+TEST(ACLResourceTest, ACLGetWithQueryTest)
+{
+ OCEntityHandlerRequest ehReq = OCEntityHandlerRequest();
+ static OCPersistentStorage ps = OCPersistentStorage();
+ OicSecAcl_t acl = OicSecAcl_t();
+ char *jsonStr = NULL;
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+ char query[] = "sub=MjIyMjIyMjIyMjIyMjIyMg==;rsrc=/a/led";
+
+ SetPersistentHandler(&ps, true);
+
+ //Populate ACL
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == populateAcl(&acl, 1)), ERROR);
+
+ //GET json POST payload
+ jsonStr = BinToAclJSON(&acl);
+ VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+ //Create Entity Handler POST request payload
+ ehReq.method = OC_REST_POST;
+ ehReq.payload = (OCPayload*)OCSecurityPayloadCreate(jsonStr);
+ ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+ EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+ //Create Entity Handler GET request wit query
+ ehReq.method = OC_REST_GET;
+ ehReq.query = (char*)OICMalloc(strlen(query)+1);
+ VERIFY_NON_NULL(TAG, ehReq.query, ERROR);
+ OICStrcpy(ehReq.query, strlen(query)+1, query);
+
+ ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+ EXPECT_TRUE(OC_EH_OK == ehRet);
+
+exit:
+ // Perform cleanup
+ OCPayloadDestroy(ehReq.payload);
+ OICFree(ehReq.query);
+ OICFree(jsonStr);
+}
#include "gtest/gtest.h"
#include "ocstack.h"
+#include "ocpayload.h"
#include "resourcemanager.h"
#include "securevirtualresourcetypes.h"
#include "credresource.h"
#include "oic_malloc.h"
#include "oic_string.h"
+#include "srmtestcommon.h"
+#include "srmutility.h"
#include "logger.h"
-#define TAG PCF("SRM-CRED-UT")
+#define TAG "SRM-CRED-UT"
#ifdef __cplusplus
extern "C" {
void InitSecCredInstance(OicSecCred_t * cred);
void DeleteCredList(OicSecCred_t* cred);
const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject);
+
#ifdef __cplusplus
}
#endif
+
OicSecCred_t * getCredList()
{
- OicSecCred_t * cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
- if(!cred)
- {
- return NULL;
- }
+
+ OicSecCred_t * cred = NULL;
+ size_t sz = 0;
+
+ cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
+ VERIFY_NON_NULL(TAG, cred, ERROR);
cred->credId = 1234;
OICStrcpy((char *)cred->subject.id, sizeof(cred->subject.id), "subject1");
#if 0
cred->roleIdsLen = 2;
cred->roleIds = (OicSecRole_t *)OICCalloc(cred->roleIdsLen, sizeof(OicSecRole_t));
+ VERIFY_NON_NULL(TAG, cred->roleIds, ERROR);
OICStrcpy((char *)cred->roleIds[0].id, sizeof(cred->roleIds[0].id), "role11");
OICStrcpy((char *)cred->roleIds[1].id, sizeof(cred->roleIds[1].id), "role12");
+
#endif
- cred->credType = 1;
+ cred->credType = SYMMETRIC_PAIR_WISE_KEY;
+ cred->privateData.data = (char *)OICCalloc(1, strlen("My private Key11") + 1);
+ VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
+ strcpy(cred->privateData.data, "My private Key11");
cred->ownersLen = 1;
cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
- if(!cred->owners)
- {
- OICFree(cred);
- return NULL;
- }
+ VERIFY_NON_NULL(TAG, cred->owners, ERROR);
OICStrcpy((char *)cred->owners[0].id, sizeof(cred->owners[0].id), "ownersId11");
cred->next = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
- if(!cred->next)
- {
- OICFree(cred->owners);
- OICFree(cred);
- return NULL;
- }
+ VERIFY_NON_NULL(TAG, cred->next, ERROR);
cred->next->credId = 5678;
OICStrcpy((char *)cred->next->subject.id, sizeof(cred->next->subject.id), "subject2");
#if 0
cred->next->roleIdsLen = 0;
#endif
- cred->next->credType = 1;
- size_t data_size = strlen("My private Key21") + 1;
- cred->next->privateData.data = (char *)OICCalloc(1, data_size);
- if(!cred->next->privateData.data)
- {
- OICFree(cred->next);
- OICFree(cred->owners);
- OICFree(cred);
- return NULL;
- }
- OICStrcpy(cred->next->privateData.data, data_size,"My private Key21");
+ cred->next->credType = SYMMETRIC_PAIR_WISE_KEY;
+ sz = strlen("My private Key21") + 1;
+ cred->next->privateData.data = (char *)OICCalloc(1, sz);
+ VERIFY_NON_NULL(TAG, cred->next->privateData.data, ERROR);
+ OICStrcpy(cred->next->privateData.data, sz,"My private Key21");
#if 0
- cred->next->publicData.data = (char *)OICCalloc(1, strlen("My Public Key123") + 1);
- OICStrcpy(cred->next->publicData.data, sizeof(cred->next->publicData.data),"My Public Key123");
+ sz = strlen("My Public Key123") + 1
+ cred->next->publicData.data = (char *)OICCalloc(1, sz);
+ VERIFY_NON_NULL(TAG, cred->next->publicData.data, ERROR);
+ OICStrcpy(cred->next->publicData.data, sz,"My Public Key123");
#endif
cred->next->ownersLen = 2;
cred->next->owners = (OicUuid_t*)OICCalloc(cred->next->ownersLen, sizeof(OicUuid_t));
- if(!cred->next->owners)
- {
- OICFree(cred->next->privateData.data);
- OICFree(cred->next);
- OICFree(cred->owners);
- OICFree(cred);
- return NULL;
- }
+ VERIFY_NON_NULL(TAG, cred->next->owners, ERROR);
OICStrcpy((char *)cred->next->owners[0].id, sizeof(cred->next->owners[0].id), "ownersId21");
OICStrcpy((char *)cred->next->owners[1].id, sizeof(cred->next->owners[1].id), "ownersId22");
+
+ return cred;
+
+exit:
+ if(cred)
+ {
+ DeleteCredList(cred);
+ cred = NULL;
+ }
return cred;
}
const OicSecCred_t *credTmp1 = NULL;
for(credTmp1 = cred; credTmp1; credTmp1 = credTmp1->next)
{
- OC_LOG_V(INFO, TAG, PCF("\ncred->credId = %d"), credTmp1->credId);
- OC_LOG_V(INFO, TAG, PCF("cred->subject.id = %s"), credTmp1->subject.id);
- OC_LOG_V(INFO, TAG, PCF("cred->credType = %d"), credTmp1->credType);
+ OC_LOG_V(INFO, TAG, "\ncred->credId = %d", credTmp1->credId);
+ OC_LOG_V(INFO, TAG, "cred->subject.id = %s", credTmp1->subject.id);
+ OC_LOG_V(INFO, TAG, "cred->credType = %d", credTmp1->credType);
if(credTmp1->privateData.data)
{
- OC_LOG_V(INFO, TAG, PCF("cred->privateData.data = %s"), credTmp1->privateData.data);
+ OC_LOG_V(INFO, TAG, "cred->privateData.data = %s", credTmp1->privateData.data);
}
if(credTmp1->publicData.data)
{
- OC_LOG_V(INFO, TAG, PCF("cred->publicData.data = %s"), credTmp1->publicData.data);
+ OC_LOG_V(INFO, TAG, "cred->publicData.data = %s", credTmp1->publicData.data);
}
- OC_LOG_V(INFO, TAG, PCF("cred->ownersLen = %zd"), credTmp1->ownersLen);
+ OC_LOG_V(INFO, TAG, "cred->ownersLen = %zd", credTmp1->ownersLen);
for(size_t i = 0; i < cred->ownersLen; i++)
{
- OC_LOG_V(INFO, TAG, PCF("cred->owners[%zd].id = %s"), i, credTmp1->owners[i].id);
+ OC_LOG_V(INFO, TAG, "cred->owners[%zd].id = %s", i, credTmp1->owners[i].id);
}
}
}
TEST(CredEntityHandlerTest, CredEntityHandlerWithDummyRequest)
{
OCEntityHandlerRequest req;
- EXPECT_EQ(OC_EH_ERROR, CredEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
+ EXPECT_EQ(OC_EH_ERROR,
+ CredEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
}
TEST(CredEntityHandlerTest, CredEntityHandlerWithNULLRequest)
{
- EXPECT_EQ(OC_EH_ERROR, CredEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, NULL));
+ EXPECT_EQ(OC_EH_ERROR,
+ CredEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, NULL));
}
TEST(CredEntityHandlerTest, CredEntityHandlerInvalidFlag)
{
OCEntityHandlerRequest req;
- EXPECT_EQ(OC_EH_ERROR, CredEntityHandler(OCEntityHandlerFlag::OC_OBSERVE_FLAG, &req));
+ EXPECT_EQ(OC_EH_ERROR,
+ CredEntityHandler(OCEntityHandlerFlag::OC_OBSERVE_FLAG, &req));
+}
+
+//Cred DELETE request
+TEST(CredEntityHandlerTest, CredEntityHandlerDeleteTest)
+{
+ OCEntityHandlerRequest ehReq = OCEntityHandlerRequest();
+ static OCPersistentStorage ps = OCPersistentStorage();
+ const OicSecCred_t* subjectCred1 = NULL;
+ const OicSecCred_t* subjectCred2 = NULL;
+ char *jsonStr = NULL;
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+ char query[] = "sub=c3ViamVjdDE=";
+
+ SetPersistentHandler(&ps, true);
+
+ OicSecCred_t *cred = getCredList();
+ VERIFY_NON_NULL(TAG, cred, ERROR);
+
+ jsonStr = BinToCredJSON(cred);
+ VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+ // Create Entity Handler POST request payload
+ ehReq.method = OC_REST_POST;
+ ehReq.payload = (OCPayload*)OCSecurityPayloadCreate(jsonStr);
+ ehRet = CredEntityHandler(OC_REQUEST_FLAG, &ehReq);
+ EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+ // Verify if SRM contains Credential for the subject
+ subjectCred1 = GetCredResourceData(&cred->subject);
+ EXPECT_TRUE(NULL != subjectCred1);
+
+ // Create Entity Handler DELETE request
+ ehReq.method = OC_REST_DELETE;
+ ehReq.query = (char*)OICMalloc(strlen(query)+1);
+ VERIFY_NON_NULL(TAG, ehReq.query, ERROR);
+ OICStrcpy(ehReq.query, strlen(query)+1, query);
+
+ ehRet = CredEntityHandler(OC_REQUEST_FLAG, &ehReq);
+ EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+ // Verify if SRM has deleted ACE for the subject
+ subjectCred2 = GetCredResourceData(&cred->subject);
+ EXPECT_TRUE(NULL == subjectCred2);
+
+exit:
+ // Perform cleanup
+ OICFree(ehReq.query);
+ OICFree(jsonStr);
+ OCPayloadDestroy(ehReq.payload);
+ if(NULL != cred)
+ {
+ DeInitCredResource();
+ DeleteCredList(cred);
+ }
}
//BinToCredJSON Tests
json = BinToCredJSON(cred);
+ OC_LOG_V(INFO, TAG, "BinToCredJSON:%s\n", json);
EXPECT_TRUE(json != NULL);
DeleteCredList(cred);
OICFree(json);
EXPECT_TRUE(json != NULL);
OicSecCred_t *cred2 = JSONToCredBin(json);
- EXPECT_TRUE(cred2 == NULL);
+ EXPECT_TRUE(cred2 != NULL);
DeleteCredList(cred1);
DeleteCredList(cred2);
OICFree(json);
OicUuid_t owners[1];
OICStrcpy((char *)owners[0].id, sizeof(owners[0].id), "ownersId21");
- OicUuid_t subject = {0};
+ OicUuid_t subject = {{0}};
OICStrcpy((char *)subject.id, sizeof(subject.id), "subject11");
char privateKey[] = "My private Key11";
privateKey, 1, owners);
printCred(cred);
+ EXPECT_TRUE(NULL != cred);
DeleteCredList(cred);
}
OicUuid_t owners[1];
OICStrcpy((char *)owners[0].id, sizeof(owners[0].id), "ownersId11");
- OicUuid_t subject = {0};
+ OicUuid_t subject = {{0}};
OICStrcpy((char *)subject.id, sizeof(subject.id), "subject11");
char privateKey[] = "My private Key11";
#include "ocserverrequest.h"
#include "oic_string.h"
#include "oic_malloc.h"
+#include "logger.h"
+
+#define TAG "SRM-DOXM"
#ifdef __cplusplus
extern "C" {
#endif
+
//Declare Doxm resource methods for testing
OCStackResult CreateDoxmResource();
OCEntityHandlerResult DoxmEntityHandler (OCEntityHandlerFlag flag,
}
#endif
+
OicSecDoxm_t * getBinDoxm()
{
OicSecDoxm_t * doxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t));
doxm->oxm[0] = OIC_JUST_WORKS;
doxm->oxmSel = OIC_JUST_WORKS;
+ doxm->sct = SYMMETRIC_PAIR_WISE_KEY;
doxm->owned = true;
//TODO: Need more clarification on deviceIDFormat field type.
//doxm.deviceIDFormat = URN;
TEST(DoxmEntityHandlerTest, DoxmEntityHandlerValidRequest)
{
EXPECT_EQ(OC_STACK_INVALID_PARAM, InitDoxmResource());
- char query[] = "oxm=0&owned=false&owner=owner1";
- OCEntityHandlerRequest req = {0};
+ char query[] = "oxm=0;owned=false;owner=owner1";
+ OCEntityHandlerRequest req = OCEntityHandlerRequest();
+ req.method = OC_REST_GET;
+ req.query = OICStrdup(query);
+ EXPECT_EQ(OC_EH_ERROR, DoxmEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
+
+ OICFree(req.query);
+}
+
+TEST(DoxmEntityHandlerTest, DoxmEntityHandlerDeviceIdQuery)
+{
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, InitDoxmResource());
+ char query[] = "deviceid=MjIyMjIyMjIyMjIyMjIyMg==";
+ OCEntityHandlerRequest req = OCEntityHandlerRequest();
req.method = OC_REST_GET;
req.query = OICStrdup(query);
EXPECT_EQ(OC_EH_ERROR, DoxmEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
OicSecDoxm_t * doxm = getBinDoxm();
char * json = BinToDoxmJSON(doxm);
+ OC_LOG_V(INFO, TAG, "BinToDoxmJSON:%s", json);
EXPECT_TRUE(json != NULL);
DeleteDoxmBinData(doxm);
--- /dev/null
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+//Not supported on Arduino due lack of absolute time need to implement iCalendar
+#ifndef WITH_ARDUINO
+
+#include "gtest/gtest.h"
+#include "iotvticalendar.h"
+#include "logger.h"
+
+#define TAG "CALENDAR-UT"
+
+static void printPeriod(IotvtICalPeriod_t *period)
+{
+ if(NULL == period)
+ {
+ return;
+ }
+
+ OC_LOG_V(INFO, TAG, "period->startDateTime.tm_year = %d",period->startDateTime.tm_year);
+ OC_LOG_V(INFO, TAG, "period->startDateTime.tm_mon = %d",period->startDateTime.tm_mon);
+ OC_LOG_V(INFO, TAG, "period->startDateTime.tm_mday = %d",period->startDateTime.tm_mday);
+ OC_LOG_V(INFO, TAG, "period->startDateTime.tm_hour = %d",period->startDateTime.tm_hour);
+ OC_LOG_V(INFO, TAG, "period->startDateTime.tm_min = %d",period->startDateTime.tm_min);
+ OC_LOG_V(INFO, TAG, "period->startDateTime.tm_sec = %d",period->startDateTime.tm_sec);
+
+ OC_LOG_V(INFO, TAG, "period->endDateTime.tm_year = %d",period->endDateTime.tm_year);
+ OC_LOG_V(INFO, TAG, "period->endDateTime.tm_mon = %d",period->endDateTime.tm_mon);
+ OC_LOG_V(INFO, TAG, "period->endDateTime.tm_mday = %d",period->endDateTime.tm_mday);
+ OC_LOG_V(INFO, TAG, "period->endDateTime.tm_hour = %d",period->endDateTime.tm_hour);
+ OC_LOG_V(INFO, TAG, "period->endDateTime.tm_min = %d",period->endDateTime.tm_min);
+ OC_LOG_V(INFO, TAG, "period->startDateTime.tm_sec = %d",period->endDateTime.tm_sec);
+}
+
+
+static void printRecur(IotvtICalRecur_t *recur)
+{
+ OC_LOG_V(INFO, TAG, "recur->freq = %d", recur->freq);
+ OC_LOG_V(INFO, TAG, "recur->until.tm_year = %d", recur->until.tm_year);
+ OC_LOG_V(INFO, TAG, "recur->until.tm_mon = %d", recur->until.tm_mon);
+ OC_LOG_V(INFO, TAG, "recur->until.tm_mday = %d", recur->until.tm_mday);
+
+ if(recur->byDay & SUNDAY)
+ {
+ OC_LOG_V(INFO, TAG, "recur->byDay = %s", "Sunday");
+ }
+ if(recur->byDay & MONDAY)
+ {
+ OC_LOG_V(INFO, TAG, "recur->byDay = %s", "Monday");
+ }
+ if(recur->byDay & TUESDAY)
+ {
+ OC_LOG_V(INFO, TAG, "recur->byDay = %s", "Tuesday");
+ }
+ if(recur->byDay & WEDNESDAY)
+ {
+ OC_LOG_V(INFO, TAG, "recur->byDay = %s", "Wednesday");
+ }
+ if(recur->byDay & THURSDAY)
+ {
+ OC_LOG_V(INFO, TAG, "recur->byDay = %s", "Thursday");
+ }
+ if(recur->byDay & FRIDAY)
+ {
+ OC_LOG_V(INFO, TAG, "recur->byDay = %s", "Friday");
+ }
+ if(recur->byDay & SATURDAY)
+ {
+ OC_LOG_V(INFO, TAG, "recur->byDay = %s", "Saturday");
+ }
+}
+
+
+static void checkValidityOfRequest(char *recurStr, char *periodStr,int startTime, int endTime,
+ int byDay)
+{
+ time_t rt;
+ IotvtICalDateTime_t t1;
+ IotvtICalDateTime_t t2;
+ int isValidWD;
+ IotvtICalResult_t result;
+
+ memset(&t1, 0, sizeof(t1));
+ memset(&t2, 0, sizeof(t2));
+
+ do
+ {
+ rt = time(0);
+ tzset();
+ localtime_r(&rt, &t1);
+
+ result = IsRequestWithinValidTime(periodStr, recurStr);
+
+ rt = time(0);
+ tzset();
+ localtime_r(&rt, &t2);
+
+ OC_LOG_V(INFO, TAG, "t1 = %02d:%02d:%02d", t1.tm_hour, t1.tm_min, t1.tm_sec );
+ OC_LOG_V(INFO, TAG, "t2 = %02d:%02d:%02d", t2.tm_hour, t2.tm_min, t2.tm_sec );
+ }while(t1.tm_hour != t2.tm_hour);
+
+ if(byDay > 0)
+ {
+ isValidWD = (0x1 << t2.tm_wday) & byDay;
+ if(isValidWD && startTime <= t2.tm_hour && endTime > t2.tm_hour)
+ {
+ EXPECT_EQ(IOTVTICAL_VALID_ACCESS, result);
+ }
+ else
+ {
+ EXPECT_EQ(IOTVTICAL_INVALID_ACCESS, result);
+ }
+ }
+ else
+ {
+ if(startTime <= t2.tm_hour && endTime > t2.tm_hour)
+ {
+ EXPECT_EQ(IOTVTICAL_VALID_ACCESS, result);
+ }
+ else
+ {
+ EXPECT_EQ(IOTVTICAL_INVALID_ACCESS, result);
+ }
+ }
+}
+
+//ParsePeriod Tests
+TEST(ParsePeriodTest, ParsePeriodValidDateTime)
+{
+ char periodStr[] = "20150629T153050/20150630T233055";
+ IotvtICalPeriod_t period = IotvtICalPeriod_t();
+ EXPECT_EQ(IOTVTICAL_SUCCESS, ParsePeriod(periodStr,&period));
+ printPeriod(&period);
+}
+
+TEST(ParsePeriodTest, ParsePeriodValidDate)
+{
+ char periodStr[] = "20150629/20150630";
+ IotvtICalPeriod_t period = IotvtICalPeriod_t();
+ EXPECT_EQ(IOTVTICAL_SUCCESS, ParsePeriod(periodStr,&period));
+ printPeriod(&period);
+}
+
+TEST(ParsePeriodTest, ParsePeriodMismatchStartDTEndDT1)
+{
+ char periodStr[] = "20150629T153050/20150630";
+ IotvtICalPeriod_t period = IotvtICalPeriod_t();
+ EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParsePeriodTest, ParsePeriodMismatchStartDTEndDT2)
+{
+ char periodStr[] = "20150629/20150630T203055";
+ IotvtICalPeriod_t period = IotvtICalPeriod_t();
+ EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParsePeriodTest, ParsePeriodInvalidStartDT1)
+{
+ char periodStr[] = "20150629T1530/20150630T203055";
+ IotvtICalPeriod_t period = IotvtICalPeriod_t();
+ EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParsePeriodTest, ParsePeriodInvalidEndtDT2)
+{
+ char periodStr[] = "20150629T153050/20150630203055";
+ IotvtICalPeriod_t period = IotvtICalPeriod_t();
+ EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParsePeriodTest, ParsePeriodInvalidStartD3)
+{
+ char periodStr[] = "201506/20150630";
+ IotvtICalPeriod_t period = IotvtICalPeriod_t();
+ EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParsePeriodTest, ParsePeriodInvalidEndD4)
+{
+ char periodStr[] = "20150629/201530";
+ IotvtICalPeriod_t period = IotvtICalPeriod_t();
+ EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParsePeriodTest, ParsePeriodEndDTBeforeStartDT)
+{
+ char periodStr[] = "20150630T203055/20150629T153050";
+ IotvtICalPeriod_t period = IotvtICalPeriod_t();
+ EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+TEST(ParsePeriodTest, ParsePeriodEndDBeforeStartD)
+{
+ char periodStr[] = "20150630/20150629";
+ IotvtICalPeriod_t period = IotvtICalPeriod_t();
+ EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParseRecurTest, ParseRecurValid1)
+{
+ char recurStr[] = "FREQ=DAILY; UNTIL=20150703; BYDAY=MO, WE, FR";
+ IotvtICalRecur_t recur = IotvtICalRecur_t();
+ EXPECT_EQ(IOTVTICAL_SUCCESS, ParseRecur(recurStr, &recur));
+ printRecur(&recur);
+}
+
+TEST(ParseRecurTest, ParseRecurValid2)
+{
+ char recurStr[] = "FREQ=DAILY";
+ IotvtICalRecur_t recur = IotvtICalRecur_t();
+ EXPECT_EQ(IOTVTICAL_SUCCESS, ParseRecur(recurStr, &recur));
+ printRecur(&recur);
+}
+
+TEST(ParseRecurTest, ParseRecurInValidFreq1)
+{
+ char recurStr[] = "FREQ=WEEKLY; UNTIL=20150703; BYDAY=TU";
+ IotvtICalRecur_t recur = IotvtICalRecur_t();
+ EXPECT_EQ(IOTVTICAL_INVALID_RRULE, ParseRecur(recurStr, &recur));
+}
+
+TEST(ParseRecurTest, ParseRecurInValidFreq2)
+{
+ char recurStr[] = "UNTIL=20150703; BYDAY=TU";
+ IotvtICalRecur_t recur = IotvtICalRecur_t();
+ EXPECT_EQ(IOTVTICAL_INVALID_RRULE, ParseRecur(recurStr, &recur));
+}
+
+TEST(ParseRecurTest, ParseRecurInValidUntil)
+{
+ char recurStr[] = "FREQ=DAILY; UNTIL=20150703T095055; BYDAY=MO, WE, FR";
+ IotvtICalRecur_t recur = IotvtICalRecur_t();
+ EXPECT_EQ(IOTVTICAL_INVALID_RRULE, ParseRecur(recurStr, &recur));
+}
+
+TEST(ParseRecurTest, ParseRecurInValidByday)
+{
+ char recurStr[] = "FREQ=DAILY; UNTIL=20150703; BYDAY=";
+ IotvtICalRecur_t recur = IotvtICalRecur_t();
+ EXPECT_EQ(IOTVTICAL_INVALID_RRULE, ParseRecur(recurStr, &recur));
+}
+
+TEST(IsRequestWithinValidTimeTest, IsRequestWithinValidTimeValidPeriod1)
+{
+ char periodStr[] = "20150630/20551230";
+ EXPECT_EQ(IOTVTICAL_VALID_ACCESS, IsRequestWithinValidTime(periodStr, NULL));
+}
+
+TEST(IsRequestWithinValidTimeTest, IsRequestWithinValidTimeValidPeriodAndRecur1)
+{
+ //Daily on days MO, WE & FR from 6:00:00am to 8:00:00pm until 20551230
+ char recurStr[] = "FREQ=DAILY; UNTIL=20551230; BYDAY=MO, WE, FR";
+ char periodStr[] = "20150630T060000/20150630T200000";
+ int startTime = 6;
+ int endTime = 20;
+ int byDay = MONDAY | WEDNESDAY | FRIDAY;
+
+ checkValidityOfRequest(recurStr, periodStr, startTime, endTime, byDay);
+}
+
+TEST(IsRequestWithinValidTimeTest, IsRequestWithinValidTimeValidPeriodAndRecur2)
+{
+ //Daily forever from 6:00:00am to 8:00:00pm
+ char recurStr[] = "FREQ=DAILY";
+ char periodStr[] = "20150630T060000/20150630T200000";
+ int startTime = 6;
+ int endTime = 20;
+ int byDay = -1;
+
+ checkValidityOfRequest(recurStr, periodStr, startTime, endTime, byDay);
+}
+
+TEST(IsRequestWithinValidTimeTest, IsRequestWithinValidTimeValidPeriodAndRecur3)
+{
+ //Daily until 20551230 from 6:00:00am to 8:00:00pm
+ char recurStr[] = "FREQ=DAILY; UNTIL=20551230";
+ char periodStr[] = "20150630T060000/20150630T200000";
+ int startTime = 6;
+ int endTime = 20;
+ int byDay = -1;
+
+ checkValidityOfRequest(recurStr, periodStr, startTime, endTime, byDay);
+
+}
+
+TEST(IsRequestWithinValidTimeTest, IsRequestWithinValidTimeValidPeriodAndRecur4)
+{
+ //Daily forever on days MO, WE & Fr from 6:00:00am to 8:00:00pm
+ char recurStr[] = "FREQ=DAILY; BYDAY=MO, WE, FR";
+ char periodStr[] = "20150630T060000/20150630T200000";
+ int startTime = 6;
+ int endTime = 20;
+ int byDay = MONDAY | WEDNESDAY | FRIDAY;
+
+ checkValidityOfRequest(recurStr, periodStr, startTime, endTime, byDay);
+
+ }
+
+TEST(IsRequestWithinValidTimeTest, IsRequestWithinValidTimeInValidPeriodAndValidRecur)
+{
+ //Daily forever on days MO, WE & Fr
+ char recurStr[] = "FREQ=DAILY; BYDAY=MO, WE, FR";
+ char periodStr[] = "20150630/20150730";
+
+ EXPECT_EQ(IOTVTICAL_INVALID_ACCESS, IsRequestWithinValidTime(periodStr, recurStr));
+}
+
+#endif
"doxm": {
"oxm": [0],
"oxmsel": 0,
+ "sct": 1,
"owned": false,
"deviceid": "MjIyMjIyMjIyMjIyMjIyMg=="
}
"tm": 48,
"om": 0,
"sm": [3, 1]
- }
+ },
+
+ "amacl": [
+ {
+ "rsrc": ["/a/led", "/a/fan"],
+ "amss": [
+ "NTU1NTU1NTU1NTU1NTU1NQ==",
+ "NjY2NjY2NjY2NjY2NjY2Ng=="
+ ],
+ "ownrs" : [
+ "MjIyMjIyMjIyMjIyMjIyMg=="
+ ]
+ },
+ {
+ "rsrc": ["/b/led", "/b/fan"],
+ "amss": [
+ "NTU1NTU1NTU1NTU1NTU1NQ==",
+ "NjY2NjY2NjY2NjY2NjY2Ng=="
+ ],
+ "ownrs" : [
+ "MjIyMjIyMjIyMjIyMjIyMg=="
+ ]
+ }
+ ],
+
+"svc": [
+ {
+ "svcdid": "NTU1NTU1NTU1NTU1NTU1NQ==",
+ "svct": 1,
+ "ownrs" : [
+ "OTk5OTk5OTk5OTk5OTk5OQ=="
+ ]
+ },
+ {
+ "svcdid": "NjY2NjY2NjY2NjY2NjY2Ng==",
+ "svct": 1,
+ "ownrs" : [
+ "OTk5OTk5OTk5OTk5OTk5OQ=="
+ ]
+ }
+ ]
}
#include "base64.h"
#include "cainterface.h"
#include "secureresourcemanager.h"
+#include "srmtestcommon.h"
#include "ocpayload.h"
#include <unistd.h>
#ifdef __cplusplus
OCEntityHandlerRequest * ehRequest);
char * BinToPstatJSON(const OicSecPstat_t * pstat);
OicSecPstat_t * JSONToPstatBin(const char * jsonStr);
-char* ReadFile(const char* filename);
const char* UNIT_TEST_JSON_FILE_NAME = "oic_unittest.json";
#ifdef __cplusplus
}
--- /dev/null
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "gtest/gtest.h"
+#include "oic_malloc.h"
+#include "ocstack.h"
+
+char* ReadFile(const char* filename)
+{
+
+ FILE *fp = NULL;
+ char *data = NULL;
+ struct stat st;
+ // TODO: Find the location of the executable and concatenate the SVR file name
+ // before opening it.
+ fp = fopen(filename, "r");
+ if (fp)
+ {
+ if (stat(filename, &st) == 0)
+ {
+ data = (char*)OICMalloc(st.st_size);
+ if (data)
+ {
+ if (fread(data, 1, st.st_size, fp) != (size_t)st.st_size)
+ {
+ printf("Error in reading file %s", filename);
+ }
+ }
+ }
+ fclose(fp);
+ }
+ else
+ {
+ printf("Unable to open %s file", filename);
+ }
+
+ return data;
+}
+
+void SetPersistentHandler(OCPersistentStorage *ps, bool set)
+{
+ if (set)
+ {
+ ps->open = fopen;
+ ps->read = fread;
+ ps->write = fwrite;
+ ps->close = fclose;
+ ps->unlink = unlink;
+ }
+ else
+ {
+ memset(ps, 0, sizeof(OCPersistentStorage));
+ }
+ EXPECT_EQ(OC_STACK_OK,
+ OCRegisterPersistentStorageHandler(ps));
+}
--- /dev/null
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef IOTVT_SRM_TEST_COMMON_H
+#define IOTVT_SRM_TEST_COMMON_H
+
+char* ReadFile(const char* filename);
+void SetPersistentHandler(OCPersistentStorage *ps, bool set);
+
+#endif //IOTVT_SRM_TEST_COMMON_H
#include "srmutility.h"
#include "oic_string.h"
-
//ParseRestQuery Tests
TEST(ParseRestQueryTest, ParseRestQueryEmpty)
{
unsigned char query[] = "";
- OicParseQueryIter_t parseIter = {0};
+ OicParseQueryIter_t parseIter = OicParseQueryIter_t();
ParseQueryIterInit(query, &parseIter);
EXPECT_EQ(NULL, GetNextQuery(&parseIter));
}
+
TEST(ParseRestQueryTest, ParseSingleRestQuery)
{
char attr[10], val[10];
unsigned char query[] = "owned=false";
- OicParseQueryIter_t parseIter = {0};
+ OicParseQueryIter_t parseIter = OicParseQueryIter_t();
ParseQueryIterInit(query, &parseIter);
EXPECT_NE((OicParseQueryIter_t *)NULL, GetNextQuery(&parseIter));
OICStrcpyPartial(attr, sizeof(attr), (char *)parseIter.attrPos, parseIter.attrLen);
OICStrcpyPartial(val, sizeof(val), (char *)parseIter.valPos, parseIter.valLen);
printf("\nAttribute: %s value: %s\n\n", attr, val);
-
}
TEST(ParseRestQueryTest, ParseRestMultipleQuery)
{
char attr[10], val[10];
- unsigned char query[] = "oxm=0&owned=true&owner=owner1";
+ unsigned char query[] = "oxm=0;owned=true;owner=owner1";
- OicParseQueryIter_t parseIter = {0};
+ OicParseQueryIter_t parseIter = OicParseQueryIter_t();
ParseQueryIterInit(query, &parseIter);
printf("\n");
while(GetNextQuery(&parseIter))
--- /dev/null
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "gtest/gtest.h"
+#include <pwd.h>
+#include <grp.h>
+#include <linux/limits.h>
+#include <sys/stat.h>
+#include "ocstack.h"
+#include "oic_malloc.h"
+#include "cJSON.h"
+#include "cainterface.h"
+#include "secureresourcemanager.h"
+#include "securevirtualresourcetypes.h"
+#include "srmresourcestrings.h"
+#include "svcresource.h"
+#include "srmtestcommon.h"
+
+using namespace std;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern char * BinToSvcJSON(const OicSecSvc_t * svc);
+extern OicSecSvc_t * JSONToSvcBin(const char * jsonStr);
+extern void DeleteSVCList(OicSecSvc_t* svc);
+#ifdef __cplusplus
+}
+#endif
+
+static const char* JSON_FILE_NAME = "oic_unittest.json";
+
+#define NUM_SVC_IN_JSON_DB (2)
+
+
+// JSON Marshalling Tests
+TEST(SVCResourceTest, JSONMarshallingTests)
+{
+ char *jsonStr1 = ReadFile(JSON_FILE_NAME);
+ if (jsonStr1)
+ {
+ OicSecSvc_t * svc = JSONToSvcBin(jsonStr1);
+ EXPECT_TRUE(NULL != svc);
+
+ int cnt = 0;
+ OicSecSvc_t * tempSvc = svc;
+ while(tempSvc)
+ {
+
+ EXPECT_EQ(tempSvc->svct, ACCESS_MGMT_SERVICE);
+ cnt++;
+ tempSvc = tempSvc->next;
+ }
+ EXPECT_EQ(cnt, NUM_SVC_IN_JSON_DB);
+
+ char * jsonStr2 = BinToSvcJSON(svc);
+ EXPECT_TRUE(NULL != jsonStr2);
+
+ OICFree(jsonStr1);
+ OICFree(jsonStr2);
+ DeleteSVCList(svc);
+ }
+}
+
/** next node in this list.*/
struct ResourceObserver *next;
+
+ /** requested payload encoding format. */
+ OCPayloadFormat acceptFormat;
+
} ResourceObserver;
#ifdef WITH_PRESENCE
uint8_t tokenLength,
OCResource *resHandle,
OCQualityOfService qos,
+ OCPayloadFormat acceptFormat,
const OCDevAddr *devAddr);
/**
#include "octypes.h"
-OCStackResult OCParsePayload(OCPayload** outPayload, const uint8_t* payload, size_t payloadSize);
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+OCStackResult OCParsePayload(OCPayload** outPayload, OCPayloadType type,
+ const uint8_t* payload, size_t payloadSize);
OCStackResult OCConvertPayload(OCPayload* payload, uint8_t** outPayload, size_t* size);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif
/** "/oic/res/d/type" .*/
OC_RESOURCE_TYPES_URI,
-
+#ifdef ROUTING_GATEWAY
+ /** "/oic/gateway" .*/
+ OC_GATEWAY_URI,
+#endif
#ifdef WITH_PRESENCE
/** "/oic/ad" .*/
OC_PRESENCE,
/** The REST method retrieved from received request PDU.*/
OCMethod method;
+ /** Accept format retrieved from the received request PDU. */
+ OCPayloadFormat acceptFormat;
+
/** resourceUrl will be filled in occoap using the path options in received request PDU.*/
char resourceUrl[MAX_URI_LENGTH];
/** payload is retrieved from the payload of the received request PDU.*/
uint8_t payload[1];
+ // WARNING: Do NOT add attributes after payload as they get overwritten
+ // when payload content gets copied over!
+
} OCServerRequest;
/**
* @param tokenLength Request token length.
* @param resourceUrl URL of resource.
* @param reqTotalSize Total size of the request.
+ * @param acceptFormat The format requested for the payload encoding.
* @param devAddr Device Address.
*
* @return
uint8_t * payload, CAToken_t requestToken,
uint8_t tokenLength,
char * resourceUrl, size_t reqTotalSize,
+ OCPayloadFormat acceptFormat,
const OCDevAddr *devAddr);
/**
* OCStackResult
*/
OCStackResult FormOCEntityHandlerRequest(
- OCEntityHandlerRequest *entityHandlerRequest,
- OCRequestHandle request,
- OCMethod method,
- OCDevAddr *endpoint,
- OCResourceHandle resource,
- char *queryBuf,
- uint8_t *payload,
- size_t payloadSize,
- uint8_t numVendorOptions,
- OCHeaderOption *vendorOptions,
- OCObserveAction observeAction,
- OCObservationId observeID);
+ OCEntityHandlerRequest * entityHandlerRequest,
+ OCRequestHandle request,
+ OCMethod method,
+ OCDevAddr *endpoint,
+ OCResourceHandle resource,
+ char * queryBuf,
+ OCPayloadType payloadType,
+ uint8_t * payload,
+ size_t payloadSize,
+ uint8_t numVendorOptions,
+ OCHeaderOption * vendorOptions,
+ OCObserveAction observeAction,
+ OCObservationId observeID);
/**
* Find a server request in the server request list and delete
#include "ocstack.h"
#include "ocstackconfig.h"
#include "occlientcb.h"
-#include <logger.h>
#include <ocrandom.h>
#include "cacommon.h"
#include "cainterface.h"
+#include "securevirtualresourcetypes.h"
#ifdef __cplusplus
extern "C" {
/** The REST method retrieved from received request PDU.*/
OCMethod method;
+ /** the requested payload format. */
+ OCPayloadFormat acceptFormat;
+
/** resourceUrl will be filled in occoap using the path options in received request PDU.*/
char resourceUrl[MAX_URI_LENGTH];
char query[MAX_QUERY_LENGTH];
/** reqJSON is retrieved from the payload of the received request PDU.*/
- uint8_t payload[MAX_REQUEST_LENGTH];
+ uint8_t *payload;
/** qos is indicating if the request is CON or NON.*/
OCQualityOfService qos;
OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16_t coapID,
const CAResponseResult_t responseResult, const CAMessageType_t type,
const uint8_t numOptions, const CAHeaderOption_t *options,
- CAToken_t token, uint8_t tokenLength);
+ CAToken_t token, uint8_t tokenLength, const char *resourceUri);
#ifdef WITH_PRESENCE
*
* @return A uint8_t representation the server instance ID.
*/
-const uint8_t* OCGetServerInstanceID(void);
+const OicUuid_t* OCGetServerInstanceID(void);
/**
* Get a string representation the server instance ID.
OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actionsetName);
-OCStackResult ExtractKeyValueFromRequest(char *request, char **key, char **value);
+OCStackResult ExtractKeyValueFromRequest(OCEntityHandlerRequest *ehRequest, char **key, char **value);
OCStackResult BuildActionSetFromString(OCActionSet **set, char* actiondesc);
OCStackResult
-BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHandlerFlag flag*/,
+BuildCollectionGroupActionCBORResponse(OCMethod method/*OCEntityHandlerFlag flag*/,
OCResource *resource, OCEntityHandlerRequest *ehRequest);
#include <stdbool.h>
#include <inttypes.h>
-#include "logger.h"
#include "octypes.h"
#ifdef WITH_RD
bool OCRepPayloadSetPropString(OCRepPayload* payload, const char* name, const char* value);
bool OCRepPayloadSetPropStringAsOwner(OCRepPayload* payload, const char* name, char* value);
-bool OCRepPayloadGetPropString(const OCRepPayload* payload, const char* name, const char** value);
+bool OCRepPayloadGetPropString(const OCRepPayload* payload, const char* name, char** value);
bool OCRepPayloadSetPropBool(OCRepPayload* payload, const char* name, bool value);
bool OCRepPayloadGetPropBool(const OCRepPayload* payload, const char* name, bool* value);
#ifndef OCSTACK_CONFIG_H_
#define OCSTACK_CONFIG_H_
-/** This would need to be updated in future as we move to support IPv6 and other
- * technologies.
- */
-#define DEV_ADDR_SIZE_MAX (16)
-
-/**
- * Maximum length of the response supported by Server for any REST request.
- * The actual repsonse length is 256 for Arduino and 1024 for other platforms.
- * Note that the stack will add a prefix and suffix to the payload.
- * @code
- * Prefix : {"oic":[
- * Suffix : ]}
- * @endcode
- * They have a combined size of 10 bytes.
- */
-#ifdef WITH_ARDUINO
-#define MAX_RESPONSE_LENGTH (256)
-#else
-#define MAX_RESPONSE_LENGTH (1024)
-#endif
-
-/**
- * Maximum length of the request supported by Client/Server for any REST request.
- */
-#ifdef WITH_ARDUINO
-#define MAX_REQUEST_LENGTH (256)
-#else
-#define MAX_REQUEST_LENGTH (1024)
-#endif
-
/**
* Maximum length of the URI supported by client/server while processing
* REST requests/responses.
/**
* Maximum Length of the vendor specific header option
*/
-#define MAX_HEADER_OPTION_DATA_LENGTH (16)
+#define MAX_HEADER_OPTION_DATA_LENGTH (20)
/**
* Sets the time to live (TTL) for response callback(s).
/** Resource Type.*/
#define OC_RSRVD_RESOURCE_TYPES_URI "/oic/res/types/d"
-
+#ifdef ROUTING_GATEWAY
+/** Gateway URI.*/
+#define OC_RSRVD_GATEWAY_URI "/oic/gateway"
+#endif
#ifdef WITH_PRESENCE
/** Presence URI through which the OIC devices advertise their presence.*/
#ifdef RA_ADAPTER
/**Remote Access over XMPP.*/
- OC_ADAPTER_REMOTE_ACCESS = (1 << 3)
+ OC_ADAPTER_REMOTE_ACCESS = (1 << 3),
+#endif
+
+#ifdef TCP_ADAPTER
+ /** CoAP over TCP.*/
+ OC_ADAPTER_TCP = (1 << 4)
#endif
} OCTransportAdapter;
/** transport modifiers.*/
OCTransportFlags flags;
+ /** for IP.*/
+ uint16_t port;
+
/** address for all adapters.*/
char addr[MAX_ADDR_STR_SIZE];
/** usually zero for default interface.*/
uint32_t interface;
-
- /** for IP.*/
- uint16_t port;
-
- /** secure node identity.*/
- OCIdentity identity;
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+ char routeData[MAX_ADDR_STR_SIZE]; //destination GatewayID:ClientId
+#endif
} OCDevAddr;
/**
/** RFCOMM over Bluetooth EDR.*/
CT_ADAPTER_RFCOMM_BTEDR = (1 << 18),
- #ifdef RA_ADAPTER
+#ifdef RA_ADAPTER
/** Remote Access over XMPP.*/
CT_ADAPTER_REMOTE_ACCESS = (1 << 19),
- #endif
+#endif
+
+#ifdef TCP_ADAPTER
+ /** CoAP over TCP.*/
+ CT_ADAPTER_TCP = (1 << 20),
+#endif
/** Insecure transport is the default (subject to change).*/
} OCMethod;
/**
+ * Formats for payload encoding.
+ */
+typedef enum
+{
+ OC_FORMAT_CBOR,
+ OC_FORMAT_UNDEFINED,
+ OC_FORMAT_UNSUPPORTED,
+} OCPayloadFormat;
+
+/**
* Host Mode of Operation.
*/
typedef enum
{
OC_CLIENT = 0,
OC_SERVER,
- OC_CLIENT_SERVER
+ OC_CLIENT_SERVER,
+ OC_GATEWAY /**< Client server mode along with routing capabilities.*/
} OCMode;
/**
/** Request is not authorized by Resource Server. */
OC_STACK_UNAUTHORIZED_REQ,
+ /** Error code from PDM */
+ OC_STACK_PDM_IS_NOT_INITIALIZED,
+ OC_STACK_DUPLICATE_UUID,
+ OC_STACK_INCONSISTENT_DB,
+
/** Insert all new error codes here!.*/
#ifdef WITH_PRESENCE
OC_STACK_PRESENCE_STOPPED = 128,
/** the payload from the request PDU.*/
OCPayload *payload;
-
} OCEntityHandlerRequest;
/** backward compatibility.*/
OCConnectivityType connType;
+ /** the security identity of the remote server.*/
+ OCIdentity identity;
+
/** the is the result of our stack, OCStackResult should contain coap/other error codes.*/
OCStackResult result;
#ifndef PAYLOAD_LOGGING_H_
#define PAYLOAD_LOGGING_H_
+#include "logger.h"
+#ifdef __TIZEN__
+#include <dlog.h>
+#endif
+
#ifdef __cplusplus
extern "C"
{
#endif
+// PL_TAG is made as generic predefined tag because of build problems in arduino for using logging
+#define PL_TAG "PayloadLog"
+
#ifdef TB_LOG
- #define OC_LOG_PAYLOAD(level, tag, payload) OCPayloadLog((level),(tag),(payload))
+ #define OC_LOG_PAYLOAD(level, payload) OCPayloadLog((level),(payload))
#define UUID_SIZE (16)
#define UUID_LENGTH (37)
const char *convertTriggerEnumToString(OCPresenceTrigger trigger);
OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr);
-static inline void OCPayloadLogRep(LogLevel level, const char* tag, OCRepPayload* payload)
+static inline void OCPayloadLogRep(LogLevel level, OCRepPayload* payload)
{
- OC_LOG(level, tag, PCF("Payload Type: Representation"));
+ OC_LOG(level, (PL_TAG), "Payload Type: Representation");
OCRepPayload* rep = payload;
int i = 1;
while(rep)
{
- OC_LOG_V(level, tag, "\tResource #%d", i);
- OC_LOG_V(level, tag, "\tURI:%s", rep->uri);
- OC_LOG(level, tag, PCF("\tResource Types:"));
+ OC_LOG_V(level, PL_TAG, "\tResource #%d", i);
+ OC_LOG_V(level, PL_TAG, "\tURI:%s", rep->uri);
+ OC_LOG(level, PL_TAG, "\tResource Types:");
OCStringLL* strll = rep->types;
while(strll)
{
- OC_LOG_V(level, tag, "\t\t%s", strll->value);
+ OC_LOG_V(level, PL_TAG, "\t\t%s", strll->value);
strll = strll->next;
}
- OC_LOG(level, tag, PCF("\tInterfaces:"));
+ OC_LOG(level, PL_TAG, "\tInterfaces:");
strll = rep->interfaces;
while(strll)
{
- OC_LOG_V(level, tag, "\t\t%s", strll->value);
+ OC_LOG_V(level, PL_TAG, "\t\t%s", strll->value);
strll = strll->next;
}
// TODO Finish Logging: Values
OCRepPayloadValue* val = rep->values;
- OC_LOG(level, tag, PCF("\tValues:"));
+ OC_LOG(level, PL_TAG, "\tValues:");
while(val)
{
switch(val->type)
{
case OCREP_PROP_NULL:
- OC_LOG_V(level, tag, "\t\t%s: NULL", val->name);
+ OC_LOG_V(level, PL_TAG, "\t\t%s: NULL", val->name);
break;
case OCREP_PROP_INT:
- OC_LOG_V(level, tag, "\t\t%s(int):%lld", val->name, val->i);
+ OC_LOG_V(level, PL_TAG, "\t\t%s(int):%lld", val->name, val->i);
break;
case OCREP_PROP_DOUBLE:
- OC_LOG_V(level, tag, "\t\t%s(double):%f", val->name, val->d);
+ OC_LOG_V(level, PL_TAG, "\t\t%s(double):%f", val->name, val->d);
break;
case OCREP_PROP_BOOL:
- OC_LOG_V(level, tag, "\t\t%s(bool):%s", val->name, val->b ? "true" : "false");
+ OC_LOG_V(level, PL_TAG, "\t\t%s(bool):%s", val->name, val->b ? "true" : "false");
break;
case OCREP_PROP_STRING:
- OC_LOG_V(level, tag, "\t\t%s(string):%s", val->name, val->str);
+ OC_LOG_V(level, PL_TAG, "\t\t%s(string):%s", val->name, val->str);
break;
case OCREP_PROP_OBJECT:
// Note: Only prints the URI (if available), to print further, you'll
// need to dig into the object better!
- OC_LOG_V(level, tag, "\t\t%s(OCRep):%s", val->name, val->obj->uri);
+ OC_LOG_V(level, PL_TAG, "\t\t%s(OCRep):%s", val->name, val->obj->uri);
break;
case OCREP_PROP_ARRAY:
switch(val->arr.type)
{
case OCREP_PROP_INT:
- OC_LOG_V(level, tag, "\t\t%s(int array):%lld x %lld x %lld",
+ OC_LOG_V(level, PL_TAG, "\t\t%s(int array):%lld x %lld x %lld",
val->name,
val->arr.dimensions[0], val->arr.dimensions[1],
val->arr.dimensions[2]);
break;
case OCREP_PROP_DOUBLE:
- OC_LOG_V(level, tag, "\t\t%s(double array):%lld x %lld x %lld",
+ OC_LOG_V(level, PL_TAG, "\t\t%s(double array):%lld x %lld x %lld",
val->name,
val->arr.dimensions[0], val->arr.dimensions[1],
val->arr.dimensions[2]);
break;
case OCREP_PROP_BOOL:
- OC_LOG_V(level, tag, "\t\t%s(bool array):%lld x %lld x %lld",
+ OC_LOG_V(level, PL_TAG, "\t\t%s(bool array):%lld x %lld x %lld",
val->name,
val->arr.dimensions[0], val->arr.dimensions[1],
val->arr.dimensions[2]);
break;
case OCREP_PROP_STRING:
- OC_LOG_V(level, tag, "\t\t%s(string array):%lld x %lld x %lld",
+ OC_LOG_V(level, PL_TAG, "\t\t%s(string array):%lld x %lld x %lld",
val->name,
val->arr.dimensions[0], val->arr.dimensions[1],
val->arr.dimensions[2]);
break;
case OCREP_PROP_OBJECT:
- OC_LOG_V(level, tag, "\t\t%s(OCRep array):%lld x %lld x %lld",
+ OC_LOG_V(level, PL_TAG, "\t\t%s(OCRep array):%lld x %lld x %lld",
val->name,
val->arr.dimensions[0], val->arr.dimensions[1],
val->arr.dimensions[2]);
break;
default:
- OC_LOG_V(ERROR, tag, "\t\t%s <-- Unknown/unsupported array type!",
+ OC_LOG_V(ERROR, PL_TAG, "\t\t%s <-- Unknown/unsupported array type!",
val->name);
break;
}
break;
default:
- OC_LOG_V(ERROR, tag, "\t\t%s <-- Unknown type!", val->name);
+ OC_LOG_V(ERROR, PL_TAG, "\t\t%s <-- Unknown type!", val->name);
break;
}
val = val -> next;
}
-static inline void OCPayloadLogDiscovery(LogLevel level, const char* tag,
- OCDiscoveryPayload* payload)
+static inline void OCPayloadLogDiscovery(LogLevel level, OCDiscoveryPayload* payload)
{
- OC_LOG(level, tag, PCF("Payload Type: Discovery"));
+ OC_LOG(level, PL_TAG, "Payload Type: Discovery");
int i = 1;
if(!payload->resources)
{
- OC_LOG(level, tag, PCF("\tNO Resources"));
+ OC_LOG(level, PL_TAG, "\tNO Resources");
return;
}
while(res)
{
- OC_LOG_V(level, tag, "\tResource #%d", i);
- OC_LOG_V(level, tag, "\tURI:%s", res->uri);
- OC_LOG(level, tag, PCF("\tSID:"));
- OC_LOG_BUFFER(level, tag, res->sid, UUID_SIZE);
- OC_LOG(level, tag, PCF("\tResource Types:"));
+ OC_LOG_V(level, PL_TAG, "\tResource #%d", i);
+ OC_LOG_V(level, PL_TAG, "\tURI:%s", res->uri);
+ OC_LOG(level, PL_TAG, "\tSID:");
+ OC_LOG_BUFFER(level, PL_TAG, res->sid, UUID_SIZE);
+ OC_LOG(level, PL_TAG, "\tResource Types:");
OCStringLL* strll = res->types;
while(strll)
{
- OC_LOG_V(level, tag, "\t\t%s", strll->value);
+ OC_LOG_V(level, PL_TAG, "\t\t%s", strll->value);
strll = strll->next;
}
- OC_LOG(level, tag, PCF("\tInterfaces:"));
+ OC_LOG(level, PL_TAG, "\tInterfaces:");
strll = res->interfaces;
while(strll)
{
- OC_LOG_V(level, tag, "\t\t%s", strll->value);
+ OC_LOG_V(level, PL_TAG, "\t\t%s", strll->value);
strll = strll->next;
}
- OC_LOG_V(level, tag, "\tBitmap: %u", res->bitmap);
- OC_LOG_V(level, tag, "\tSecure?: %s", res->secure ? "true" : "false");
- OC_LOG_V(level, tag, "\tPort: %u", res->port);
- OC_LOG(level, tag, PCF(""));
+ OC_LOG_V(level, PL_TAG, "\tBitmap: %u", res->bitmap);
+ OC_LOG_V(level, PL_TAG, "\tSecure?: %s", res->secure ? "true" : "false");
+ OC_LOG_V(level, PL_TAG, "\tPort: %u", res->port);
+ OC_LOG(level, PL_TAG, "");
res = res->next;
++i;
}
}
-static inline void OCPayloadLogDevice(LogLevel level, const char* tag, OCDevicePayload* payload)
+static inline void OCPayloadLogDevice(LogLevel level, OCDevicePayload* payload)
{
- OC_LOG(level, tag, PCF("Payload Type: Device"));
- OC_LOG_V(level, tag, "\tURI:%s", payload->uri);
- OC_LOG(level, tag, PCF("\tSID:"));
- OC_LOG_BUFFER(level, tag, payload->sid, UUID_SIZE);
- OC_LOG_V(level, tag, "\tDevice Name:%s", payload->deviceName);
- OC_LOG_V(level, tag, "\tSpec Version%s", payload->specVersion);
- OC_LOG_V(level, tag, "\tData Model Version:%s", payload->dataModelVersion);
+ OC_LOG(level, PL_TAG, "Payload Type: Device");
+ OC_LOG_V(level, PL_TAG, "\tURI:%s", payload->uri);
+ OC_LOG(level, PL_TAG, "\tSID:");
+ OC_LOG_BUFFER(level, PL_TAG, payload->sid, UUID_SIZE);
+ OC_LOG_V(level, PL_TAG, "\tDevice Name:%s", payload->deviceName);
+ OC_LOG_V(level, PL_TAG, "\tSpec Version%s", payload->specVersion);
+ OC_LOG_V(level, PL_TAG, "\tData Model Version:%s", payload->dataModelVersion);
}
-static inline void OCPayloadLogPlatform(LogLevel level, const char* tag, OCPlatformPayload* payload)
+static inline void OCPayloadLogPlatform(LogLevel level, OCPlatformPayload* payload)
{
- OC_LOG(level, tag, PCF("Payload Type: Platform"));
- OC_LOG_V(level, tag, "\tURI:%s", payload->uri);
- OC_LOG_V(level, tag, "\tPlatform ID:%s", payload->info.platformID);
- OC_LOG_V(level, tag, "\tMfg Name:%s", payload->info.manufacturerName);
- OC_LOG_V(level, tag, "\tMfg URL:%s", payload->info.manufacturerUrl);
- OC_LOG_V(level, tag, "\tModel Number:%s", payload->info.modelNumber);
- OC_LOG_V(level, tag, "\tDate of Mfg:%s", payload->info.dateOfManufacture);
- OC_LOG_V(level, tag, "\tPlatform Version:%s", payload->info.platformVersion);
- OC_LOG_V(level, tag, "\tOS Version:%s", payload->info.operatingSystemVersion);
- OC_LOG_V(level, tag, "\tHardware Version:%s", payload->info.hardwareVersion);
- OC_LOG_V(level, tag, "\tFirmware Version:%s", payload->info.firmwareVersion);
- OC_LOG_V(level, tag, "\tSupport URL:%s", payload->info.supportUrl);
- OC_LOG_V(level, tag, "\tSystem Time:%s", payload->info.systemTime);
+ OC_LOG(level, PL_TAG, "Payload Type: Platform");
+ OC_LOG_V(level, PL_TAG, "\tURI:%s", payload->uri);
+ OC_LOG_V(level, PL_TAG, "\tPlatform ID:%s", payload->info.platformID);
+ OC_LOG_V(level, PL_TAG, "\tMfg Name:%s", payload->info.manufacturerName);
+ OC_LOG_V(level, PL_TAG, "\tMfg URL:%s", payload->info.manufacturerUrl);
+ OC_LOG_V(level, PL_TAG, "\tModel Number:%s", payload->info.modelNumber);
+ OC_LOG_V(level, PL_TAG, "\tDate of Mfg:%s", payload->info.dateOfManufacture);
+ OC_LOG_V(level, PL_TAG, "\tPlatform Version:%s", payload->info.platformVersion);
+ OC_LOG_V(level, PL_TAG, "\tOS Version:%s", payload->info.operatingSystemVersion);
+ OC_LOG_V(level, PL_TAG, "\tHardware Version:%s", payload->info.hardwareVersion);
+ OC_LOG_V(level, PL_TAG, "\tFirmware Version:%s", payload->info.firmwareVersion);
+ OC_LOG_V(level, PL_TAG, "\tSupport URL:%s", payload->info.supportUrl);
+ OC_LOG_V(level, PL_TAG, "\tSystem Time:%s", payload->info.systemTime);
}
-static inline void OCPayloadLogPresence(LogLevel level, const char* tag, OCPresencePayload* payload)
+static inline void OCPayloadLogPresence(LogLevel level, OCPresencePayload* payload)
{
- OC_LOG(level, tag, PCF("Payload Type: Presence"));
- OC_LOG_V(level, tag, "\tSequence Number:%u", payload->sequenceNumber);
- OC_LOG_V(level, tag, "\tMax Age:%d", payload->maxAge);
- OC_LOG_V(level, tag, "\tTrigger:%s", convertTriggerEnumToString(payload->trigger));
- OC_LOG_V(level, tag, "\tResource Type:%s", payload->resourceType);
+ OC_LOG(level, PL_TAG, "Payload Type: Presence");
+ OC_LOG_V(level, PL_TAG, "\tSequence Number:%u", payload->sequenceNumber);
+ OC_LOG_V(level, PL_TAG, "\tMax Age:%d", payload->maxAge);
+ OC_LOG_V(level, PL_TAG, "\tTrigger:%s", convertTriggerEnumToString(payload->trigger));
+ OC_LOG_V(level, PL_TAG, "\tResource Type:%s", payload->resourceType);
}
-static inline void OCPayloadLogSecurity(LogLevel level, const char* tag,
- OCSecurityPayload* payload)
+static inline void OCPayloadLogSecurity(LogLevel level, OCSecurityPayload* payload)
{
- OC_LOG(level, tag, PCF("Payload Type: Security"));
- OC_LOG_V(level, tag, "\tSecurity Data: %s", payload->securityData);
+ OC_LOG(level, PL_TAG, "Payload Type: Security");
+ OC_LOG_V(level, PL_TAG, "\tSecurity Data: %s", payload->securityData);
}
-static inline void OCPayloadLog(LogLevel level, const char* tag, OCPayload* payload)
+static inline void OCPayloadLog(LogLevel level, OCPayload* payload)
{
if(!payload)
{
- OC_LOG(level, tag, PCF("NULL Payload"));
+ OC_LOG(level, PL_TAG, "NULL Payload");
return;
}
switch(payload->type)
{
case PAYLOAD_TYPE_REPRESENTATION:
- OCPayloadLogRep(level, tag, (OCRepPayload*)payload);
+ OCPayloadLogRep(level, (OCRepPayload*)payload);
break;
case PAYLOAD_TYPE_DISCOVERY:
- OCPayloadLogDiscovery(level, tag, (OCDiscoveryPayload*)payload);
+ OCPayloadLogDiscovery(level, (OCDiscoveryPayload*)payload);
break;
case PAYLOAD_TYPE_DEVICE:
- OCPayloadLogDevice(level, tag, (OCDevicePayload*)payload);
+ OCPayloadLogDevice(level, (OCDevicePayload*)payload);
break;
case PAYLOAD_TYPE_PLATFORM:
- OCPayloadLogPlatform(level, tag, (OCPlatformPayload*)payload);
+ OCPayloadLogPlatform(level, (OCPlatformPayload*)payload);
break;
case PAYLOAD_TYPE_PRESENCE:
- OCPayloadLogPresence(level, tag, (OCPresencePayload*)payload);
+ OCPayloadLogPresence(level, (OCPresencePayload*)payload);
break;
case PAYLOAD_TYPE_SECURITY:
- OCPayloadLogSecurity(level, tag, (OCSecurityPayload*)payload);
+ OCPayloadLogSecurity(level, (OCSecurityPayload*)payload);
break;
#ifdef WITH_RD
case PAYLOAD_TYPE_RD:
break;
#endif
default:
- OC_LOG_V(level, tag, "Unknown Payload Type: %d", payload->type);
+ OC_LOG_V(level, PL_TAG, "Unknown Payload Type: %d", payload->type);
break;
}
}
#else
- #define OC_LOG_PAYLOAD(level, tag, payload)
+ #define OC_LOG_PAYLOAD(level, payload)
#endif
#ifdef __cplusplus
Import('env')
+transport = env.get('TARGET_TRANSPORT')
+if 'BLE' in transport:
+ # Only supported for ethernet and WiFi.
+ Return()
+
arduino_simplecs_env = env.Clone()
######################################################################
# Build flags
const char *getResult(OCStackResult result);
-PROGMEM const char TAG[] = "ArduinoServer";
+#define TAG "ArduinoServer"
int gLightUnderObservation = 0;
void createLightResource();
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD)
{
- OC_LOG(ERROR, TAG, PCF("WiFi shield not present"));
+ OC_LOG(ERROR, TAG, ("WiFi shield not present"));
return -1;
}
OC_LOG_V(INFO, TAG, "WiFi Shield Firmware version %s", fwVersion);
if ( strncmp(fwVersion, ARDUINO_WIFI_SHIELD_UDP_FW_VER, sizeof(ARDUINO_WIFI_SHIELD_UDP_FW_VER)) !=0 )
{
- OC_LOG(DEBUG, TAG, PCF("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
+ OC_LOG(DEBUG, TAG, ("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
return -1;
}
// wait 10 seconds for connection:
delay(10000);
}
- OC_LOG(DEBUG, TAG, PCF("Connected to wifi"));
+ OC_LOG(DEBUG, TAG, ("Connected to wifi"));
IPAddress ip = WiFi.localIP();
OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
OCRepPayload* payload = OCRepPayloadCreate();
if(!payload)
{
- OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+ OC_LOG(ERROR, TAG, ("Failed to allocate Payload"));
return OC_EH_ERROR;
}
if(entityHandlerRequest && (flag & OC_REQUEST_FLAG))
{
- OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+ OC_LOG (INFO, TAG, ("Flag includes OC_REQUEST_FLAG"));
if(OC_REST_GET == entityHandlerRequest->method)
{
{
if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
{
- OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
+ OC_LOG (INFO, TAG, ("Received OC_OBSERVE_REGISTER from client"));
gLightUnderObservation = 1;
}
else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
{
- OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
+ OC_LOG (INFO, TAG, ("Received OC_OBSERVE_DEREGISTER from client"));
gLightUnderObservation = 0;
}
}
// Add your initialization code here
// Note : This will initialize Serial port on Arduino at 115200 bauds
OC_LOG_INIT();
- OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
+ OC_LOG(DEBUG, TAG, ("OCServer is starting..."));
// Connect to Ethernet or WiFi network
if (ConnectToNetwork() != 0)
{
- OC_LOG(ERROR, TAG, PCF("Unable to connect to network"));
+ OC_LOG(ERROR, TAG, ("Unable to connect to network"));
return;
}
// Initialize the OC Stack in Server mode
if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCStack init error"));
+ OC_LOG(ERROR, TAG, ("OCStack init error"));
return;
}
// Give CPU cycles to OCStack to perform send/recv and other OCStack stuff
if (OCProcess() != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCStack process error"));
+ OC_LOG(ERROR, TAG, ("OCStack process error"));
return;
}
ChangeLightRepresentation(NULL);
# Source files and Targets
######################################################################
ocserver = samples_env.Program('ocserver', ['ocserver.cpp', 'common.cpp'])
+if samples_env.get('ROUTING') == 'GW':
+ ocrouting = samples_env.Program('ocrouting', ['ocrouting.cpp', 'common.cpp'])
occlient = samples_env.Program('occlient', ['occlient.cpp', 'common.cpp'])
ocserverslow = samples_env.Program('ocserverslow', ['ocserverslow.cpp', 'common.cpp'])
occlientslow = samples_env.Program('occlientslow', ['occlientslow.cpp', 'common.cpp'])
#include "ocpayload.h"
#include "payload_logging.h"
+#ifdef ROUTING_GATEWAY
+/**
+ * Maximum number of gateway requests to form the routing table.
+ */
+#define MAX_NUM_GATEWAY_REQUEST 20
+
+/**
+ * Sleep duration after every OCProcess().
+ */
+#define SLEEP_DURATION 100000
+#endif
// Tracking user input
-static int UNICAST_DISCOVERY = 0;
-static int TEST_CASE = 0;
-static int CONNECTIVITY = 0;
+static int UnicastDiscovery = 0;
+static int TestCase = 0;
+static int Connectivity = 0;
-static const char * UNICAST_DEVICE_DISCOVERY_QUERY = "coap://%s/oic/d";
-static const char * MULTICAST_DEVICE_DISCOVERY_QUERY = "/oic/d";
-static const char * UNICAST_PLATFORM_DISCOVERY_QUERY = "coap://%s/oic/p";
-static const char * MULTICAST_PLATFORM_DISCOVERY_QUERY = "/oic/p";
+static const char *DEVICE_DISCOVERY_QUERY = "%s/oic/d";
+static const char *PLATFORM_DISCOVERY_QUERY = "%s/oic/p";
+static const char *RESOURCE_DISCOVERY_QUERY = "%s/oic/res";
-static const char * UNICAST_RESOURCE_DISCOVERY_QUERY = "coap://%s/oic/res";
-static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oic/res";
//The following variable determines the interface protocol (IPv4, IPv6, etc)
-//to be used for sending unicast messages. Default set to IPv4.
-static OCConnectivityType OC_CONNTYPE = CT_ADAPTER_IP;
-static std::string coapServerIP = "255.255.255.255";
-static std::string coapServerPort = "5683";
+//to be used for sending unicast messages. Default set to IP dual stack.
+static OCConnectivityType ConnType = CT_ADAPTER_IP;
+static OCDevAddr serverAddr;
+static char discoveryAddr[100];
static std::string coapServerResource = "/a/light";
-// Size to hold IPV4_ADDRESS:PORT
-static const int IPV4_ADDR_SIZE = 24;
-//Use ipv4addr for both InitDiscovery and InitPlatformOrDeviceDiscovery
-char ipv4addr[IPV4_ADDR_SIZE];
+
void StripNewLineChar(char* str);
// The handle for the observe registration
{
OCRepPayload* payload = OCRepPayloadCreate();
- if(!payload)
+ if (!payload)
{
std::cout << "Failed to create put payload object"<<std::endl;
std::exit(1);
}
OCStackResult InvokeOCDoResource(std::ostringstream &query,
+ OCDevAddr *remoteAddr,
OCMethod method,
OCQualityOfService qos,
OCClientResponseHandler cb,
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- ret = OCDoResource(&handle, method, query.str().c_str(), 0,
+ ret = OCDoResource(&handle, method, query.str().c_str(), remoteAddr,
(method == OC_REST_PUT) ? putPayload() : NULL,
- (OC_CONNTYPE), qos, &cbData, options, numOptions);
+ (ConnType), qos, &cbData, options, numOptions);
if (ret != OC_STACK_OK)
{
OCStackApplicationResult putReqCB(void* ctx, OCDoHandle /*handle*/,
OCClientResponse * clientResponse)
{
- if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
+ if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
}
- if(clientResponse)
+ if (clientResponse)
{
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- OC_LOG(INFO, TAG, PCF("=============> Put Response"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("=============> Put Response"));
}
else
{
OCStackApplicationResult postReqCB(void *ctx, OCDoHandle /*handle*/,
OCClientResponse *clientResponse)
{
- if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
+ if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully");
}
- if(clientResponse)
+ if (clientResponse)
{
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- OC_LOG(INFO, TAG, PCF("=============> Post Response"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("=============> Post Response"));
}
else
{
OCDoHandle /*handle*/,
OCClientResponse *clientResponse)
{
- if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
+ if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for DELETE recvd successfully");
}
- if(clientResponse)
+ if (clientResponse)
{
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- OC_LOG(INFO, TAG, PCF("=============> Delete Response"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("=============> Delete Response"));
}
else
{
OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/,
OCClientResponse * clientResponse)
{
- if(clientResponse == NULL)
+ if (clientResponse == NULL)
{
OC_LOG(INFO, TAG, "getReqCB received NULL clientResponse");
return OC_STACK_DELETE_TRANSACTION;
}
- if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
+ if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
}
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- OC_LOG(INFO, TAG, PCF("=============> Get Response"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("=============> Get Response"));
- if(clientResponse->numRcvdVendorSpecificHeaderOptions > 0)
+ if (clientResponse->numRcvdVendorSpecificHeaderOptions > 0)
{
OC_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)
+ if (((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
{
OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
((OCHeaderOption)rcvdOptions[i]).optionID );
OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle /*handle*/,
OCClientResponse * clientResponse)
{
- if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
+ if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for OBS query recvd successfully");
}
- if(clientResponse)
+ if (clientResponse)
{
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
OC_LOG_V(INFO, TAG, "Callback Context for OBSERVE notification recvd successfully %d",
gNumObserveNotifies);
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- OC_LOG(INFO, TAG, PCF("=============> Obs Response"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("=============> Obs Response"));
gNumObserveNotifies++;
if (gNumObserveNotifies == 15) //large number to test observing in DELETE case.
{
- if(TEST_CASE == TEST_OBS_REQ_NON || TEST_CASE == TEST_OBS_REQ_CON)
+ if (TestCase == TEST_OBS_REQ_NON || TestCase == TEST_OBS_REQ_CON)
{
if (OCCancel (gObserveDoHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK)
{
}
return OC_STACK_DELETE_TRANSACTION;
}
- else if(TEST_CASE == TEST_OBS_REQ_NON_CANCEL_IMM)
+ else if (TestCase == TEST_OBS_REQ_NON_CANCEL_IMM)
{
if (OCCancel (gObserveDoHandle, OC_HIGH_QOS, NULL, 0) != OC_STACK_OK)
{
}
}
}
- if(clientResponse->sequenceNumber == OC_OBSERVE_REGISTER)
+ if (clientResponse->sequenceNumber == OC_OBSERVE_REGISTER)
{
OC_LOG(INFO, TAG, "This also serves as a registration confirmation");
}
- else if(clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER)
+ else if (clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER)
{
OC_LOG(INFO, TAG, "This also serves as a deregistration confirmation");
return OC_STACK_DELETE_TRANSACTION;
}
- else if(clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION)
+ else if (clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION)
{
OC_LOG(INFO, TAG, "This also tells you that registration/deregistration failed");
return OC_STACK_DELETE_TRANSACTION;
if (clientResponse)
{
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
- OC_LOG_V(INFO, TAG, "NONCE NUMBER: %u", clientResponse->sequenceNumber);
OC_LOG_V(INFO, TAG, "Callback Context for Presence notification recvd successfully %d",
gNumPresenceNotifies);
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- OC_LOG(INFO, TAG, PCF("=============> Presence Response"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("=============> Presence Response"));
gNumPresenceNotifies++;
if (gNumPresenceNotifies == 20)
{
// This is a function called back when a device is discovered
OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/,
- OCClientResponse * clientResponse)
+ OCClientResponse * clientResponse)
{
if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
{
"Device =============> Discovered @ %s:%d",
clientResponse->devAddr.addr,
clientResponse->devAddr.port);
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
- OC_CONNTYPE = clientResponse->connType;
+ ConnType = clientResponse->connType;
+ serverAddr = clientResponse->devAddr;
parseClientResponse(clientResponse);
- switch(TEST_CASE)
+ switch(TestCase)
{
case TEST_GET_REQ_NON:
InitGetRequest(OC_LOW_QOS, 0, 0);
return OC_STACK_KEEP_TRANSACTION;
}
-OCStackApplicationResult PlatformDiscoveryReqCB (void* ctx,
- OCDoHandle /*handle*/,
- OCClientResponse * clientResponse)
+OCStackApplicationResult PlatformDiscoveryReqCB(void* ctx,
+ OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for Platform DISCOVER query recvd successfully");
}
- if(clientResponse)
+ if (clientResponse)
{
- OC_LOG(INFO, TAG, PCF("Discovery Response:"));
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("Discovery Response:"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
}
else
{
OC_LOG_V(INFO, TAG, "PlatformDiscoveryReqCB received Null clientResponse");
}
- return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
+ return (UnicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
}
-OCStackApplicationResult DeviceDiscoveryReqCB (void* ctx, OCDoHandle /*handle*/,
- OCClientResponse * clientResponse)
+OCStackApplicationResult DeviceDiscoveryReqCB(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for Device DISCOVER query recvd successfully");
}
- if(clientResponse)
+ if (clientResponse)
{
- OC_LOG(INFO, TAG, PCF("Discovery Response:"));
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("Discovery Response:"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
}
else
{
OC_LOG_V(INFO, TAG, "PlatformDiscoveryReqCB received Null clientResponse");
}
- return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
+ return (UnicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
}
#ifdef WITH_PRESENCE
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
std::ostringstream query;
std::ostringstream querySuffix;
- query << "coap://" << coapServerIP << ":" << coapServerPort << OC_RSRVD_PRESENCE_URI;
- if(TEST_CASE == TEST_OBS_PRESENCE)
+ query << OC_RSRVD_PRESENCE_URI;
+ if (TestCase == TEST_OBS_PRESENCE)
{
- result = InvokeOCDoResource(query, OC_REST_PRESENCE, OC_LOW_QOS,
- presenceCB, NULL, 0);
+ result = InvokeOCDoResource(query, &serverAddr, OC_REST_PRESENCE,
+ OC_LOW_QOS, presenceCB, NULL, 0);
}
- if(TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTER || TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTERS)
+ if (TestCase == TEST_OBS_PRESENCE_WITH_FILTER || TestCase == TEST_OBS_PRESENCE_WITH_FILTERS)
{
querySuffix.str("");
querySuffix << query.str() << "?rt=core.led";
- result = InvokeOCDoResource(querySuffix, OC_REST_PRESENCE, OC_LOW_QOS,
- presenceCB, NULL, 0);
+ result = InvokeOCDoResource(querySuffix, &serverAddr, OC_REST_PRESENCE,
+ OC_LOW_QOS, presenceCB, NULL, 0);
}
- if(TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTERS)
+ if (TestCase == TEST_OBS_PRESENCE_WITH_FILTERS)
{
- if(result == OC_STACK_OK)
+ if (result == OC_STACK_OK)
{
querySuffix.str("");
querySuffix << query.str() << "?rt=core.fan";
- result = InvokeOCDoResource(querySuffix, OC_REST_PRESENCE, OC_LOW_QOS,
+ result = InvokeOCDoResource(querySuffix, &serverAddr, OC_REST_PRESENCE, OC_LOW_QOS,
presenceCB, NULL, 0);
}
}
- if(TEST_CASE == TEST_OBS_MULTICAST_PRESENCE)
+ if (TestCase == TEST_OBS_MULTICAST_PRESENCE)
{
- if(result == OC_STACK_OK)
+ if (result == OC_STACK_OK)
{
std::ostringstream multicastPresenceQuery;
multicastPresenceQuery.str("");
multicastPresenceQuery << "coap://" << OC_MULTICAST_PREFIX << OC_RSRVD_PRESENCE_URI;
- result = InvokeOCDoResource(multicastPresenceQuery, OC_REST_PRESENCE, OC_LOW_QOS,
+ result = InvokeOCDoResource(multicastPresenceQuery, &serverAddr, OC_REST_PRESENCE, OC_LOW_QOS,
presenceCB, NULL, 0);
}
}
{
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
std::ostringstream query;
- query << "coap://" << coapServerIP << ":" << coapServerPort << "/SomeUnknownResource";
- return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
+ query << "/SomeUnknownResource";
+ return (InvokeOCDoResource(query, &serverAddr, OC_REST_GET, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
getReqCB, NULL, 0));
}
{
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
std::ostringstream query;
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
- return (InvokeOCDoResource(query,
- OC_REST_OBSERVE, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, obsReqCB, NULL, 0));
+ query << coapServerResource;
+ return (InvokeOCDoResource(query, &serverAddr, OC_REST_OBSERVE,
+ (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, obsReqCB, NULL, 0));
}
int InitPutRequest(OCQualityOfService qos)
{
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
std::ostringstream query;
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
- return (InvokeOCDoResource(query, OC_REST_PUT, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
+ query << coapServerResource;
+ return (InvokeOCDoResource(query, &serverAddr, OC_REST_PUT, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
putReqCB, NULL, 0));
}
OCStackResult result;
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
std::ostringstream query;
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
+ query << coapServerResource;
// First POST operation (to create an Light instance)
- result = InvokeOCDoResource(query, OC_REST_POST,
+ result = InvokeOCDoResource(query, &serverAddr, OC_REST_POST,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
postReqCB, NULL, 0);
if (OC_STACK_OK != result)
}
// Second POST operation (to create an Light instance)
- result = InvokeOCDoResource(query, OC_REST_POST,
+ result = InvokeOCDoResource(query, &serverAddr, OC_REST_POST,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
postReqCB, NULL, 0);
if (OC_STACK_OK != result)
}
// This POST operation will update the original resourced /a/light
- return (InvokeOCDoResource(query, OC_REST_POST,
+ return (InvokeOCDoResource(query, &serverAddr, OC_REST_POST,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
postReqCB, NULL, 0));
}
{
sleep (30);//long enough to give the server time to finish deleting the resource.
std::ostringstream query;
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
+ query << coapServerResource;
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
qos = OC_HIGH_QOS;
}
- OCStackResult result = InvokeOCDoResource(query, OC_REST_DELETE,
+ OCStackResult result = InvokeOCDoResource(query, &serverAddr, OC_REST_DELETE,
qos,
deleteReqCB, NULL, 0);
{
OCStackResult result;
std::ostringstream query;
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
+ query << coapServerResource;
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
// First DELETE operation
- result = InvokeOCDoResource(query, OC_REST_DELETE,
+ result = InvokeOCDoResource(query, &serverAddr, OC_REST_DELETE,
qos,
deleteReqCB, NULL, 0);
if (OC_STACK_OK != result)
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
std::ostringstream query;
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
+ query << coapServerResource;
// ocserver is written to only process "power<X" query.
if (getWithQuery)
}
if (withVendorSpecificHeaderOptions)
{
- return (InvokeOCDoResource(query, OC_REST_GET,
+ return (InvokeOCDoResource(query, &serverAddr, OC_REST_GET,
(qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, getReqCB, options, 2));
}
else
{
- return (InvokeOCDoResource(query, OC_REST_GET,
+ return (InvokeOCDoResource(query, &serverAddr, OC_REST_GET,
(qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, getReqCB, NULL, 0));
}
}
OCCallbackData cbData;
char szQueryUri[64] = { 0 };
+ snprintf(szQueryUri, sizeof (szQueryUri) - 1, PLATFORM_DISCOVERY_QUERY, discoveryAddr);
+
cbData.cb = PlatformDiscoveryReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- if(UNICAST_DISCOVERY)
- {
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PLATFORM_DISCOVERY_QUERY, ipv4addr);
- }
- else
- {
- strncpy(szQueryUri, MULTICAST_PLATFORM_DISCOVERY_QUERY, sizeof(szQueryUri) -1 );
- }
- szQueryUri[sizeof(szQueryUri) -1] = '\0';
-
- if(UNICAST_DISCOVERY)
- {
- ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,
- (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, &cbData, NULL, 0);
- }
- else
- {
-
- ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, OC_CONNTYPE,
- (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, &cbData, NULL, 0);
- }
-
+ ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
+ (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
+ &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "OCStack device error");
OCStackResult ret;
OCCallbackData cbData;
- char szQueryUri[64] = { 0 };
+ char szQueryUri[100] = { 0 };
+
+ snprintf(szQueryUri, sizeof (szQueryUri) - 1, DEVICE_DISCOVERY_QUERY, discoveryAddr);
cbData.cb = DeviceDiscoveryReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- if(UNICAST_DISCOVERY)
- {
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_DEVICE_DISCOVERY_QUERY, ipv4addr);
- }
- else
- {
- strncpy(szQueryUri, MULTICAST_DEVICE_DISCOVERY_QUERY, sizeof(szQueryUri) -1 );
- }
- szQueryUri[sizeof(szQueryUri) -1] = '\0';
-
- if(UNICAST_DISCOVERY)
- {
- ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,
- (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, &cbData, NULL, 0);
- }
- else
- {
- ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, OC_CONNTYPE,
- (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, &cbData, NULL, 0);
- }
-
+ ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
+ (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
+ &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "OCStack device error");
{
OCStackResult ret;
OCCallbackData cbData;
- /* Start a discovery query*/
- char szQueryUri[64] = { 0 };
+ char szQueryUri[100] = { 0 };
- if (UNICAST_DISCOVERY)
- {
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_RESOURCE_DISCOVERY_QUERY, ipv4addr);
- }
- else
- {
- strcpy(szQueryUri, MULTICAST_RESOURCE_DISCOVERY_QUERY);
- }
+ snprintf(szQueryUri, sizeof (szQueryUri) - 1, RESOURCE_DISCOVERY_QUERY, discoveryAddr);
cbData.cb = discoveryReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- if(UNICAST_DISCOVERY)
- {
- ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,
- (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, &cbData, NULL, 0);
- }
- else
- {
- ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, OC_CONNTYPE,
- (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, &cbData, NULL, 0);
- }
+
+ ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
+ (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
+ &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "OCStack resource error");
switch(opt)
{
case 'u':
- UNICAST_DISCOVERY = atoi(optarg);
+ UnicastDiscovery = atoi(optarg);
break;
case 't':
- TEST_CASE = atoi(optarg);
+ TestCase = atoi(optarg);
break;
case 'c':
- CONNECTIVITY = atoi(optarg);
+ Connectivity = atoi(optarg);
break;
default:
PrintUsage();
}
}
- if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) ||
- (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) ||
- (CONNECTIVITY < CT_ADAPTER_DEFAULT || CONNECTIVITY >= MAX_CT))
+ if ((UnicastDiscovery != 0 && UnicastDiscovery != 1) ||
+ (TestCase < TEST_DISCOVER_REQ || TestCase >= MAX_TESTS) ||
+ (Connectivity < CT_ADAPTER_DEFAULT || Connectivity >= MAX_CT))
{
PrintUsage();
return -1;
}
- /* Initialize OCStack*/
- if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK)
+ if (OCInit1(OC_CLIENT, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS) != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "OCStack init error");
return 0;
}
- if(CONNECTIVITY == CT_ADAPTER_DEFAULT || CONNECTIVITY == CT_IP)
+#ifdef ROUTING_GATEWAY
+ /*
+ * Before invoking Discover resource, we process the gateway requests
+ * and form the routing table.
+ */
+ for (int index = 0; index < MAX_NUM_GATEWAY_REQUEST; index++)
{
- OC_CONNTYPE = CT_ADAPTER_IP;
+ if (OC_STACK_OK != OCProcess())
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+ usleep(SLEEP_DURATION);
+ }
+#endif
+ if (Connectivity == CT_ADAPTER_DEFAULT || Connectivity == CT_IP)
+ {
+ ConnType = CT_ADAPTER_IP;
}
else
{
PrintUsage();
}
- if (UNICAST_DISCOVERY)
+ discoveryAddr[0] = '\0';
+
+ if (UnicastDiscovery)
{
- OC_LOG(INFO, TAG, "Enter IP address with port number of the Server hosting resource");
- OC_LOG(INFO, TAG, "as follows - eg: 192.168.0.15:45454 (IP:Port) \n");
+ OC_LOG(INFO, TAG, "Enter IP address of server with optional port number");
+ OC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n");
+ OC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n");
- if (fgets(ipv4addr, IPV4_ADDR_SIZE, stdin))
+ if (fgets(discoveryAddr, sizeof (discoveryAddr), stdin))
{
//Strip newline char from ipv4addr
- StripNewLineChar(ipv4addr);
+ StripNewLineChar(discoveryAddr);
}
else
{
- OC_LOG(ERROR, TAG, "!! Bad input for IPV4 address. !!");
+ OC_LOG(ERROR, TAG, "!! Bad input for IP address. !!");
return OC_STACK_INVALID_PARAM;
}
}
- if(UNICAST_DISCOVERY == 0 && TEST_CASE == TEST_DISCOVER_DEV_REQ)
+ if (UnicastDiscovery == 0 && TestCase == TEST_DISCOVER_DEV_REQ)
{
InitDeviceDiscovery(OC_LOW_QOS);
}
- else if(UNICAST_DISCOVERY == 0 && TEST_CASE == TEST_DISCOVER_PLATFORM_REQ)
+ else if (UnicastDiscovery == 0 && TestCase == TEST_DISCOVER_PLATFORM_REQ)
{
InitPlatformDiscovery(OC_LOW_QOS);
}
OC_LOG(ERROR, TAG, "OCStack process error");
return 0;
}
-
- sleep(2);
+#ifndef ROUTING_GATEAWAY
+ sleep(1);
+#endif
}
OC_LOG(INFO, TAG, "Exiting occlient main loop...");
return 0;
}
-std::string getIPAddrTBServer(OCClientResponse * clientResponse)
-{
- if (!clientResponse)
- {
- return "";
- }
- if (!clientResponse->addr)
- {
- return "";
- }
-
- return std::string(clientResponse->devAddr.addr);
-}
-
-std::string getPortTBServer(OCClientResponse * clientResponse)
-{
- if (!clientResponse)
- {
- return "";
- }
- if (!clientResponse->addr)
- {
- return "";
- }
- std::ostringstream ss;
- ss << clientResponse->devAddr.port;
- return ss.str();
-}
-
std::string getConnectivityType (OCConnectivityType connType)
{
switch (connType & CT_MASK_ADAPTER)
std::string getQueryStrForGetPut(OCClientResponse * /*clientResponse*/)
{
-
return "/a/light";
}
void parseClientResponse(OCClientResponse * clientResponse)
{
- coapServerIP = getIPAddrTBServer(clientResponse);
- coapServerPort = getPortTBServer(clientResponse);
coapServerResource = getQueryStrForGetPut(clientResponse);
}
#define MAX_IP_ADDR_ST_SZ 16 //string size of "155.255.255.255" (15 + 1)
#define MAX_PORT_ST_SZ 6 //string size of "65535" (5 + 1)
-static int IPV4_ADDR_SIZE = 24;
-static int UNICAST_DISCOVERY = 0;
-static int TEST_CASE = 0;
-static int CONNECTIVITY = 0;
-
-static const char UNICAST_DISCOVERY_QUERY[] = "coap://%s/oic/res";
+static int UnicastDiscovery = 0;
+static int TestCase = 0;
+static int Connectivity = 0;
//The following variable determines the interface protocol (IP, etc)
//to be used for sending unicast messages. Default set to IP.
-static OCConnectivityType OC_CONNTYPE = CT_ADAPTER_IP;
-static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oic/res";
+static OCConnectivityType ConnType = CT_ADAPTER_IP;
+static const char *RESOURCE_DISCOVERY_QUERY = "%s/oic/res";
int gQuitFlag = 0;
return resourceList;
}
-OCStackResult InvokeOCDoResource(std::ostringstream &query, OCMethod method,
- OCConnectivityType connType, OCQualityOfService qos,
- OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions)
+OCStackResult InvokeOCDoResource(std::ostringstream &query,
+ OCMethod method,
+ const OCDevAddr *dest,
+ OCQualityOfService qos,
+ OCClientResponseHandler cb,
+ OCHeaderOption * options, uint8_t numOptions)
{
OCStackResult ret;
OCCallbackData cbData;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- ret = OCDoResource(NULL, method, query.str().c_str(), 0,
+ ret = OCDoResource(NULL, method, query.str().c_str(), dest,
(method == OC_REST_PUT || method == OC_REST_POST) ? putPayload() : NULL,
- connType, qos, &cbData, options, numOptions);
+ CT_DEFAULT, qos, &cbData, options, numOptions);
if (ret != OC_STACK_OK)
{
}
OCStackApplicationResult putReqCB(void* ctx, OCDoHandle /*handle*/,
- OCClientResponse * clientResponse)
+ OCClientResponse * clientResponse)
{
if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
if(clientResponse)
{
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- OC_LOG(INFO, TAG, PCF("=============> Put Response"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("=============> Put Response"));
}
else
{
}
OCStackApplicationResult postReqCB(void *ctx, OCDoHandle /*handle*/,
- OCClientResponse *clientResponse)
+ OCClientResponse *clientResponse)
{
if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
if(clientResponse)
{
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- OC_LOG(INFO, TAG, PCF("=============> Post Response"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("=============> Post Response"));
}
else
{
}
OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/,
- OCClientResponse * clientResponse)
+ OCClientResponse * clientResponse)
{
if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
{
{
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- OC_LOG(INFO, TAG, PCF("=============> Get Response"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("=============> Get Response"));
if (clientResponse->numRcvdVendorSpecificHeaderOptions > 0 )
{
* This is a function called back when a device is discovered
*/
OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/,
- OCClientResponse * clientResponse)
+ OCClientResponse * clientResponse)
{
if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
"Device =============> Discovered @ %s:%d",
clientResponse->devAddr.addr,
clientResponse->devAddr.port);
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
collectUniqueResource(clientResponse);
}
{
OC_LOG(ERROR, TAG, "<====DISCOVERY Callback fail to receive clientResponse====>\n");
}
- return (UNICAST_DISCOVERY) ?
+ return (UnicastDiscovery) ?
OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
}
OC_LOG_V(ERROR, TAG, "Resource null, can't do PUT request\n");
return -1;
}
- query << "coap://" << resource->ip << ":" << resource->port << resource->uri ;
+ query << resource->uri;
OC_LOG_V(INFO, TAG,"Executing InitPutRequest, Query: %s", query.str().c_str());
- return (InvokeOCDoResource(query, OC_REST_PUT, resource->connType,
+ return (InvokeOCDoResource(query, OC_REST_PUT, &resource->endpoint,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
putReqCB, NULL, 0));
}
OCStackResult result;
std::ostringstream query;
//Get most recently inserted resource
- const ResourceNode * resource = getResource();
+ const ResourceNode *resource = getResource();
if(!resource)
{
return -1;
}
- query << "coap://" << resource->ip << ":" << resource->port << resource->uri ;
+ query << resource->uri;
OC_LOG_V(INFO, TAG,"Executing InitPostRequest, Query: %s", query.str().c_str());
// First POST operation (to create an LED instance)
- result = InvokeOCDoResource(query, OC_REST_POST, resource->connType,
+ result = InvokeOCDoResource(query, OC_REST_POST, &resource->endpoint,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
postReqCB, NULL, 0);
if (OC_STACK_OK != result)
}
// Second POST operation (to create an LED instance)
- result = InvokeOCDoResource(query, OC_REST_POST, resource->connType,
+ result = InvokeOCDoResource(query, OC_REST_POST, &resource->endpoint,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
postReqCB, NULL, 0);
if (OC_STACK_OK != result)
}
// This POST operation will update the original resourced /a/led
- return (InvokeOCDoResource(query, OC_REST_POST,resource->connType,
+ return (InvokeOCDoResource(query, OC_REST_POST, &resource->endpoint,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
postReqCB, NULL, 0));
}
OC_LOG_V(ERROR, TAG, "Resource null, can't do GET request\n");
return -1;
}
- query << "coap://" << resource->ip << ":" << resource->port << resource->uri ;
+ query << resource->uri;
OC_LOG_V(INFO, TAG,"Executing InitGetRequest, Query: %s", query.str().c_str());
- return (InvokeOCDoResource(query, OC_REST_GET, resource->connType,
+ return (InvokeOCDoResource(query, OC_REST_GET, &resource->endpoint,
(qos == OC_HIGH_QOS)?OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0));
}
{
OCStackResult ret;
OCCallbackData cbData;
- /* Start a discovery query*/
- char szQueryUri[64] = {};
- if (UNICAST_DISCOVERY)
+ char queryUri[200];
+ char ipaddr[100] = { '\0' };
+
+ if (UnicastDiscovery)
{
- char ipv4addr[IPV4_ADDR_SIZE];
- OC_LOG(INFO, TAG, "Enter IP address with port of the Server hosting resource"\
- "(Ex: 192.168.0.15:1234) ");
+ OC_LOG(INFO, TAG, "Enter IP address (with optional port) of the Server hosting resource\n");
+ OC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n");
+ OC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n");
- if (fgets(ipv4addr, IPV4_ADDR_SIZE, stdin))
+ if (fgets(ipaddr, sizeof (ipaddr), stdin))
{
- //Strip newline char from ipv4addr
- StripNewLineChar(ipv4addr);
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_DISCOVERY_QUERY, ipv4addr);
+ StripNewLineChar(ipaddr); //Strip newline char from ipaddr
}
else
{
- OC_LOG(ERROR, TAG, "!! Bad input for IPV4 address. !!");
+ OC_LOG(ERROR, TAG, "!! Bad input for IP address. !!");
return OC_STACK_INVALID_PARAM;
}
}
- else
- {
- OICStrcpy(szQueryUri, sizeof(szQueryUri), MULTICAST_RESOURCE_DISCOVERY_QUERY);
- }
+
+ snprintf(queryUri, sizeof (queryUri), RESOURCE_DISCOVERY_QUERY, ipaddr);
+
cbData.cb = discoveryReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- if (UNICAST_DISCOVERY)
- {
- ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,
- OC_LOW_QOS, &cbData, NULL, 0);
- }
- else
- {
- ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, CT_DEFAULT,
- OC_LOW_QOS, &cbData, NULL, 0);
- }
+ ret = OCDoResource(NULL, OC_REST_DISCOVER, queryUri, 0, 0, CT_DEFAULT,
+ OC_LOW_QOS, &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "OCStack resource error");
return ret;
}
-const char *getIPAddr(const OCClientResponse *clientResponse)
-{
- if (!clientResponse)
- {
- return "";
- }
-
- const OCDevAddr *devAddr = &clientResponse->devAddr;
- char *ipaddr = (char *) OICCalloc(1, strlen(devAddr->addr) +1);
- if (ipaddr)
- {
- snprintf(ipaddr, MAX_IP_ADDR_ST_SZ, "%s", devAddr->addr);
- }
- else
- {
- OC_LOG(ERROR, TAG, "Memory not allocated to ipaddr");
- }
- return ipaddr;
-}
-
-const char *getPort(const OCClientResponse *clientResponse)
-{
- if(!clientResponse)
- {
- return "";
- }
-
- char *port = NULL;
- if((port = (char *)OICCalloc(1, MAX_PORT_ST_SZ)))
- {
- snprintf(port, MAX_PORT_ST_SZ, "%d", clientResponse->devAddr.port);
- }
- else
- {
- OC_LOG(ERROR, TAG, "Memory not allocated to port");
- }
- return port;
-}
-
void queryResource()
{
- switch(TEST_CASE)
+ switch(TestCase)
{
case TEST_DISCOVER_REQ:
break;
{
iter->sid = sid_cpy;
iter->uri = uri_cpy;
- iter->ip = getIPAddr(clientResponse);
- iter->port = getPort(clientResponse);
- iter->connType = clientResponse->connType;
+ iter->endpoint = clientResponse->devAddr;
iter->next = NULL;
}
else
OC_LOG(INFO, TAG, "*****************************************************");
OC_LOG_V(INFO, TAG, "sid = %s",iter->sid);
OC_LOG_V(INFO, TAG, "uri = %s", iter->uri);
- OC_LOG_V(INFO, TAG, "ip = %s", iter->ip);
- OC_LOG_V(INFO, TAG, "port = %s", iter->port);
- switch (iter->connType & CT_MASK_ADAPTER)
+ OC_LOG_V(INFO, TAG, "ip = %s", iter->endpoint.addr);
+ OC_LOG_V(INFO, TAG, "port = %d", iter->endpoint.port);
+ switch (iter->endpoint.adapter)
{
case OC_ADAPTER_IP:
OC_LOG(INFO, TAG, "connType = Default (IPv4)");
resourceList = resourceList->next;
OICFree((void *)temp->sid);
OICFree((void *)temp->uri);
- OICFree((void *)temp->ip);
- OICFree((void *)temp->port);
OICFree(temp);
}
resourceList = NULL;
switch(opt)
{
case 'u':
- UNICAST_DISCOVERY = atoi(optarg);
+ UnicastDiscovery = atoi(optarg);
break;
case 't':
- TEST_CASE = atoi(optarg);
+ TestCase = atoi(optarg);
break;
case 'c':
-
- CONNECTIVITY = atoi(optarg);
+ Connectivity = atoi(optarg);
break;
default:
PrintUsage();
}
}
- if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) ||
- (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) ||
- (CONNECTIVITY < CT_ADAPTER_DEFAULT || CONNECTIVITY >= MAX_CT))
+ if ((UnicastDiscovery != 0 && UnicastDiscovery != 1) ||
+ (TestCase < TEST_DISCOVER_REQ || TestCase >= MAX_TESTS) ||
+ (Connectivity < CT_ADAPTER_DEFAULT || Connectivity >= MAX_CT))
{
PrintUsage();
return -1;
}
/* Initialize OCStack*/
- if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK)
+ if (OCInit1(OC_CLIENT, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS) != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "OCStack init error");
return 0;
}
- if(CONNECTIVITY == CT_ADAPTER_DEFAULT || CONNECTIVITY == CT_IP)
+ if(Connectivity == CT_ADAPTER_DEFAULT || Connectivity == CT_IP)
{
- OC_CONNTYPE = CT_ADAPTER_IP;//CT_DEFAULT;
+ ConnType = CT_ADAPTER_IP;//CT_DEFAULT;
}
else
{
//-----------------------------------------------------------------------------
#define TAG "occlientbasicops"
#define DEFAULT_CONTEXT_VALUE 0x99
-#ifndef MAX_LENGTH_IPv4_ADDR
-#define MAX_LENGTH_IPv4_ADDR 16
-#endif
//-----------------------------------------------------------------------------
// Typedefs
{
const char * sid;
const char * uri;
- const char * ip;
- const char * port;
- OCConnectivityType connType;
+ OCDevAddr endpoint;
ResourceNode * next;
};
/* call getResult in common.cpp to get the result in string format. */
const char *getResult(OCStackResult result);
-/* Get the IP address of the server */
-const char * getIPAddr(const OCClientResponse * clientResponse);
-
-/* Get the port number the server is listening on */
-const char * getPort(const OCClientResponse * clientResponse);
-
/* Performs GET/PUT/POST query on most recently discovered resource*/
void queryResource();
* to the lower layers
*/
OCStackResult InvokeOCDoResource(std::ostringstream &query,
- OCMethod method, OCQualityOfService qos,
+ OCMethod method, OCDevAddr *dest, OCQualityOfService qos,
OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions);
/*
#include "payload_logging.h"
#include "logger.h"
const char *getResult(OCStackResult result);
-std::string getIPAddrTBServer(OCClientResponse * clientResponse);
-std::string getPortTBServer(OCClientResponse * clientResponse);
std::string getQueryStrForGetPut();
-#define TAG PCF("occlient")
+#define TAG ("occlient")
#define DEFAULT_CONTEXT_VALUE 0x99
#ifndef MAX_LENGTH_IPv4_ADDR
#define MAX_LENGTH_IPv4_ADDR 16
CT_ADAPTER_DEFAULT = 0,
CT_IP,
MAX_CT
-} CLIENT_CONNECTIVITY_TYPE;
+} CLIENT_ConnectivityType_TYPE;
-unsigned static int TEST = TEST_INVALID;
-unsigned static int CONNECTIVITY = 0;
+unsigned static int TestType = TEST_INVALID;
+unsigned static int ConnectivityType = 0;
typedef struct
{
//The following variable determines the interface protocol (IP, etc)
//to be used for sending unicast messages. Default set to IP.
-static OCConnectivityType OC_CONNTYPE = CT_ADAPTER_IP;
-static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oic/res";
+static OCConnectivityType ConnType = CT_ADAPTER_IP;
+static const char * RESOURCE_DISCOVERY_QUERY = "/oic/res";
// The handle for the observe registration
OCDoHandle gObserveDoHandle;
if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG_V(INFO, TAG, "Callback Context for PUT query recvd successfully");
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
}
return OC_STACK_KEEP_TRANSACTION;
if(clientResponse->sequenceNumber == 0)
{
OC_LOG_V(INFO, TAG, "Callback Context for GET query recvd successfully");
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
}
else
{
OC_LOG_V(INFO, TAG, "Callback Context for Get recvd successfully %d",
gNumObserveNotifies);
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);;
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);;
gNumObserveNotifies++;
if (gNumObserveNotifies == 3)
{
}
}
}
- if(TEST == TEST_PUT_DEFAULT || TEST == TEST_PUT_BATCH || TEST == TEST_PUT_LINK_LIST)
+ if(TestType == TEST_PUT_DEFAULT || TestType == TEST_PUT_BATCH || TestType == TEST_PUT_LINK_LIST)
{
InitPutRequest(clientResponse);
}
return OC_STACK_KEEP_TRANSACTION;
}
-
// This is a function called back when a device is discovered
OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/,
- OCClientResponse * clientResponse)
+ OCClientResponse * clientResponse)
{
OC_LOG(INFO, TAG,
"Entering discoveryReqCB (Application Layer CB)");
"Device =============> Discovered @ %s:%d",
clientResponse->devAddr.addr,
clientResponse->devAddr.port);
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
- OC_CONNTYPE = clientResponse->connType;
+ ConnType = clientResponse->connType;
- if(TEST == TEST_UNKNOWN_RESOURCE_GET_DEFAULT || TEST == TEST_UNKNOWN_RESOURCE_GET_BATCH ||\
- TEST == TEST_UNKNOWN_RESOURCE_GET_LINK_LIST)
+ if(TestType == TEST_UNKNOWN_RESOURCE_GET_DEFAULT || TestType == TEST_UNKNOWN_RESOURCE_GET_BATCH ||\
+ TestType == TEST_UNKNOWN_RESOURCE_GET_LINK_LIST)
{
InitGetRequestToUnavailableResource(clientResponse);
}
OCStackResult ret;
OCCallbackData cbData;
std::ostringstream getQuery;
- getQuery << "coap://" << clientResponse->devAddr.addr << ":" <<
- clientResponse->devAddr.port << "/SomeUnknownResource";
+ getQuery << "/SomeUnknownResource";
cbData.cb = getReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- ret = OCDoResource(NULL, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_CONNTYPE, OC_LOW_QOS,
- &cbData, NULL, 0);
+ ret = OCDoResource(NULL, OC_REST_GET, getQuery.str().c_str(),
+ &clientResponse->devAddr, 0, ConnType, OC_LOW_QOS,
+ &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "OCStack resource error");
OCCallbackData cbData;
OCDoHandle handle;
std::ostringstream obsReg;
- obsReg << "coap://" << clientResponse->devAddr.addr << ":" <<
- clientResponse->devAddr.addr <<
- getQueryStrForGetPut();
+ obsReg << getQueryStrForGetPut();
cbData.cb = getReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
OC_LOG_V(INFO, TAG, "OBSERVE payload from client =");
OCPayload* payload = putPayload();
- OC_LOG_PAYLOAD(INFO, TAG, payload);
+ OC_LOG_PAYLOAD(INFO, payload);
OCPayloadDestroy(payload);
- ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(), 0, 0, OC_CONNTYPE,
- OC_LOW_QOS, &cbData, NULL, 0);
+ ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(),
+ &clientResponse->devAddr, 0, ConnType,
+ OC_LOW_QOS, &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "OCStack resource error");
std::ostringstream getQuery;
getQuery << "coap://" << clientResponse->devAddr.addr << ":" <<
clientResponse->devAddr.port <<
- "/a/room" << queryInterface[TEST].text;
+ "/a/room" << queryInterface[TestType].text;
cbData.cb = putReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
OC_LOG_V(INFO, TAG, "PUT payload from client = ");
OCPayload* payload = putPayload();
- OC_LOG_PAYLOAD(INFO, TAG, payload);
+ OC_LOG_PAYLOAD(INFO, payload);
OCPayloadDestroy(payload);
- ret = OCDoResource(NULL, OC_REST_PUT, getQuery.str().c_str(), 0, putPayload(),
- OC_CONNTYPE, OC_LOW_QOS, &cbData, NULL, 0);
+ ret = OCDoResource(NULL, OC_REST_PUT, getQuery.str().c_str(),
+ &clientResponse->devAddr, putPayload(), ConnType,
+ OC_LOW_QOS, &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "OCStack resource error");
//* Make a GET query*/
std::ostringstream getQuery;
- getQuery << "coap://" << clientResponse->devAddr.addr << ":" <<
- clientResponse->devAddr.port <<
- "/a/room" << queryInterface[TEST].text;
+ getQuery << "/a/room" << queryInterface[TestType].text;
std::cout << "Get Query: " << getQuery.str() << std::endl;
cbData.cb = getReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- ret = OCDoResource(NULL, OC_REST_GET,
- getQuery.str().c_str(), 0, 0, OC_CONNTYPE, OC_LOW_QOS,
- &cbData, NULL, 0);
+ ret = OCDoResource(NULL, OC_REST_GET, getQuery.str().c_str(),
+ &clientResponse->devAddr, 0, ConnType, OC_LOW_QOS,
+ &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "OCStack resource error");
/* Start a discovery query*/
char szQueryUri[64] = { 0 };
- strcpy(szQueryUri, MULTICAST_RESOURCE_DISCOVERY_QUERY);
+ strcpy(szQueryUri, RESOURCE_DISCOVERY_QUERY);
cbData.cb = discoveryReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, OC_CONNTYPE,
+ ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, ConnType,
OC_LOW_QOS,
&cbData, NULL, 0);
if (ret != OC_STACK_OK)
switch (opt)
{
case 't':
- TEST = atoi(optarg);
+ TestType = atoi(optarg);
break;
case 'c':
- CONNECTIVITY = atoi(optarg);
+ ConnectivityType = atoi(optarg);
break;
default:
PrintUsage();
return -1;
}
}
- if ((TEST <= TEST_INVALID || TEST >= MAX_TESTS) ||
- CONNECTIVITY >= MAX_CT)
+ if ((TestType <= TEST_INVALID || TestType >= MAX_TESTS) ||
+ ConnectivityType >= MAX_CT)
{
PrintUsage();
return -1;
return 0;
}
- if(CONNECTIVITY == CT_ADAPTER_DEFAULT || CONNECTIVITY == CT_IP)
+ if(ConnectivityType == CT_ADAPTER_DEFAULT || ConnectivityType == CT_IP)
{
- OC_CONNTYPE = CT_ADAPTER_IP;
+ ConnType = CT_ADAPTER_IP;
}
else
{
OC_LOG(INFO, TAG, "Default Connectivity type selected...");
- OC_CONNTYPE = CT_ADAPTER_IP;
+ ConnType = CT_ADAPTER_IP;
}
InitDiscovery();
#include "payload_logging.h"
// Tracking user input
-static int UNICAST_DISCOVERY = 0;
-static int TEST_CASE = 0;
-static int CONNECTIVITY = 0;
+static int UnicastDiscovery = 0;
+static int TestCase = 0;
+static int ConnectivityType = 0;
-static const char * UNICAST_DISCOVERY_QUERY = "coap://%s/oic/res";
-static std::string coapServerIP = "255.255.255.255";
-static uint16_t coapServerPort = 5683;
static std::string coapServerResource = "/a/led";
//The following variable determines the interface protocol (IP, etc)
//to be used for sending unicast messages. Default set to IP.
-static OCConnectivityType OC_CONNTYPE = CT_ADAPTER_IP;
-static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oic/res";
-static int IPV4_ADDR_SIZE = 24;
+static OCConnectivityType AdapterType = CT_ADAPTER_IP;
+static OCDevAddr endpoint;
+static const char *RESOURCE_DISCOVERY_QUERY = "%s/oic/res";
void StripNewLineChar(char* str);
int gQuitFlag = 0;
static void PrintUsage()
{
- OC_LOG(INFO, TAG, "Usage : occlient -c <0|1|2> -u <0|1> -t <1|2|3>");
+ OC_LOG(INFO, TAG, "Usage : occlient -c <0|1> -u <0|1> -t <1|2|3>");
OC_LOG(INFO, TAG, "-c 0 : Default auto-selection");
OC_LOG(INFO, TAG, "-c 1 : IP Connectivity Type");
OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources");
}
OCStackResult InvokeOCDoResource(std::ostringstream &query,
- OCMethod method, OCQualityOfService qos,
+ OCMethod method, OCDevAddr *dest, OCQualityOfService qos,
OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions)
{
OCStackResult ret;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- ret = OCDoResource(NULL, method, query.str().c_str(), 0,
+ ret = OCDoResource(NULL, method, query.str().c_str(), dest,
(method == OC_REST_PUT) ? putPayload() : NULL,
- OC_CONNTYPE, qos, &cbData, options, numOptions);
+ AdapterType, qos, &cbData, options, numOptions);
if (ret != OC_STACK_OK)
{
return ret;
}
-OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+OCStackApplicationResult getReqCB(void* ctx,
+ OCDoHandle /*handle*/, OCClientResponse * clientResponse)
{
if(clientResponse == NULL)
{
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
OC_LOG(INFO, TAG, "Get Response =============> ");
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
if(clientResponse->rcvdVendorSpecificHeaderOptions &&
clientResponse->numRcvdVendorSpecificHeaderOptions)
}
// This is a function called back when a device is discovered
-OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
+OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/,
OCClientResponse * clientResponse)
{
if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
OC_LOG_V(INFO, TAG, "Discovered @ %s:%u =============> ",
clientResponse->devAddr.addr, clientResponse->devAddr.port);
- OC_LOG_PAYLOAD (INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD (INFO, clientResponse->payload);
- parseClientResponse(clientResponse);
+ endpoint = clientResponse->devAddr;
- switch(TEST_CASE)
+ switch(TestCase)
{
case TEST_NON_CON_OP:
InitGetRequest(OC_LOW_QOS);
}
}
- return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
+ return UnicastDiscovery ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
}
{
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
std::ostringstream query;
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
+ query << coapServerResource;
OC_LOG_V (INFO, TAG, "Performing GET with query : %s", query.str().c_str());
- return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)?
- OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0));
+ return (InvokeOCDoResource(query, OC_REST_GET, &endpoint,
+ (qos == OC_HIGH_QOS)? OC_HIGH_QOS : OC_LOW_QOS,
+ getReqCB, NULL, 0));
}
int InitPutRequest(OCQualityOfService qos)
{
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
std::ostringstream query;
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
+ query << coapServerResource;
OC_LOG_V (INFO, TAG, "Performing PUT with query : %s", query.str().c_str());
- return (InvokeOCDoResource(query, OC_REST_PUT, (qos == OC_HIGH_QOS)?
- OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0));
+ return (InvokeOCDoResource(query, OC_REST_PUT, &endpoint,
+ (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
+ getReqCB, NULL, 0));
}
int InitDiscovery()
{
OCStackResult ret;
OCCallbackData cbData;
- /* Start a discovery query*/
- char szQueryUri[64] = { 0 };
- if (UNICAST_DISCOVERY)
+ char queryUri[200];
+ char ipaddr[100] = { '\0' };
+
+ if (UnicastDiscovery)
{
- char ipv4addr[IPV4_ADDR_SIZE];
- OC_LOG(INFO, TAG, "Enter IPv4:port of the Server hosting resource"\
- "(Ex: 192.168.0.15:1234)");
- if (fgets(ipv4addr, IPV4_ADDR_SIZE, stdin))
+ OC_LOG(INFO, TAG, "Enter IP address (with optional port) of the Server hosting resource\n");
+ OC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n");
+ OC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n");
+
+ if (fgets(ipaddr, sizeof (ipaddr), stdin))
{
- //Strip newline char from ipv4addr
- StripNewLineChar(ipv4addr);
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_DISCOVERY_QUERY, ipv4addr);
+ StripNewLineChar(ipaddr); //Strip newline char from ipaddr
}
else
{
- OC_LOG(ERROR, TAG, "!! Bad input for IPV4 address. !!");
+ OC_LOG(ERROR, TAG, "!! Bad input for IP address. !!");
return OC_STACK_INVALID_PARAM;
}
}
- else
- {
- OICStrcpy(szQueryUri, sizeof(szQueryUri), MULTICAST_RESOURCE_DISCOVERY_QUERY);
- }
+
+ snprintf(queryUri, sizeof (queryUri), RESOURCE_DISCOVERY_QUERY, ipaddr);
+
cbData.cb = discoveryReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- if(UNICAST_DISCOVERY)
- {
- ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,
- OC_LOW_QOS, &cbData, NULL, 0);
- }
- else
- {
- ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, CT_DEFAULT,
- OC_LOW_QOS, &cbData, NULL, 0);
- }
+
+ ret = OCDoResource(NULL, OC_REST_DISCOVER, queryUri, 0, 0, CT_DEFAULT,
+ OC_LOW_QOS, &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "OCStack resource error");
switch(opt)
{
case 'u':
- UNICAST_DISCOVERY = atoi(optarg);
+ UnicastDiscovery = atoi(optarg);
break;
case 't':
- TEST_CASE = atoi(optarg);
+ TestCase = atoi(optarg);
break;
case 'c':
- CONNECTIVITY = atoi(optarg);
+ ConnectivityType = atoi(optarg);
break;
default:
PrintUsage();
}
}
- if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) ||
- (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) ||
- (CONNECTIVITY < CT_ADAPTER_DEFAULT || CONNECTIVITY >= MAX_CT))
+ if ((UnicastDiscovery != 0 && UnicastDiscovery != 1) ||
+ (TestCase < TEST_DISCOVER_REQ || TestCase >= MAX_TESTS) ||
+ (ConnectivityType < CT_ADAPTER_DEFAULT || ConnectivityType >= MAX_CT))
{
PrintUsage();
return -1;
return 0;
}
- if(CONNECTIVITY == CT_ADAPTER_DEFAULT || CONNECTIVITY == CT_IP)
+ if(ConnectivityType == CT_ADAPTER_DEFAULT || ConnectivityType == CT_IP)
{
- OC_CONNTYPE = CT_ADAPTER_IP;
+ AdapterType = CT_ADAPTER_IP;
}
else
{
OC_LOG(INFO, TAG, "Default Connectivity type selected...");
- OC_CONNTYPE = CT_ADAPTER_IP;
+ AdapterType = CT_ADAPTER_IP;
}
InitDiscovery();
return 0;
}
-std::string getQueryStrForGetPut(OCClientResponse * clientResponse)
+std::string getQueryStrForGetPut(OCClientResponse * /*clientResponse*/)
{
return "/a/led";
}
-void parseClientResponse(OCClientResponse * clientResponse)
-{
- coapServerIP = clientResponse->devAddr.addr;
- coapServerPort = clientResponse->devAddr.port;
- coapServerResource = getQueryStrForGetPut(clientResponse);
-}
-
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
if(clientResponse->numRcvdVendorSpecificHeaderOptions > 0)
{
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
OC_LOG_V(INFO, TAG, "OBSERVE notification %d recvd", gNumObserveNotifies);
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
gNumObserveNotifies++;
if (gNumObserveNotifies == maxNotification)
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
OC_LOG_V(INFO, TAG, "NONCE NUMBER: %u", clientResponse->sequenceNumber);
OC_LOG_V(INFO, TAG, "PRESENCE notification %d recvd", gNumPresenceNotifies);
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
gNumPresenceNotifies++;
if (gNumPresenceNotifies == maxNotification)
}
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
responseAddr = clientResponse->devAddr;
if(clientResponse)
{
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
}
else
{
if(clientResponse)
{
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
}
else
{
--- /dev/null
+/* ****************************************************************
+ *
+ * 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 <string.h>
+#include <string>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include <array>
+#include "ocstack.h"
+#include "logger.h"
+#include "ocpayload.h"
+
+#define TAG "ocrouting"
+
+int gQuitFlag = 0;
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+ if (signum == SIGINT)
+ {
+ gQuitFlag = 1;
+ }
+}
+
+int main()
+{
+ OC_LOG(DEBUG, TAG, "OCRouting sample is starting...");
+
+ if (OCInit(NULL, 0, OC_GATEWAY) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack init error");
+ return 0;
+ }
+
+ // Break from loop with Ctrl-C
+ OC_LOG(INFO, TAG, "Entering ocrouting main loop...");
+
+ signal(SIGINT, handleSigInt);
+
+ while (!gQuitFlag)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+ }
+
+ OC_LOG(INFO, TAG, "Exiting ocrouting main loop...");
+
+ if (OCStop() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ }
+
+ return 0;
+}
OCEntityHandlerResult
OCEntityHandlerCb (OCEntityHandlerFlag flag,
- OCEntityHandlerRequest *entityHandlerRequest, void* callback)
+ OCEntityHandlerRequest *entityHandlerRequest, void* /*callback*/)
{
OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
OCEntityHandlerResult ehResult = OC_EH_OK;
- OCEntityHandlerResponse response = { 0 };
+ OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, { },{ 0 }, false };
// Validate pointer
if (!entityHandlerRequest)
PrintUsage();
return -1;
}
- #ifdef RA_ADAPTER
+#ifdef RA_ADAPTER
OCRAInfo_t rainfo;
rainfo.hostname = "localhost";
rainfo.port = 5222;
rainfo.user_jid = "";
OCSetRAInfo(&rainfo);
- #endif
+#endif
OC_LOG(DEBUG, TAG, "OCServer is starting...");
OC_LOG(ERROR, TAG, "OCStack process error");
return 0;
}
-
+#ifndef ROUTING_GATEWAY
sleep(2);
+#endif
}
/*
OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
OCEntityHandlerResult ehResult = OC_EH_ERROR;
- OCEntityHandlerResponse response = {0};
+ OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, { },{ 0 }, false };
// Validate pointer
if (!entityHandlerRequest)
//The only case when this entity handler is for a non-existing resource.
OCEntityHandlerResult
OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
- OCEntityHandlerRequest *entityHandlerRequest, char* uri, void* callbackParam)
+ OCEntityHandlerRequest *entityHandlerRequest, char* uri, void* /*callbackParam*/)
{
OC_LOG_V(INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
OCEntityHandlerRequest * ehRequest,
- void* callback)
+ void* /*callback*/)
{
OCEntityHandlerResult ret = OC_EH_OK;
OCEntityHandlerResponse response;
}
OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag,
- OCEntityHandlerRequest * ehRequest,void* callbackParam)
+ OCEntityHandlerRequest * ehRequest,void* /*callbackParam*/)
{
OCEntityHandlerResult ret = OC_EH_OK;
OCEntityHandlerResponse response;
}
OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag,
- OCEntityHandlerRequest * ehRequest, void* callback)
+ OCEntityHandlerRequest * ehRequest, void* /*callback*/)
{
OCEntityHandlerResult ret = OC_EH_OK;
OCEntityHandlerResponse response;
{
if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
{
- OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+ OC_LOG(ERROR, TAG, ("Incoming payload not a representation"));
return nullptr;
}
}
OCEntityHandlerResult OCEntityHandlerCb (OCEntityHandlerFlag flag,
- OCEntityHandlerRequest *entityHandlerRequest, void* callbackParam)
+ OCEntityHandlerRequest *entityHandlerRequest, void* /*callbackParam*/)
{
OCEntityHandlerResult result = OC_EH_ERROR;
OCEntityHandlerRequest *request = NULL;
{
OC_LOG_V (INFO, TAG, "request query %s from client",
entityHandlerRequest->query);
- OC_LOG_PAYLOAD (INFO, TAG, entityHandlerRequest->payload);
+ OC_LOG_PAYLOAD (INFO, entityHandlerRequest->payload);
// Make deep copy of received request and queue it for slow processing
request = CopyRequest(entityHandlerRequest);
}
}
-int main(int argc, char* argv[])
+int main(int /*argc*/, char** /*argv[]*/)
{
OC_LOG(DEBUG, TAG, "OCServer is starting...");
#include "common.h"
#define TAG "occlientbasicops"
-static int UNICAST_DISCOVERY = 0;
-static int TEST_CASE = 0;
-static int CONN_TYPE = 0;
+static int UnicastDiscovery = 0;
+static int TestCase = 0;
+static int ConnType = 0;
-static int IPV4_ADDR_SIZE = 24;
-static char UNICAST_DISCOVERY_QUERY[] = "coap://%s/oic/res";
-static char MULTICAST_DISCOVERY_QUERY[] = "/oic/res";
+static char DISCOVERY_QUERY[] = "%s/oic/res";
OCConnectivityType discoveryReqConnType = CT_ADAPTER_IP;
+static OCDevAddr endpoint;
-static std::string coapServerIP;
-static std::string coapServerPort;
static std::string coapServerResource;
static int coapSecureResource;
static OCConnectivityType ocConnType;
-
//Secure Virtual Resource database for Iotivity Client application
//It contains Client's Identity and the PSK credentials
//of other devices which the client trusts
" Initiate Nonconfirmable Get/Put/Post Requests");
OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Confirmable Get/Put/Post Requests");
OC_LOG(INFO, TAG, "-c 0 : Default auto-selection");
- OC_LOG(INFO, TAG, "-c 1 : IPv4 Connectivity Type");
+ OC_LOG(INFO, TAG, "-c 1 : IP Connectivity Type");
}
OCStackResult InvokeOCDoResource(std::ostringstream &query,
- OCMethod method, OCQualityOfService qos,
- OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions)
+ OCMethod method,
+ const OCDevAddr *dest,
+ OCQualityOfService qos,
+ OCClientResponseHandler cb,
+ OCHeaderOption * options, uint8_t numOptions)
{
OCStackResult ret;
OCCallbackData cbData;
cbData.context = NULL;
cbData.cd = NULL;
- ret = OCDoResource(NULL, method, query.str().c_str(), 0,
+ ret = OCDoResource(NULL, method, query.str().c_str(), dest,
(method == OC_REST_PUT || method == OC_REST_POST) ? putPayload() : NULL,
ocConnType, qos, &cbData, options, numOptions);
return ret;
}
-OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+OCStackApplicationResult putReqCB(void*, OCDoHandle, OCClientResponse * clientResponse)
{
OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
if(clientResponse)
{
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- OC_LOG(INFO, TAG, PCF("=============> Put Response"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("=============> Put Response"));
}
return OC_STACK_DELETE_TRANSACTION;
}
-OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
+OCStackApplicationResult postReqCB(void *, OCDoHandle, OCClientResponse *clientResponse)
{
OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully");
if(clientResponse)
{
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- OC_LOG(INFO, TAG, PCF("=============> Post Response"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("=============> Post Response"));
}
return OC_STACK_DELETE_TRANSACTION;
}
-OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+OCStackApplicationResult getReqCB(void*, OCDoHandle, OCClientResponse * clientResponse)
{
OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
{
OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- OC_LOG(INFO, TAG, PCF("=============> Get Response"));
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
+ OC_LOG(INFO, TAG, ("=============> Get Response"));
}
return OC_STACK_DELETE_TRANSACTION;
}
// This is a function called back when a device is discovered
-OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
+OCStackApplicationResult discoveryReqCB(void*, OCDoHandle,
OCClientResponse * clientResponse)
{
OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
if (clientResponse->result == OC_STACK_OK)
{
- OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ OC_LOG_PAYLOAD(INFO, clientResponse->payload);
ocConnType = clientResponse->connType;
+ endpoint = clientResponse->devAddr;
if (parseClientResponse(clientResponse) != -1)
{
- switch(TEST_CASE)
+ switch(TestCase)
{
case TEST_NON_CON_OP:
InitGetRequest(OC_LOW_QOS);
}
}
- return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
+ return (UnicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
}
{
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
std::ostringstream query;
- query << (coapSecureResource ? "coaps://" : "coap://") << coapServerIP
- << ":" << coapServerPort << coapServerResource;
- return (InvokeOCDoResource(query, OC_REST_PUT,
+ query << coapServerResource;
+ endpoint.flags = (OCTransportFlags)(endpoint.flags|OC_SECURE);
+ return (InvokeOCDoResource(query, OC_REST_PUT, &endpoint,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), putReqCB, NULL, 0));
}
OCStackResult result;
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
std::ostringstream query;
- query << (coapSecureResource ? "coaps://" : "coap://") << coapServerIP
- << ":" << coapServerPort << coapServerResource;
+ query << coapServerResource;
+ endpoint.flags = (OCTransportFlags)(endpoint.flags|OC_SECURE);
// First POST operation (to create an LED instance)
- result = InvokeOCDoResource(query, OC_REST_POST,
+ result = InvokeOCDoResource(query, OC_REST_POST, &endpoint,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
postReqCB, NULL, 0);
if (OC_STACK_OK != result)
}
// Second POST operation (to create an LED instance)
- result = InvokeOCDoResource(query, OC_REST_POST,
+ result = InvokeOCDoResource(query, OC_REST_POST, &endpoint,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
postReqCB, NULL, 0);
if (OC_STACK_OK != result)
}
// This POST operation will update the original resourced /a/led
- return (InvokeOCDoResource(query, OC_REST_POST,
+ return (InvokeOCDoResource(query, OC_REST_POST, &endpoint,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
postReqCB, NULL, 0));
}
{
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
std::ostringstream query;
- query << (coapSecureResource ? "coaps://" : "coap://") << coapServerIP
- << ":" << coapServerPort << coapServerResource;
+ query << coapServerResource;
+ endpoint.flags = (OCTransportFlags)(endpoint.flags|OC_SECURE);
- return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)?
- OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0));
+ return (InvokeOCDoResource(query, OC_REST_GET, &endpoint,
+ ((qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS),
+ getReqCB, NULL, 0));
}
int InitDiscovery()
{
OCStackResult ret;
- OCMethod method;
OCCallbackData cbData;
- char szQueryUri[MAX_URI_LENGTH] = { 0 };
+ char queryUri[200];
+ char ipaddr[100] = { '\0' };
- if (UNICAST_DISCOVERY)
+ if (UnicastDiscovery)
{
- char ipv4addr[IPV4_ADDR_SIZE];
- OC_LOG(INFO, TAG, "Enter IPv4 address:port of the Server hosting secure resource"\
- "(Ex: 11.12.13.14:1234)\n");
- if (fgets(ipv4addr, IPV4_ADDR_SIZE, stdin))
+ OC_LOG(INFO, TAG, "Enter IP address (with optional port) of the Server hosting resource\n");
+ OC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n");
+ OC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n");
+
+ if (fgets(ipaddr, sizeof (ipaddr), stdin))
{
- //Strip newline char from ipv4addr
- StripNewLineChar(ipv4addr);
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_DISCOVERY_QUERY, ipv4addr);
+ StripNewLineChar(ipaddr); //Strip newline char from ipaddr
}
else
{
- OC_LOG(ERROR, TAG, "!! Bad input for IPV4 address. !!");
+ OC_LOG(ERROR, TAG, "!! Bad input for IP address. !!");
return OC_STACK_INVALID_PARAM;
}
- method = OC_REST_GET;
- }
- else
- {
- //Send discovery request on Wifi and Ethernet interface
- discoveryReqConnType = CT_DEFAULT;
- OICStrcpy(szQueryUri, sizeof(szQueryUri), MULTICAST_DISCOVERY_QUERY);
- method = OC_REST_DISCOVER;
}
+ snprintf(queryUri, sizeof (queryUri), DISCOVERY_QUERY, ipaddr);
cbData.cb = discoveryReqCB;
cbData.context = NULL;
/* Start a discovery query*/
OC_LOG_V(INFO, TAG, "Initiating %s Resource Discovery : %s\n",
- (UNICAST_DISCOVERY) ? "Unicast" : "Multicast",
- szQueryUri);
+ (UnicastDiscovery) ? "Unicast" : "Multicast",
+ queryUri);
- ret = OCDoResource(NULL, method, szQueryUri, 0, 0,
- discoveryReqConnType, OC_LOW_QOS,
- &cbData, NULL, 0);
+ ret = OCDoResource(NULL, OC_REST_DISCOVER, queryUri, 0, 0, CT_DEFAULT,
+ OC_LOW_QOS, &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "OCStack resource error");
switch(opt)
{
case 'u':
- UNICAST_DISCOVERY = atoi(optarg);
+ UnicastDiscovery = atoi(optarg);
break;
case 't':
- TEST_CASE = atoi(optarg);
+ TestCase = atoi(optarg);
break;
case 'c':
- CONN_TYPE = atoi(optarg);
+ ConnType = atoi(optarg);
break;
default:
PrintUsage();
}
}
- if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) ||
- (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS)||
- (CONN_TYPE < CT_ADAPTER_DEFAULT || CONN_TYPE >= MAX_CT))
+ if ((UnicastDiscovery != 0 && UnicastDiscovery != 1) ||
+ (TestCase < TEST_DISCOVER_REQ || TestCase >= MAX_TESTS)||
+ (ConnType < CT_ADAPTER_DEFAULT || ConnType >= MAX_CT))
{
PrintUsage();
return -1;
}
- if(CONN_TYPE == CT_ADAPTER_DEFAULT || CONN_TYPE == CT_IP)
+ if(ConnType == CT_ADAPTER_DEFAULT || ConnType == CT_IP)
{
discoveryReqConnType = CT_DEFAULT;
}
// Initialize Persistent Storage for SVR database
- OCPersistentStorage ps = {};
- ps.open = client_fopen;
- ps.read = fread;
- ps.write = fwrite;
- ps.close = fclose;
- ps.unlink = unlink;
+ OCPersistentStorage ps = { client_fopen, fread, fwrite, fclose, unlink };
OCRegisterPersistentStorageHandler(&ps);
/* Initialize OCStack*/
return 0;
}
-std::string getPortTBServer(OCClientResponse * clientResponse)
-{
- if(!clientResponse) return "";
- std::ostringstream ss;
- ss << clientResponse->devAddr.port;
- return ss.str();
-}
-
int parseClientResponse(OCClientResponse * clientResponse)
{
OCResourcePayload* res = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
// Initialize all global variables
coapServerResource.clear();
- coapServerPort.clear();
- coapServerIP.clear();
coapSecureResource = 0;
- while(res)
+ while (res)
{
coapServerResource.assign(res->uri);
OC_LOG_V(INFO, TAG, "Uri -- %s", coapServerResource.c_str());
- if(res->secure)
+ if (res->secure)
{
+ endpoint.port = res->port;
coapSecureResource = 1;
}
OC_LOG_V(INFO, TAG, "Secure -- %s", coapSecureResource == 1 ? "YES" : "NO");
- std::ostringstream ss;
- ss << res->port;
- coapServerPort = ss.str();
- std::cout<<"PORT: "<<coapServerPort;
-
// If we discovered a secure resource, exit from here
if (coapSecureResource)
{
res = res->next;
}
- coapServerIP = clientResponse->devAddr.addr;
-
- if(coapServerPort.length() == 0 || coapServerPort == "0")
- {
- coapServerPort = getPortTBServer(clientResponse);
- OC_LOG_V(INFO, TAG, "Hosting Server Port -- %s", coapServerPort.c_str());
- }
-
return 0;
}
#include "ocstack.h"
//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define DEFAULT_CONTEXT_VALUE 0x99
+
+//-----------------------------------------------------------------------------
// Typedefs
//-----------------------------------------------------------------------------
#include "ocserverbasicops.h"
#include "common.h"
+
int gQuitFlag = 0;
static LEDResource LED;
OCEntityHandlerResult
OCEntityHandlerCb (OCEntityHandlerFlag flag,
OCEntityHandlerRequest *entityHandlerRequest,
- void* callbackParam)
+ void* /*callbackParam*/)
{
OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
OCEntityHandlerResult ehResult = OC_EH_ERROR;
- OCEntityHandlerResponse response = {};
-
+ OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, { },{ 0 }, false };
// Validate pointer
if (!entityHandlerRequest)
{
return fopen(CRED_FILE, mode);
}
-int main(int argc, char* argv[])
+int main(int /*argc*/, char* /*argv*/[])
{
struct timespec timeout;
OC_LOG(DEBUG, TAG, "OCServer is starting...");
// Initialize Persistent Storage for SVR database
- OCPersistentStorage ps = {};
- ps.open = server_fopen;
- ps.read = fread;
- ps.write = fwrite;
- ps.close = fclose;
- ps.unlink = unlink;
+ OCPersistentStorage ps = { server_fopen, fread, fwrite, fclose, unlink };
OCRegisterPersistentStorageHandler(&ps);
if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
"/oic/p",
"/oic/res/types/d",
"/oic/ad",
- "/oic/sec/acl"
+ "/oic/sec/acl",
+ "/oic/sec/amacl"
],
"perms": 2,
"ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
"doxm": {
"oxm": [0],
"oxmsel": 0,
+ "sct": 1,
"owned": true,
"deviceid": "MjIyMjIyMjIyMjIyMjIyMg==",
"ownr": "MjIyMjIyMjIyMjIyMjIyMg=="
"/oic/p",
"/oic/res/types/d",
"/oic/ad",
- "/oic/sec/acl"
+ "/oic/sec/acl",
+ "/oic/sec/amacl"
],
"perms": 2,
"ownrs" : ["MTExMTExMTExMTExMTExMQ=="]
},
{
"sub": "MjIyMjIyMjIyMjIyMjIyMg==",
+ "rsrc": ["/oic/sec/acl",
+ "/oic/sec/cred"],
+ "perms": 8,
+ "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+ },
+ {
+ "sub": "MjIyMjIyMjIyMjIyMjIyMg==",
+ "rsrc": ["/a/led"],
+ "perms": 6,
+ "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+ },
+ {
+ "sub": "MTExMTIyMjIzMzMzNDQ0NA==",
"rsrc": ["/a/led"],
"perms": 6,
+ "prds" : ["20150630T060000/20150630T220000", "20150630T060000/20150630T200000"],
+ "recurs" : ["FREQ=DAILY; BYDAY=MO, WE, FR", "FREQ=DAILY; BYDAY=TU, TH; UNTIL=20160630"],
+ "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+ },
+ {
+ "sub": "Nzc3Nzc3Nzc3Nzc3Nzc3Nw==",
+ "rsrc": ["/a/led"],
+ "perms": 6,
+ "prds" : ["20150630T060000/20150630T220000"],
+ "recurs" : ["FREQ=DAILY; UNTIL=20150630"],
"ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
}
],
"doxm": {
"oxm": [0],
"oxmsel": 0,
+ "sct": 1,
"owned": true,
"deviceid": "MTExMTExMTExMTExMTExMQ==",
- "ownr": "MjIyMjIyMjIyMjIyMjIyMg=="
+ "ownr": "YWRtaW5EZXZpY2VVVUlEAA=="
},
"cred": [{
"credid": 1,
"credtyp": 1,
"pvdata": "QUFBQUFBQUFBQUFBQUFBQQ==",
"ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+ },
+ {
+ "credid": 2,
+ "sub": "MTExMTIyMjIzMzMzNDQ0NA==",
+ "credtyp": 1,
+ "pvdata": "QUFBQUFBQUFBQUFBQUFBQQ==",
+ "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+ },
+ {
+ "credid": 3,
+ "sub": "Nzc3Nzc3Nzc3Nzc3Nzc3Nw==",
+ "credtyp": 1,
+ "pvdata": "QUFBQUFBQUFBQUFBQUFBQQ==",
+ "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
}]
}
help_vars.Add(ListVariable('TARGET_TRANSPORT', 'Target transport', 'ALL', ['ALL', 'IP', 'BT', 'BLE']))
help_vars.Add(EnumVariable('TARGET_ARCH', 'Target architecture', default_arch, os_arch_map[target_os]))
help_vars.Add(EnumVariable('SECURED', 'Build with DTLS', '0', allowed_values=('0', '1')))
+help_vars.Add(EnumVariable('ROUTING', 'Enable routing', 'EP', allowed_values=('GW', 'EP')))
######################################################################
# Platform(build target) specific options: SDK/NDK & toolchain
env.SetDir(env.GetLaunchDir())
env['ROOT_DIR']=env.GetLaunchDir()
+env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+if env.get('ROUTING') == 'GW':
+ env.AppendUnique(CPPDEFINES = ['ROUTING_GATEWAY'])
+elif env.get('ROUTING') == 'EP':
+ env.AppendUnique(CPPDEFINES = ['ROUTING_EP'])
+env.AppendUnique(CPPDEFINES = ['__TIZEN__'])
+
Export('env')
######################################################################
#include "logger.h"
#include "occlient.h"
#include "ocpayload.h"
+#include "payload_logging.h"
+
using namespace std;
+#ifdef ROUTING_GATEWAY
+/**
+ * Maximum number of gateway requests to form the routing table.
+ */
+#define MAX_NUM_GATEWAY_REQUEST 20
+
+/**
+ * Sleep duration after every OCProcess().
+ */
+#define SLEEP_DURATION 100000
+#endif
+
// Tracking user input
-static int UNICAST_DISCOVERY = 0;
-static int TEST_CASE = 0;
-static int CONNECTIVITY = 0;
-
-static const char * UNICAST_DEVICE_DISCOVERY_QUERY = "coap://%s/oic/d";
-static const char * MULTICAST_DEVICE_DISCOVERY_QUERY = "/oic/d";
-static const char * UNICAST_PLATFORM_DISCOVERY_QUERY = "coap://%s/oic/p";
-static const char * MULTICAST_PLATFORM_DISCOVERY_QUERY = "/oic/p";
-
-static const char * UNICAST_RESOURCE_DISCOVERY_QUERY = "coap://%s/oic/res";
-static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oic/res";
-// The following variable determines the interface protocol (IPv4, IPv6, etc)
-//to be used for sending unicast messages. Default set to IPv4.
-static OCConnectivityType OC_CONNTYPE = CT_ADAPTER_IP;
-static std::string coapServerIP = "255.255.255.255";
-static std::string coapServerPort = "5683";
+static int g_unicastDiscovery = 0;
+static int g_testCase = 0;
+static int g_connectivity = 0;
+
+static const char *DEVICE_DISCOVERY_QUERY = "%s/oic/d";
+static const char *PLATFORM_DISCOVERY_QUERY = "%s/oic/p";
+static const char *RESOURCE_DISCOVERY_QUERY = "%s/oic/res";
+
+//The following variable determines the interface protocol (IPv4, IPv6, etc)
+//to be used for sending unicast messages. Default set to IP dual stack.
+static OCConnectivityType g_connType = CT_ADAPTER_IP;
+static OCDevAddr g_serverAddr;
+static char g_discoveryAddr[100];
static std::string coapServerResource = "/a/light";
-// Size to hold ADDRESS
-static const int MAX_ADDR_SIZE = 24;
-//Use unicastAddr for both InitDiscovery and InitPlatformOrDeviceDiscovery
-char unicastAddr[MAX_ADDR_SIZE];
+
void StripNewLineChar(char* str);
// The handle for the observe registration
if(!payload)
{
std::cout << "Failed to create put payload object"<<std::endl;
- std::exit(1);
+ exit(1);
}
OCRepPayloadSetPropInt(payload, "power", 15);
cout << "Hello";
cout << "\nUsage : occlient -u <0|1> -t <1..17> -c <0|1|2>";
cout << "\n-u <0|1> : Perform multicast/unicast discovery of resources";
- cout << "\n-c 0 : Default IPv4 and IPv6 auto-selection";
- cout << "\n-c 1 : IPv4 Connectivity Type";
- cout << "\n-c 2 : IPv6 Connectivity Type (IPv6 not currently supported)";
- cout << "\n-c 3 : EDR Connectivity Type (IPv6 not currently supported)";
+ cout << "\n-c 0 : Default IP selection";
+ cout << "\n-c 1 : IP Connectivity Type";
+ cout << "\n-c 2 : EDR Connectivity Type (IPv6 not currently supported)";
cout << "\n-t 1 : Discover Resources";
cout << "\n-t 2 : Discover Resources and Initiate Nonconfirmable Get Request";
cout << "\n-t 3 : Discover Resources and Initiate Nonconfirmable Get Request with query filter";
}
OCStackResult InvokeOCDoResource(std::ostringstream &query,
+ OCDevAddr *remoteAddr,
OCMethod method,
OCQualityOfService qos,
OCClientResponseHandler cb,
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- ret = OCDoResource(&handle, method, query.str().c_str(), 0,
+ ret = OCDoResource(&handle, method, query.str().c_str(), remoteAddr,
(method == OC_REST_PUT) ? putPayload() : NULL,
- (OC_CONNTYPE), qos, &cbData, options, numOptions);
+ (g_connType), qos, &cbData, options, numOptions);
if (ret != OC_STACK_OK)
{
return ret;
}
-OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+OCStackApplicationResult putReqCB(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
- if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
+ if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
cout << "\nCallback Context for PUT recvd successfully";
}
- if(clientResponse)
+ if (clientResponse)
{
cout << "\nStackResult: " << getResult(clientResponse->result);
cout << "\nJSON = " << clientResponse->payload;
return OC_STACK_DELETE_TRANSACTION;
}
-OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
+OCStackApplicationResult postReqCB(void *ctx, OCDoHandle /*handle*/,
+ OCClientResponse *clientResponse)
{
- if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
+ if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
cout << "\nCallback Context for POST recvd successfully";
}
- if(clientResponse)
+ if (clientResponse)
{
cout << "\nStackResult: " << getResult(clientResponse->result);
cout << "\nJSON = " << clientResponse->payload;
}
OCStackApplicationResult deleteReqCB(void *ctx,
- OCDoHandle handle, OCClientResponse *clientResponse)
+ OCDoHandle /*handle*/,
+ OCClientResponse *clientResponse)
{
if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
if(clientResponse)
{
cout << "\nStackResult: " << getResult(clientResponse->result);
- //OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ //OC_LOG_PAYLOAD(INFO, clientResponse->payload);
}
else
{
return OC_STACK_DELETE_TRANSACTION;
}
-OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
- if(clientResponse == NULL)
+ if (clientResponse == NULL)
{
cout << "\ngetReqCB received NULL clientResponse";
return OC_STACK_DELETE_TRANSACTION;
}
- if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
+ if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
cout << "\nCallback Context for GET query recvd successfully";
}
cout << "\nSEQUENCE NUMBER: " << clientResponse->sequenceNumber;
//OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
- if(clientResponse->numRcvdVendorSpecificHeaderOptions > 0)
+ if (clientResponse->numRcvdVendorSpecificHeaderOptions > 0)
{
cout << "\nReceived 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)
+ if (((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
{
cout << "\nReceived option ID " << ((OCHeaderOption)rcvdOptions[i]).optionID;
}
return OC_STACK_DELETE_TRANSACTION;
}
-OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
- if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
+ if (ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
cout << "\nCallback Context for OBS query recvd successfully";
}
- if(clientResponse)
+ if (clientResponse)
{
cout << "\nStackResult: " << getResult(clientResponse->result);
cout << "\nSEQUENCE NUMBER: " << clientResponse->sequenceNumber;
cout << "\nCallback Context for OBSERVE notification recvd successfully ";
- //OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ //OC_LOG_PAYLOAD(INFO, clientResponse->payload);
gNumObserveNotifies++;
if (gNumObserveNotifies == 15) //large number to test observing in DELETE case.
{
- if(TEST_CASE == TEST_OBS_REQ_NON || TEST_CASE == TEST_OBS_REQ_CON)
+ if (g_testCase == TEST_OBS_REQ_NON || g_testCase == TEST_OBS_REQ_CON)
{
if (OCCancel (gObserveDoHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK)
{
}
return OC_STACK_DELETE_TRANSACTION;
}
- else if(TEST_CASE == TEST_OBS_REQ_NON_CANCEL_IMM)
+ else if (g_testCase == TEST_OBS_REQ_NON_CANCEL_IMM)
{
if (OCCancel (gObserveDoHandle, OC_HIGH_QOS, NULL, 0) != OC_STACK_OK)
{
}
}
}
- if(clientResponse->sequenceNumber == OC_OBSERVE_REGISTER)
+ if (clientResponse->sequenceNumber == OC_OBSERVE_REGISTER)
{
cout << "\nThis also serves as a registration confirmation";
}
- else if(clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER)
+ else if (clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER)
{
cout << "\nThis also serves as a deregistration confirmation";
return OC_STACK_DELETE_TRANSACTION;
}
- else if(clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION)
+ else if (clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION)
{
cout << "\nThis also tells you that registration/deregistration failed";
return OC_STACK_DELETE_TRANSACTION;
return OC_STACK_KEEP_TRANSACTION;
}
#ifdef WITH_PRESENCE
-OCStackApplicationResult presenceCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+OCStackApplicationResult presenceCB(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
{
cout << "\nStackResult: " << getResult(clientResponse->result);
cout << "\nNONCE NUMBER: " << clientResponse->sequenceNumber;
cout << "\nCallback Context for Presence notification recvd successfully ";
- //OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ //OC_LOG_PAYLOAD(INFO, clientResponse->payload);
gNumPresenceNotifies++;
if (gNumPresenceNotifies == 20)
{
#endif
// This is a function called back when a device is discovered
-OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
- OCClientResponse * clientResponse)
+OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
{
if (clientResponse)
{
+ if (NULL == clientResponse->payload)
+ {
+ cout << "\nPayload is NULL, No resources found";
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
cout << "\nStackResult: " << getResult(clientResponse->result);
std::string connectionType = getConnectivityType (clientResponse->connType);
cout << "\nDiscovered on " << connectionType.c_str();
cout << "\nDevice ======> Discovered ";
cout << clientResponse->devAddr.addr;
- //TODO: Bug in RI layer. Its returning 65600 instead of CT_ADAPTER_IP
- if (65600 == clientResponse->connType)
+ if (CT_ADAPTER_IP == clientResponse->connType)
{
cout << ":" << clientResponse->devAddr.port;
}
- //OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ //OC_LOG_PAYLOAD(INFO, clientResponse->payload);
cout << "\nConnectivity type: " << clientResponse->connType;
- OC_CONNTYPE = clientResponse->connType;
+ g_connType = clientResponse->connType;
+ g_serverAddr = clientResponse->devAddr;
parseClientResponse(clientResponse);
- switch(TEST_CASE)
+ switch(g_testCase)
{
case TEST_GET_REQ_NON:
InitGetRequest(OC_LOW_QOS, 0, 0);
return OC_STACK_KEEP_TRANSACTION;
}
-OCStackApplicationResult PlatformDiscoveryReqCB (void* ctx, OCDoHandle handle,
- OCClientResponse * clientResponse)
+OCStackApplicationResult PlatformDiscoveryReqCB(void* ctx,
+ OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
{
cout << "\nCallback Context for Platform DISCOVER query recvd successfully";
}
- if(clientResponse)
+ if (clientResponse)
{
//OC_LOG truncates the response as it is too long.
- //OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ //OC_LOG_PAYLOAD(INFO, clientResponse->payload);
}
else
{
cout << "\nPlatformDiscoveryReqCB received Null clientResponse";
}
- return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
+ return (g_unicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
}
-OCStackApplicationResult DeviceDiscoveryReqCB (void* ctx, OCDoHandle handle,
- OCClientResponse * clientResponse)
+OCStackApplicationResult DeviceDiscoveryReqCB(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
{
cout << "\nCallback Context for Device DISCOVER query recvd successfully";
}
- if(clientResponse)
+ if (clientResponse)
{
//OC_LOG truncates the response as it is too long.
cout << "\nDiscovery response: ";
cout << "\nPlatformDiscoveryReqCB received Null clientResponse";
}
- return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
+ return (g_unicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION;
}
#ifdef WITH_PRESENCE
cout << "\nExecuting " << __func__;
std::ostringstream query;
std::ostringstream querySuffix;
- query << "coap://" << coapServerIP << ":" << coapServerPort << OC_RSRVD_PRESENCE_URI;
- if(TEST_CASE == TEST_OBS_PRESENCE)
+ query << OC_RSRVD_PRESENCE_URI;
+ if (g_testCase == TEST_OBS_PRESENCE)
{
- result = InvokeOCDoResource(query, OC_REST_PRESENCE, OC_LOW_QOS,
- presenceCB, NULL, 0);
+ result = InvokeOCDoResource(query, &g_serverAddr, OC_REST_PRESENCE,
+ OC_LOW_QOS, presenceCB, NULL, 0);
}
- if(TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTER || TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTERS)
+ if (g_testCase == TEST_OBS_PRESENCE_WITH_FILTER || g_testCase == TEST_OBS_PRESENCE_WITH_FILTERS)
{
querySuffix.str("");
querySuffix << query.str() << "?rt=core.led";
- result = InvokeOCDoResource(querySuffix, OC_REST_PRESENCE, OC_LOW_QOS,
- presenceCB, NULL, 0);
+ result = InvokeOCDoResource(querySuffix, &g_serverAddr, OC_REST_PRESENCE,
+ OC_LOW_QOS, presenceCB, NULL, 0);
}
- if(TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTERS)
+ if (g_testCase == TEST_OBS_PRESENCE_WITH_FILTERS)
{
- if(result == OC_STACK_OK)
+ if (result == OC_STACK_OK)
{
querySuffix.str("");
querySuffix << query.str() << "?rt=core.fan";
- result = InvokeOCDoResource(querySuffix, OC_REST_PRESENCE, OC_LOW_QOS,
+ result = InvokeOCDoResource(querySuffix, &g_serverAddr, OC_REST_PRESENCE, OC_LOW_QOS,
presenceCB, NULL, 0);
}
}
- if(TEST_CASE == TEST_OBS_MULTICAST_PRESENCE)
+ if (g_testCase == TEST_OBS_MULTICAST_PRESENCE)
{
- if(result == OC_STACK_OK)
+ if (result == OC_STACK_OK)
{
std::ostringstream multicastPresenceQuery;
multicastPresenceQuery.str("");
multicastPresenceQuery << "coap://" << OC_MULTICAST_PREFIX << OC_RSRVD_PRESENCE_URI;
- result = InvokeOCDoResource(multicastPresenceQuery, OC_REST_PRESENCE, OC_LOW_QOS,
+ result = InvokeOCDoResource(multicastPresenceQuery, &g_serverAddr, OC_REST_PRESENCE, OC_LOW_QOS,
presenceCB, NULL, 0);
}
}
{
cout << "\nExecuting " << __func__;
std::ostringstream query;
-
- //TODO: Bug in RI layer. Its returning 65600 instead of CT_ADAPTER_IP
- if (65600 == OC_CONNTYPE)
- {
- query << "coap://" << coapServerIP << ":" << coapServerPort << "/SomeUnknownResource";
- }
- else
- {
- query << "coap://" << coapServerIP << "/SomeUnknownResource";
- }
-
- return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
+ query << "/SomeUnknownResource";
+ return (InvokeOCDoResource(query, &g_serverAddr, OC_REST_GET, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
getReqCB, NULL, 0));
}
{
cout << "\nExecuting " << __func__;
std::ostringstream query;
- //TODO: Bug in RI layer. Its returning 65600 instead of CT_ADAPTER_IP
- if (65600 == OC_CONNTYPE)
- {
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
- }
- else
- {
- query << "coap://" << coapServerIP << coapServerResource;
- }
- return (InvokeOCDoResource(query,
- OC_REST_OBSERVE, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, obsReqCB, NULL, 0));
+ query << coapServerResource;
+ return (InvokeOCDoResource(query, &g_serverAddr, OC_REST_OBSERVE,
+ (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, obsReqCB, NULL, 0));
}
int InitPutRequest(OCQualityOfService qos)
{
cout << "\nExecuting " << __func__;
std::ostringstream query;
- //TODO: Bug in RI layer. Its returning 65600 instead of CT_ADAPTER_IP
- if (65600 == OC_CONNTYPE)
- {
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
- }
- else
- {
- query << "coap://" << coapServerIP << coapServerResource;
- }
- return (InvokeOCDoResource(query, OC_REST_PUT, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
+ query << coapServerResource;
+ return (InvokeOCDoResource(query, &g_serverAddr, OC_REST_PUT, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS,
putReqCB, NULL, 0));
}
OCStackResult result;
cout << "\nExecuting " << __func__;
std::ostringstream query;
-
- //TODO: Bug in RI layer. Its returning 65600 instead of CT_ADAPTER_IP
- if (65600 == OC_CONNTYPE)
- {
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
- }
- else
- {
- query << "coap://" << coapServerIP << coapServerResource;
- }
+ query << coapServerResource;
// First POST operation (to create an Light instance)
- result = InvokeOCDoResource(query, OC_REST_POST,
+ result = InvokeOCDoResource(query, &g_serverAddr, OC_REST_POST,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
postReqCB, NULL, 0);
if (OC_STACK_OK != result)
}
// Second POST operation (to create an Light instance)
- result = InvokeOCDoResource(query, OC_REST_POST,
+ result = InvokeOCDoResource(query, &g_serverAddr, OC_REST_POST,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
postReqCB, NULL, 0);
if (OC_STACK_OK != result)
}
// This POST operation will update the original resourced /a/light
- return (InvokeOCDoResource(query, OC_REST_POST,
+ return (InvokeOCDoResource(query, &g_serverAddr, OC_REST_POST,
((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS),
postReqCB, NULL, 0));
}
{
sleep (30);//long enough to give the server time to finish deleting the resource.
std::ostringstream query;
-
- //TODO: Bug in RI layer. Its returning 65600 instead of CT_ADAPTER_IP
- if (65600 == OC_CONNTYPE)
- {
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
- }
- else
- {
- query << "coap://" << coapServerIP << coapServerResource;
- }
+ query << coapServerResource;
cout << "\nExecuting " << __func__;
qos = OC_HIGH_QOS;
}
- OCStackResult result = InvokeOCDoResource(query, OC_REST_DELETE,
+ OCStackResult result = InvokeOCDoResource(query, &g_serverAddr, OC_REST_DELETE,
qos,
deleteReqCB, NULL, 0);
{
OCStackResult result;
std::ostringstream query;
- //TODO: Bug in RI layer. Its returning 65600 instead of CT_ADAPTER_IP
- if (65600 == OC_CONNTYPE)
- {
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
- }
- else
- {
- query << "coap://" << coapServerIP << coapServerResource;
- }
+ query << coapServerResource;
cout << "\nExecuting " << __func__;
// First DELETE operation
- result = InvokeOCDoResource(query, OC_REST_DELETE,
+ result = InvokeOCDoResource(query, &g_serverAddr, OC_REST_DELETE,
qos,
deleteReqCB, NULL, 0);
if (OC_STACK_OK != result)
cout << "\nExecuting " << __func__;
std::ostringstream query;
-
- //TODO: Bug in RI layer. Its returning 65600 instead of CT_ADAPTER_IP
- if (65600 == OC_CONNTYPE)
- {
- query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
- }
- else
- {
- query << "coap://" << coapServerIP << coapServerResource;
- }
+ query << coapServerResource;
// ocserver is written to only process "power<X" query.
if (getWithQuery)
}
if (withVendorSpecificHeaderOptions)
{
- return (InvokeOCDoResource(query, OC_REST_GET,
+ return (InvokeOCDoResource(query, &g_serverAddr, OC_REST_GET,
(qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, getReqCB, options, 2));
}
else
{
- return (InvokeOCDoResource(query, OC_REST_GET,
+ return (InvokeOCDoResource(query, &g_serverAddr, OC_REST_GET,
(qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, getReqCB, NULL, 0));
}
}
OCCallbackData cbData;
char szQueryUri[64] = { 0 };
+ snprintf(szQueryUri, sizeof (szQueryUri) - 1, PLATFORM_DISCOVERY_QUERY, g_discoveryAddr);
+
cbData.cb = PlatformDiscoveryReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- if(UNICAST_DISCOVERY)
- {
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_PLATFORM_DISCOVERY_QUERY, unicastAddr);
- }
- else
- {
- strncpy(szQueryUri, MULTICAST_PLATFORM_DISCOVERY_QUERY, sizeof(szQueryUri) -1 );
- }
- szQueryUri[sizeof(szQueryUri) -1] = '\0';
-
- if(UNICAST_DISCOVERY)
- {
- ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,
- (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, &cbData, NULL, 0);
- }
- else
- {
-
- ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, OC_CONNTYPE,
- (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, &cbData, NULL, 0);
- }
-
+ ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
+ (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
+ &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
cout << "\nOCStack device error";
OCStackResult ret;
OCCallbackData cbData;
- char szQueryUri[64] = { 0 };
+ char szQueryUri[100] = { 0 };
+
+ snprintf(szQueryUri, sizeof (szQueryUri) - 1, DEVICE_DISCOVERY_QUERY, g_discoveryAddr);
cbData.cb = DeviceDiscoveryReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- if(UNICAST_DISCOVERY)
- {
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_DEVICE_DISCOVERY_QUERY, unicastAddr);
- }
- else
- {
- strncpy(szQueryUri, MULTICAST_DEVICE_DISCOVERY_QUERY, sizeof(szQueryUri) -1 );
- }
- szQueryUri[sizeof(szQueryUri) -1] = '\0';
-
- if(UNICAST_DISCOVERY)
- {
- ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,
- (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, &cbData, NULL, 0);
- }
- else
- {
- ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, OC_CONNTYPE,
- (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, &cbData, NULL, 0);
- }
-
+ ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
+ (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
+ &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
cout << "\nOCStack device error";
{
OCStackResult ret;
OCCallbackData cbData;
- /* Start a discovery query*/
- char szQueryUri[64] = { 0 };
+ char szQueryUri[100] = { 0 };
- if (UNICAST_DISCOVERY)
- {
- snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_RESOURCE_DISCOVERY_QUERY, unicastAddr);
- }
- else
- {
- strcpy(szQueryUri, MULTICAST_RESOURCE_DISCOVERY_QUERY);
- }
+ snprintf(szQueryUri, sizeof (szQueryUri) - 1, RESOURCE_DISCOVERY_QUERY, g_discoveryAddr);
cbData.cb = discoveryReqCB;
cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- if(UNICAST_DISCOVERY)
- {
- ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE,
- (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, &cbData, NULL, 0);
- }
- else
- {
- ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, OC_CONNTYPE,
- (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS, &cbData, NULL, 0);
- }
+
+ ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, CT_DEFAULT,
+ (qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS,
+ &cbData, NULL, 0);
if (ret != OC_STACK_OK)
{
cout << "\nOCStack resource error";
switch(opt)
{
case 'u':
- UNICAST_DISCOVERY = atoi(optarg);
+ g_unicastDiscovery = atoi(optarg);
break;
case 't':
- TEST_CASE = atoi(optarg);
+ g_testCase = atoi(optarg);
break;
case 'c':
- CONNECTIVITY = atoi(optarg);
+ g_connectivity = atoi(optarg);
break;
default:
PrintUsage();
}
}
- if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) ||
- (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) ||
- (CONNECTIVITY < CT_ADAPTER_DEFAULT || CONNECTIVITY >= MAX_CT))
+ if ((g_unicastDiscovery != 0 && g_unicastDiscovery != 1) ||
+ (g_testCase < TEST_DISCOVER_REQ || g_testCase >= MAX_TESTS) ||
+ (g_connectivity < CT_ADAPTER_DEFAULT || g_connectivity >= MAX_CT))
{
PrintUsage();
return -1;
cout << "\nEntering occlient main loop...\n";
- /* Initialize OCStack*/
- if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK)
+ if (OCInit1(OC_CLIENT, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS) != OC_STACK_OK)
{
cout << "\nOCStack init error";
return 0;
}
- if(CONNECTIVITY == CT_ADAPTER_DEFAULT || CONNECTIVITY == CT_IPV4)
+#ifdef ROUTING_GATEWAY
+ /*
+ * Before invoking Discover resource, we process the gateway requests
+ * and form the routing table.
+ */
+ for (int index = 0; index < MAX_NUM_GATEWAY_REQUEST; index++)
{
- OC_CONNTYPE = CT_ADAPTER_IP;
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+ usleep(SLEEP_DURATION);
}
- else if(CONNECTIVITY == CT_IPV6)
+#endif
+
+ if (g_connectivity == CT_ADAPTER_DEFAULT || g_connectivity == CT_IP)
{
- //TODO: Remove when IPv6 is available.
- cout << "\nIPv6 is currently not supported !!!!";
- PrintUsage();
- return -1;
+ g_connType = CT_ADAPTER_IP;
}
- else if(CONNECTIVITY == CT_EDR)
+ else if(g_connectivity == CT_EDR)
{
- OC_CONNTYPE = CT_ADAPTER_RFCOMM_BTEDR;
-
- cout << "\nSelected EDR Adapter!!! Device is scanning for OIC supported Servers....\n";
- // Sleep is added as after initialization, EDR adapter needs to start scanning and find
- // the devices.
- sleep(10);
+ cout << "\nSelected EDR Adapter\n";
+ g_connType = CT_ADAPTER_RFCOMM_BTEDR;
}
else
{
PrintUsage();
}
- if (UNICAST_DISCOVERY)
+ g_discoveryAddr[0] = '\0';
+
+ if (g_unicastDiscovery)
{
cout << "\nEnter address of Server hosting resource as given below:";
cout << "\nIP Adapter: 192.168.0.15:45454(IP:Port)";
cout << "\nEDR/BLE Adapter: AB:BC:CD:DE:EF:FG(MAC Address)";
cout << "\nInput: ";
- if (fgets(unicastAddr, MAX_ADDR_SIZE, stdin))
+ if (fgets(g_discoveryAddr, sizeof (g_discoveryAddr), stdin))
{
//Strip newline char from unicastAddr
- StripNewLineChar(unicastAddr);
+ StripNewLineChar(g_discoveryAddr);
}
else
{
}
}
- if(UNICAST_DISCOVERY == 0 && TEST_CASE == TEST_DISCOVER_DEV_REQ)
+ if (g_unicastDiscovery == 0 && g_testCase == TEST_DISCOVER_DEV_REQ)
{
InitDeviceDiscovery(OC_LOW_QOS);
}
- else if(UNICAST_DISCOVERY == 0 && TEST_CASE == TEST_DISCOVER_PLATFORM_REQ)
+ else if (g_unicastDiscovery == 0 && g_testCase == TEST_DISCOVER_PLATFORM_REQ)
{
InitPlatformDiscovery(OC_LOW_QOS);
}
}
// Break from loop with Ctrl+C
+ OC_LOG(INFO, TAG, "Entering occlient main loop...");
signal(SIGINT, handleSigInt);
while (!gQuitFlag)
{
cout << "\nOCStack process error\n";
return 0;
}
-
- sleep(2);
+#ifndef ROUTING_GATEWAY
+ sleep(1);
+#endif
}
cout << "\nExiting occlient main loop...\n";
return 0;
}
-std::string getIPAddrTBServer(OCClientResponse * clientResponse)
-{
- if (!clientResponse)
- {
- return "";
- }
- if (!clientResponse->addr)
- {
- return "";
- }
-
- return std::string(clientResponse->devAddr.addr);
-}
-
-std::string getPortTBServer(OCClientResponse * clientResponse)
-{
- if (!clientResponse)
- {
- return "";
- }
- if (!clientResponse->addr)
- {
- return "";
- }
- std::ostringstream ss;
- ss << clientResponse->devAddr.port;
- return ss.str();
-}
-
std::string getConnectivityType (OCConnectivityType connType)
{
switch (connType & CT_MASK_ADAPTER)
}
}
-std::string getQueryStrForGetPut(OCClientResponse * clientResponse)
+std::string getQueryStrForGetPut(OCClientResponse * /*clientResponse*/)
{
-
return "/a/light";
}
void parseClientResponse(OCClientResponse * clientResponse)
{
- coapServerIP = getIPAddrTBServer(clientResponse);
- coapServerPort = getPortTBServer(clientResponse);
coapServerResource = getQueryStrForGetPut(clientResponse);
}
*/
typedef enum {
CT_ADAPTER_DEFAULT = 0,
- CT_IPV4,
- CT_IPV6,
+ CT_IP,
CT_EDR,
MAX_CT
} CLIENT_CONNECTIVITY_TYPE;
--- /dev/null
+/* ****************************************************************
+ *
+ * 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 <string.h>
+#include <string>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include <array>
+#include <iostream>
+#include "ocstack.h"
+#include "logger.h"
+#include "ocpayload.h"
+
+using namespace std;
+
+#define TAG "ocrouting"
+
+int gQuitFlag = 0;
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+ if (signum == SIGINT)
+ {
+ gQuitFlag = 1;
+ }
+}
+
+int main()
+{
+ cout << "\nOCRouting sample is starting...";
+
+ if (OCInit(NULL, 0, OC_GATEWAY) != OC_STACK_OK)
+ {
+ cout << "\nOCStack init error";
+ return 0;
+ }
+
+ // Break from loop with Ctrl-C
+ cout << "\nEntering ocrouting main loop...";
+
+ signal(SIGINT, handleSigInt);
+
+ while (!gQuitFlag)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ cout << "\nOCStack process error";
+ return 0;
+ }
+ }
+
+ cout << "\nExiting ocrouting main loop...";
+
+ if (OCStop() != OC_STACK_OK)
+ {
+ cout << "\nOCStack process error";
+ }
+
+ return 0;
+}
}
}
+ OCPayloadDestroy(response.payload);
return ehResult;
}
cout << "\nOCStack process error";
return 0;
}
-
- sleep(2);
+#ifndef ROUTING_GATEWAY
+ sleep(1);
+#endif
}
/*
*/
int createLightResource (char *uri, LightResource *lightResource);
-/* This method converts the payload to JSON format */
-char* constructJsonResponse (OCEntityHandlerRequest *ehRequest);
+/* This method constructs a response from the request */
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
/* This method changes the Light power using an independent thread
* and notifies the observers of new state of the resource.
/* Following methods process the PUT, GET, POST, Delete,
* & Observe requests */
OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
- char *payload,
- uint16_t maxPayloadSize);
+ OCRepPayload **payload);
OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
- char *payload,
- uint16_t maxPayloadSize);
+ OCRepPayload **payload);
OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
OCEntityHandlerResponse *response,
- char *payload,
- uint16_t maxPayloadSize);
-OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest,
- char *payload,
- uint16_t maxPayloadSize);
-
-OCEntityHandlerResult ProcessNonExistingResourceRequest (OCEntityHandlerRequest *ehRequest,
- char *payload,
- uint16_t maxPayloadSize);
+ OCRepPayload **payload);
+OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest);
+
+OCEntityHandlerResult ProcessNonExistingResourceRequest (OCEntityHandlerRequest *ehRequest);
void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest);
void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest);
%build
scons TARGET_OS=tizen -c
-scons TARGET_OS=tizen TARGET_TRANSPORT=%{TARGET_TRANSPORT} SECURED=%{SECURED} RELEASE=%{RELEASE}
+scons TARGET_OS=tizen TARGET_TRANSPORT=%{TARGET_TRANSPORT} SECURED=%{SECURED} RELEASE=%{RELEASE} ROUTING=%{ROUTING}
%install
cp -rf %{ROOTDIR}/com.oic.ri.sample.xml %{buildroot}/%{_datadir}/packages
cp -rf %{ROOTDIR}/scons/occlient %{buildroot}/usr/apps/com.oic.ri.sample/bin/
cp -rf %{ROOTDIR}/scons/ocserver %{buildroot}/usr/apps/com.oic.ri.sample/bin/
+cp -rf %{ROOTDIR}/scons/ocrouting %{buildroot}/usr/apps/com.oic.ri.sample/bin/
%files
%manifest com.oic.ri.sample.manifest
%defattr(-,root,root,-)
/usr/apps/com.oic.ri.sample/bin/occlient
/usr/apps/com.oic.ri.sample/bin/ocserver
+/usr/apps/com.oic.ri.sample/bin/ocrouting
/%{_datadir}/packages/com.oic.ri.sample.xml
target_os = env.get('TARGET_OS')
transport = env.get('TARGET_TRANSPORT')
secured = env.get('SECURED')
-
+routing = env.get('ROUTING')
OIC_LIB = 'oic'
root_dir = env.get('ROOT_DIR')
build_dir = env.get('BUILD_DIR')
sample_dir = build_dir
-env.AppendUnique(CPPFLAGS = ['-std=c++11', '-fPIC', '-D__TIZEN__','-DWITH_POSIX', '-Wall', '-DSLP_SDK_LOG', '-g','-D_GNU_SOURCE','-DTIZEN_DEBUG_ENABLE', '-DTB_LOG','`pkg-config', '--cflags', '--libs','dlog', 'com.oic.ri', 'capi-network-wifi',
+env.AppendUnique(CPPFLAGS = ['-std=c++0x', '-fPIC', '-D__TIZEN__','-DWITH_POSIX', '-Wall', '-DSLP_SDK_LOG', '-g','-D_GNU_SOURCE','-DTIZEN_DEBUG_ENABLE', '-DTB_LOG','`pkg-config', '--cflags', '--libs','dlog', 'com.oic.ri', 'capi-network-wifi',
'gobject-2.0','glib-2.0`'])
+if routing == 'GW':
+ env.AppendUnique(CPPDEFINES = ['ROUTING_GATEWAY'])
+elif routing == 'EP':
+ env.AppendUnique(CPPDEFINES = ['ROUTING_EP'])
+
env.Append(LIBS=[
'-lm', '-lpthread', '-lrt', '-ldl', '-lstdc++', '-lgobject-2.0', '-lgio-2.0', '-lglib-2.0', '-lcapi-network-wifi', '-ldlog', '-lcapi-network-bluetooth', '-lconnectivity_abstraction', 'coap', '-loctbstack', 'ocsrm', 'c_common'
])
#env.Program('ri_sample', [ri_sample_src,])
env.Program('occlient', [sample_dir + 'occlient.cpp', sample_dir + 'common.cpp'])
-env.Program('ocserver', [sample_dir + 'ocserver.cpp', sample_dir + 'common.cpp'])
\ No newline at end of file
+env.Program('ocserver', [sample_dir + 'ocserver.cpp', sample_dir + 'common.cpp'])
+env.Program('ocrouting', [sample_dir + 'ocrouting.cpp', sample_dir + 'common.cpp'])
release_mode = env.get('RELEASE')
secured = env.get('SECURED')
logging = env.get('LOGGING')
+routing = env.get('ROUTING')
+
+env.PrependUnique(CPPPATH = [
+ '../../../../logger/include',
+ '../../../../stack/include',
+ '../../../../../../extlibs/cjson',
+ '../../../../../oc_logger/include',
+ '../../../../../connectivity/lib/libcoap-4.1.1'
+ ])
+
+env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+if routing == 'GW':
+ env.AppendUnique(CPPDEFINES = ['ROUTING_GATEWAY'])
+elif routing == 'EP':
+ env.AppendUnique(CPPDEFINES = ['ROUTING_EP'])
+env.AppendUnique(CPPDEFINES = ['__TIZEN__'])
print "Given Transport is %s" % transport
print "Given OS is %s" % target_os
if target_os == 'tizen':
- command = "sh resource/csdk/stack/samples/tizen/build/gbsbuild.sh %s %s %s %s %s" % (transport, secured, buildsample, release_mode, logging)
+ command = "sh resource/csdk/stack/samples/tizen/build/gbsbuild.sh %s %s %s %s %s %s" % (transport, secured, buildsample, release_mode, logging, routing)
print "Created Command is %s" % command
gbs_script = env.Command('gbs_build', None, command)
AlwaysBuild ('gbs_script')
\ No newline at end of file
echo $5
export LOGGING=$5
+echo $6
+export ROUTING=$6
echo $TARGET_TRANSPORT
echo $BUILD_SAMPLE
cp -R ./iotivityconfig/* $sourcedir/tmp/iotivityconfig/
cp -R ./SConscript $sourcedir/tmp/
+cp -R $sourcedir/iotivity.pc.in $sourcedir/tmp/
+
cd $sourcedir/tmp
echo `pwd`
fi
echo "Calling core gbs build command"
-gbscommand="gbs build -A armv7l -B ~/GBS-ROOT-RI --include-all --define 'TARGET_TRANSPORT $1' --define 'SECURED $2' --define 'RELEASE $4' --define 'LOGGING $5' --repository ./"
+gbscommand="gbs build -A armv7l -B ~/GBS-ROOT-RI --include-all --define 'TARGET_TRANSPORT $1' --define 'SECURED $2' --define 'RELEASE $4' --define 'LOGGING $5' --define 'ROUTING $6' --repository ./"
echo $gbscommand
if eval $gbscommand; then
echo "Core build is successful"
git commit -m "Initial commit"
fi
echo "Calling sample gbs build command"
- gbscommand="gbs build -A armv7l -B ~/GBS-ROOT-RI --include-all --define 'TARGET_TRANSPORT $1' --define 'SECURED $2' --define 'RELEASE $4' --define 'LOGGING $5' --repository ./"
+ gbscommand="gbs build -A armv7l -B ~/GBS-ROOT-RI --include-all --define 'TARGET_TRANSPORT $1' --define 'SECURED $2' --define 'RELEASE $4' --define 'LOGGING $5' --define 'ROUTING $6' --repository ./"
echo $gbscommand
if eval $gbscommand; then
echo "Sample build is successful"
echo %{ROOTDIR}
scons TARGET_OS=tizen -c
-scons TARGET_OS=tizen TARGET_TRANSPORT=%{TARGET_TRANSPORT} SECURED=%{SECURED} RELEASE=%{RELEASE} LOGGING=%{LOGGING}
+scons TARGET_OS=tizen TARGET_TRANSPORT=%{TARGET_TRANSPORT} SECURED=%{SECURED} RELEASE=%{RELEASE} LOGGING=%{LOGGING} ROUTING=%{ROUTING}
%install
mkdir -p %{DEST_INC_DIR}
cp resource/oc_logger/include/targets/oc_ostream_logger.h %{DEST_INC_DIR}
cp resource/csdk/stack/include/ocpresence.h %{DEST_INC_DIR}
cp resource/csdk/stack/include/ocpayload.h %{DEST_INC_DIR}
+cp resource/c_common/platform_features.h %{DEST_INC_DIR}
+cp resource/csdk/stack/include/payload_logging.h %{DEST_INC_DIR}
cp extlibs/cjson/cJSON.h %{DEST_INC_DIR}
cp -rf %{ROOTDIR}/com.oic.ri.pc %{DEST_LIB_DIR}/pkgconfig/
#include "cainterface.h"
/// Module Name
-#define TAG PCF("occlientcb")
+#define TAG "occlientcb"
struct ClientCB *cbList = NULL;
static OCMulticastNode * mcPresenceNodes = NULL;
ClientCB *cbNode = NULL;
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
if(method == OC_REST_PRESENCE)
{ // Retrieve the presence callback structure for this specific requestUri.
cbNode = GetClientCB(NULL, 0, NULL, requestUri);
}
- #endif // WITH_PRESENCE
+#endif // WITH_PRESENCE
if(!cbNode)// If it does not already exist, create new node.
{
}
else
{
- OC_LOG(INFO, TAG, PCF("Adding client callback with token"));
+ OC_LOG(INFO, TAG, "Adding client callback with token");
OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
cbNode->callBack = cbData->cb;
cbNode->context = cbData->context;
*handle = cbNode->handle;
}
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
if(method == OC_REST_PRESENCE && resourceTypeName)
{
// Amend the found or created node by adding a new resourceType to it.
{
OICFree(resourceTypeName);
}
- #else
+#else
OICFree(resourceTypeName);
- #endif
+#endif
return OC_STACK_OK;
- exit:
- return OC_STACK_NO_MEMORY;
+exit:
+ return OC_STACK_NO_MEMORY;
}
void DeleteClientCB(ClientCB * cbNode)
if(cbNode)
{
LL_DELETE(cbList, cbNode);
- OC_LOG (INFO, TAG, PCF("Deleting token"));
+ OC_LOG (INFO, TAG, "Deleting token");
OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)cbNode->token, cbNode->tokenLength);
CADestroyToken (cbNode->token);
OICFree(cbNode->devAddr);
cbNode->deleteCallback(cbNode->context);
}
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
if(cbNode->presence)
{
OICFree(cbNode->presence->timeOut);
pointer = next;
}
}
- #endif // WITH_PRESENCE
+#endif // WITH_PRESENCE
OICFree(cbNode);
cbNode = NULL;
}
if (cbNode->TTL < now)
{
- OC_LOG(INFO, TAG, PCF("Deleting timed-out callback"));
+ OC_LOG(INFO, TAG, "Deleting timed-out callback");
DeleteClientCB(cbNode);
}
}
if(token && *token && tokenLength <= CA_MAX_TOKEN_LEN && tokenLength > 0)
{
- OC_LOG (INFO, TAG, PCF ("Looking for token"));
+ OC_LOG (INFO, TAG, "Looking for token");
OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
- OC_LOG(INFO, TAG, PCF("\tFound in callback list"));
+ OC_LOG(INFO, TAG, "\tFound in callback list");
LL_FOREACH(cbList, out)
{
OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->token, tokenLength);
CheckAndDeleteTimedOutCB(out);
}
}
- OC_LOG(INFO, TAG, PCF("Callback Not found !!"));
+ OC_LOG(INFO, TAG, "Callback Not found !!");
return NULL;
}
}
}
}
- OC_LOG(INFO, TAG, PCF("MulticastNode Not found !!"));
+ OC_LOG(INFO, TAG, "MulticastNode Not found !!");
return NULL;
}
#include "oicgroup.h"
-#define TAG PCF("occollection")
+#define TAG "occollection"
#define NUM_PARAM_IN_QUERY 2 // The expected number of parameters in a query
#define NUM_FIELDS_IN_QUERY 2 // The expected number of fields in a query
//TODO: Query and URL validation is being done for virtual resource case
// using ValidateUrlQuery function. We should be able to merge it with this
// function.
- OC_LOG(INFO, TAG, PCF("Entering ValidateQuery"));
+ OC_LOG(INFO, TAG, "Entering ValidateQuery");
if (!query)
+ {
return OC_STACK_ERROR;
+ }
if(!ifParam || !rtParam)
{
if (!(*query))
{
// Query string is empty
- OC_LOG_V(INFO, TAG, PCF("Empty query string, use default IF and RT"));
+ OC_LOG(INFO, TAG, "Empty query string, use default IF and RT");
*ifParam = STACK_IF_DEFAULT;
*rtParam = (char *) OCGetResourceTypeName (resource, 0);
return OC_STACK_OK;
}
token = strtok_r (NULL, OC_QUERY_SEPARATOR, &endStr);
}
+
if (numFields > NUM_FIELDS_IN_QUERY)
{
// current release supports one IF value, one RT value and no other params
static OCStackResult
HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
{
+ if (!ehRequest)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
OCStackResult stackRet = OC_STACK_OK;
OCEntityHandlerResult ehResult = OC_EH_ERROR;
OCResource * collResource = (OCResource *) ehRequest->resource;
if(stackRet == OC_STACK_OK)
{
- OCRepPayloadSetUri(payload, collResource->uri);
+ if (collResource)
+ {
+ OCRepPayloadSetUri(payload, collResource->uri);
+ }
}
if(stackRet == OC_STACK_OK)
if (stackRet == OC_STACK_OK)
{
- for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+ for (uint8_t i = 0; i < MAX_CONTAINED_RESOURCES; i++)
{
OCResource* temp = collResource->rsrcResources[i];
if (temp)
// as slow response
if(ehResult == OC_EH_SLOW)
{
- OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+ OC_LOG(INFO, TAG, "This is a slow resource");
((OCServerRequest *)ehRequest->requestHandle)->slowFlag = 1;
stackRet = EntityHandlerCodeToOCStackCode(ehResult);
}
if(resource)
{
uint8_t num = 0;
- for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+ for (uint8_t i = 0; i < MAX_CONTAINED_RESOURCES; i++)
{
if (resource->rsrcResources[i])
{
return result;
}
- if(!((ehRequest->method == OC_REST_GET) ||
- (ehRequest->method == OC_REST_PUT) ||
- (ehRequest->method == OC_REST_POST)))
+ switch (ehRequest->method)
{
- return OC_STACK_ERROR;
- }
+ case OC_REST_GET:
+ switch (ifQueryParam)
+ {
+ case STACK_IF_DEFAULT:
+ // Get attributes of collection resource and properties of contained resources
+ // M1 release does not support attributes for collection resource, so the GET
+ // operation is same as the GET on LL interface.
+ OC_LOG(INFO, TAG, "STACK_IF_DEFAULT");
+ return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
- if (ehRequest->method == OC_REST_GET)
- {
- switch (ifQueryParam)
- {
- case STACK_IF_DEFAULT:
- // Get attributes of collection resource and properties of contined resource
- // M1 release does not support attributes for collection resource, so the GET
- // operation is same as the GET on LL interface.
- OC_LOG(INFO, TAG, PCF("STACK_IF_DEFAULT"));
- return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
-
- case STACK_IF_LL:
- OC_LOG(INFO, TAG, PCF("STACK_IF_LL"));
- return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
-
- case STACK_IF_BATCH:
- OC_LOG(INFO, TAG, PCF("STACK_IF_BATCH"));
- ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler =
- HandleAggregateResponse;
-
- ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
- GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
-
- return HandleBatchInterface(ehRequest);
-
- case STACK_IF_GROUP:
- return BuildCollectionGroupActionJSONResponse(OC_REST_GET/*flag*/,
- (OCResource *) ehRequest->resource, ehRequest);
- default:
- return OC_STACK_ERROR;
- }
- }
- else if (ehRequest->method == OC_REST_PUT)
- {
- switch (ifQueryParam)
- {
- case STACK_IF_DEFAULT:
- // M1 release does not support PUT on default interface
- return OC_STACK_ERROR;
-
- case STACK_IF_LL:
- // LL interface only supports GET
- return OC_STACK_ERROR;
-
- case STACK_IF_BATCH:
- ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler =
- HandleAggregateResponse;
- ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
- GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
- return HandleBatchInterface(ehRequest);
-
- case STACK_IF_GROUP:
+ case STACK_IF_LL:
+ OC_LOG(INFO, TAG, "STACK_IF_LL");
+ return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
+
+ case STACK_IF_BATCH:
+ OC_LOG(INFO, TAG, "STACK_IF_BATCH");
+ ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler =
+ HandleAggregateResponse;
+
+ ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
+ GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
+
+ return HandleBatchInterface(ehRequest);
+
+ case STACK_IF_GROUP:
+ return BuildCollectionGroupActionCBORResponse(OC_REST_GET/*flag*/,
+ (OCResource *) ehRequest->resource, ehRequest);
+
+ default:
+ return OC_STACK_ERROR;
+ }
+
+ case OC_REST_PUT:
+ switch (ifQueryParam)
{
- OC_LOG(INFO, TAG, PCF("IF_COLLECTION PUT with request ::\n"));
- OC_LOG_PAYLOAD(INFO, TAG, ehRequest->payload);
- return BuildCollectionGroupActionJSONResponse(OC_REST_PUT/*flag*/,
- (OCResource *) ehRequest->resource, ehRequest);
+ case STACK_IF_DEFAULT:
+ // M1 release does not support PUT on default interface
+ return OC_STACK_ERROR;
+
+ case STACK_IF_LL:
+ // LL interface only supports GET
+ return OC_STACK_ERROR;
+
+ case STACK_IF_BATCH:
+ ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler =
+ HandleAggregateResponse;
+ ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
+ GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
+ return HandleBatchInterface(ehRequest);
+
+ case STACK_IF_GROUP:
+ OC_LOG(INFO, TAG, "IF_COLLECTION PUT with request ::\n");
+ OC_LOG_PAYLOAD(INFO, ehRequest->payload);
+ return BuildCollectionGroupActionCBORResponse(OC_REST_PUT/*flag*/,
+ (OCResource *) ehRequest->resource, ehRequest);
+
+ default:
+ return OC_STACK_ERROR;
}
- default:
- return OC_STACK_ERROR;
- }
- }
- else if (ehRequest->method == OC_REST_POST)
- {
- switch (ifQueryParam)
- {
- case STACK_IF_GROUP:
+ case OC_REST_POST:
+ switch (ifQueryParam)
{
- OC_LOG(INFO, TAG, PCF("IF_COLLECTION POST with request ::\n"));
- OC_LOG_PAYLOAD(INFO, TAG, ehRequest->payload);
- return BuildCollectionGroupActionJSONResponse(OC_REST_POST/*flag*/,
- (OCResource *) ehRequest->resource, ehRequest);
+ case STACK_IF_DEFAULT:
+ // M1 release does not support POST on default interface
+ return OC_STACK_ERROR;
+
+ case STACK_IF_LL:
+ // LL interface only supports GET
+ return OC_STACK_ERROR;
+
+ case STACK_IF_BATCH:
+ ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler =
+ HandleAggregateResponse;
+ ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
+ GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
+ return HandleBatchInterface(ehRequest);
+
+ case STACK_IF_GROUP:
+ OC_LOG(INFO, TAG, "IF_COLLECTION POST with request ::\n");
+ OC_LOG_PAYLOAD(INFO, ehRequest->payload);
+ return BuildCollectionGroupActionCBORResponse(OC_REST_POST/*flag*/,
+ (OCResource *) ehRequest->resource, ehRequest);
+
+ default:
+ return OC_STACK_ERROR;
}
- default:
- return OC_STACK_ERROR;
- }
- }
- else if (ehRequest->method == OC_REST_POST)
- {
- if(ifQueryParam == STACK_IF_GROUP)
- {
- OC_LOG(INFO, TAG, PCF("IF_COLLECTION POST with request ::\n"));
- OC_LOG_PAYLOAD(INFO, TAG, ehRequest->payload);
- return BuildCollectionGroupActionJSONResponse(OC_REST_POST/*flag*/,
- (OCResource *) ehRequest->resource, ehRequest);
- }
- else
- {
+ case OC_REST_DELETE:
+ // TODO implement DELETE accordingly to the desired behavior
+ return OC_STACK_ERROR;
+
+ default:
return OC_STACK_ERROR;
- }
}
- return result;
}
#include "oic_string.h"
#include "ocpayload.h"
#include "ocserverrequest.h"
+#include "logger.h"
#include "utlist.h"
#include "pdu.h"
// Module Name
-#define MOD_NAME PCF("ocobserve")
+#define MOD_NAME "ocobserve"
-#define TAG PCF("OCStackObserve")
+#define TAG "OCStackObserve"
#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
{
OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
resourceObserver->lowQosCount);
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
if((resourceObserver->forceHighQos \
|| resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT) \
&& method != OC_REST_PRESENCE)
- #else
+#else
if(resourceObserver->forceHighQos \
|| resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT)
- #endif
+#endif
{
resourceObserver->lowQosCount = 0;
// at some point we have to to send CON to check on the
// availability of observer
- OC_LOG(INFO, TAG, PCF("This time we are sending the notification as High qos"));
+ OC_LOG(INFO, TAG, "This time we are sending the notification as High qos");
decidedQoS = OC_HIGH_QOS;
}
else
OCQualityOfService qos)
#endif
{
- OC_LOG(INFO, TAG, PCF("Entering SendObserverNotification"));
+ OC_LOG(INFO, TAG, "Entering SendObserverNotification");
if(!resPtr)
{
return OC_STACK_INVALID_PARAM;
if (resourceObserver->resource == resPtr)
{
numObs++;
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
if(method != OC_REST_PRESENCE)
{
- #endif
+#endif
qos = DetermineObserverQoS(method, resourceObserver, qos);
result = AddServerRequest(&request, 0, 0, 1, OC_REST_GET,
0, resPtr->sequenceNum, qos, resourceObserver->query,
NULL, NULL,
resourceObserver->token, resourceObserver->tokenLength,
- resourceObserver->resUri, 0,
+ resourceObserver->resUri, 0, resourceObserver->acceptFormat,
&resourceObserver->devAddr);
if(request)
&request->devAddr,
(OCResourceHandle) resPtr,
request->query,
+ PAYLOAD_TYPE_REPRESENTATION,
request->payload,
request->payloadSize,
request->numRcvdVendorSpecificHeaderOptions,
OCPayloadDestroy(ehRequest.payload);
}
}
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
}
else
{
OCEntityHandlerResponse ehResponse = {0};
//This is effectively the implementation for the presence entity handler.
- OC_LOG(DEBUG, TAG, PCF("This notification is for Presence"));
+ OC_LOG(DEBUG, TAG, "This notification is for Presence");
result = AddServerRequest(&request, 0, 0, 1, OC_REST_GET,
0, resPtr->sequenceNum, qos, resourceObserver->query,
NULL, NULL,
resourceObserver->token, resourceObserver->tokenLength,
- resourceObserver->resUri, 0,
+ resourceObserver->resUri, 0, resourceObserver->acceptFormat,
&resourceObserver->devAddr);
if(result == OC_STACK_OK)
OCPresencePayloadDestroy(presenceResBuf);
}
}
- #endif
+#endif
// Since we are in a loop, set an error flag to indicate at least one error occurred.
if (result != OC_STACK_OK)
if (numObs == 0)
{
- OC_LOG(INFO, TAG, PCF("Resource has no observers"));
+ OC_LOG(INFO, TAG, "Resource has no observers");
result = OC_STACK_NO_OBSERVERS;
}
else if (observeErrorFlag)
{
- OC_LOG(ERROR, TAG, PCF("Observer notification error"));
+ OC_LOG(ERROR, TAG, "Observer notification error");
result = OC_STACK_ERROR;
}
return result;
OCStackResult result = OC_STACK_ERROR;
bool observeErrorFlag = false;
- OC_LOG(INFO, TAG, PCF("Entering SendListObserverNotification"));
+ OC_LOG(INFO, TAG, "Entering SendListObserverNotification");
while(numIds)
{
observer = GetObserverUsingId (*obsIdList);
result = AddServerRequest(&request, 0, 0, 1, OC_REST_GET,
0, resource->sequenceNum, qos, observer->query,
NULL, NULL, observer->token, observer->tokenLength,
- observer->resUri, 0,
+ observer->resUri, 0, observer->acceptFormat,
&observer->devAddr);
if(request)
}
else
{
- OC_LOG(ERROR, TAG, PCF("Observer notification error"));
+ OC_LOG(ERROR, TAG, "Observer notification error");
return OC_STACK_ERROR;
}
}
{
ResourceObserver *resObs = NULL;
- OC_LOG(INFO, TAG, PCF("Entering GenerateObserverId"));
+ OC_LOG(INFO, TAG, "Entering GenerateObserverId");
VERIFY_NON_NULL (observationId);
do
resObs = GetObserverUsingId (*observationId);
} while (NULL != resObs);
- OC_LOG_V(INFO, TAG, "Generated bservation ID is %u", *observationId);
+ OC_LOG_V(INFO, TAG, "GeneratedObservation ID is %u", *observationId);
return OC_STACK_OK;
exit:
uint8_t tokenLength,
OCResource *resHandle,
OCQualityOfService qos,
+ OCPayloadFormat acceptFormat,
const OCDevAddr *devAddr)
{
// Check if resource exists and is observable.
VERIFY_NON_NULL (obsNode->resUri);
obsNode->qos = qos;
+ obsNode->acceptFormat = acceptFormat;
if(query)
{
obsNode->query = OICStrdup(query);
}
}
}
- OC_LOG(INFO, TAG, PCF("Observer node not found!!"));
+ OC_LOG(INFO, TAG, "Observer node not found!!");
return NULL;
}
if(token && *token)
{
- OC_LOG(INFO, TAG,PCF("Looking for token"));
+ OC_LOG(INFO, TAG, "Looking for token");
OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
- OC_LOG(INFO, TAG,PCF("\tFound token:"));
+ OC_LOG(INFO, TAG, "\tFound token:");
LL_FOREACH (serverObsList, out)
{
}
else
{
- OC_LOG(ERROR, TAG,PCF("Passed in NULL token"));
+ OC_LOG(ERROR, TAG, "Passed in NULL token");
}
- OC_LOG(INFO, TAG, PCF("Observer node not found!!"));
+ OC_LOG(INFO, TAG, "Observer node not found!!");
return NULL;
}
uint8_t numOptions,
uint8_t observeFlag)
{
- if(!caHdrOpt)
+ if(!caHdrOpt || !ocHdrOpt)
{
return OC_STACK_INVALID_PARAM;
}
}
tmpHdrOpt[0].protocolID = CA_COAP_ID;
tmpHdrOpt[0].optionID = COAP_OPTION_OBSERVE;
- tmpHdrOpt[0].optionLength = sizeof(uint32_t);
+ tmpHdrOpt[0].optionLength = sizeof(uint8_t);
tmpHdrOpt[0].optionData[0] = observeFlag;
for (uint8_t i = 0; i < numOptions; i++)
{
{
return OC_STACK_INVALID_PARAM;
}
- *observationOption = OC_OBSERVE_NO_OPTION;
if(!options || !numOptions)
{
return OC_STACK_INVALID_PARAM;
}
+ *observationOption = OC_OBSERVE_NO_OPTION;
+
for(uint8_t i = 0; i < *numOptions; i++)
{
if(options[i].protocolID == CA_COAP_ID &&
static void OCCopyPropertyValueArray(OCRepPayloadValue* dest, OCRepPayloadValue* source)
{
+ if(!dest || !source)
+ {
+ return;
+ }
+
size_t dimTotal = calcDimTotal(source->arr.dimensions);
switch(source->arr.type)
{
}
break;
default:
- OC_LOG(ERROR, TAG, PCF("CopyPropertyValueArray invalid type"));
+ OC_LOG(ERROR, TAG, "CopyPropertyValueArray invalid type");
break;
}
}
val = val->next;
}
- OC_LOG(ERROR, TAG, PCF("FindAndSetValue reached point after while loop, pointer corruption?"));
+ OC_LOG(ERROR, TAG, "FindAndSetValue reached point after while loop, pointer corruption?");
return NULL;
}
return val->type == OCREP_PROP_NULL;
}
-bool OCRepPayloadSetNull(OCRepPayload* payload, const char* name)
+static bool OCRepPayloadSetProp(OCRepPayload* payload, const char* name,
+ void* value, OCRepPayloadPropType type)
{
- OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_NULL);
- return val != NULL;
-}
-
-bool OCRepPayloadSetPropInt(OCRepPayload* payload,
- const char* name, int64_t value)
-{
- OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_INT);
-
+ OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, type);
if(!val)
{
return false;
}
+ switch(type)
+ {
+ case OCREP_PROP_INT:
+ val->i = *(int64_t*)value;
+ break;
+ case OCREP_PROP_DOUBLE:
+ val->d = *(double*)value;
+ break;
+ case OCREP_PROP_BOOL:
+ val->b = *(bool*)value;
+ break;
+ case OCREP_PROP_OBJECT:
+ val->obj = (OCRepPayload*)value;
+ break;
+ case OCREP_PROP_STRING:
+ val->str = (char*)value;
+ return val->str != NULL;
+ case OCREP_PROP_NULL:
+ return val != NULL;
+ case OCREP_PROP_ARRAY:
+ default:
+ return false;
+ }
- val->i = value;
return true;
}
+bool OCRepPayloadSetNull(OCRepPayload* payload, const char* name)
+{
+ return OCRepPayloadSetProp(payload, name, NULL, OCREP_PROP_NULL);
+}
+
+bool OCRepPayloadSetPropInt(OCRepPayload* payload,
+ const char* name, int64_t value)
+{
+ return OCRepPayloadSetProp(payload, name, &value, OCREP_PROP_INT);
+}
+
bool OCRepPayloadGetPropInt(const OCRepPayload* payload, const char* name, int64_t* value)
{
OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
bool OCRepPayloadSetPropDouble(OCRepPayload* payload,
const char* name, double value)
{
- OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_DOUBLE);
-
- if(!val )
- {
- return false;
- }
-
- val->d = value;
- return true;
+ return OCRepPayloadSetProp(payload, name, &value, OCREP_PROP_DOUBLE);
}
bool OCRepPayloadGetPropDouble(const OCRepPayload* payload, const char* name, double* value)
bool OCRepPayloadSetPropStringAsOwner(OCRepPayload* payload, const char* name, char* value)
{
- OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_STRING);
-
- if(!val)
- {
- return false;
- }
-
- val->str = value;
- return val->str != NULL;
+ return OCRepPayloadSetProp(payload, name, value, OCREP_PROP_STRING);
}
-bool OCRepPayloadGetPropString(const OCRepPayload* payload, const char* name, const char** value)
+bool OCRepPayloadGetPropString(const OCRepPayload* payload, const char* name, char** value)
{
OCRepPayloadValue* val = OCRepPayloadFindValue(payload, name);
bool OCRepPayloadSetPropBool(OCRepPayload* payload,
const char* name, bool value)
{
- OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_BOOL);
-
- if(!val)
- {
- return false;
- }
-
- val->b = value;
- return true;
+ return OCRepPayloadSetProp(payload, name, &value, OCREP_PROP_BOOL);
}
bool OCRepPayloadGetPropBool(const OCRepPayload* payload, const char* name, bool* value)
bool OCRepPayloadSetPropObjectAsOwner(OCRepPayload* payload, const char* name, OCRepPayload* value)
{
- OCRepPayloadValue* val = OCRepPayloadFindAndSetValue(payload, name, OCREP_PROP_OBJECT);
-
- if(!val)
- {
- return false;
- }
-
- val->obj = value;
- return true;
+ return OCRepPayloadSetProp(payload, name, value, OCREP_PROP_OBJECT);
}
bool OCRepPayloadGetPropObject(const OCRepPayload* payload, const char* name, OCRepPayload** value)
OCStringLL* cur = pl->interfaces;
ifPtr = ifPtr->next;
- while(ifPtr)
+ while(ifPtr && cur)
{
cur->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
if(!cur->next)
static void OCCopyPlatformInfo(const OCPlatformInfo* platformInfo, OCPlatformPayload* target)
{
+ if(!platformInfo || !target)
+ {
+ return;
+ }
+
target->info.platformID = OICStrdup(platformInfo->platformID);
target->info.manufacturerName = OICStrdup(platformInfo->manufacturerName);
target->info.manufacturerUrl = OICStrdup(platformInfo->manufacturerUrl);
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include "ocpayloadcbor.h"
+#include "platform_features.h"
#include <stdlib.h>
#include "oic_malloc.h"
#include "logger.h"
#include "ocresourcehandler.h"
#include "cbor.h"
-#define TAG PCF("OCPayloadConvert")
+#define TAG "OCPayloadConvert"
+// Arbitrarily chosen size that seems to contain the majority of packages
+#define INIT_SIZE (255)
-static OCStackResult OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t** outPayload,
+// Functions all return either a CborError, or a negative version of the OC_STACK return values
+static int64_t OCConvertPayloadHelper(OCPayload* payload, uint8_t* outPayload, size_t* size);
+static int64_t OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t* outPayload,
size_t* size);
-static OCStackResult OCConvertDevicePayload(OCDevicePayload* payload, uint8_t** outPayload,
+static int64_t OCConvertDevicePayload(OCDevicePayload* payload, uint8_t* outPayload,
size_t* size);
-static OCStackResult OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t** outPayload,
+static int64_t OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t* outPayload,
size_t* size);
-static OCStackResult OCConvertRepPayload(OCRepPayload* payload, uint8_t** outPayload, size_t* size);
-static OCStackResult OCConvertPresencePayload(OCPresencePayload* payload, uint8_t** outPayload,
+static int64_t OCConvertRepPayload(OCRepPayload* payload, uint8_t* outPayload, size_t* size);
+static int64_t OCConvertPresencePayload(OCPresencePayload* payload, uint8_t* outPayload,
size_t* size);
-static OCStackResult OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t** outPayload,
+static int64_t OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t* outPayload,
size_t* size);
+static int64_t OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload);
+static int64_t OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* valArray);
-bool AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
+static int64_t AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
const char* value);
-bool ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
+static int64_t ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
const char* value);
-
OCStackResult OCConvertPayload(OCPayload* payload, uint8_t** outPayload, size_t* size)
{
+ // TinyCbor Version 47a78569c0 or better on master is required for the re-allocation
+ // strategy to work. If you receive the following assertion error, please do a git-pull
+ // from the extlibs/tinycbor/tinycbor directory
+ #define CborNeedsUpdating (CborErrorOutOfMemory < CborErrorDataTooLarge)
+ OC_STATIC_ASSERT(!CborNeedsUpdating, "tinycbor needs to be updated to at least 47a78569c0");
+ #undef CborNeedsUpdating
+ if (!payload)
+ {
+ OC_LOG(ERROR, TAG, "Payload parameter NULL");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ if (!outPayload || !size)
+ {
+ OC_LOG(ERROR, TAG, "Out parameter/s parameter NULL");
+ return OC_STACK_INVALID_PARAM;
+ }
+
OC_LOG_V(INFO, TAG, "Converting payload of type %d", payload->type);
+
+ size_t curSize = INIT_SIZE;
+ uint8_t* out = (uint8_t*)OICCalloc(1, curSize);
+ int64_t err = OCConvertPayloadHelper(payload, out, &curSize);
+
+ if (err == CborErrorOutOfMemory)
+ {
+ // reallocate "out" and try again!
+ uint8_t* out2 = (uint8_t*)OICRealloc(out, curSize);
+
+ if (!out2)
+ {
+ OICFree(out);
+ return OC_STACK_NO_MEMORY;
+ }
+
+ out = out2;
+ err = OCConvertPayloadHelper(payload, out, &curSize);
+ }
+
+ if (err == 0)
+ {
+ if (curSize < INIT_SIZE)
+ {
+ uint8_t* out2 = (uint8_t*)OICRealloc(out, curSize);
+
+ if (!out2)
+ {
+ OICFree(out);
+ return OC_STACK_NO_MEMORY;
+ }
+
+ out = out2;
+ }
+
+ *size = curSize;
+ *outPayload = out;
+ return OC_STACK_OK;
+ }
+ else if (err < 0)
+ {
+ return (OCStackResult)-err;
+ }
+ else
+ {
+ return OC_STACK_ERROR;
+ }
+}
+
+static int64_t OCConvertPayloadHelper(OCPayload* payload, uint8_t* outPayload, size_t* size)
+{
switch(payload->type)
{
case PAYLOAD_TYPE_DISCOVERY:
}
}
-static OCStackResult OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t** outPayload,
- size_t* size)
+static int64_t checkError(int64_t err, CborEncoder* encoder, uint8_t* outPayload, size_t* size)
{
- *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
- *size = MAX_REQUEST_LENGTH;
-
- if(!*outPayload)
+ if (err == CborErrorOutOfMemory)
{
- return OC_STACK_NO_MEMORY;
+ *size += encoder->ptr - encoder->end;
+ return err;
}
-
+ else if (err != 0)
+ {
+ OC_LOG_V(ERROR, TAG, "Convert Payload failed", err);
+ return err;
+ }
+ else
+ {
+ *size = encoder->ptr - outPayload;
+ return 0;
+ }
+}
+static int64_t OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t* outPayload,
+ size_t* size)
+{
CborEncoder encoder;
- bool err = false;
+ int64_t err = 0;
- cbor_encoder_init(&encoder, *outPayload, *size, 0);
+ cbor_encoder_init(&encoder, outPayload, *size, 0);
CborEncoder rootArray;
- err = err || cbor_encoder_create_array(&encoder, &rootArray, 2);
- err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_SECURITY);
-
+ err = err | cbor_encoder_create_array(&encoder, &rootArray, 1);
CborEncoder map;
- err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
+ err = err | cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
if(payload->securityData)
{
- err = err || AddTextStringToMap(&map, OC_RSRVD_REPRESENTATION,
+ err = err | AddTextStringToMap(&map, OC_RSRVD_REPRESENTATION,
sizeof(OC_RSRVD_REPRESENTATION) - 1,
payload->securityData);
}
- err = err || cbor_encoder_close_container(&rootArray, &map);
-
- err = err || cbor_encoder_close_container(&encoder, &rootArray);
-
- if(err)
- {
- OC_LOG_V(ERROR, TAG, "Convert Security Payload failed", err);
- OICFree(*outPayload);
- return OC_STACK_ERROR;
- }
-
- *size = encoder.ptr - *outPayload;
- uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
+ err = err | cbor_encoder_close_container(&rootArray, &map);
- if(!tempPayload)
- {
- OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
- OICFree(*outPayload);
- return OC_STACK_ERROR;
- }
+ err = err | cbor_encoder_close_container(&encoder, &rootArray);
+ return checkError(err, &encoder, outPayload, size);
- *outPayload = tempPayload;
- return OC_STACK_OK;
}
-static OCStackResult OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t** outPayload,
+static int64_t OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t* outPayload,
size_t* size)
{
- *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
- *size = MAX_REQUEST_LENGTH;
-
- if(!*outPayload)
- {
- return OC_STACK_NO_MEMORY;
- }
-
CborEncoder encoder = {0};
- bool err = false;
+ int64_t err = 0;
size_t resourceCount = OCDiscoveryPayloadGetResourceCount(payload);
- cbor_encoder_init(&encoder, *outPayload, *size, 0);
+ cbor_encoder_init(&encoder, outPayload, *size, 0);
CborEncoder rootArray;
- err = err || cbor_encoder_create_array(&encoder, &rootArray, 1 + resourceCount);
- err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DISCOVERY);
+ err = err | cbor_encoder_create_array(&encoder, &rootArray, resourceCount);
for(size_t i = 0; i < resourceCount; ++i)
{
if(!resource)
{
- OICFree(*outPayload);
return OC_STACK_INVALID_PARAM;
}
- err = err || cbor_encoder_create_map(&rootArray, &map, 3);
+ err = err | cbor_encoder_create_map(&rootArray, &map, 3);
// Uri
- err = err || AddTextStringToMap(&map, OC_RSRVD_HREF,
+ err = err | AddTextStringToMap(&map, OC_RSRVD_HREF,
sizeof(OC_RSRVD_HREF) - 1,
resource->uri);
// Server ID
- err = err || cbor_encode_text_string(&map, OC_RSRVD_SERVER_INSTANCE_ID,
+ err = err | cbor_encode_text_string(&map, OC_RSRVD_SERVER_INSTANCE_ID,
sizeof(OC_RSRVD_SERVER_INSTANCE_ID) - 1);
- err = err || cbor_encode_byte_string(&map, resource->sid, UUID_SIZE);
+ err = err | cbor_encode_byte_string(&map, resource->sid, UUID_SIZE);
// Prop Tag
{
CborEncoder propMap;
- err = err || cbor_encode_text_string(&map, OC_RSRVD_PROPERTY,
+ err = err | cbor_encode_text_string(&map, OC_RSRVD_PROPERTY,
sizeof(OC_RSRVD_PROPERTY) -1 );
- err = err || cbor_encoder_create_map(&map, &propMap, 3);
+ err = err | cbor_encoder_create_map(&map, &propMap, 3);
// Resource Type
{
CborEncoder rtArray;
- err = err || cbor_encode_text_string(&propMap, OC_RSRVD_RESOURCE_TYPE,
+ err = err | cbor_encode_text_string(&propMap, OC_RSRVD_RESOURCE_TYPE,
sizeof(OC_RSRVD_RESOURCE_TYPE) - 1);
- err = err || cbor_encoder_create_array(&propMap, &rtArray, CborIndefiniteLength);
+ err = err | cbor_encoder_create_array(&propMap, &rtArray, CborIndefiniteLength);
OCStringLL* rtPtr = resource->types;
while(rtPtr)
{
- err = err || cbor_encode_text_string(&rtArray, rtPtr->value,
+ err = err | cbor_encode_text_string(&rtArray, rtPtr->value,
strlen(rtPtr->value));
rtPtr = rtPtr->next;
}
- err = err || cbor_encoder_close_container(&propMap, &rtArray);
+ err = err | cbor_encoder_close_container(&propMap, &rtArray);
}
// Interface Types
{
CborEncoder ifArray;
- err = err || cbor_encode_text_string(&propMap, OC_RSRVD_INTERFACE,
+ err = err | cbor_encode_text_string(&propMap, OC_RSRVD_INTERFACE,
sizeof(OC_RSRVD_INTERFACE) - 1);
- err = err || cbor_encoder_create_array(&propMap, &ifArray, CborIndefiniteLength);
+ err = err | cbor_encoder_create_array(&propMap, &ifArray, CborIndefiniteLength);
OCStringLL* ifPtr = resource->interfaces;
while(ifPtr)
{
- err = err || cbor_encode_text_string(&ifArray, ifPtr->value,
+ err = err | cbor_encode_text_string(&ifArray, ifPtr->value,
strlen(ifPtr->value));
ifPtr= ifPtr->next;
}
- err = err || cbor_encoder_close_container(&propMap, &ifArray);
+ err = err | cbor_encoder_close_container(&propMap, &ifArray);
}
// Policy
{
CborEncoder policyMap;
- err = err || cbor_encode_text_string(&propMap, OC_RSRVD_POLICY,
+ err = err | cbor_encode_text_string(&propMap, OC_RSRVD_POLICY,
sizeof(OC_RSRVD_POLICY) - 1);
- err = err || cbor_encoder_create_map(&propMap, &policyMap, CborIndefiniteLength);
+ err = err | cbor_encoder_create_map(&propMap, &policyMap, CborIndefiniteLength);
// Bitmap
- err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_BITMAP,
+ err = err | cbor_encode_text_string(&policyMap, OC_RSRVD_BITMAP,
sizeof(OC_RSRVD_BITMAP) - 1);
- err = err || cbor_encode_uint(&policyMap, resource->bitmap);
+ err = err | cbor_encode_uint(&policyMap, resource->bitmap);
if(resource->secure)
{
- err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_SECURE,
+ err = err | cbor_encode_text_string(&policyMap, OC_RSRVD_SECURE,
sizeof(OC_RSRVD_SECURE) - 1);
- err = err || cbor_encode_boolean(&policyMap, OC_RESOURCE_SECURE);
+ err = err | cbor_encode_boolean(&policyMap, OC_RESOURCE_SECURE);
if(resource->port != 0)
{
- err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_HOSTING_PORT,
+ err = err | cbor_encode_text_string(&policyMap, OC_RSRVD_HOSTING_PORT,
sizeof(OC_RSRVD_HOSTING_PORT) - 1);
- err = err || cbor_encode_uint(&policyMap, resource->port);
+ err = err | cbor_encode_uint(&policyMap, resource->port);
}
}
- err = err || cbor_encoder_close_container(&propMap, &policyMap);
+ err = err | cbor_encoder_close_container(&propMap, &policyMap);
}
// Close
- err = err || cbor_encoder_close_container(&map, &propMap);
+ err = err | cbor_encoder_close_container(&map, &propMap);
}
// Close Item
- err = err || cbor_encoder_close_container(&rootArray, &map);
+ err = err | cbor_encoder_close_container(&rootArray, &map);
}
// Close main array
- err = err || cbor_encoder_close_container(&encoder, &rootArray);
-
- if(err)
- {
- OC_LOG_V(ERROR, TAG, "Convert Discovery Payload failed with : %d", err);
- return OC_STACK_ERROR;
- }
-
- *size = encoder.ptr - *outPayload;
- uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
-
- if(!tempPayload)
- {
- OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
- OICFree(*outPayload);
- return OC_STACK_ERROR;
- }
+ err = err | cbor_encoder_close_container(&encoder, &rootArray);
- *outPayload = tempPayload;
- return OC_STACK_OK;
+ return checkError(err, &encoder, outPayload, size);
}
-static OCStackResult OCConvertDevicePayload(OCDevicePayload* payload, uint8_t** outPayload,
+static int64_t OCConvertDevicePayload(OCDevicePayload* payload, uint8_t* outPayload,
size_t* size)
{
- *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
- *size = MAX_REQUEST_LENGTH;
-
- if(!*outPayload)
- {
- return OC_STACK_NO_MEMORY;
- }
-
CborEncoder encoder = {0};
- bool err = false;
+ int64_t err = 0;
- cbor_encoder_init(&encoder, *outPayload, *size, 0);
+ cbor_encoder_init(&encoder, outPayload, *size, 0);
CborEncoder rootArray;
- err = err || cbor_encoder_create_array(&encoder, &rootArray, 2);
- err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DEVICE);
+ err = err | cbor_encoder_create_array(&encoder, &rootArray, 1);
{
CborEncoder map;
- err = err || cbor_encoder_create_map(&rootArray, &map, 2);
+ err = err | cbor_encoder_create_map(&rootArray, &map, 2);
// uri
- err = err || AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1,
+ err = err | AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1,
payload->uri);
// Rep Map
{
CborEncoder repMap;
- err = err || cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION,
+ err = err | cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION,
sizeof(OC_RSRVD_REPRESENTATION) - 1);
- err = err || cbor_encoder_create_map(&map, &repMap, 4);
+ err = err | cbor_encoder_create_map(&map, &repMap, 4);
// Device ID
- err = err || cbor_encode_text_string(&repMap, OC_RSRVD_DEVICE_ID,
+ err = err | cbor_encode_text_string(&repMap, OC_RSRVD_DEVICE_ID,
sizeof(OC_RSRVD_DEVICE_ID) - 1);
- err = err || cbor_encode_byte_string(&repMap, payload->sid, UUID_SIZE);
+ err = err | cbor_encode_byte_string(&repMap, payload->sid, UUID_SIZE);
// Device Name
- err = err || AddTextStringToMap(&repMap, OC_RSRVD_DEVICE_NAME,
+ err = err | AddTextStringToMap(&repMap, OC_RSRVD_DEVICE_NAME,
sizeof(OC_RSRVD_DEVICE_NAME) - 1,
payload->deviceName);
// Device Spec Version
- err = err || AddTextStringToMap(&repMap, OC_RSRVD_SPEC_VERSION,
+ err = err | AddTextStringToMap(&repMap, OC_RSRVD_SPEC_VERSION,
sizeof(OC_RSRVD_SPEC_VERSION) - 1,
payload->specVersion);
// Device data Model Version
- err = err || AddTextStringToMap(&repMap, OC_RSRVD_DATA_MODEL_VERSION,
+ err = err | AddTextStringToMap(&repMap, OC_RSRVD_DATA_MODEL_VERSION,
sizeof(OC_RSRVD_DATA_MODEL_VERSION) - 1,
payload->dataModelVersion);
- err = err || cbor_encoder_close_container(&map, &repMap);
+ err = err | cbor_encoder_close_container(&map, &repMap);
}
// Close Map
- err = err || cbor_encoder_close_container(&rootArray, &map);
+ err = err | cbor_encoder_close_container(&rootArray, &map);
}
// Close main array
- err = err || cbor_encoder_close_container(&encoder, &rootArray);
+ err = err | cbor_encoder_close_container(&encoder, &rootArray);
- if(err)
- {
- OC_LOG_V(ERROR, TAG, "Convert Device Payload failed with : %d", err);
- return OC_STACK_ERROR;
- }
-
- *size = encoder.ptr - *outPayload;
- uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
-
- if(!tempPayload)
- {
- OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
- OICFree(*outPayload);
- return OC_STACK_ERROR;
- }
-
- *outPayload = tempPayload;
- return OC_STACK_OK;
+ return checkError(err, &encoder, outPayload, size);
}
-static OCStackResult OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t** outPayload,
+static int64_t OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t* outPayload,
size_t* size)
{
- *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
- *size = MAX_REQUEST_LENGTH;
-
- if(!*outPayload)
- {
- return OC_STACK_NO_MEMORY;
- }
-
CborEncoder encoder = {0};
- bool err = false;
+ int64_t err = 0;
- cbor_encoder_init(&encoder, *outPayload, *size, 0);
+ cbor_encoder_init(&encoder, outPayload, *size, 0);
CborEncoder rootArray;
- err = err || cbor_encoder_create_array(&encoder, &rootArray, 2);
- err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PLATFORM);
+ err = err | cbor_encoder_create_array(&encoder, &rootArray, 1);
{
CborEncoder map;
- err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
+ err = err | cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
// uri
- err = err || AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1,
+ err = err | AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1,
payload->uri);
// Rep Map
{
CborEncoder repMap;
- err = err || cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION,
+ err = err | cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION,
sizeof(OC_RSRVD_REPRESENTATION) - 1);
- err = err || cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength);
+ err = err | cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength);
// Platform ID
- err = err || AddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_ID,
+ err = err | AddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_ID,
sizeof(OC_RSRVD_PLATFORM_ID) - 1,
payload->info.platformID);
// MFG Name
- err = err || AddTextStringToMap(&repMap, OC_RSRVD_MFG_NAME,
+ err = err | AddTextStringToMap(&repMap, OC_RSRVD_MFG_NAME,
sizeof(OC_RSRVD_MFG_NAME) - 1,
payload->info.manufacturerName);
// MFG Url
- err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_URL,
+ err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_URL,
sizeof(OC_RSRVD_MFG_URL) - 1,
payload->info.manufacturerUrl);
// Model Num
- err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MODEL_NUM,
+ err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MODEL_NUM,
sizeof(OC_RSRVD_MODEL_NUM) - 1,
payload->info.modelNumber);
// Date of Mfg
- err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_DATE,
+ err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_DATE,
sizeof(OC_RSRVD_MFG_DATE) - 1,
payload->info.dateOfManufacture);
// Platform Version
- err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_VERSION,
+ err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_VERSION,
sizeof(OC_RSRVD_PLATFORM_VERSION) - 1,
payload->info.platformVersion);
// OS Version
- err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_OS_VERSION,
+ err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_OS_VERSION,
sizeof(OC_RSRVD_OS_VERSION) - 1,
payload->info.operatingSystemVersion);
// Hardware Version
- err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_HARDWARE_VERSION,
+ err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_HARDWARE_VERSION,
sizeof(OC_RSRVD_HARDWARE_VERSION) - 1,
payload->info.hardwareVersion);
// Firmware Version
- err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_FIRMWARE_VERSION,
+ err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_FIRMWARE_VERSION,
sizeof(OC_RSRVD_FIRMWARE_VERSION) - 1,
payload->info.firmwareVersion);
// Support URL
- err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SUPPORT_URL,
+ err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SUPPORT_URL,
sizeof(OC_RSRVD_SUPPORT_URL) - 1,
payload->info.supportUrl);
// System Time
- err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SYSTEM_TIME,
+ err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SYSTEM_TIME,
sizeof(OC_RSRVD_SYSTEM_TIME) - 1,
payload->info.systemTime);
- err = err || cbor_encoder_close_container(&map, &repMap);
+ err = err | cbor_encoder_close_container(&map, &repMap);
}
// Close Map
- err = err || cbor_encoder_close_container(&rootArray, &map);
+ err = err | cbor_encoder_close_container(&rootArray, &map);
}
// Close main array
- err = err || cbor_encoder_close_container(&encoder, &rootArray);
-
- if(err)
- {
- OC_LOG_V(ERROR, TAG, "Convert Platform Payload failed with : %d", err);
- return OC_STACK_ERROR;
- }
+ err = err | cbor_encoder_close_container(&encoder, &rootArray);
- *size = encoder.ptr - *outPayload;
- uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
+ return checkError(err, &encoder, outPayload, size);
+}
- if(!tempPayload)
+static int64_t OCConvertArrayItem(CborEncoder* array, const OCRepPayloadValueArray* valArray,
+ size_t index)
+{
+ int64_t err = 0;
+ switch (valArray->type)
{
- OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
- OICFree(*outPayload);
- return OC_STACK_ERROR;
+ case OCREP_PROP_NULL:
+ OC_LOG(ERROR, TAG, "ConvertArray Invalid NULL");
+ err = CborUnknownError;
+ break;
+ case OCREP_PROP_INT:
+ err = err | cbor_encode_int(array, valArray->iArray[index]);
+ break;
+ case OCREP_PROP_DOUBLE:
+ err = err | cbor_encode_double(array, valArray->dArray[index]);
+ break;
+ case OCREP_PROP_BOOL:
+ err = err | cbor_encode_boolean(array, valArray->bArray[index]);
+ break;
+ case OCREP_PROP_STRING:
+ if (!valArray->strArray[index])
+ {
+ err = err | cbor_encode_null(array);
+ }
+ else
+ {
+ err = err | cbor_encode_text_string(array, valArray->strArray[index],
+ strlen(valArray->strArray[index]));
+ }
+ break;
+ case OCREP_PROP_OBJECT:
+ if (!valArray->objArray[index])
+ {
+ err = err | cbor_encode_null(array);
+ }
+ else
+ {
+ err = OCConvertSingleRepPayload(array, valArray->objArray[index]);
+ }
+ break;
+ case OCREP_PROP_ARRAY:
+ OC_LOG(ERROR, TAG, "ConvertArray Invalid child array");
+ err = CborUnknownError;
+ break;
}
- *outPayload = tempPayload;
-
- return OC_STACK_OK;
+ return err;
}
-
-static bool OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload);
-
-static bool OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* valArray)
+static int64_t OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* valArray)
{
CborEncoder array;
- bool err = false;
+ int64_t err = 0;
+
+ err = err | cbor_encoder_create_array(parent, &array, valArray->dimensions[0]);
- err = err || cbor_encoder_create_array(parent, &array, CborIndefiniteLength);
- err = err || cbor_encode_uint(&array, valArray->type);
- for(int i = 0; i < MAX_REP_ARRAY_DEPTH; ++i)
+ for (size_t i = 0; i < valArray->dimensions[0];++i)
{
- err = err || cbor_encode_uint(&array, valArray->dimensions[i]);
- }
+ if (valArray->dimensions[1] != 0)
+ {
+ CborEncoder array2;
+ err = err | cbor_encoder_create_array(&array, &array2, valArray->dimensions[1]);
- size_t dimTotal = calcDimTotal(valArray->dimensions);
+ for (size_t j = 0; j < valArray->dimensions[1]; ++j)
+ {
+ if (valArray->dimensions[2] != 0)
+ {
+ CborEncoder array3;
+ err = err | cbor_encoder_create_array(&array2, &array3,
+ valArray->dimensions[2]);
- for(size_t i = 0; i < dimTotal; ++i)
- {
- switch(valArray->type)
+ for(size_t k = 0; k < valArray->dimensions[2]; ++k)
+ {
+ OCConvertArrayItem(&array3, valArray,
+ j * valArray->dimensions[2] +
+ i * valArray->dimensions[2] * valArray->dimensions[1] +
+ k);
+ }
+ err = err | cbor_encoder_close_container(&array2, &array3);
+ }
+ else
+ {
+ OCConvertArrayItem(&array2, valArray,
+ i * valArray->dimensions[1] + j);
+ }
+ }
+ err = err | cbor_encoder_close_container(&array, &array2);
+ }
+ else
{
- case OCREP_PROP_NULL:
- OC_LOG(ERROR, TAG, PCF("ConvertArray Invalid NULL"));
- err = CborUnknownError;
- break;
- case OCREP_PROP_INT:
- err = err || cbor_encode_int(&array, valArray->iArray[i]);
- break;
- case OCREP_PROP_DOUBLE:
- err = err || cbor_encode_double(&array, valArray->dArray[i]);
- break;
- case OCREP_PROP_BOOL:
- err = err || cbor_encode_boolean(&array, valArray->bArray[i]);
- break;
- case OCREP_PROP_STRING:
- err = err || cbor_encode_text_string(&array, valArray->strArray[i],
- strlen(valArray->strArray[i]));
- break;
- case OCREP_PROP_OBJECT:
- err = OCConvertSingleRepPayload(&array, valArray->objArray[i]);
- break;
- case OCREP_PROP_ARRAY:
- OC_LOG(ERROR, TAG, PCF("ConvertArray Invalid child array"));
- err = CborUnknownError;
- break;
+ OCConvertArrayItem(&array, valArray, i);
}
}
-
- err = err || cbor_encoder_close_container(parent, &array);
+ err = err | cbor_encoder_close_container(parent, &array);
return err;
}
-static bool OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload)
+static int64_t OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload)
{
- bool err = false;
+ int64_t err = 0;
CborEncoder map;
- err = err || cbor_encoder_create_map(parent, &map, CborIndefiniteLength);
+ err = err | cbor_encoder_create_map(parent, &map, CborIndefiniteLength);
// Uri
- err = err || ConditionalAddTextStringToMap(&map, OC_RSRVD_HREF,
+ err = err | ConditionalAddTextStringToMap(&map, OC_RSRVD_HREF,
sizeof(OC_RSRVD_HREF) - 1,
payload->uri);
// resource types, interfaces
if(payload->types || payload->interfaces)
{
- OC_LOG_V(INFO, TAG, "Payload has types or interfaces");
- err = err || cbor_encode_text_string(&map,
+ OC_LOG(INFO, TAG, "Payload has types or interfaces");
+ err = err | cbor_encode_text_string(&map,
OC_RSRVD_PROPERTY,
sizeof(OC_RSRVD_PROPERTY) - 1);
CborEncoder propMap;
- err = err || cbor_encoder_create_map(&map, &propMap, 2);
+ err = err | cbor_encoder_create_map(&map, &propMap, 2);
CborEncoder curArray;
if(payload->types)
{
- err = err || cbor_encode_text_string(&propMap,
+ err = err | cbor_encode_text_string(&propMap,
OC_RSRVD_RESOURCE_TYPE,
sizeof(OC_RSRVD_RESOURCE_TYPE) - 1);
- err = err || cbor_encoder_create_array(&propMap, &curArray, CborIndefiniteLength);
+ err = err | cbor_encoder_create_array(&propMap, &curArray, CborIndefiniteLength);
OCStringLL* val = payload->types;
while(val)
{
- err = err || cbor_encode_text_string(&curArray, val->value, strlen(val->value));
+ err = err | cbor_encode_text_string(&curArray, val->value, strlen(val->value));
val = val->next;
}
- err = err || cbor_encoder_close_container(&propMap, &curArray);
+ err = err | cbor_encoder_close_container(&propMap, &curArray);
}
if(payload->interfaces)
{
- err = err || cbor_encode_text_string(&propMap,
+ err = err | cbor_encode_text_string(&propMap,
OC_RSRVD_INTERFACE,
sizeof(OC_RSRVD_INTERFACE) - 1);
- err = err || cbor_encoder_create_array(&propMap, &curArray, CborIndefiniteLength);
+ err = err | cbor_encoder_create_array(&propMap, &curArray, CborIndefiniteLength);
OCStringLL* val = payload->interfaces;
while(val)
{
- err = err || cbor_encode_text_string(&curArray, val->value, strlen(val->value));
+ err = err | cbor_encode_text_string(&curArray, val->value, strlen(val->value));
val = val->next;
}
- err = err || cbor_encoder_close_container(&propMap, &curArray);
+ err = err | cbor_encoder_close_container(&propMap, &curArray);
}
- err = err || cbor_encoder_close_container(&map, &propMap);
+ err = err | cbor_encoder_close_container(&map, &propMap);
}
// Rep Map
{
CborEncoder repMap;
- err = err || cbor_encode_text_string(&map,
+ err = err | cbor_encode_text_string(&map,
OC_RSRVD_REPRESENTATION,
sizeof(OC_RSRVD_REPRESENTATION) - 1);
- err = err || cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength);
+ err = err | cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength);
OCRepPayloadValue* value = payload->values;
while(value)
{
- err = err || cbor_encode_text_string(&repMap,
+ err = err | cbor_encode_text_string(&repMap,
value->name,
strlen(value->name));
switch(value->type)
{
case OCREP_PROP_NULL:
- err = err || cbor_encode_null(&repMap);
+ err = err | cbor_encode_null(&repMap);
break;
case OCREP_PROP_INT:
- err = err || cbor_encode_int(&repMap,
+ err = err | cbor_encode_int(&repMap,
value->i);
break;
case OCREP_PROP_DOUBLE:
- err = err || cbor_encode_double(&repMap,
+ err = err | cbor_encode_double(&repMap,
value->d);
break;
case OCREP_PROP_BOOL:
- err = err || cbor_encode_boolean(&repMap,
+ err = err | cbor_encode_boolean(&repMap,
value->b);
break;
case OCREP_PROP_STRING:
- err = err || cbor_encode_text_string(&repMap,
+ err = err | cbor_encode_text_string(&repMap,
value->str, strlen(value->str));
break;
case OCREP_PROP_OBJECT:
- err = err || OCConvertSingleRepPayload(&repMap, value->obj);
+ err = err | OCConvertSingleRepPayload(&repMap, value->obj);
break;
case OCREP_PROP_ARRAY:
- err = err || OCConvertArray(&repMap, &value->arr);
+ err = err | OCConvertArray(&repMap, &value->arr);
break;
default:
OC_LOG_V(ERROR, TAG, "Invalid Prop type: %d",
value = value->next;
}
- err = err || cbor_encoder_close_container(&map, &repMap);
+ err = err | cbor_encoder_close_container(&map, &repMap);
}
// Close Map
- err = err || cbor_encoder_close_container(parent, &map);
+ err = err | cbor_encoder_close_container(parent, &map);
return err;
}
-static OCStackResult OCConvertRepPayload(OCRepPayload* payload, uint8_t** outPayload, size_t* size)
+static int64_t OCConvertRepPayload(OCRepPayload* payload, uint8_t* outPayload, size_t* size)
{
- *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
- *size = MAX_REQUEST_LENGTH;
-
- if(!*outPayload)
- {
- return OC_STACK_NO_MEMORY;
- }
-
CborEncoder encoder = {0};
- bool err = false;
+ int64_t err = 0;
- cbor_encoder_init(&encoder, *outPayload, *size, 0);
+ cbor_encoder_init(&encoder, outPayload, *size, 0);
CborEncoder rootArray;
- err = err || cbor_encoder_create_array(&encoder, &rootArray, CborIndefiniteLength);
- err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_REPRESENTATION);
+ err = err | cbor_encoder_create_array(&encoder, &rootArray, CborIndefiniteLength);
- while(payload != NULL && !err)
+ while(payload != NULL && (err == 0 || err == CborErrorOutOfMemory))
{
- err = err || OCConvertSingleRepPayload(&rootArray, payload);
+ err = err | OCConvertSingleRepPayload(&rootArray, payload);
payload = payload->next;
}
// Close main array
- err = err || cbor_encoder_close_container(&encoder, &rootArray);
-
- if(err)
- {
- OC_LOG_V(ERROR, TAG, "Convert Rep Payload failed with : %d", err);
- return OC_STACK_ERROR;
- }
-
- *size = encoder.ptr - *outPayload;
- uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
-
- if(!tempPayload)
- {
- OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
- OICFree(*outPayload);
- return OC_STACK_ERROR;
- }
-
- *outPayload = tempPayload;
+ err = err | cbor_encoder_close_container(&encoder, &rootArray);
- return OC_STACK_OK;
+ return checkError(err, &encoder, outPayload, size);
}
-static OCStackResult OCConvertPresencePayload(OCPresencePayload* payload,
- uint8_t** outPayload, size_t* size)
+static int64_t OCConvertPresencePayload(OCPresencePayload* payload,
+ uint8_t* outPayload, size_t* size)
{
- *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH);
- *size = MAX_REQUEST_LENGTH;
-
- if(!*outPayload)
- {
- return OC_STACK_NO_MEMORY;
- }
-
CborEncoder encoder = {0};
- bool err = false;
+ int64_t err = 0;
- cbor_encoder_init(&encoder, *outPayload, *size, 0);
+ cbor_encoder_init(&encoder, outPayload, *size, 0);
CborEncoder rootArray;
- err = err || cbor_encoder_create_array(&encoder, &rootArray, 2);
- err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PRESENCE);
-
+ err = err | cbor_encoder_create_array(&encoder, &rootArray, 1);
CborEncoder map;
- err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
+ err = err | cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength);
// Sequence Number
- err = err || cbor_encode_text_string(&map,
+ err = err | cbor_encode_text_string(&map,
OC_RSRVD_NONCE,
sizeof(OC_RSRVD_NONCE) - 1);
- err = err || cbor_encode_uint(&map, payload->sequenceNumber);
+ err = err | cbor_encode_uint(&map, payload->sequenceNumber);
// Max Age
- err = err || cbor_encode_text_string(&map,
+ err = err | cbor_encode_text_string(&map,
OC_RSRVD_TTL,
sizeof(OC_RSRVD_TTL) - 1);
- err = err || cbor_encode_uint(&map, payload->maxAge);
+ err = err | cbor_encode_uint(&map, payload->maxAge);
// Trigger
const char* triggerStr = convertTriggerEnumToString(payload->trigger);
- err = err || AddTextStringToMap(&map, OC_RSRVD_TRIGGER, sizeof(OC_RSRVD_TRIGGER) - 1,
+ err = err | AddTextStringToMap(&map, OC_RSRVD_TRIGGER, sizeof(OC_RSRVD_TRIGGER) - 1,
triggerStr);
// Resource type name
if(payload->trigger != OC_PRESENCE_TRIGGER_DELETE)
{
- err = err || ConditionalAddTextStringToMap(&map, OC_RSRVD_RESOURCE_TYPE,
+ err = err | ConditionalAddTextStringToMap(&map, OC_RSRVD_RESOURCE_TYPE,
sizeof(OC_RSRVD_RESOURCE_TYPE) - 1, payload->resourceType);
}
// Close Map
- err = err || cbor_encoder_close_container(&rootArray, &map);
- err = err || cbor_encoder_close_container(&encoder, &rootArray);
-
- if(err)
- {
- OC_LOG_V(ERROR, TAG, "Convert Presence Payload failed with : %d", err);
- return OC_STACK_ERROR;
- }
-
- *size = encoder.ptr - *outPayload;
- uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size);
-
- if(!tempPayload)
- {
- OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!"));
- OICFree(*outPayload);
- return OC_STACK_ERROR;
- }
-
- *outPayload = tempPayload;
+ err = err | cbor_encoder_close_container(&rootArray, &map);
+ err = err | cbor_encoder_close_container(&encoder, &rootArray);
- return OC_STACK_OK;
+ return checkError(err, &encoder, outPayload, size);
}
-bool AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
+static int64_t AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
const char* value)
{
- return cbor_encode_text_string(map, key, keylen) ||
+ return cbor_encode_text_string(map, key, keylen) |
cbor_encode_text_string(map, value, strlen(value));
}
-bool ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
+static int64_t ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen,
const char* value)
{
- return value ? AddTextStringToMap(map, key, keylen, value) : false;
+ return value ? AddTextStringToMap(map, key, keylen, value) : 0;
}
#include "ocpayload.h"
#include "cbor.h"
-#define TAG PCF("OCPayloadParse")
+#define TAG "OCPayloadParse"
static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* arrayVal);
static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arrayVal);
static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* arrayVal);
static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* arrayVal);
-OCStackResult OCParsePayload(OCPayload** outPayload, const uint8_t* payload, size_t payloadSize)
+OCStackResult OCParsePayload(OCPayload** outPayload, OCPayloadType payloadType,
+ const uint8_t* payload, size_t payloadSize)
{
CborParser parser;
CborValue rootValue;
// enter the array
err = err || cbor_value_enter_container(&rootValue, &arrayValue);
- int payloadType = 0;
- err = err || cbor_value_get_int(&arrayValue, &payloadType);
- err = err || cbor_value_advance_fixed(&arrayValue);
-
- if(err)
+ if(err || arrayValue.type != CborMapType)
{
OC_LOG_V(ERROR, TAG, "CBOR payload parse failed :%d", err);
return OC_STACK_MALFORMED_RESPONSE;
static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* arrayVal)
{
+ if (!outPayload)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
bool err = false;
char * securityData = NULL;
}
else
{
- OC_LOG_V(ERROR, TAG, PCF("Cbor main value not a map"));
+ OC_LOG(ERROR, TAG, "Cbor main value not a map");
return OC_STACK_MALFORMED_RESPONSE;
}
if(err)
{
- OC_LOG_V(ERROR, TAG, "Cbor in error condition");
+ OC_LOG(ERROR, TAG, "Cbor in error condition");
OICFree(securityData);
return OC_STACK_MALFORMED_RESPONSE;
}
static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* arrayVal)
{
+ if (!outPayload)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
bool err = false;
OCDiscoveryPayload* out = OCDiscoveryPayloadCreate();
OCResourcePayload* resource = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
if(!resource)
{
- OC_LOG_V(ERROR, TAG, "Memory allocation failed");
+ OC_LOG(ERROR, TAG, "Memory allocation failed");
OCDiscoveryPayloadDestroy(out);
return OC_STACK_NO_MEMORY;
}
llPtr = resource->types;
if(!llPtr)
{
- OC_LOG(ERROR, TAG, PCF("Memory allocation failed"));
+ OC_LOG(ERROR, TAG, "Memory allocation failed");
OICFree(resource->uri);
OICFree(resource->sid);
OICFree(resource);
llPtr = llPtr->next;
if(!llPtr)
{
- OC_LOG(ERROR, TAG, PCF("Memory allocation failed"));
+ OC_LOG(ERROR, TAG, "Memory allocation failed");
OICFree(resource->uri);
OICFree(resource->sid);
OCFreeOCStringLL(resource->types);
}
else
{
- OC_LOG(ERROR, TAG, PCF("Unknown state in resource type copying"));
+ OC_LOG(ERROR, TAG, "Unknown state in resource type copying");
OICFree(resource->uri);
OICFree(resource->sid);
OCFreeOCStringLL(resource->types);
llPtr = resource->interfaces;
if(!llPtr)
{
- OC_LOG_V(ERROR, TAG, "Memory allocation failed");
+ OC_LOG(ERROR, TAG, "Memory allocation failed");
OICFree(resource->uri);
OICFree(resource->sid);
OCFreeOCStringLL(resource->types);
llPtr = llPtr->next;
if(!llPtr)
{
- OC_LOG_V(ERROR, TAG, "Memory allocation failed");
+ OC_LOG(ERROR, TAG, "Memory allocation failed");
OICFree(resource->uri);
OICFree(resource->sid);
OCFreeOCStringLL(resource->types);
}
else
{
- OC_LOG(ERROR, TAG, PCF("Unknown state in resource interfaces copying"));
+ OC_LOG(ERROR, TAG, "Unknown state in resource interfaces copying");
OICFree(resource->uri);
OICFree(resource->sid);
OCFreeOCStringLL(resource->types);
static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arrayVal)
{
+ if (!outPayload)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
bool err = false;
if(cbor_value_is_map(arrayVal))
}
else
{
- OC_LOG(ERROR, TAG, PCF("Root device node was not a map"));
+ OC_LOG(ERROR, TAG, "Root device node was not a map");
return OC_STACK_MALFORMED_RESPONSE;
}
static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* arrayVal)
{
+ if (!outPayload)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
bool err = false;
if(cbor_value_is_map(arrayVal))
OICFree(info.platformVersion);
OICFree(info.supportUrl);
OICFree(info.systemTime);
- OC_LOG(ERROR, TAG, PCF("CBOR error In ParsePlatformPayload"));
+ OC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
return OC_STACK_MALFORMED_RESPONSE;
}
}
else
{
- OC_LOG(ERROR, TAG, PCF("Root device node was not a map"));
+ OC_LOG(ERROR, TAG, "Root device node was not a map");
return OC_STACK_MALFORMED_RESPONSE;
}
}
-static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* container)
+static OCRepPayloadPropType DecodeCborType(CborType type)
{
+ switch (type)
+ {
+ case CborNullType:
+ return OCREP_PROP_NULL;
+ case CborIntegerType:
+ return OCREP_PROP_INT;
+ case CborDoubleType:
+ return OCREP_PROP_DOUBLE;
+ case CborBooleanType:
+ return OCREP_PROP_BOOL;
+ case CborTextStringType:
+ return OCREP_PROP_STRING;
+ case CborMapType:
+ return OCREP_PROP_OBJECT;
+ case CborArrayType:
+ return OCREP_PROP_ARRAY;
+ default:
+ return OCREP_PROP_NULL;
+ }
+}
+static bool OCParseArrayFindDimensionsAndType(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
+ OCRepPayloadPropType* type)
+{
+ bool err = false;
CborValue insideArray;
+ *type = OCREP_PROP_NULL;
+ dimensions[0] = dimensions[1] = dimensions[2] = 0;
+
+ err = err || cbor_value_enter_container(parent, &insideArray);
+
+ while (cbor_value_is_valid(&insideArray))
+ {
+ OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
+
+ if (tempType == OCREP_PROP_ARRAY)
+ {
+ size_t subdim[MAX_REP_ARRAY_DEPTH];
+ tempType = OCREP_PROP_NULL;
+ err = err || OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
+
+ if (subdim[2] != 0)
+ {
+ OC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
+ }
+
+ dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
+ dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
+
+ if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL
+ && *type != tempType)
+ {
+ OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
+ return true;
+ }
+ else if (*type == OCREP_PROP_NULL)
+ {
+ // We don't know the type of this array yet, so the assignment is OK
+ *type = tempType;
+ }
+ }
+ else if (*type == OCREP_PROP_NULL)
+ {
+ // We don't know the type of this array yet, so the assignment is OK
+ *type = tempType;
+ }
+ // tempType is allowed to be NULL, since it might now know the answer yet
+ else if (tempType != OCREP_PROP_NULL && *type != tempType)
+ {
+ // this is an invalid situation!
+ OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
+ return true;
+ }
+
+ ++dimensions[0];
+ cbor_value_advance(&insideArray);
+ }
+
+ return err;
+}
+
+static size_t getAllocSize(OCRepPayloadPropType type)
+{
+ switch (type)
+ {
+ case OCREP_PROP_INT:
+ return sizeof (int64_t);
+ case OCREP_PROP_DOUBLE:
+ return sizeof (double);
+ case OCREP_PROP_BOOL:
+ return sizeof (bool);
+ case OCREP_PROP_STRING:
+ return sizeof (char*);
+ case OCREP_PROP_OBJECT:
+ return sizeof (OCRepPayload*);
+ default:
+ return 0;
+ }
+}
+
+static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
+{
+ return
+ (dimensions[1] == 0 ? 1 : dimensions[1]) *
+ (dimensions[2] == 0 ? 1 : dimensions[2]) *
+ elementNum;
+}
+
+static bool OCParseArrayFillArray(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
+ OCRepPayloadPropType type, void* targetArray)
+{
bool err = false;
- uint64_t tempInt = 0;
+ CborValue insideArray;
+
+ err = err || cbor_value_enter_container(parent, &insideArray);
+
+ size_t i = 0;
+ char* tempStr = NULL;
+ size_t tempLen = 0;
+ OCRepPayload* tempPl = NULL;
+
+ size_t newdim[MAX_REP_ARRAY_DEPTH];
+ newdim[0] = dimensions[1];
+ newdim[1] = dimensions[2];
+ newdim[2] = 0;
+
+ while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
+ {
+ if (cbor_value_get_type(&insideArray) != CborNullType)
+ {
+ switch (type)
+ {
+ case OCREP_PROP_INT:
+ if (dimensions[1] == 0)
+ {
+ err = err || cbor_value_get_int64(&insideArray,
+ &(((int64_t*)targetArray)[i]));
+ }
+ else
+ {
+ err = err || OCParseArrayFillArray(&insideArray, newdim,
+ type,
+ &(((int64_t*)targetArray)[arrayStep(dimensions, i)])
+ );
+ }
+ break;
+ case OCREP_PROP_DOUBLE:
+ if (dimensions[1] == 0)
+ {
+ err = err || cbor_value_get_double(&insideArray,
+ &(((double*)targetArray)[i]));
+ }
+ else
+ {
+ err = err || OCParseArrayFillArray(&insideArray, newdim,
+ type,
+ &(((double*)targetArray)[arrayStep(dimensions, i)])
+ );
+ }
+ break;
+ case OCREP_PROP_BOOL:
+ if (dimensions[1] == 0)
+ {
+ err = err || cbor_value_get_boolean(&insideArray,
+ &(((bool*)targetArray)[i]));
+ }
+ else
+ {
+ err = err || OCParseArrayFillArray(&insideArray, newdim,
+ type,
+ &(((bool*)targetArray)[arrayStep(dimensions, i)])
+ );
+ }
+ break;
+ case OCREP_PROP_STRING:
+ if (dimensions[1] == 0)
+ {
+ err = err || cbor_value_dup_text_string(&insideArray,
+ &tempStr, &tempLen, NULL);
+ ((char**)targetArray)[i] = tempStr;
+ tempStr = NULL;
+ }
+ else
+ {
+ err = err || OCParseArrayFillArray(&insideArray, newdim,
+ type,
+ &(((char**)targetArray)[arrayStep(dimensions, i)])
+ );
+ }
+ break;
+ case OCREP_PROP_OBJECT:
+ if (dimensions[1] == 0)
+ {
+ err = err || OCParseSingleRepPayload(&tempPl, &insideArray);
+ ((OCRepPayload**)targetArray)[i] = tempPl;
+ tempPl = NULL;
+ }
+ else
+ {
+ err = err || OCParseArrayFillArray(&insideArray, newdim,
+ type,
+ &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)])
+ );
+ }
+ break;
+ default:
+ OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
+ err = true;
+ break;
+ }
+ }
+ ++i;
+ err = err || cbor_value_advance(&insideArray);
+ }
+
+ return err;
+}
+
+static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* container)
+{
OCRepPayloadPropType type;
size_t dimensions[MAX_REP_ARRAY_DEPTH];
- err = err || cbor_value_enter_container(container, &insideArray);
+ bool err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
- err = err || cbor_value_get_uint64(&insideArray, &tempInt);
- err = err || cbor_value_advance_fixed(&insideArray);
- type = (OCRepPayloadPropType)tempInt;
+ if (err)
+ {
+ OC_LOG(ERROR, TAG, "Array details weren't clear");
+ return err;
+ }
- for(int i = 0; i < MAX_REP_ARRAY_DEPTH; ++ i)
+ if (type == OCREP_PROP_NULL)
{
- err = err || cbor_value_get_uint64(&insideArray, &tempInt);
- err = err || cbor_value_advance_fixed(&insideArray);
- dimensions[i] = tempInt;
+ err = err || OCRepPayloadSetNull(out, name);
+ err = err || cbor_value_advance(container);
+ return err;
}
size_t dimTotal = calcDimTotal(dimensions);
+ size_t allocSize = getAllocSize(type);
+ void* arr = OICCalloc(dimTotal, allocSize);
- void* arr = NULL;
- char* tempStr;
- size_t len;
- OCRepPayload* pl;
- switch(type)
+ if (!arr)
+ {
+ OC_LOG(ERROR, TAG, "Array Parse allocation failed");
+ return true;
+ }
+
+ err = err || OCParseArrayFillArray(container, dimensions, type, arr);
+
+ switch (type)
{
case OCREP_PROP_INT:
- arr = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
- if (arr)
- {
- for(size_t i = 0; i < dimTotal && !err; ++i)
- {
- err = err || cbor_value_get_int64(&insideArray, &(((int64_t*)arr)[i]));
- err = err || cbor_value_advance_fixed(&insideArray);
- }
- if(err || !OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t*)arr, dimensions))
- {
- OICFree(arr);
- err = true;
- }
- }
- else
+ if (err || !OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t*)arr, dimensions))
{
+ OICFree(arr);
err = true;
}
break;
case OCREP_PROP_DOUBLE:
- arr = (double*)OICMalloc(dimTotal * sizeof(double));
- if(arr)
- {
- for(size_t i = 0; i < dimTotal && !err; ++i)
- {
- err = err || cbor_value_get_double(&insideArray, &(((double*)arr)[i]));
- err = err || cbor_value_advance_fixed(&insideArray);
- }
- if(err || !OCRepPayloadSetDoubleArrayAsOwner(out, name, (double*)arr, dimensions))
- {
- OICFree(arr);
- err = true;
- }
- }
- else
+ if (err || !OCRepPayloadSetDoubleArrayAsOwner(out, name, (double*)arr, dimensions))
{
+ OICFree(arr);
err = true;
}
break;
case OCREP_PROP_BOOL:
- arr = (bool*)OICMalloc(dimTotal * sizeof(bool));
- if(arr)
- {
- for(size_t i = 0; i < dimTotal && !err; ++i)
- {
- err = err || cbor_value_get_boolean(&insideArray, &(((bool*)arr)[i]));
- err = err || cbor_value_advance_fixed(&insideArray);
- }
- if(err && !OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions))
- {
- OICFree(arr);
- err = true;
- }
- }
- else
+ if (err || !OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions))
{
+ OICFree(arr);
err = true;
}
break;
case OCREP_PROP_STRING:
- arr = (char**)OICMalloc(dimTotal * sizeof(char*));
- if(arr)
+ if (err || !OCRepPayloadSetStringArrayAsOwner(out, name, (char**)arr, dimensions))
{
- for(size_t i = 0; i < dimTotal && !err; ++i)
- {
- err = err || cbor_value_dup_text_string(&insideArray, &tempStr,
- &len, NULL);
- err = err || cbor_value_advance(&insideArray);
- ((char**)arr)[i] = tempStr;
- }
- if(err || !OCRepPayloadSetStringArrayAsOwner(out, name, (char**)arr, dimensions))
+ for(size_t i = 0; i < dimTotal; ++i)
{
- OICFree(arr);
- err = true;
+ OICFree(((char**)arr)[i]);
}
- }
- else
- {
+ OICFree(arr);
err = true;
}
break;
case OCREP_PROP_OBJECT:
- arr = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
- if(arr)
+ if (err || !OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions))
{
- for(size_t i = 0; i < dimTotal && !err; ++i)
- {
- pl = NULL;
- err = err || OCParseSingleRepPayload(&pl, &insideArray);
- err = err || cbor_value_advance(&insideArray);
- ((OCRepPayload**)arr)[i] = pl;
- }
- if(err || !OCRepPayloadSetPropObjectArrayAsOwner(out, name,
- (OCRepPayload**)arr, dimensions))
+ for(size_t i = 0; i < dimTotal; ++i)
{
- OICFree(arr);
- err = true;
+ OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
}
- }
- else
- {
+ OICFree(arr);
err = true;
}
break;
static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue* repParent)
{
+ if (!outPayload)
+ {
+ return false;
+ }
+
*outPayload = OCRepPayloadCreate();
OCRepPayload* curPayload = *outPayload;
bool err = false;
err = err || cbor_value_leave_container(&insidePropArray, &ifArray);
}
}
+
err = err || cbor_value_map_find_value(repParent, OC_RSRVD_REPRESENTATION, &curVal);
if(cbor_value_is_map(&curVal))
{
while(!err && cbor_value_is_valid(&repMap))
{
char* name;
- err = err || cbor_value_dup_text_string(&repMap, &name, &len, NULL);
+ err = err || cbor_value_dup_text_string(&repMap, &name, &len, NULL);
- err = err || cbor_value_advance(&repMap);
+ err = err || cbor_value_advance(&repMap);
int64_t intval = 0;
bool boolval = false;
}
static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* arrayVal)
{
+ if (!outPayload)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
bool err = false;
OCRepPayload* rootPayload = NULL;
if(err)
{
OCRepPayloadDestroy(rootPayload);
- OC_LOG_V(ERROR, TAG, PCF("CBOR error in ParseRepPayload"));
+ OC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
return OC_STACK_MALFORMED_RESPONSE;
}
}
static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* arrayVal)
{
+ if (!outPayload)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
bool err = false;
if(cbor_value_is_map(arrayVal))
{
if(err)
{
OCPayloadDestroy(*outPayload);
- OC_LOG_V(ERROR, TAG, PCF("CBOR error Parse Presence Payload"));
+ OC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
return OC_STACK_MALFORMED_RESPONSE;
}
}
else
{
- OC_LOG(ERROR, TAG, PCF("Root presence node was not a map"));
+ OC_LOG(ERROR, TAG, "Root presence node was not a map");
return OC_STACK_MALFORMED_RESPONSE;
}
}
// For POSIX.1-2001 base specification,
// Refer http://pubs.opengroup.org/onlinepubs/009695399/
#define _POSIX_C_SOURCE 200112L
-#include "ocresource.h"
#include <string.h>
+#include "ocresource.h"
#include "ocresourcehandler.h"
#include "ocobserve.h"
#include "occollection.h"
#include "logger.h"
#include "cJSON.h"
#include "ocpayload.h"
-
+#include "secureresourcemanager.h"
#include "cacommon.h"
#include "cainterface.h"
#ifdef WITH_RD
#include "rd_server.h"
+#endif
+
+#ifdef ROUTING_GATEWAY
+#include "routingmanager.h"
#endif
/// Module Name
-#define TAG PCF("ocresource")
+#define TAG "ocresource"
#define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
{OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
- TAG, PCF(#arg " is NULL")); return (retVal); } }
+ TAG, #arg " is NULL"); return (retVal); } }
extern OCResource *headResource;
static OCPlatformInfo savedPlatformInfo = {0};
{
if (numKeyValuePairsParsed >= 2)
{
- OC_LOG(ERROR, TAG, PCF("More than 2 queries params in URI."));
+ OC_LOG(ERROR, TAG, "More than 2 queries params in URI.");
return OC_STACK_INVALID_QUERY;
}
{
return OC_RESOURCE_TYPES_URI;
}
+#ifdef ROUTING_GATEWAY
+ else if (0 == strcmp(uriInRequest, OC_RSRVD_GATEWAY_URI))
+ {
+ return OC_GATEWAY_URI;
+ }
+#endif
#ifdef WITH_PRESENCE
else if (strcmp(uriInRequest, OC_RSRVD_PRESENCE_URI) == 0)
{
if (uri == OC_PRESENCE)
{
//Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
- OC_LOG(INFO, TAG, PCF("OC_PRESENCE Request for virtual resource."));
+ OC_LOG(INFO, TAG, "OC_PRESENCE Request for virtual resource.");
return OC_STACK_OK;
}
#endif
}
else
{
- OCResource *resourcePtr = NULL;
- resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
+ OCResource *resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
*resource = resourcePtr;
if (!resourcePtr)
{
resourceTypePtr = resourceTypePtr->next;
}
- OC_LOG_V(INFO, TAG, PCF("%s does not contain rt=%s."), resource->uri, resourceTypeFilter);
+ OC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
return false;
}
interfacePtr = interfacePtr->next;
}
- OC_LOG_V(INFO, TAG, PCF("%s does not contain if=%s."), resource->uri, interfaceFilter);
+ OC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
return false;
}
{
if (!resource)
{
- OC_LOG(ERROR, TAG, PCF("Invalid resource"));
+ OC_LOG(ERROR, TAG, "Invalid resource");
return false;
}
if (!((interfaceFilter && *interfaceFilter ) ||
(resourceTypeFilter && *resourceTypeFilter)))
{
- OC_LOG_V(INFO, TAG, PCF("%s no query string for EXPLICIT_DISCOVERABLE \
- resource"), resource->uri);
+ OC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE \
+ resource", resource->uri);
return false;
}
}
else if ( !(resource->resourceProperties & OC_ACTIVE) ||
!(resource->resourceProperties & OC_DISCOVERABLE))
{
- OC_LOG_V(INFO, TAG, PCF("%s not ACTIVE or DISCOVERABLE"), resource->uri);
+ OC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
return false;
}
bool bMulticast = false; // Was the discovery request a multicast request?
OCPayload* payload = NULL;
- OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource"));
+ OC_LOG(INFO, TAG, "Entering HandleVirtualResource");
OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
}
else if (virtualUriInRequest == OC_DEVICE_URI)
{
- payload = (OCPayload*)OCDevicePayloadCreate(OC_RSRVD_DEVICE_URI,
- OCGetServerInstanceID(), savedDeviceInfo.deviceName,
- OC_SPEC_VERSION, OC_DATA_MODEL_VERSION);
- if (!payload)
+ const OicUuid_t* deviceId = OCGetServerInstanceID();
+ if (!deviceId)
{
- discoveryResult = OC_STACK_NO_MEMORY;
+ discoveryResult = OC_STACK_ERROR;
}
else
{
- discoveryResult = OC_STACK_OK;
+ payload = (OCPayload*) OCDevicePayloadCreate(OC_RSRVD_DEVICE_URI,
+ (const uint8_t*) &deviceId->id, savedDeviceInfo.deviceName,
+ OC_SPEC_VERSION, OC_DATA_MODEL_VERSION);
+ if (!payload)
+ {
+ discoveryResult = OC_STACK_NO_MEMORY;
+ }
+ else
+ {
+ discoveryResult = OC_STACK_OK;
+ }
}
}
else if (virtualUriInRequest == OC_PLATFORM_URI)
discoveryResult = OC_STACK_OK;
}
}
+#ifdef ROUTING_GATEWAY
+ else if (OC_GATEWAY_URI == virtualUriInRequest)
+ {
+ // Received request for a gateway
+ OC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
+ discoveryResult = RMHandleGatewayRequest(request, resource);
+
+ }
+#endif
/**
* Step 2: Send the discovery response
* request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
*/
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
if ((virtualUriInRequest == OC_PRESENCE) &&
(resource->resourceProperties & OC_ACTIVE))
{
}
else
#endif
+#ifdef ROUTING_GATEWAY
+ // Gateway uses the RMHandleGatewayRequest to respond to the request.
+ if (OC_GATEWAY != virtualUriInRequest)
+#endif
{
if(discoveryResult == OC_STACK_OK)
{
else
{
// Ignoring the discovery request as per RFC 7252, Section #8.2
- OC_LOG_V(INFO, TAG, "Silently ignoring the request since device does not have \
+ OC_LOG(INFO, TAG, "Silently ignoring the request since device does not have \
any useful data to send");
}
}
OCEntityHandlerResult ehResult = OC_EH_ERROR;
OCEntityHandlerRequest ehRequest = {0};
- OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
+ OC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
result = FormOCEntityHandlerRequest(&ehRequest,
(OCRequestHandle) request,
request->method,
&request->devAddr,
(OCResourceHandle) NULL, request->query,
+ PAYLOAD_TYPE_REPRESENTATION,
request->payload,
request->payloadSize,
request->numRcvdVendorSpecificHeaderOptions,
(char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
if(ehResult == OC_EH_SLOW)
{
- OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+ OC_LOG(INFO, TAG, "This is a slow resource");
request->slowFlag = 1;
}
else if(ehResult == OC_EH_ERROR)
OCEntityHandlerRequest ehRequest = {0};
- OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler"));
+ OC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
+ OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
+ // check the security resource
+ if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
+ {
+ type = PAYLOAD_TYPE_SECURITY;
+ }
result = FormOCEntityHandlerRequest(&ehRequest,
(OCRequestHandle)request,
request->method,
&request->devAddr,
(OCResourceHandle)resource,
request->query,
+ type,
request->payload,
request->payloadSize,
request->numRcvdVendorSpecificHeaderOptions,
if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
{
- OC_LOG(INFO, TAG, PCF("No observation requested"));
+ OC_LOG(INFO, TAG, "No observation requested");
ehFlag = OC_REQUEST_FLAG;
}
else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER && !collectionResource)
{
- OC_LOG(INFO, TAG, PCF("Observation registration requested"));
+ OC_LOG(INFO, TAG, "Observation registration requested");
result = GenerateObserverId(&ehRequest.obsInfo.obsId);
VERIFY_SUCCESS(result, OC_STACK_OK);
result = AddObserver ((const char*)(request->resourceUrl),
(const char *)(request->query),
ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
- resource, request->qos,
+ resource, request->qos, request->acceptFormat,
&request->devAddr);
if(result == OC_STACK_OK)
{
- OC_LOG(INFO, TAG, PCF("Added observer successfully"));
+ OC_LOG(INFO, TAG, "Added observer successfully");
request->observeResult = OC_STACK_OK;
ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
}
// The error in observeResult for the request will be used when responding to this
// request by omitting the observation option/sequence number.
request->observeResult = OC_STACK_ERROR;
- OC_LOG(ERROR, TAG, PCF("Observer Addition failed"));
+ OC_LOG(ERROR, TAG, "Observer Addition failed");
ehFlag = OC_REQUEST_FLAG;
}
else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
!collectionResource)
{
- OC_LOG(INFO, TAG, PCF("Deregistering observation requested"));
+ OC_LOG(INFO, TAG, "Deregistering observation requested");
resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
if(result == OC_STACK_OK)
{
- OC_LOG(INFO, TAG, PCF("Removed observer successfully"));
+ OC_LOG(INFO, TAG, "Removed observer successfully");
request->observeResult = OC_STACK_OK;
}
else
{
result = OC_STACK_OK;
request->observeResult = OC_STACK_ERROR;
- OC_LOG(ERROR, TAG, PCF("Observer Removal failed"));
+ OC_LOG(ERROR, TAG, "Observer Removal failed");
}
}
else
ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
if(ehResult == OC_EH_SLOW)
{
- OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+ OC_LOG(INFO, TAG, "This is a slow resource");
request->slowFlag = 1;
}
else if(ehResult == OC_EH_ERROR)
&request->devAddr,
(OCResourceHandle)resource,
request->query,
+ PAYLOAD_TYPE_REPRESENTATION,
request->payload,
request->payloadSize,
request->numRcvdVendorSpecificHeaderOptions,
}
case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
{
- OC_LOG(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER"));
+ OC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
return OC_STACK_ERROR;
}
case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
}
default:
{
- OC_LOG(INFO, TAG, PCF("Invalid Resource Determination"));
+ OC_LOG(INFO, TAG, "Invalid Resource Determination");
return OC_STACK_ERROR;
}
}
void DeletePlatformInfo()
{
- OC_LOG(INFO, TAG, PCF("Deleting platform info."));
+ OC_LOG(INFO, TAG, "Deleting platform info.");
OICFree(savedPlatformInfo.platformID);
savedPlatformInfo.platformID = NULL;
if (res != OC_STACK_OK)
{
- OC_LOG_V(ERROR, TAG, PCF("Failed to save platform info. errno(%d)"), res);
+ OC_LOG_V(ERROR, TAG, "Failed to save platform info. errno(%d)", res);
}
else
{
- OC_LOG(ERROR, TAG, PCF("Platform info saved."));
+ OC_LOG(INFO, TAG, "Platform info saved.");
}
return res;
void DeleteDeviceInfo()
{
- OC_LOG(INFO, TAG, PCF("Deleting device info."));
+ OC_LOG(INFO, TAG, "Deleting device info.");
OICFree(savedDeviceInfo.deviceName);
savedDeviceInfo.deviceName = NULL;
if(OCGetServerInstanceID() == NULL)
{
- OC_LOG(INFO, TAG, PCF("Device ID generation failed"));
+ OC_LOG(INFO, TAG, "Device ID generation failed");
res = OC_STACK_ERROR;
goto exit;
}
- OC_LOG(INFO, TAG, PCF("Device initialized successfully."));
+ OC_LOG(INFO, TAG, "Device initialized successfully.");
return OC_STACK_OK;
- exit:
- DeleteDeviceInfo();
- return res;
-
+exit:
+ DeleteDeviceInfo();
+ return res;
}
#include "oic_string.h"
#include "ocpayload.h"
#include "ocpayloadcbor.h"
+#include "logger.h"
+
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+#include "routingutility.h"
+#endif
#include "cacommon.h"
#include "cainterface.h"
// Module Name
#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
-#define TAG PCF("ocserverrequest")
+#define TAG "ocserverrequest"
static struct OCServerRequest * serverRequestList = NULL;
static struct OCServerResponse * serverResponseList = NULL;
*/
static OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle)
{
+ if (!response)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
OCServerResponse * serverResponse = NULL;
serverResponse = (OCServerResponse *) OICCalloc(1, sizeof(OCServerResponse));
serverResponse->requestHandle = requestHandle;
*response = serverResponse;
- OC_LOG(INFO, TAG, PCF("Server Response Added!!"));
+ OC_LOG(INFO, TAG, "Server Response Added!!");
LL_APPEND (serverResponseList, serverResponse);
return OC_STACK_OK;
OICFree(serverRequest->requestToken);
OICFree(serverRequest);
serverRequest = NULL;
- OC_LOG(INFO, TAG, PCF("Server Request Removed!!"));
+ OC_LOG(INFO, TAG, "Server Request Removed!!");
}
}
LL_DELETE(serverResponseList, serverResponse);
OICFree(serverResponse->payload);
OICFree(serverResponse);
- OC_LOG(INFO, TAG, PCF("Server Response Removed!!"));
+ OC_LOG(INFO, TAG, "Server Response Removed!!");
}
}
}
}
+/**
+ * Ensure no accept header option is included when sending responses and add routing info to
+ * outgoing response.
+ *
+ * @param object CA remote endpoint.
+ * @param requestInfo CA request info.
+ *
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+static OCStackResult OCSendResponse(const CAEndpoint_t *object, CAResponseInfo_t *responseInfo)
+{
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+ // Add route info in RM option.
+ OCStackResult rmResult = RMAddInfo(object->routeData, &(responseInfo->info.options),
+ &(responseInfo->info.numOptions));
+ if(OC_STACK_OK != rmResult)
+ {
+ OC_LOG(ERROR, TAG, "Add option failed");
+ return rmResult;
+ }
+#endif
+
+ // Do not include the accept header option
+ responseInfo->info.acceptFormat = CA_FORMAT_UNDEFINED;
+ CAResult_t result = CASendResponse(object, responseInfo);
+ if(CA_STATUS_OK != result)
+ {
+ OC_LOG_V(ERROR, TAG, "CASendResponse failed with CA error %u", result);
+ return CAResultToOCResult(result);
+ }
+ return OC_STACK_OK;
+}
+
//-------------------------------------------------------------------------------------------------
// Internal APIs
//-------------------------------------------------------------------------------------------------
{
if(!token)
{
- OC_LOG(ERROR, TAG, PCF("Invalid Parameter Token"));
+ OC_LOG(ERROR, TAG, "Invalid Parameter Token");
return NULL;
}
OCServerRequest * out = NULL;
- OC_LOG(INFO, TAG,PCF("Get server request with token"));
+ OC_LOG(INFO, TAG,"Get server request with token");
OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
- OC_LOG(INFO, TAG,PCF("Found token"));
+ OC_LOG(INFO, TAG,"Found token");
LL_FOREACH (serverRequestList, out)
{
OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->requestToken, tokenLength);
return out;
}
}
- OC_LOG(ERROR, TAG, PCF("Server Request not found!!"));
+ OC_LOG(ERROR, TAG, "Server Request not found!!");
return NULL;
}
return out;
}
}
- OC_LOG(ERROR, TAG, PCF("Server Request not found!!"));
+ OC_LOG(ERROR, TAG, "Server Request not found!!");
return NULL;
}
return out;
}
}
- OC_LOG(ERROR, TAG, PCF("Server Response not found!!"));
+ OC_LOG(ERROR, TAG, "Server Response not found!!");
return NULL;
}
OCQualityOfService qos, char * query,
OCHeaderOption * rcvdVendorSpecificHeaderOptions,
uint8_t * payload, CAToken_t requestToken, uint8_t tokenLength,
- char * resourceUrl, size_t reqTotalSize, const OCDevAddr *devAddr)
+ char * resourceUrl, size_t reqTotalSize, OCPayloadFormat acceptFormat,
+ const OCDevAddr *devAddr)
{
+ if (!request)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
OCServerRequest * serverRequest = NULL;
+ OC_LOG_V(INFO, TAG, "addserverrequest entry!! [%s:%u]", devAddr->addr, devAddr->port);
+
serverRequest = (OCServerRequest *) OICCalloc(1, sizeof(OCServerRequest) +
(reqTotalSize ? reqTotalSize : 1) - 1);
VERIFY_NON_NULL(devAddr);
serverRequest->observationOption = observationOption;
serverRequest->observeResult = OC_STACK_ERROR;
serverRequest->qos = qos;
+ serverRequest->acceptFormat = acceptFormat;
serverRequest->ehResponseHandler = HandleSingleResponse;
serverRequest->numResponses = 1;
serverRequest->devAddr = *devAddr;
*request = serverRequest;
- OC_LOG(INFO, TAG, PCF("Server Request Added!!"));
+ OC_LOG(INFO, TAG, "Server Request Added!!");
LL_APPEND (serverRequestList, serverRequest);
return OC_STACK_OK;
OCDevAddr *endpoint,
OCResourceHandle resource,
char * queryBuf,
+ OCPayloadType payloadType,
uint8_t * payload,
size_t payloadSize,
uint8_t numVendorOptions,
if(payload && payloadSize)
{
- if(OCParsePayload(&entityHandlerRequest->payload, payload, payloadSize) != OC_STACK_OK)
+ if(OCParsePayload(&entityHandlerRequest->payload, payloadType,
+ payload, payloadSize) != OC_STACK_OK)
{
return OC_STACK_ERROR;
}
}
}
-CAResponseResult_t ConvertEHResultToCAResult (OCEntityHandlerResult result)
+CAResponseResult_t ConvertEHResultToCAResult (OCEntityHandlerResult result, OCMethod method)
{
- CAResponseResult_t caResult = CA_BAD_REQ;
+ CAResponseResult_t caResult;
switch (result)
{
case OC_EH_OK:
- caResult = CA_SUCCESS;
+ switch (method)
+ {
+ case OC_REST_PUT:
+ case OC_REST_POST:
+ // This Response Code is like HTTP 204 "No Content" but only used in
+ // response to POST and PUT requests.
+ caResult = CA_CHANGED;
+ break;
+ case OC_REST_GET:
+ // This Response Code is like HTTP 200 "OK" but only used in response to
+ // GET requests.
+ caResult = CA_CONTENT;
+ break;
+ default:
+ // This should not happen but,
+ // give it a value just in case but output an error
+ caResult = CA_CONTENT;
+ OC_LOG_V(ERROR, TAG, "Unexpected OC_EH_OK return code for method [d].", method);
+ }
break;
case OC_EH_ERROR:
caResult = CA_BAD_REQ;
caResult = CA_DELETED;
break;
case OC_EH_SLOW:
- caResult = CA_SUCCESS;
+ caResult = CA_CONTENT;
break;
case OC_EH_FORBIDDEN:
caResult = CA_UNAUTHORIZED_REQ;
* @return
* OCStackResult
*/
-
OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
{
OCStackResult result = OC_STACK_ERROR;
CopyDevAddrToEndpoint(&serverRequest->devAddr, &responseEndpoint);
responseInfo.info.resourceUri = serverRequest->resourceUrl;
- responseInfo.result = ConvertEHResultToCAResult(ehResponse->ehResult);
+ responseInfo.result = ConvertEHResultToCAResult(ehResponse->ehResult, serverRequest->method);
if(serverRequest->notificationFlag && serverRequest->qos == OC_HIGH_QOS)
{
{
responseInfo.info.type = CA_MSG_NONCONFIRM;
}
+ else
+ {
+ OC_LOG(ERROR, TAG, "default responseInfo type is NON");
+ responseInfo.info.type = CA_MSG_NONCONFIRM;
+ }
char rspToken[CA_MAX_TOKEN_LEN + 1] = {};
responseInfo.info.messageId = serverRequest->coapID;
if(!responseInfo.info.options)
{
- OC_LOG(FATAL, TAG, PCF("Memory alloc for options failed"));
+ OC_LOG(FATAL, TAG, "Memory alloc for options failed");
return OC_STACK_NO_MEMORY;
}
responseInfo.info.options[0].protocolID = CA_COAP_ID;
responseInfo.info.options[0].optionID = COAP_OPTION_OBSERVE;
responseInfo.info.options[0].optionLength = sizeof(uint32_t);
- memcpy(responseInfo.info.options[0].optionData,
- &(serverRequest->observationOption), sizeof(uint32_t));
+ uint8_t* observationData = (uint8_t*)responseInfo.info.options[0].optionData;
+ uint32_t observationOption= serverRequest->observationOption;
+
+ for (size_t i=sizeof(uint32_t); i; --i)
+ {
+ observationData[i-1] = observationOption & 0xFF;
+ observationOption >>=8;
+ }
// Point to the next header option before copying vender specific header options
optionsPointer += 1;
responseInfo.info.options = NULL;
}
+ responseInfo.isMulticast = false;
+ responseInfo.info.payload = NULL;
+ responseInfo.info.payloadSize = 0;
+ responseInfo.info.payloadFormat = CA_FORMAT_UNDEFINED;
+
// Put the JSON prefix and suffix around the payload
if(ehResponse->payload)
{
- OCStackResult result;
- if((result = OCConvertPayload(ehResponse->payload, &responseInfo.info.payload,
- &responseInfo.info.payloadSize))
- != OC_STACK_OK)
+ if (ehResponse->payload->type == PAYLOAD_TYPE_PRESENCE)
+ {
+ responseInfo.isMulticast = true;
+ }
+ else
{
- OC_LOG(ERROR, TAG, "Error converting payload");
- OICFree(responseInfo.info.options);
- return result;
+ responseInfo.isMulticast = false;
}
- if(responseInfo.info.payloadSize > MAX_RESPONSE_LENGTH)
+ switch(serverRequest->acceptFormat)
{
- OICFree(responseInfo.info.payload);
- OC_LOG(ERROR, TAG, "Payload too long!");
- OICFree(responseInfo.info.options);
- return OC_STACK_INVALID_PARAM;
+ case OC_FORMAT_UNDEFINED:
+ // No preference set by the client, so default to CBOR then
+ case OC_FORMAT_CBOR:
+ if((result = OCConvertPayload(ehResponse->payload, &responseInfo.info.payload,
+ &responseInfo.info.payloadSize))
+ != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "Error converting payload");
+ OICFree(responseInfo.info.options);
+ return result;
+ }
+ responseInfo.info.payloadFormat = CA_FORMAT_APPLICATION_CBOR;
+ break;
+ default:
+ responseInfo.result = CA_NOT_ACCEPTABLE;
}
}
- else
- {
- responseInfo.info.payload = NULL;
- responseInfo.info.payloadSize = 0;
- }
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
CATransportAdapter_t CAConnTypes[] = {
CA_ADAPTER_IP,
CA_ADAPTER_GATT_BTLE,
CA_ADAPTER_RFCOMM_BTEDR
- #ifdef RA_ADAPTER
+#ifdef RA_ADAPTER
, CA_ADAPTER_REMOTE_ACCESS
- #endif
+#endif
+
+#ifdef TCP_ADAPTER
+ , CA_ADAPTER_TCP
+#endif
};
- int size = sizeof(CAConnTypes)/ sizeof(CATransportAdapter_t);
+ size_t size = sizeof(CAConnTypes)/ sizeof(CATransportAdapter_t);
CATransportAdapter_t adapter = responseEndpoint.adapter;
- CAResult_t caResult = CA_STATUS_FAILED;
- result = OC_STACK_OK;
-
// Default adapter, try to send response out on all adapters.
if (adapter == CA_DEFAULT_ADAPTER)
{
CA_ADAPTER_GATT_BTLE |
CA_ADAPTER_RFCOMM_BTEDR
- #ifdef RA_ADAP
+#ifdef RA_ADAP
| CA_ADAPTER_REMOTE_ACCESS
- #endif
+#endif
+
+#ifdef TCP_ADAPTER
+ | CA_ADAPTER_TCP
+#endif
);
}
- for(int i = 0; i < size; i++ )
+ result = OC_STACK_OK;
+ OCStackResult tempResult = OC_STACK_OK;
+
+ for(size_t i = 0; i < size; i++ )
{
responseEndpoint.adapter = (CATransportAdapter_t)(adapter & CAConnTypes[i]);
if(responseEndpoint.adapter)
{
- //The result is set to OC_STACK_OK only if CASendResponse succeeds in sending the
+ //The result is set to OC_STACK_OK only if OCSendResponse succeeds in sending the
//response on all the n/w interfaces else it is set to OC_STACK_ERROR
- caResult = CASendResponse(&responseEndpoint, &responseInfo);
- if(caResult != CA_STATUS_OK)
- {
- OC_LOG_V(ERROR, TAG, "CASendResponse failed with CA error %u", caResult);
- result = CAResultToOCResult(caResult);
- }
+ tempResult = OCSendResponse(&responseEndpoint, &responseInfo);
+ }
+ if(OC_STACK_OK != tempResult)
+ {
+ result = tempResult;
}
}
- #else
+#else
- OC_LOG(INFO, TAG, PCF("Calling CASendResponse with:"));
+ OC_LOG(INFO, TAG, "Calling OCSendResponse with:");
OC_LOG_V(INFO, TAG, "\tEndpoint address: %s", responseEndpoint.addr);
OC_LOG_V(INFO, TAG, "\tEndpoint adapter: %s", responseEndpoint.adapter);
OC_LOG_V(INFO, TAG, "\tResponse result : %s", responseInfo.result);
OC_LOG_V(INFO, TAG, "\tResponse for uri: %s", responseInfo.info.resourceUri);
- CAResult_t caResult = CASendResponse(&responseEndpoint, &responseInfo);
- if(caResult != CA_STATUS_OK)
- {
- OC_LOG(ERROR, TAG, PCF("CASendResponse failed"));
- result = CAResultToOCResult(caResult);
- }
- else
- {
- result = OC_STACK_OK;
- }
- #endif
+ result = OCSendResponse(&responseEndpoint, &responseInfo);
+#endif
OICFree(responseInfo.info.payload);
OICFree(responseInfo.info.options);
*/
OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
{
- OCStackResult stackRet = OC_STACK_ERROR;
- OCServerRequest * serverRequest = NULL;
- OCServerResponse * serverResponse = NULL;
-
if(!ehResponse || !ehResponse->payload)
{
- OC_LOG(ERROR, TAG, PCF("HandleAggregateResponse invalid parameters"));
+ OC_LOG(ERROR, TAG, "HandleAggregateResponse invalid parameters");
return OC_STACK_INVALID_PARAM;
}
OC_LOG(INFO, TAG, "Inside HandleAggregateResponse");
- serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
- serverResponse = GetServerResponseUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+ OCServerRequest *serverRequest = GetServerRequestUsingHandle((OCServerRequest *)
+ ehResponse->requestHandle);
+ OCServerResponse *serverResponse = GetServerResponseUsingHandle((OCServerRequest *)
+ ehResponse->requestHandle);
+ OCStackResult stackRet = OC_STACK_ERROR;
if(serverRequest)
{
if(!serverResponse)
{
- OC_LOG(INFO, TAG, PCF("This is the first response fragment"));
+ OC_LOG(INFO, TAG, "This is the first response fragment");
stackRet = AddServerResponse(&serverResponse, ehResponse->requestHandle);
if (OC_STACK_OK != stackRet)
{
- OC_LOG(ERROR, TAG, PCF("Error adding server response"));
+ OC_LOG(ERROR, TAG, "Error adding server response");
return stackRet;
}
VERIFY_NON_NULL(serverResponse);
if(ehResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)
{
stackRet = OC_STACK_ERROR;
- OC_LOG(ERROR, TAG, PCF("Error adding payload, as it was the incorrect type"));
+ OC_LOG(ERROR, TAG, "Error adding payload, as it was the incorrect type");
goto exit;
}
if(serverRequest->numResponses == 0)
{
- OC_LOG(INFO, TAG, PCF("This is the last response fragment"));
+ OC_LOG(INFO, TAG, "This is the last response fragment");
ehResponse->payload = serverResponse->payload;
stackRet = HandleSingleResponse(ehResponse);
//Delete the request and response
}
else
{
- OC_LOG(INFO, TAG, PCF("More response fragments to come"));
+ OC_LOG(INFO, TAG, "More response fragments to come");
stackRet = OC_STACK_OK;
}
}
#include "ocrandom.h"
#include "oic_malloc.h"
#include "oic_string.h"
+#include "logger.h"
#include "ocserverrequest.h"
#include "secureresourcemanager.h"
+#include "doxmresource.h"
#include "cacommon.h"
#include "cainterface.h"
#include "ocpayload.h"
#include "ocpayloadcbor.h"
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+#include "routingutility.h"
+#ifdef ROUTING_GATEWAY
+#include "routingmanager.h"
+#endif
+#endif
+
#ifdef WITH_ARDUINO
#include "Time.h"
#else
OCDeviceEntityHandler defaultDeviceHandler;
void* defaultDeviceHandlerCallbackParameter = NULL;
+#ifdef TCP_ADAPTER
+static const char COAP_TCP[] = "coap+tcp:";
+#endif
+
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
-#define TAG PCF("OCStack")
+#define TAG "OCStack"
#define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
{OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
- TAG, PCF(#arg " is NULL")); return (retVal); } }
+ TAG, #arg " is NULL"); return (retVal); } }
#define VERIFY_NON_NULL_NR(arg, logLevel) { if (!(arg)) { OC_LOG((logLevel), \
- TAG, PCF(#arg " is NULL")); return; } }
+ TAG, #arg " is NULL"); return; } }
#define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
goto exit;} }
* Convert OCStackResult to CAResponseResult_t.
*
* @param caCode OCStackResult code.
- * @return ::CA_SUCCESS on success, some other value upon failure.
+ * @param method OCMethod method the return code replies to.
+ * @return ::CA_CONTENT on OK, some other value upon failure.
*/
-static CAResponseResult_t OCToCAStackResult(OCStackResult ocCode);
+static CAResponseResult_t OCToCAStackResult(OCStackResult ocCode, OCMethod method);
/**
* Convert OCTransportFlags_t to CATransportModifiers_t.
*/
static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds);
+/**
+ * Ensure the accept header option is set appropriatly before sending the requests and routing
+ * header option is updated with destination.
+ *
+ * @param object CA remote endpoint.
+ * @param requestInfo CA request info.
+ *
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+static OCStackResult OCSendRequest(const CAEndpoint_t *object, CARequestInfo_t *requestInfo);
+
//-----------------------------------------------------------------------------
// Internal functions
//-----------------------------------------------------------------------------
out->flags = CAToOCTransportFlags(in->flags);
OICStrcpy(out->addr, sizeof(out->addr), in->addr);
out->port = in->port;
+ out->interface = in->interface;
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+ memcpy(out->routeData, in->routeData, sizeof(out->routeData));
+#endif
}
void CopyDevAddrToEndpoint(const OCDevAddr *in, CAEndpoint_t *out)
out->adapter = (CATransportAdapter_t)in->adapter;
out->flags = OCToCATransportFlags(in->flags);
OICStrcpy(out->addr, sizeof(out->addr), in->addr);
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+ memcpy(out->routeData, in->routeData, sizeof(out->routeData));
+#endif
out->port = in->port;
-}
-
-static OCStackResult OCCreateEndpoint(OCDevAddr *devAddr, CAEndpoint_t **endpoint)
-{
- VERIFY_NON_NULL(devAddr, FATAL, OC_STACK_INVALID_PARAM);
- VERIFY_NON_NULL(endpoint, FATAL, OC_STACK_INVALID_PARAM);
-
- CAEndpoint_t *ep = (CAEndpoint_t *)OICMalloc(sizeof (CAEndpoint_t));
- if (!ep)
- {
- return OC_STACK_NO_MEMORY;
- }
-
- ep->adapter = (CATransportAdapter_t)devAddr->adapter;
- if (!ep->adapter)
- {
- ep->adapter = CA_ADAPTER_IP;
- }
- ep->flags = OCToCATransportFlags(devAddr->flags);
- OICStrcpy(ep->addr, sizeof(ep->addr), devAddr->addr);
- ep->port = devAddr->port;
-
- *endpoint = ep;
-
- return OC_STACK_OK;
-}
-
-static void OCDestroyEndpoint(CAEndpoint_t *endpoint)
-{
- free(endpoint);
+ out->interface = in->interface;
}
void FixUpClientResponse(OCClientResponse *cr)
((cr->devAddr.adapter << CT_ADAPTER_SHIFT) | (cr->devAddr.flags & CT_MASK_FLAGS));
}
+static OCStackResult OCSendRequest(const CAEndpoint_t *object, CARequestInfo_t *requestInfo)
+{
+ VERIFY_NON_NULL(object, FATAL, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(requestInfo, FATAL, OC_STACK_INVALID_PARAM);
+
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+ OCStackResult rmResult = RMAddInfo(object->routeData, &(requestInfo->info.options),
+ &(requestInfo->info.numOptions));
+ if (OC_STACK_OK != rmResult)
+ {
+ OC_LOG(ERROR, TAG, "Add destination option failed");
+ return rmResult;
+ }
+#endif
+
+ // OC stack prefer CBOR encoded payloads.
+ requestInfo->info.acceptFormat = CA_FORMAT_APPLICATION_CBOR;
+ CAResult_t result = CASendRequest(object, requestInfo);
+ if(CA_STATUS_OK != result)
+ {
+ OC_LOG_V(ERROR, TAG, "CASendRequest failed with CA error %u", result);
+ return CAResultToOCResult(result);
+ }
+ return OC_STACK_OK;
+}
//-----------------------------------------------------------------------------
// Internal API function
//-----------------------------------------------------------------------------
switch(status)
{
case OC_OBSERVER_NOT_INTERESTED:
- OC_LOG(DEBUG, TAG, PCF("observer not interested in our notifications"));
+ OC_LOG(DEBUG, TAG, "observer not interested in our notifications");
observer = GetObserverUsingToken (token, tokenLength);
if(observer)
{
OC_REST_NOMETHOD,
&observer->devAddr,
(OCResourceHandle)NULL,
- NULL, NULL, 0, 0, NULL,
+ NULL, PAYLOAD_TYPE_REPRESENTATION,
+ NULL, 0, 0, NULL,
OC_OBSERVE_DEREGISTER,
observer->observeId);
if(result != OC_STACK_OK)
result = DeleteObserverUsingToken (token, tokenLength);
if(result == OC_STACK_OK)
{
- OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+ OC_LOG(DEBUG, TAG, "Removed observer successfully");
}
else
{
result = OC_STACK_OK;
- OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
+ OC_LOG(DEBUG, TAG, "Observer Removal failed");
}
break;
case OC_OBSERVER_STILL_INTERESTED:
- OC_LOG(DEBUG, TAG, PCF("observer still interested, reset the failedCount"));
+ OC_LOG(DEBUG, TAG, "observer still interested, reset the failedCount");
observer = GetObserverUsingToken (token, tokenLength);
if(observer)
{
break;
case OC_OBSERVER_FAILED_COMM:
- OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
+ OC_LOG(DEBUG, TAG, "observer is unreachable");
observer = GetObserverUsingToken (token, tokenLength);
if(observer)
{
OC_REST_NOMETHOD,
&observer->devAddr,
(OCResourceHandle)NULL,
- NULL, NULL, 0, 0, NULL,
+ NULL, PAYLOAD_TYPE_REPRESENTATION,
+ NULL, 0, 0, NULL,
OC_OBSERVE_DEREGISTER,
observer->observeId);
if(result != OC_STACK_OK)
result = DeleteObserverUsingToken (token, tokenLength);
if(result == OC_STACK_OK)
{
- OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+ OC_LOG(DEBUG, TAG, "Removed observer successfully");
}
else
{
result = OC_STACK_OK;
- OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
+ OC_LOG(DEBUG, TAG, "Observer Removal failed");
}
}
else
}
break;
default:
- OC_LOG(ERROR, TAG, PCF("Unknown status"));
+ OC_LOG(ERROR, TAG, "Unknown status");
result = OC_STACK_ERROR;
break;
}
switch(caCode)
{
- case CA_SUCCESS:
- ret = OC_STACK_OK;
- break;
case CA_CREATED:
ret = OC_STACK_RESOURCE_CREATED;
break;
case CA_DELETED:
ret = OC_STACK_RESOURCE_DELETED;
break;
+ case CA_CHANGED:
+ case CA_CONTENT:
+ ret = OC_STACK_OK;
+ break;
case CA_BAD_REQ:
ret = OC_STACK_INVALID_QUERY;
break;
return ret;
}
-CAResponseResult_t OCToCAStackResult(OCStackResult ocCode)
+CAResponseResult_t OCToCAStackResult(OCStackResult ocCode, OCMethod method)
{
CAResponseResult_t ret = CA_INTERNAL_SERVER_ERROR;
switch(ocCode)
{
case OC_STACK_OK:
- ret = CA_SUCCESS;
+ switch (method)
+ {
+ case OC_REST_PUT:
+ case OC_REST_POST:
+ // This Response Code is like HTTP 204 "No Content" but only used in
+ // response to POST and PUT requests.
+ ret = CA_CHANGED;
+ break;
+ case OC_REST_GET:
+ // This Response Code is like HTTP 200 "OK" but only used in response to
+ // GET requests.
+ ret = CA_CONTENT;
+ break;
+ default:
+ // This should not happen but,
+ // give it a value just in case but output an error
+ ret = CA_CONTENT;
+ OC_LOG_V(ERROR, TAG, "Unexpected OC_STACK_OK return code for method [d].", method);
+ }
break;
case OC_STACK_RESOURCE_CREATED:
ret = CA_CREATED;
cbNode->presence->TTL = maxAgeSeconds;
- for(int index = 0; index < PresenceTimeOutSize; index++)
+ for (int index = 0; index < PresenceTimeOutSize; index++)
{
// Guard against overflow
if (cbNode->presence->TTL < (UINT32_MAX/(MILLISECONDS_PER_SECOND*PresenceTimeOut[index]))
int presenceSubscribe = 0;
int multicastPresenceSubscribe = 0;
- if (responseInfo->result != CA_SUCCESS)
+ if (responseInfo->result != CA_CONTENT)
{
OC_LOG_V(ERROR, TAG, "HandlePresenceResponse failed %d", responseInfo->result);
return OC_STACK_ERROR;
// check for unicast presence
uriLen = FormCanonicalPresenceUri(endpoint, OC_RSRVD_PRESENCE_URI, presenceUri);
- if (uriLen < 0 || uriLen >= sizeof (presenceUri))
+ if (uriLen < 0 || (size_t)uriLen >= sizeof (presenceUri))
{
return OC_STACK_INVALID_URI;
}
// check for multiicast presence
CAEndpoint_t ep = { .adapter = endpoint->adapter,
.flags = endpoint->flags };
- OICStrcpy(ep.addr, sizeof(ep.addr), OC_MULTICAST_IP);
- ep.port = OC_MULTICAST_PORT;
uriLen = FormCanonicalPresenceUri(&ep, OC_RSRVD_PRESENCE_URI, presenceUri);
if (!presenceSubscribe && !multicastPresenceSubscribe)
{
- OC_LOG(ERROR, TAG, PCF("Received a presence notification, but no callback, ignoring"));
+ OC_LOG(ERROR, TAG, "Received a presence notification, but no callback, ignoring");
goto exit;
}
if (responseInfo->info.payload)
{
- result = OCParsePayload(&response.payload, responseInfo->info.payload,
+ result = OCParsePayload(&response.payload,
+ PAYLOAD_TYPE_PRESENCE,
+ responseInfo->info.payload,
responseInfo->info.payloadSize);
if(result != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("Presence parse failed"));
+ OC_LOG(ERROR, TAG, "Presence parse failed");
goto exit;
}
if(!response.payload || response.payload->type != PAYLOAD_TYPE_PRESENCE)
{
- OC_LOG(ERROR, TAG, PCF("Presence payload was wrong type"));
+ OC_LOG(ERROR, TAG, "Presence payload was wrong type");
result = OC_STACK_ERROR;
goto exit;
}
{
if(cbNode->sequenceNumber == response.sequenceNumber)
{
- OC_LOG(INFO, TAG, PCF("No presence change"));
+ OC_LOG(INFO, TAG, "No presence change");
goto exit;
}
if(maxAge == 0)
{
- OC_LOG(INFO, TAG, PCF("Stopping presence"));
+ OC_LOG(INFO, TAG, "Stopping presence");
response.result = OC_STACK_PRESENCE_STOPPED;
if(cbNode->presence)
{
if(!(cbNode->presence))
{
- OC_LOG(ERROR, TAG, PCF("Could not allocate memory for cbNode->presence"));
+ OC_LOG(ERROR, TAG, "Could not allocate memory for cbNode->presence");
result = OC_STACK_NO_MEMORY;
goto exit;
}
OICMalloc(PresenceTimeOutSize * sizeof(uint32_t));
if(!(cbNode->presence->timeOut)){
OC_LOG(ERROR, TAG,
- PCF("Could not allocate memory for cbNode->presence->timeOut"));
+ "Could not allocate memory for cbNode->presence->timeOut");
OICFree(cbNode->presence);
result = OC_STACK_NO_MEMORY;
goto exit;
{
if(mcNode->nonce == response.sequenceNumber)
{
- OC_LOG(INFO, TAG, PCF("No presence change (Multicast)"));
+ OC_LOG(INFO, TAG, "No presence change (Multicast)");
goto exit;
}
mcNode->nonce = response.sequenceNumber;
if(maxAge == 0)
{
- OC_LOG(INFO, TAG, PCF("Stopping presence"));
+ OC_LOG(INFO, TAG, "Stopping presence");
response.result = OC_STACK_PRESENCE_STOPPED;
}
}
if (!uri)
{
OC_LOG(INFO, TAG,
- PCF("No Memory for URI to store in the presence node"));
+ "No Memory for URI to store in the presence node");
result = OC_STACK_NO_MEMORY;
goto exit;
}
if(result == OC_STACK_NO_MEMORY)
{
OC_LOG(INFO, TAG,
- PCF("No Memory for Multicast Presence Node"));
+ "No Memory for Multicast Presence Node");
OICFree(uri);
goto exit;
}
VERIFY_NON_NULL_NR(endPoint, FATAL);
VERIFY_NON_NULL_NR(responseInfo, FATAL);
- OC_LOG(INFO, TAG, PCF("Enter HandleCAResponses"));
+ OC_LOG(INFO, TAG, "Enter HandleCAResponses");
+
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+#ifdef ROUTING_GATEWAY
+ bool needRIHandling = false;
+ /*
+ * Routing manager is going to update either of endpoint or response or both.
+ * This typecasting is done to avoid unnecessary duplication of Endpoint and responseInfo
+ * RM can update "routeData" option in endPoint so that future RI requests can be sent to proper
+ * destination.
+ */
+ OCStackResult ret = RMHandleResponse((CAResponseInfo_t *)responseInfo, (CAEndpoint_t *)endPoint,
+ &needRIHandling);
+ if(ret != OC_STACK_OK || !needRIHandling)
+ {
+ OC_LOG_V(INFO, TAG, "Routing status![%d]. Not forwarding to RI", ret);
+ return;
+ }
+#endif
+
+ /*
+ * Put source in sender endpoint so that the next packet from application can be routed to
+ * proper destination and remove "RM" coap header option before passing request / response to
+ * RI as this option will make no sense to either RI or application.
+ */
+ RMUpdateInfo((CAHeaderOption_t **) &(responseInfo->info.options),
+ (uint8_t *) &(responseInfo->info.numOptions),
+ (CAEndpoint_t *) endPoint);
+#endif
if(responseInfo->info.resourceUri &&
strcmp(responseInfo->info.resourceUri, OC_RSRVD_PRESENCE_URI) == 0)
if(cbNode)
{
- OC_LOG(INFO, TAG, PCF("There is a cbNode associated with the response token"));
+ OC_LOG(INFO, TAG, "There is a cbNode associated with the response token");
if(responseInfo->result == CA_EMPTY)
{
- OC_LOG(INFO, TAG, PCF("Receiving A ACK/RESET for this token"));
+ OC_LOG(INFO, TAG, "Receiving A ACK/RESET for this token");
// We do not have a case for the client to receive a RESET
if(responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
{
//This is the case of receiving an ACK on a request to a slow resource!
- OC_LOG(INFO, TAG, PCF("This is a pure ACK"));
+ OC_LOG(INFO, TAG, "This is a pure ACK");
//TODO: should we inform the client
// app that at least the request was received at the server?
}
}
else if(responseInfo->result == CA_RETRANSMIT_TIMEOUT)
{
- OC_LOG(INFO, TAG, PCF("Receiving A Timeout for this token"));
- OC_LOG(INFO, TAG, PCF("Calling into application address space"));
+ OC_LOG(INFO, TAG, "Receiving A Timeout for this token");
+ OC_LOG(INFO, TAG, "Calling into application address space");
OCClientResponse response =
{.devAddr = {.adapter = OC_DEFAULT_ADAPTER}};
CopyEndpointToDevAddr(endPoint, &response.devAddr);
FixUpClientResponse(&response);
response.resourceUri = responseInfo->info.resourceUri;
+ memcpy(response.identity.id, responseInfo->info.identity.id,
+ sizeof (response.identity.id));
+ response.identity.id_length = responseInfo->info.identity.id_length;
response.result = CAToOCStackResult(responseInfo->result);
cbNode->callBack(cbNode->context,
}
else
{
- OC_LOG(INFO, TAG, PCF("This is a regular response, A client call back is found"));
- OC_LOG(INFO, TAG, PCF("Calling into application address space"));
+ OC_LOG(INFO, TAG, "This is a regular response, A client call back is found");
+ OC_LOG(INFO, TAG, "Calling into application address space");
OCClientResponse response =
{.devAddr = {.adapter = OC_DEFAULT_ADAPTER}};
CopyEndpointToDevAddr(endPoint, &response.devAddr);
FixUpClientResponse(&response);
response.resourceUri = responseInfo->info.resourceUri;
+ memcpy(response.identity.id, responseInfo->info.identity.id,
+ sizeof (response.identity.id));
+ response.identity.id_length = responseInfo->info.identity.id_length;
response.result = CAToOCStackResult(responseInfo->result);
+
if(responseInfo->info.payload &&
- responseInfo->info.payloadSize &&
- OC_STACK_OK != OCParsePayload(&response.payload, responseInfo->info.payload,
- responseInfo->info.payloadSize))
+ responseInfo->info.payloadSize)
{
- OC_LOG(ERROR, TAG, PCF("Error converting payload"));
- OCPayloadDestroy(response.payload);
- return;
+ OCPayloadType type = PAYLOAD_TYPE_INVALID;
+ // check the security resource
+ if (SRMIsSecurityResourceURI(cbNode->requestUri))
+ {
+ type = PAYLOAD_TYPE_SECURITY;
+ }
+ else if (cbNode->method == OC_REST_DISCOVER)
+ {
+ if (strncmp(OC_RSRVD_WELL_KNOWN_URI,cbNode->requestUri,
+ sizeof(OC_RSRVD_WELL_KNOWN_URI) - 1) == 0)
+ {
+ type = PAYLOAD_TYPE_DISCOVERY;
+ }
+ else if (strcmp(cbNode->requestUri, OC_RSRVD_DEVICE_URI) == 0)
+ {
+ type = PAYLOAD_TYPE_DEVICE;
+ }
+ else if (strcmp(cbNode->requestUri, OC_RSRVD_PLATFORM_URI) == 0)
+ {
+ type = PAYLOAD_TYPE_PLATFORM;
+ }
+ else
+ {
+ OC_LOG_V(ERROR, TAG, "Unknown Payload type in Discovery: %d %s",
+ cbNode->method, cbNode->requestUri);
+ return;
+ }
+ }
+ else if (cbNode->method == OC_REST_GET ||
+ cbNode->method == OC_REST_PUT ||
+ cbNode->method == OC_REST_POST ||
+ cbNode->method == OC_REST_OBSERVE ||
+ cbNode->method == OC_REST_OBSERVE_ALL ||
+ cbNode->method == OC_REST_DELETE)
+ {
+ OC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_REPRESENTATION: %d %s",
+ cbNode->method, cbNode->requestUri);
+ type = PAYLOAD_TYPE_REPRESENTATION;
+ }
+ else
+ {
+ OC_LOG_V(ERROR, TAG, "Unknown Payload type: %d %s",
+ cbNode->method, cbNode->requestUri);
+ return;
+ }
+
+ if(OC_STACK_OK != OCParsePayload(&response.payload,
+ type,
+ responseInfo->info.payload,
+ responseInfo->info.payloadSize))
+ {
+ OC_LOG(ERROR, TAG, "Error converting payload");
+ OCPayloadDestroy(response.payload);
+ return;
+ }
}
response.numRcvdVendorSpecificHeaderOptions = 0;
//First option always with option ID is COAP_OPTION_OBSERVE if it is available.
if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
{
- memcpy (&(response.sequenceNumber),
- &(responseInfo->info.options[0].optionData), sizeof(uint32_t));
+ size_t i;
+ uint32_t observationOption;
+ uint8_t* optionData = (uint8_t*)responseInfo->info.options[0].optionData;
+ for (observationOption=0, i=0;
+ i<sizeof(uint32_t) && i<responseInfo->info.options[0].optionLength;
+ i++)
+ {
+ observationOption =
+ (observationOption << 8) | optionData[i];
+ }
+ response.sequenceNumber = observationOption;
+
response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
start = 1;
}
if(response.numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
{
- OC_LOG(ERROR, TAG, PCF("#header options are more than MAX_HEADER_OPTIONS"));
+ OC_LOG(ERROR, TAG, "#header options are more than MAX_HEADER_OPTIONS");
OCPayloadDestroy(response.payload);
return;
}
response.sequenceNumber > OC_OFFSET_SEQUENCE_NUMBER &&
response.sequenceNumber <= cbNode->sequenceNumber)
{
- OC_LOG_V(INFO, TAG, PCF("Received stale notification. Number :%d"),
+ OC_LOG_V(INFO, TAG, "Received stale notification. Number :%d",
response.sequenceNumber);
}
else
if(responseInfo->info.type == CA_MSG_CONFIRM)
{
SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY,
- CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0);
+ CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0, NULL);
}
OCPayloadDestroy(response.payload);
if(observer)
{
- OC_LOG(INFO, TAG, PCF("There is an observer associated with the response token"));
+ OC_LOG(INFO, TAG, "There is an observer associated with the response token");
if(responseInfo->result == CA_EMPTY)
{
- OC_LOG(INFO, TAG, PCF("Receiving A ACK/RESET for this token"));
+ OC_LOG(INFO, TAG, "Receiving A ACK/RESET for this token");
if(responseInfo->info.type == CA_MSG_RESET)
{
- OC_LOG(INFO, TAG, PCF("This is a RESET"));
+ OC_LOG(INFO, TAG, "This is a RESET");
OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
OC_OBSERVER_NOT_INTERESTED);
}
else if(responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
{
- OC_LOG(INFO, TAG, PCF("This is a pure ACK"));
+ OC_LOG(INFO, TAG, "This is a pure ACK");
OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
OC_OBSERVER_STILL_INTERESTED);
}
}
else if(responseInfo->result == CA_RETRANSMIT_TIMEOUT)
{
- OC_LOG(INFO, TAG, PCF("Receiving Time Out for an observer"));
+ OC_LOG(INFO, TAG, "Receiving Time Out for an observer");
OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
OC_OBSERVER_FAILED_COMM);
}
if(!cbNode && !observer)
{
- if(myStackMode == OC_CLIENT || myStackMode == OC_CLIENT_SERVER)
+ if(myStackMode == OC_CLIENT || myStackMode == OC_CLIENT_SERVER
+ || myStackMode == OC_GATEWAY)
{
- OC_LOG(INFO, TAG, PCF("This is a client, but no cbNode was found for token"));
+ OC_LOG(INFO, TAG, "This is a client, but no cbNode was found for token");
if(responseInfo->result == CA_EMPTY)
{
- OC_LOG(INFO, TAG, PCF("Receiving CA_EMPTY in the ocstack"));
+ OC_LOG(INFO, TAG, "Receiving CA_EMPTY in the ocstack");
}
else
{
- OC_LOG(INFO, TAG, PCF("Received a message without callbacks. Sending RESET"));
+ OC_LOG(INFO, TAG, "Received a message without callbacks. Sending RESET");
SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY,
- CA_MSG_RESET, 0, NULL, NULL, 0);
+ CA_MSG_RESET, 0, NULL, NULL, 0, NULL);
}
}
- if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER)
+ if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER
+ || myStackMode == OC_GATEWAY)
{
- OC_LOG(INFO, TAG, PCF("This is a server, but no observer was found for token"));
+ OC_LOG(INFO, TAG, "This is a server, but no observer was found for token");
if (responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
{
- OC_LOG_V(INFO, TAG, PCF("Received ACK at server for messageId : %d"),
+ OC_LOG_V(INFO, TAG, "Received ACK at server for messageId : %d",
responseInfo->info.messageId);
}
if (responseInfo->info.type == CA_MSG_RESET)
{
- OC_LOG_V(INFO, TAG, PCF("Received RESET at server for messageId : %d"),
+ OC_LOG_V(INFO, TAG, "Received RESET at server for messageId : %d",
responseInfo->info.messageId);
}
}
return;
}
- OC_LOG(INFO, TAG, PCF("Exit HandleCAResponses"));
+ OC_LOG(INFO, TAG, "Exit HandleCAResponses");
}
/*
*/
void HandleCAErrorResponse(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errrorInfo)
{
- OC_LOG(INFO, TAG, PCF("Enter HandleCAErrorResponse"));
+ OC_LOG(INFO, TAG, "Enter HandleCAErrorResponse");
if(NULL == endPoint)
{
- OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
+ OC_LOG(ERROR, TAG, "endPoint is NULL");
return;
}
if(NULL == errrorInfo)
{
- OC_LOG(ERROR, TAG, PCF("errrorInfo is NULL"));
+ OC_LOG(ERROR, TAG, "errrorInfo is NULL");
return;
}
- OC_LOG(INFO, TAG, PCF("Exit HandleCAErrorResponse"));
+ OC_LOG(INFO, TAG, "Exit HandleCAErrorResponse");
}
/*
OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16_t coapID,
const CAResponseResult_t responseResult, const CAMessageType_t type,
const uint8_t numOptions, const CAHeaderOption_t *options,
- CAToken_t token, uint8_t tokenLength)
+ CAToken_t token, uint8_t tokenLength, const char *resourceUri)
{
CAResponseInfo_t respInfo = {
.result = responseResult
respInfo.info.token = token;
respInfo.info.tokenLength = tokenLength;
respInfo.info.type = type;
+ respInfo.info.resourceUri = OICStrdup (resourceUri);
+ respInfo.info.acceptFormat = CA_FORMAT_UNDEFINED;
+
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+ // Add the destination to route option from the endpoint->routeData.
+ OCStackResult result = RMAddInfo(endPoint->routeData,
+ &(respInfo.info.options),
+ &(respInfo.info.numOptions));
+ if(OC_STACK_OK != result)
+ {
+ OC_LOG_V(ERROR, TAG, "Add routing option failed [%d]", result);
+ return result;
+ }
+#endif
CAResult_t caResult = CASendResponse(endPoint, &respInfo);
- if(caResult != CA_STATUS_OK)
+
+ // resourceUri in the info field is cloned in the CA layer and
+ // thus ownership is still here.
+ OICFree (respInfo.info.resourceUri);
+
+ if(CA_STATUS_OK != caResult)
{
- OC_LOG(ERROR, TAG, PCF("CASendResponse error"));
- return OC_STACK_ERROR;
+ OC_LOG(ERROR, TAG, "CASendResponse error");
+ return CAResultToOCResult(caResult);
}
return OC_STACK_OK;
}
//This function will be called back by CA layer when a request is received
void HandleCARequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
{
- OC_LOG(INFO, TAG, PCF("Enter HandleCARequests"));
+ OC_LOG(INFO, TAG, "Enter HandleCARequests");
if(!endPoint)
{
- OC_LOG(ERROR, TAG, PCF("endPoint is NULL"));
+ OC_LOG(ERROR, TAG, "endPoint is NULL");
return;
}
if(!requestInfo)
{
- OC_LOG(ERROR, TAG, PCF("requestInfo is NULL"));
+ OC_LOG(ERROR, TAG, "requestInfo is NULL");
+ return;
+ }
+
+#if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
+#ifdef ROUTING_GATEWAY
+ bool needRIHandling = false;
+ /*
+ * Routing manager is going to update either of endpoint or request or both.
+ * This typecasting is done to avoid unnecessary duplication of Endpoint and requestInfo
+ * RM can update "routeData" option in endPoint so that future RI requests can be sent to proper
+ * destination. It can also remove "RM" coap header option before passing request / response to
+ * RI as this option will make no sense to either RI or application.
+ */
+ OCStackResult ret = RMHandleRequest((CARequestInfo_t *)requestInfo, (CAEndpoint_t *)endPoint,
+ &needRIHandling);
+ if(OC_STACK_OK != ret || !needRIHandling)
+ {
+ OC_LOG_V(INFO, TAG, "Routing status![%d]. Not forwarding to RI", ret);
return;
}
+#endif
+
+ /*
+ * Put source in sender endpoint so that the next packet from application can be routed to
+ * proper destination and remove RM header option.
+ */
+ RMUpdateInfo((CAHeaderOption_t **) &(requestInfo->info.options),
+ (uint8_t *) &(requestInfo->info.numOptions),
+ (CAEndpoint_t *) endPoint);
+#endif
OCStackResult requestResult = OC_STACK_ERROR;
OCServerProtocolRequest serverRequest = {0};
- OC_LOG_V(INFO, TAG, PCF("Endpoint URI : %s"), requestInfo->info.resourceUri);
+ OC_LOG_V(INFO, TAG, "Endpoint URI : %s", requestInfo->info.resourceUri);
char * uriWithoutQuery = NULL;
char * query = NULL;
OC_LOG_V(ERROR, TAG, "getQueryFromUri() failed with OC error code %d\n", requestResult);
return;
}
- OC_LOG_V(INFO, TAG, PCF("URI without query: %s"), uriWithoutQuery);
- OC_LOG_V(INFO, TAG, PCF("Query : %s"), query);
+ OC_LOG_V(INFO, TAG, "URI without query: %s", uriWithoutQuery);
+ OC_LOG_V(INFO, TAG, "Query : %s", query);
if(strlen(uriWithoutQuery) < MAX_URI_LENGTH)
{
}
else
{
- OC_LOG(ERROR, TAG, PCF("URI length exceeds MAX_URI_LENGTH."));
+ OC_LOG(ERROR, TAG, "URI length exceeds MAX_URI_LENGTH.");
OICFree(uriWithoutQuery);
OICFree(query);
return;
}
else
{
- OC_LOG(ERROR, TAG, PCF("Query length exceeds MAX_QUERY_LENGTH."));
+ OC_LOG(ERROR, TAG, "Query length exceeds MAX_QUERY_LENGTH.");
OICFree(query);
return;
}
}
- if (requestInfo->info.payload)
+ if ((requestInfo->info.payload) && (0 < requestInfo->info.payloadSize))
{
serverRequest.reqTotalSize = requestInfo->info.payloadSize;
- memcpy (&(serverRequest.payload), requestInfo->info.payload,
+ serverRequest.payload = (uint8_t *) OICMalloc(requestInfo->info.payloadSize);
+ memcpy (serverRequest.payload, requestInfo->info.payload,
requestInfo->info.payloadSize);
}
else
SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_REQ,
requestInfo->info.type, requestInfo->info.numOptions,
requestInfo->info.options, requestInfo->info.token,
- requestInfo->info.tokenLength);
+ requestInfo->info.tokenLength, requestInfo->info.resourceUri);
+ OICFree(serverRequest.payload);
return;
}
SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_INTERNAL_SERVER_ERROR,
requestInfo->info.type, requestInfo->info.numOptions,
requestInfo->info.options, requestInfo->info.token,
- requestInfo->info.tokenLength);
+ requestInfo->info.tokenLength, requestInfo->info.resourceUri);
+ OICFree(serverRequest.payload);
return;
}
memcpy(serverRequest.requestToken, requestInfo->info.token, requestInfo->info.tokenLength);
+ switch (requestInfo->info.acceptFormat)
+ {
+ case CA_FORMAT_APPLICATION_CBOR:
+ serverRequest.acceptFormat = OC_FORMAT_CBOR;
+ break;
+ case CA_FORMAT_UNDEFINED:
+ serverRequest.acceptFormat = OC_FORMAT_UNDEFINED;
+ break;
+ default:
+ serverRequest.acceptFormat = OC_FORMAT_UNSUPPORTED;
+ }
+
if (requestInfo->info.type == CA_MSG_CONFIRM)
{
serverRequest.qos = OC_HIGH_QOS;
if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
{
OC_LOG(ERROR, TAG,
- PCF("The request info numOptions is greater than MAX_HEADER_OPTIONS"));
+ "The request info numOptions is greater than MAX_HEADER_OPTIONS");
SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_OPT,
requestInfo->info.type, requestInfo->info.numOptions,
requestInfo->info.options, requestInfo->info.token,
- requestInfo->info.tokenLength);
+ requestInfo->info.tokenLength, requestInfo->info.resourceUri);
+ OICFree(serverRequest.payload);
OICFree(serverRequest.requestToken);
return;
}
if(requestResult == OC_STACK_SLOW_RESOURCE)
{
SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_EMPTY,
- CA_MSG_ACKNOWLEDGE,0, NULL, NULL, 0);
+ CA_MSG_ACKNOWLEDGE,0, NULL, NULL, 0, NULL);
}
else if(requestResult != OC_STACK_OK)
{
- OC_LOG_V(ERROR, TAG, PCF("HandleStackRequests failed. error: %d"), requestResult);
+ OC_LOG_V(ERROR, TAG, "HandleStackRequests failed. error: %d", requestResult);
- CAResponseResult_t stackResponse = OCToCAStackResult(requestResult);
+ CAResponseResult_t stackResponse =
+ OCToCAStackResult(requestResult, serverRequest.method);
SendDirectStackResponse(endPoint, requestInfo->info.messageId, stackResponse,
requestInfo->info.type, requestInfo->info.numOptions,
requestInfo->info.options, requestInfo->info.token,
- requestInfo->info.tokenLength);
+ requestInfo->info.tokenLength, requestInfo->info.resourceUri);
}
// requestToken is fed to HandleStackRequests, which then goes to AddServerRequest.
// The token is copied in there, and is thus still owned by this function.
+ OICFree(serverRequest.payload);
OICFree(serverRequest.requestToken);
- OC_LOG(INFO, TAG, PCF("Exit HandleCARequests"));
+ OC_LOG(INFO, TAG, "Exit HandleCARequests");
}
OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
{
- OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
+ OC_LOG(INFO, TAG, "Entering HandleStackRequests (OCStack Layer)");
OCStackResult result = OC_STACK_ERROR;
ResourceHandling resHandling;
OCResource *resource;
if(!protocolRequest)
{
- OC_LOG(ERROR, TAG, PCF("protocolRequest is NULL"));
+ OC_LOG(ERROR, TAG, "protocolRequest is NULL");
return OC_STACK_INVALID_PARAM;
}
protocolRequest->tokenLength);
if(!request)
{
- OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
+ OC_LOG(INFO, TAG, "This is a new Server Request");
result = AddServerRequest(&request, protocolRequest->coapID,
- protocolRequest->delayedResNeeded, 0,
- protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
+ protocolRequest->delayedResNeeded, 0, protocolRequest->method,
+ protocolRequest->numRcvdVendorSpecificHeaderOptions,
protocolRequest->observationOption, protocolRequest->qos,
protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
protocolRequest->payload, protocolRequest->requestToken,
- protocolRequest->tokenLength,
- protocolRequest->resourceUrl, protocolRequest->reqTotalSize,
+ protocolRequest->tokenLength, protocolRequest->resourceUrl,
+ protocolRequest->reqTotalSize, protocolRequest->acceptFormat,
&protocolRequest->devAddr);
if (OC_STACK_OK != result)
{
- OC_LOG(ERROR, TAG, PCF("Error adding server request"));
+ OC_LOG(ERROR, TAG, "Error adding server request");
return result;
}
if(!request)
{
- OC_LOG(ERROR, TAG, PCF("Out of Memory"));
+ OC_LOG(ERROR, TAG, "Out of Memory");
return OC_STACK_NO_MEMORY;
}
}
else
{
- OC_LOG(INFO, TAG, PCF("This is either a repeated or blocked Server Request"));
+ OC_LOG(INFO, TAG, "This is either a repeated or blocked Server Request");
}
if(request->requestComplete)
{
- OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
+ OC_LOG(INFO, TAG, "This Server Request is complete");
result = DetermineResourceHandling (request, &resHandling, &resource);
if (result == OC_STACK_OK)
{
}
else
{
- OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
+ OC_LOG(INFO, TAG, "This Server Request is incomplete");
result = OC_STACK_CONTINUE;
}
return result;
if (!info.platformID)
{
- OC_LOG(ERROR, TAG, PCF("No platform ID found."));
+ OC_LOG(ERROR, TAG, "No platform ID found.");
return false;
}
if(lenManufacturerName == 0 || lenManufacturerName > MAX_MANUFACTURER_NAME_LENGTH)
{
- OC_LOG(ERROR, TAG, PCF("Manufacturer name fails length requirements."));
+ OC_LOG(ERROR, TAG, "Manufacturer name fails length requirements.");
return false;
}
}
else
{
- OC_LOG(ERROR, TAG, PCF("No manufacturer name present"));
+ OC_LOG(ERROR, TAG, "No manufacturer name present");
return false;
}
{
if(strlen(info.manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH)
{
- OC_LOG(ERROR, TAG, PCF("Manufacturer url fails length requirements."));
+ OC_LOG(ERROR, TAG, "Manufacturer url fails length requirements.");
return false;
}
}
{
(void) ipAddr;
(void) port;
-#ifdef RA_ADAPTER
- if(!gRASetInfo)
- {
- OC_LOG(ERROR, TAG, PCF("Need to call OCSetRAInfo before calling OCInit"));
- return OC_STACK_ERROR;
- }
-#endif
return OCInit1(mode, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS);
}
{
if(stackState == OC_STACK_INITIALIZED)
{
- OC_LOG(INFO, TAG, PCF("Subsequent calls to OCInit() without calling \
- OCStop() between them are ignored."));
+ OC_LOG(INFO, TAG, "Subsequent calls to OCInit() without calling \
+ OCStop() between them are ignored.");
return OC_STACK_OK;
}
+#ifndef ROUTING_GATEWAY
+ if (OC_GATEWAY == mode)
+ {
+ OC_LOG(ERROR, TAG, "Routing Manager not supported");
+ return OC_STACK_INVALID_PARAM;
+ }
+#endif
+
+#ifdef RA_ADAPTER
+ if(!gRASetInfo)
+ {
+ OC_LOG(ERROR, TAG, "Need to call OCSetRAInfo before calling OCInit");
+ return OC_STACK_ERROR;
+ }
+#endif
+
OCStackResult result = OC_STACK_ERROR;
- OC_LOG(INFO, TAG, PCF("Entering OCInit"));
+ OC_LOG(INFO, TAG, "Entering OCInit");
// Validate mode
- if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)))
+ if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)
+ || (mode == OC_GATEWAY)))
{
- OC_LOG(ERROR, TAG, PCF("Invalid mode"));
+ OC_LOG(ERROR, TAG, "Invalid mode");
return OC_STACK_ERROR;
}
myStackMode = mode;
- if (mode == OC_CLIENT || mode == OC_CLIENT_SERVER)
+ if (mode == OC_CLIENT || mode == OC_CLIENT_SERVER || mode == OC_GATEWAY)
{
caglobals.client = true;
}
- if (mode == OC_SERVER || mode == OC_CLIENT_SERVER)
+ if (mode == OC_SERVER || mode == OC_CLIENT_SERVER || mode == OC_GATEWAY)
{
caglobals.server = true;
}
caglobals.serverFlags = (CATransportFlags_t)serverFlags;
if (!(caglobals.serverFlags & CA_IPFAMILY_MASK))
{
- caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4);
+ caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4|CA_IPV6);
}
caglobals.clientFlags = (CATransportFlags_t)clientFlags;
if (!(caglobals.clientFlags & CA_IPFAMILY_MASK))
{
+ caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4|CA_IPV6);
+ }
+
+#ifdef TCP_ADAPTER
+ if (!(caglobals.serverFlags & CA_IPFAMILY_MASK))
+ {
+ caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4);
+ }
+ if (!(caglobals.clientFlags & CA_IPFAMILY_MASK))
+ {
caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4);
}
+#endif
defaultDeviceHandler = NULL;
defaultDeviceHandlerCallbackParameter = NULL;
case OC_CLIENT:
CARegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
result = CAResultToOCResult(CAStartDiscoveryServer());
- OC_LOG(INFO, TAG, PCF("Client mode: CAStartDiscoveryServer"));
+ OC_LOG(INFO, TAG, "Client mode: CAStartDiscoveryServer");
break;
case OC_SERVER:
SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
result = CAResultToOCResult(CAStartListeningServer());
- OC_LOG(INFO, TAG, PCF("Server mode: CAStartListeningServer"));
+ OC_LOG(INFO, TAG, "Server mode: CAStartListeningServer");
break;
case OC_CLIENT_SERVER:
+ case OC_GATEWAY:
SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
result = CAResultToOCResult(CAStartListeningServer());
if(result == OC_STACK_OK)
VERIFY_SUCCESS(result, OC_STACK_OK);
#ifdef WITH_PRESENCE
- PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
+ PresenceTimeOutSize = sizeof (PresenceTimeOut) / sizeof (PresenceTimeOut[0]) - 1;
#endif // WITH_PRESENCE
//Update Stack state to initialized
// TODO after BeachHead delivery: consolidate into single SRMInit()
}
+#ifdef ROUTING_GATEWAY
+ if (OC_GATEWAY == myStackMode)
+ {
+ result = RMInitialize();
+ }
+#endif
+
exit:
if(result != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
+ OC_LOG(ERROR, TAG, "Stack initialization error");
deleteAllResources();
CATerminate();
stackState = OC_STACK_UNINITIALIZED;
OCStackResult OCStop()
{
- OC_LOG(INFO, TAG, PCF("Entering OCStop"));
+ OC_LOG(INFO, TAG, "Entering OCStop");
if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
{
- OC_LOG(DEBUG, TAG, PCF("Stack already stopping, exiting"));
+ OC_LOG(DEBUG, TAG, "Stack already stopping, exiting");
return OC_STACK_OK;
}
else if (stackState != OC_STACK_INITIALIZED)
{
- OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
+ OC_LOG(ERROR, TAG, "Stack not initialized");
return OC_STACK_ERROR;
}
stackState = OC_STACK_UNINIT_IN_PROGRESS;
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
// Ensure that the TTL associated with ANY and ALL presence notifications originating from
// here send with the code "OC_STACK_PRESENCE_STOPPED" result.
presenceResource.presenceTTL = 0;
- #endif // WITH_PRESENCE
+#endif // WITH_PRESENCE
+
+#ifdef ROUTING_GATEWAY
+ if (OC_GATEWAY == myStackMode)
+ {
+ RMTerminate();
+ }
+#endif
// Free memory dynamically allocated for resources
deleteAllResources();
/**
* A request uri consists of the following components in order:
* example
- * optional prefix "coap://"
+ * optionally one of
+ * CoAP over UDP prefix "coap://"
+ * CoAP over TCP prefix "coap+tcp://"
* optionally one of
* IPv6 address "[1234::5678]"
* IPv4 address "192.168.1.1"
return OC_STACK_INVALID_URI;
}
+#ifdef TCP_ADAPTER
+ // process url scheme
+ size_t prefixLen = slash2 - fullUri;
+ bool istcp = false;
+ if (prefixLen)
+ {
+ if ((prefixLen == sizeof(COAP_TCP) - 1) && (!strncmp(fullUri, COAP_TCP, prefixLen)))
+ {
+ istcp = true;
+ }
+ }
+#endif
+
+ // TODO: this logic should come in with unit tests exercising the various strings
// processs url prefix, if any
size_t urlLen = slash - start;
// port
size_t len = 0;
if (urlLen && devAddr)
{ // construct OCDevAddr
- if (OC_ADAPTER_IP == adapter)
+ 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;
+ }
+ adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
+ flags = (OCTransportFlags)(flags | OC_IP_USE_V6);
+ }
+ else
{
- if (start[0] == '[')
- { // ipv6 address
- char *close = strchr(++start, ']');
- if (!close || close > slash)
- {
- return OC_STACK_INVALID_URI;
+ char *dot = strchr(start, '.');
+ if (dot && dot < slash)
+ { // ipv4 address
+ colon = strchr(start, ':');
+ end = (colon && colon < slash) ? colon : slash;
+#ifdef TCP_ADAPTER
+ if (istcp)
+ { // coap over tcp
+ adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_TCP);
}
- end = close;
- if (close[1] == ':')
+ else
+#endif
{
- colon = close + 1;
+ adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
+ flags = (OCTransportFlags)(flags | OC_IP_USE_V4);
}
}
else
- { // ipv4 address
+ { // MAC address
end = slash;
- colon = strchr(start, ':');
- end = (colon && colon < slash) ? colon : slash;
- }
- len = end - start;
- if (len >= sizeof(da->addr))
- {
- return OC_STACK_INVALID_URI;
}
- // collect port, if any
- if (colon && colon < slash)
+ }
+ len = end - start;
+ if (len >= sizeof(da->addr))
+ {
+ return OC_STACK_INVALID_URI;
+ }
+ // collect port, if any
+ if (colon && colon < slash)
+ {
+ for (colon++; colon < slash; colon++)
{
- for (colon++; colon < slash; colon++)
+ char c = colon[0];
+ if (c < '0' || c > '9')
{
- char c = colon[0];
- if (c < '0' || c > '9')
- {
- return OC_STACK_INVALID_URI;
- }
- port = 10 * port + c - '0';
+ return OC_STACK_INVALID_URI;
}
+ port = 10 * port + c - '0';
}
}
- else
- {
- /**
- * This is for Non-IP adapters(EDR and BLE).
- * The address will be between "//" and "/" in the request URI.
- * [Ex. coap://AB:BC:CD:DE:EF:FG/resource_uri]
- */
- end = slash;
- }
len = end - start;
if (len >= sizeof(da->addr))
OCHeaderOption *options,
uint8_t numOptions)
{
- OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
+ OC_LOG(INFO, TAG, "Entering OCDoResource");
// Validate input parameters
VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
uint8_t tokenLength = CA_MAX_TOKEN_LEN;
ClientCB *clientCB = NULL;
OCDoHandle resHandle = NULL;
- CAEndpoint_t *endpoint = NULL;
+ CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
OCDevAddr tmpDevAddr = { OC_DEFAULT_ADAPTER };
uint32_t ttl = 0;
OCTransportAdapter adapter;
}
else
{
+ tmpDevAddr.adapter = adapter;
+ tmpDevAddr.flags = flags;
destination = &tmpDevAddr;
requestInfo.isMulticast = true;
}
// CA_DISCOVER will become GET and isMulticast
requestInfo.method = CA_GET;
break;
- #ifdef WITH_PRESENCE
+#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
+#endif
default:
result = OC_STACK_INVALID_METHOD;
goto exit;
if (!devAddr && !destination)
{
- OC_LOG_V(DEBUG, TAG, "no devAddr and no destination");
+ OC_LOG(DEBUG, TAG, "no devAddr and no destination");
result = OC_STACK_INVALID_PARAM;
goto exit;
}
caResult = CAGenerateToken(&token, tokenLength);
if (caResult != CA_STATUS_OK)
{
- OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
+ OC_LOG(ERROR, TAG, "CAGenerateToken error");
result= OC_STACK_ERROR;
goto exit;
}
requestInfo.info.numOptions = numOptions;
}
- // create remote endpoint
- result = OCCreateEndpoint(devAddr, &endpoint);
+ CopyDevAddrToEndpoint(devAddr, &endpoint);
+
if(payload)
{
if((result =
OCConvertPayload(payload, &requestInfo.info.payload, &requestInfo.info.payloadSize))
!= OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("Failed to create CBOR Payload"));
+ OC_LOG(ERROR, TAG, "Failed to create CBOR Payload");
goto exit;
}
+ requestInfo.info.payloadFormat = CA_FORMAT_APPLICATION_CBOR;
}
else
{
requestInfo.info.payload = NULL;
requestInfo.info.payloadSize = 0;
+ requestInfo.info.payloadFormat = CA_FORMAT_UNDEFINED;
}
-
-
if (result != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("CACreateEndpoint error"));
+ OC_LOG(ERROR, TAG, "CACreateEndpoint error");
goto exit;
}
// prepare for response
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
if (method == OC_REST_PRESENCE)
{
char *presenceUri = NULL;
- result = OCPreparePresence(endpoint, resourceUri, &presenceUri);
+ result = OCPreparePresence(&endpoint, resourceUri, &presenceUri);
if (OC_STACK_OK != result)
{
goto exit;
// look for callbacks into the application.
resourceUri = presenceUri;
}
- #endif
+#endif
ttl = GetTicks(MAX_CB_TIMEOUT_SECONDS * MILLISECONDS_PER_SECOND);
result = AddClientCB(&clientCB, cbData, token, tokenLength, &resHandle,
resourceType = NULL; // Client CB list entry now owns it
// send request
- caResult = CASendRequest(endpoint, &requestInfo);
- if (caResult != CA_STATUS_OK)
+ result = OCSendRequest(&endpoint, &requestInfo);
+ if (OC_STACK_OK != result)
{
- OC_LOG(ERROR, TAG, PCF("CASendRequest"));
- result = OC_STACK_COMM_ERROR;
goto exit;
}
exit:
if (result != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
+ OC_LOG(ERROR, TAG, "OCDoResource error");
FindAndDeleteClientCB(clientCB);
CADestroyToken(token);
if (handle)
OICFree(devAddr);
OICFree(resourceUri);
OICFree(resourceType);
- OICFree(endpoint);
if (hdrOptionMemAlloc)
{
OICFree(requestInfo.info.options);
* Remove the callback associated on client side.
*/
OCStackResult ret = OC_STACK_OK;
- CAEndpoint_t* endpoint = NULL;
- CAResult_t caResult;
+ CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
CARequestInfo_t requestInfo = {.method = CA_GET};
ClientCB *clientCB = GetClientCB(NULL, 0, handle, NULL);
if (!clientCB)
{
- OC_LOG(ERROR, TAG, PCF("Client callback not found. Called OCCancel twice?"));
+ OC_LOG(ERROR, TAG, "Client callback not found. Called OCCancel twice?");
goto Error;
}
}
else
{
- OC_LOG(INFO, TAG, PCF("Cancelling observation as CONFIRMABLE"));
+ OC_LOG(INFO, TAG, "Cancelling observation as CONFIRMABLE");
}
requestData.type = qualityOfServiceToMessageType(qos);
requestInfo.method = CA_GET;
requestInfo.info = requestData;
- ret = OCCreateEndpoint(clientCB->devAddr, &endpoint);
- if (ret != OC_STACK_OK)
- {
- OC_LOG(ERROR, TAG, PCF("CACreateEndpoint error"));
- goto Error;
- }
+ CopyDevAddrToEndpoint(clientCB->devAddr, &endpoint);
// send request
- caResult = CASendRequest(endpoint, &requestInfo);
- if (caResult != CA_STATUS_OK)
- {
- OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
- ret = OC_STACK_ERROR;
- }
- ret = CAResultToOCResult (caResult);
+ ret = OCSendRequest(&endpoint, &requestInfo);
break;
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
case OC_REST_PRESENCE:
FindAndDeleteClientCB(clientCB);
break;
- #endif
+#endif
default:
ret = OC_STACK_INVALID_METHOD;
}
Error:
- OCDestroyEndpoint(endpoint);
if (requestData.numOptions > 0)
{
OICFree(requestData.options);
{
OICFree (requestData.resourceUri);
}
-
return ret;
}
*/
OCStackResult OCRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
{
- OC_LOG(INFO, TAG, PCF("RegisterPersistentStorageHandler !!"));
+ OC_LOG(INFO, TAG, "RegisterPersistentStorageHandler !!");
if(!persistentStorageHandler)
{
- OC_LOG(ERROR, TAG, PCF("The persistent storage handler is invalid"));
+ OC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
return OC_STACK_INVALID_PARAM;
}
else
!persistentStorageHandler->unlink ||
!persistentStorageHandler->write)
{
- OC_LOG(ERROR, TAG, PCF("The persistent storage handler is invalid"));
+ OC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
return OC_STACK_INVALID_PARAM;
}
}
// the following line floods the log with messages that are irrelevant
// to most purposes. Uncomment as needed.
- //OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
+ //OC_LOG(INFO, TAG, "Entering RequestPresence");
ClientCB* cbNode = NULL;
OCClientResponse clientResponse;
OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
cbNode->presence->TTLlevel);
OC_LOG_V(DEBUG, TAG, "current ticks %d", now);
- if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
+ if (cbNode->presence->TTLlevel > PresenceTimeOutSize)
{
goto exit;
}
OC_LOG_V(DEBUG, TAG, "timeout ticks %d",
cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
}
-
if (cbNode->presence->TTLlevel >= PresenceTimeOutSize)
{
- OC_LOG(DEBUG, TAG, PCF("No more timeout ticks"));
+ OC_LOG(DEBUG, TAG, "No more timeout ticks");
clientResponse.sequenceNumber = 0;
clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
continue;
}
- CAResult_t caResult = CA_STATUS_OK;
- CAEndpoint_t* endpoint = NULL;
+ CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
CARequestInfo_t requestInfo = {.method = CA_GET};
- OC_LOG(DEBUG, TAG, PCF("time to test server presence"));
+ OC_LOG(DEBUG, TAG, "time to test server presence");
- result = OCCreateEndpoint(cbNode->devAddr, &endpoint);
- if (result != OC_STACK_OK)
- {
- OC_LOG(ERROR, TAG, PCF("CACreateEndpoint error"));
- goto exit;
- }
+ CopyDevAddrToEndpoint(cbNode->devAddr, &endpoint);
requestData.type = CA_MSG_NONCONFIRM;
requestData.token = cbNode->token;
requestInfo.method = CA_GET;
requestInfo.info = requestData;
- caResult = CASendRequest(endpoint, &requestInfo);
- OCDestroyEndpoint(endpoint);
-
- if (caResult != CA_STATUS_OK)
+ result = OCSendRequest(&endpoint, &requestInfo);
+ if (OC_STACK_OK != result)
{
- OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
goto exit;
}
exit:
if (result != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
+ OC_LOG(ERROR, TAG, "OCProcessPresence error");
}
+
return result;
}
#endif // WITH_PRESENCE
OCStackResult OCProcess()
{
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
OCProcessPresence();
- #endif
+#endif
CAHandleRequestResponse();
+#ifdef ROUTING_GATEWAY
+ RMProcess();
+#endif
return OC_STACK_OK;
}
if (OC_MAX_PRESENCE_TTL_SECONDS < ttl)
{
presenceResource.presenceTTL = OC_MAX_PRESENCE_TTL_SECONDS;
- OC_LOG(INFO, TAG, PCF("Setting Presence TTL to max value"));
+ OC_LOG(INFO, TAG, "Setting Presence TTL to max value");
}
else if (0 == ttl)
{
presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
- OC_LOG(INFO, TAG, PCF("Setting Presence TTL to default value"));
+ OC_LOG(INFO, TAG, "Setting Presence TTL to default value");
}
else
{
presenceState = OC_PRESENCE_INITIALIZED;
OCDevAddr devAddr = { OC_DEFAULT_ADAPTER };
- OICStrcpy(devAddr.addr, sizeof(devAddr.addr), OC_MULTICAST_IP);
- devAddr.port = OC_MULTICAST_PORT;
CAToken_t caToken = NULL;
CAResult_t caResult = CAGenerateToken(&caToken, tokenLength);
if (caResult != CA_STATUS_OK)
{
- OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
+ OC_LOG(ERROR, TAG, "CAGenerateToken error");
CADestroyToken(caToken);
return OC_STACK_ERROR;
}
AddObserver(OC_RSRVD_PRESENCE_URI, NULL, 0, caToken, tokenLength,
- (OCResource *)presenceResource.handle, OC_LOW_QOS, &devAddr);
+ (OCResource *)presenceResource.handle, OC_LOW_QOS, OC_FORMAT_UNDEFINED, &devAddr);
CADestroyToken(caToken);
}
if(result != OC_STACK_OK)
{
OC_LOG(ERROR, TAG,
- PCF("Changing the presence resource properties to ACTIVE not successful"));
+ "Changing the presence resource properties to ACTIVE not successful");
return result;
}
OCStackResult OCSetPlatformInfo(OCPlatformInfo platformInfo)
{
- OC_LOG(INFO, TAG, PCF("Entering OCSetPlatformInfo"));
+ OC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
- if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER)
+ if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER || myStackMode == OC_GATEWAY)
{
if (validatePlatformInfo(platformInfo))
{
OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
{
- OC_LOG(INFO, TAG, PCF("Entering OCSetDeviceInfo"));
+ OC_LOG(INFO, TAG, "Entering OCSetDeviceInfo");
if (!deviceInfo.deviceName || deviceInfo.deviceName[0] == '\0')
{
- OC_LOG(ERROR, TAG, PCF("Null or empty device name."));
+ OC_LOG(ERROR, TAG, "Null or empty device name.");
return OC_STACK_INVALID_PARAM;
}
char *str = NULL;
OCStackResult result = OC_STACK_ERROR;
- OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
+ OC_LOG(INFO, TAG, "Entering OCCreateResource");
if(myStackMode == OC_CLIENT)
{
// Validate parameters
if(!uri || uri[0]=='\0' || strlen(uri)>=MAX_URI_LENGTH )
{
- OC_LOG(ERROR, TAG, PCF("URI is empty or too long"));
+ OC_LOG(ERROR, TAG, "URI is empty or too long");
return OC_STACK_INVALID_URI;
}
// Is it presented during resource discovery?
if (!handle || !resourceTypeName || resourceTypeName[0] == '\0' )
{
- OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
+ OC_LOG(ERROR, TAG, "Input parameter is NULL");
return OC_STACK_INVALID_PARAM;
}
> (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE |
OC_EXPLICIT_DISCOVERABLE))
{
- OC_LOG(ERROR, TAG, PCF("Invalid property"));
+ OC_LOG(ERROR, TAG, "Invalid property");
return OC_STACK_INVALID_PARAM;
}
result = BindResourceTypeToResource(pointer, resourceTypeName);
if (result != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
+ OC_LOG(ERROR, TAG, "Error adding resourcetype");
goto exit;
}
result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
if (result != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
+ OC_LOG(ERROR, TAG, "Error adding resourceinterface");
goto exit;
}
*handle = pointer;
result = OC_STACK_OK;
- #ifdef WITH_PRESENCE
- if(presenceResource.handle)
+#ifdef WITH_PRESENCE
+ if (presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
SendPresenceNotification(pointer->rsrcType, OC_PRESENCE_TRIGGER_CREATE);
}
- #endif
+#endif
exit:
if (result != OC_STACK_OK)
{
OCResource *resource = NULL;
uint8_t i = 0;
- OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
+ OC_LOG(INFO, TAG, "Entering OCBindResource");
// Validate parameters
VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
// Container cannot contain itself
if (collectionHandle == resourceHandle)
{
- OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
+ OC_LOG(ERROR, TAG, "Added handle equals collection handle");
return OC_STACK_INVALID_PARAM;
}
resource = findResource((OCResource *) collectionHandle);
if (!resource)
{
- OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
+ OC_LOG(ERROR, TAG, "Collection handle not found");
return OC_STACK_INVALID_PARAM;
}
if (!resource->rsrcResources[i])
{
resource->rsrcResources[i] = (OCResource *) resourceHandle;
- OC_LOG(INFO, TAG, PCF("resource bound"));
+ OC_LOG(INFO, TAG, "resource bound");
- #ifdef WITH_PRESENCE
- if(presenceResource.handle)
+#ifdef WITH_PRESENCE
+ if (presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
OC_PRESENCE_TRIGGER_CHANGE);
}
- #endif
+#endif
return OC_STACK_OK;
}
OCResource *resource = NULL;
uint8_t i = 0;
- OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
+ OC_LOG(INFO, TAG, "Entering OCUnBindResource");
// Validate parameters
VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
// Container cannot contain itself
if (collectionHandle == resourceHandle)
{
- OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
+ OC_LOG(ERROR, TAG, "removing handle equals collection handle");
return OC_STACK_INVALID_PARAM;
}
resource = findResource((OCResource *) collectionHandle);
if (!resource)
{
- OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
+ OC_LOG(ERROR, TAG, "Collection handle not found");
return OC_STACK_INVALID_PARAM;
}
if (resourceHandle == resource->rsrcResources[i])
{
resource->rsrcResources[i] = (OCResource *) NULL;
- OC_LOG(INFO, TAG, PCF("resource unbound"));
+ OC_LOG(INFO, TAG, "resource unbound");
// Send notification when resource is unbounded successfully.
- #ifdef WITH_PRESENCE
- if(presenceResource.handle)
+#ifdef WITH_PRESENCE
+ if (presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
OC_PRESENCE_TRIGGER_CHANGE);
}
- #endif
+#endif
return OC_STACK_OK;
}
}
- OC_LOG(INFO, TAG, PCF("resource not found in collection"));
+ OC_LOG(INFO, TAG, "resource not found in collection");
// Unable to add resourceHandle, so return error
return OC_STACK_ERROR;
resource = findResource((OCResource *) handle);
if (!resource)
{
- OC_LOG(ERROR, TAG, PCF("Resource not found"));
+ OC_LOG(ERROR, TAG, "Resource not found");
return OC_STACK_ERROR;
}
result = BindResourceTypeToResource(resource, resourceTypeName);
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
}
- #endif
+#endif
return result;
}
resource = findResource((OCResource *) handle);
if (!resource)
{
- OC_LOG(ERROR, TAG, PCF("Resource not found"));
+ OC_LOG(ERROR, TAG, "Resource not found");
return OC_STACK_ERROR;
}
result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
- #ifdef WITH_PRESENCE
- if(presenceResource.handle)
+#ifdef WITH_PRESENCE
+ if (presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
}
- #endif
+#endif
return result;
}
{
if (!handle)
{
- OC_LOG(ERROR, TAG, PCF("Invalid handle for deletion"));
+ OC_LOG(ERROR, TAG, "Invalid handle for deletion");
return OC_STACK_INVALID_PARAM;
}
OCResource *resource = findResource((OCResource *) handle);
if (resource == NULL)
{
- OC_LOG(ERROR, TAG, PCF("Resource not found"));
+ OC_LOG(ERROR, TAG, "Resource not found");
return OC_STACK_NO_RESOURCE;
}
if (deleteResource((OCResource *) handle) != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
+ OC_LOG(ERROR, TAG, "Error deleting resource");
return OC_STACK_ERROR;
}
resource = findResource((OCResource *)handle);
if (!resource)
{
- OC_LOG(ERROR, TAG, PCF("Resource not found"));
+ OC_LOG(ERROR, TAG, "Resource not found");
return OC_STACK_ERROR;
}
resource->entityHandler = entityHandler;
resource->entityHandlerCallbackParam = callbackParam;
- #ifdef WITH_PRESENCE
- if(presenceResource.handle)
+#ifdef WITH_PRESENCE
+ if (presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
}
- #endif
+#endif
return OC_STACK_OK;
}
resource = findResource((OCResource *)handle);
if (!resource)
{
- OC_LOG(ERROR, TAG, PCF("Resource not found"));
+ OC_LOG(ERROR, TAG, "Resource not found");
return NULL;
}
OCMethod method = OC_REST_NOMETHOD;
uint32_t maxAge = 0;
- OC_LOG(INFO, TAG, PCF("Notifying all observers"));
- #ifdef WITH_PRESENCE
+ OC_LOG(INFO, TAG, "Notifying all observers");
+#ifdef WITH_PRESENCE
if(handle == presenceResource.handle)
{
return OC_STACK_OK;
}
- #endif // WITH_PRESENCE
+#endif // WITH_PRESENCE
VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
// Verify that the resource exists
incrementSequenceNumber(resPtr);
method = OC_REST_OBSERVE;
maxAge = MAX_OBSERVE_AGE;
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
result = SendAllObserverNotification (method, resPtr, maxAge,
OC_PRESENCE_TRIGGER_DELETE, NULL, qos);
- #else
+#else
result = SendAllObserverNotification (method, resPtr, maxAge, qos);
- #endif
+#endif
return result;
}
}
const OCRepPayload *payload,
OCQualityOfService qos)
{
- OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
+ OC_LOG(INFO, TAG, "Entering OCNotifyListOfObservers");
OCResource *resPtr = NULL;
//TODO: we should allow the server to define this
OCStackResult result = OC_STACK_ERROR;
OCServerRequest *serverRequest = NULL;
- OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
+ OC_LOG(INFO, TAG, "Entering OCDoResponse");
// Validate input parameters
VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
if (resourceProperties
> (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW))
{
- OC_LOG(ERROR, TAG, PCF("Invalid property"));
+ OC_LOG(ERROR, TAG, "Invalid property");
return OC_STACK_INVALID_PARAM;
}
if(!enable)
headResource = NULL;
tailResource = NULL;
// Init Virtual Resources
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
result = OCCreateResource(&presenceResource.handle,
result = OCChangeResourceProperty(
&(((OCResource *) presenceResource.handle)->resourceProperties),
OC_ACTIVE, 0);
- #endif
+#endif
if (result == OC_STACK_OK)
{
while (pointer)
{
temp = pointer->next;
- #ifdef WITH_PRESENCE
- if(pointer != (OCResource *) presenceResource.handle)
+#ifdef WITH_PRESENCE
+ if (pointer != (OCResource *) presenceResource.handle)
{
- #endif // WITH_PRESENCE
+#endif // WITH_PRESENCE
deleteResource(pointer);
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
}
- #endif // WITH_PRESENCE
+#endif // WITH_PRESENCE
pointer = temp;
}
SRMDeInitSecureResources();
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
// Ensure that the last resource to be deleted is the presence resource. This allows for all
// presence notification attributed to their deletion to be processed.
deleteResource((OCResource *) presenceResource.handle);
- #endif // WITH_PRESENCE
+#endif // WITH_PRESENCE
}
OCStackResult deleteResource(OCResource *resource)
OCResource *temp = NULL;
if(!resource)
{
- OC_LOG_V(DEBUG,TAG,"resource is NULL");
+ OC_LOG(DEBUG,TAG,"resource is NULL");
return OC_STACK_INVALID_PARAM;
}
{
// Invalidate all Resource Properties.
resource->resourceProperties = (OCResourceProperty) 0;
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
if(resource != (OCResource *) presenceResource.handle)
{
- #endif // WITH_PRESENCE
+#endif // WITH_PRESENCE
OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
- #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
}
if(presenceResource.handle)
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_DELETE);
}
- #endif
+#endif
// Only resource in list.
if (temp == headResource && temp == tailResource)
{
char *pointerToDelimiter = strstr(uri, "?");
- uriWithoutQueryLen = pointerToDelimiter == NULL ? uriLen : pointerToDelimiter - uri;
+ uriWithoutQueryLen = pointerToDelimiter == NULL ? uriLen : (size_t)(pointerToDelimiter - uri);
queryLen = pointerToDelimiter == NULL ? 0 : uriLen - uriWithoutQueryLen - 1;
if (uriWithoutQueryLen)
return OC_STACK_NO_MEMORY;
}
-const uint8_t* OCGetServerInstanceID(void)
+const OicUuid_t* OCGetServerInstanceID(void)
{
static bool generated = false;
- static ServerID sid;
- if(generated)
+ static OicUuid_t sid;
+ if (generated)
{
- return sid;
+ return &sid;
}
- if (OCGenerateUuid(sid) != RAND_UUID_OK)
+ if (GetDoxmDeviceID(&sid) != OC_STACK_OK)
{
- OC_LOG(FATAL, TAG, PCF("Generate UUID for Server Instance failed!"));
+ OC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
return NULL;
}
generated = true;
- return sid;
+ return &sid;
}
const char* OCGetServerInstanceIDString(void)
return sidStr;
}
- const uint8_t* sid = OCGetServerInstanceID();
+ const OicUuid_t* sid = OCGetServerInstanceID();
- if(OCConvertUuidToString(sid, sidStr) != RAND_UUID_OK)
+ if(OCConvertUuidToString(sid->id, sidStr) != RAND_UUID_OK)
{
- OC_LOG(FATAL, TAG, PCF("Generate UUID String for Server Instance failed!"));
+ OC_LOG(FATAL, TAG, "Generate UUID String for Server Instance failed!");
return NULL;
}
CA_ADAPTER_RFCOMM_BTEDR,
CA_ADAPTER_GATT_BTLE
- #ifdef RA_ADAPTER
+#ifdef RA_ADAPTER
,CA_ADAPTER_REMOTE_ACCESS
- #endif
+#endif
};
int numConnTypes = sizeof(connTypes)/sizeof(connTypes[0]);
return OC_STACK_ERROR;
}
}
+
#include "oicgroup.h"
#include "cJSON.h"
+#include "cbor.h"
+#include "ocpayload.h"
#include "oic_malloc.h"
#include "oic_string.h"
#include "occollection.h"
#include <pthread.h>
#endif
-#define TAG PCF("OICGROUP")
+#define TAG "OICGROUP"
#define DESC_DELIMITER "\""
#define ACTION_DELIMITER "*"
#define DO_ACTION "DoAction"
#define GET_ACTIONSET "GetActionSet"
#define ACTIONSET "ActionSet"
+#define CANCEL_ACTIONSET "CancelAction"
#define DELETE_ACTIONSET "DelActionSet"
-#define OIC_ACTION_PREFIX "{\"oic\":[{\"rep\":{"
+#define DEFAULT_CONTEXT_VALUE 0x99
+
#define VARIFY_POINTER_NULL(pointer, result, toExit) \
if(pointer == NULL) \
{\
void AddScheduledResource(ScheduledResourceInfo **head,
ScheduledResourceInfo* add)
{
- OC_LOG(INFO, TAG, PCF("AddScheduledResource Entering..."));
+ OC_LOG(INFO, TAG, "AddScheduledResource Entering...");
#ifndef WITH_ARDUINO
pthread_mutex_lock(&lock);
ScheduledResourceInfo* GetScheduledResource(ScheduledResourceInfo *head)
{
- OC_LOG(INFO, TAG, PCF("GetScheduledResource Entering..."));
+ OC_LOG(INFO, TAG, "GetScheduledResource Entering...");
#ifndef WITH_ARDUINO
pthread_mutex_lock(&lock);
if (diffTm <= (time_t) 0)
{
- OC_LOG(INFO, TAG, PCF("return Call INFO."));
+ OC_LOG(INFO, TAG, "return Call INFO.");
goto exit;
}
#endif
if (tmp == NULL)
{
- OC_LOG(INFO, TAG, PCF("Cannot Find Call Info."));
+ OC_LOG(INFO, TAG, "Cannot Find Call Info.");
}
return tmp;
}
ScheduledResourceInfo* GetScheduledResourceByActionSetName(ScheduledResourceInfo *head, char *setName)
{
- OC_LOG(INFO, TAG, PCF("GetScheduledResourceByActionSetName Entering..."));
+ OC_LOG(INFO, TAG, "GetScheduledResourceByActionSetName Entering...");
#ifndef WITH_ARDUINO
pthread_mutex_lock(&lock);
{
if (strcmp(tmp->actionset->actionsetName, setName) == 0)
{
- OC_LOG(INFO, TAG, PCF("return Call INFO."));
+ OC_LOG(INFO, TAG, "return Call INFO.");
goto exit;
}
tmp = tmp->next;
#endif
if (tmp == NULL)
{
- OC_LOG(INFO, TAG, PCF("Cannot Find Call Info."));
+ OC_LOG(INFO, TAG, "Cannot Find Call Info.");
}
return tmp;
}
#ifndef WITH_ARDUINO
pthread_mutex_lock(&lock);
#endif
- OC_LOG(INFO, TAG, PCF("RemoveScheduledResource Entering..."));
+ OC_LOG(INFO, TAG, "RemoveScheduledResource Entering...");
ScheduledResourceInfo *tmp = NULL;
if (del == NULL)
}
-OCStackResult ExtractKeyValueFromRequest(char *request, char **key,
- char **value)
+OCStackResult ExtractKeyValueFromRequest(OCEntityHandlerRequest *ehRequest,
+ char **key, char **value)
{
OCStackResult result = OC_STACK_OK;
- size_t length = 0;
- char* pRequest = (char *) request + strlen(OIC_ACTION_PREFIX);
- char* iterToken, *iterTokenPtr;
+ char *actionSetStr;
- iterToken = (char *) strtok_r(pRequest, ":", &iterTokenPtr);
- VARIFY_POINTER_NULL(iterToken, result, exit);
- length = strlen(iterToken) + 1;
+ if( NULL == ehRequest->payload )
+ {
+ result = OC_STACK_ERROR;
+ goto exit;
+ }
- *key = (char *) OICMalloc(length);
- VARIFY_POINTER_NULL(*key, result, exit)
+ OCRepPayload* input;
- strncpy(*key, iterToken + 1, length);
- ((*key)[((length - 1) - 2)]) = '\0';
+ input = (OCRepPayload*)(ehRequest->payload);
- iterToken = (char *) strtok_r(NULL, "}", &iterTokenPtr);
- VARIFY_POINTER_NULL(iterToken, result, exit);
- length = strlen(iterToken) + 1;
+ if(OCRepPayloadGetPropString(input, ACTIONSET, &actionSetStr))
+ {
+ *key = OICStrdup(ACTIONSET);
+ VARIFY_POINTER_NULL(*key, result, exit);
- *value = (char *) OICMalloc(length);
- VARIFY_POINTER_NULL(*value, result, exit)
+ *value = OICStrdup(actionSetStr);
+ VARIFY_POINTER_NULL(*value, result, exit);
+ }
+ else if(OCRepPayloadGetPropString(input, DO_ACTION, &actionSetStr))
+ {
+ *key = OICStrdup(DO_ACTION);
+ VARIFY_POINTER_NULL(*key, result, exit);
+
+ *value = OICStrdup(actionSetStr);
+ VARIFY_POINTER_NULL(*value, result, exit);
+ }
+ else if(OCRepPayloadGetPropString(input, GET_ACTIONSET, &actionSetStr))
+ {
+ *key = OICStrdup(GET_ACTIONSET);
+ VARIFY_POINTER_NULL(*key, result, exit);
- strncpy(*value, iterToken + 1, length);
- ((*value)[((length - 1) - 2)]) = '\0';
+ *value = OICStrdup(actionSetStr);
+ VARIFY_POINTER_NULL(*value, result, exit);
+ }
+ else if(OCRepPayloadGetPropString(input, DELETE_ACTIONSET, &actionSetStr))
+ {
+ *key = OICStrdup(DELETE_ACTIONSET);
+ VARIFY_POINTER_NULL(*key, result, exit);
+
+ *value = OICStrdup(actionSetStr);
+ VARIFY_POINTER_NULL(*value, result, exit);
+ }
+ else if(OCRepPayloadGetPropString(input, CANCEL_ACTIONSET, &actionSetStr))
+ {
+ *key = OICStrdup(CANCEL_ACTIONSET);
+ VARIFY_POINTER_NULL(*key, result, exit);
+
+ *value = OICStrdup(actionSetStr);
+ VARIFY_POINTER_NULL(*value, result, exit);
+ }
+ else
+ {
+ result = OC_STACK_ERROR;
+ }
exit:
if (result != OC_STACK_OK)
OCAction *action = NULL;
OCCapability *capa = NULL;
- OC_LOG(INFO, TAG, PCF("Build ActionSet Instance."));
+ OC_LOG(INFO, TAG, "Build ActionSet Instance.");
*set = (OCActionSet*) OICMalloc(sizeof(OCActionSet));
VARIFY_POINTER_NULL(*set, result, exit)
if (strcmp(key, "uri") == 0)
{
- OC_LOG(INFO, TAG, PCF("Build OCAction Instance."));
+ OC_LOG(INFO, TAG, "Build OCAction Instance.");
if(action)
{
{
if ((key != NULL) && (value != NULL))
{
- OC_LOG(INFO, TAG, PCF("Build OCCapability Instance."));
+ OC_LOG(INFO, TAG, "Build OCCapability Instance.");
capa = (OCCapability*) OICMalloc(sizeof(OCCapability));
VARIFY_POINTER_NULL(capa, result, exit)
OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc)
{
+ // Can't use the macros here as they are hardcoded to 'exit' and will
+ // result in dereferencing a null pointer.
+ if (!actionset || !desc)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
char temp[1024] = { 0 };
- int remaining = 1023;
+ size_t remaining = sizeof(temp) - 1;
OCStackResult res = OC_STACK_ERROR;
OCAction *action = actionset->head;
while (action != NULL)
{
+ if (remaining < (strlen("uri=") + strlen(action->resourceUri) + 1))
+ {
+ res = OC_STACK_ERROR;
+ goto exit;
+ }
strcat(temp, "uri=");
remaining -= strlen("uri=");
strcat(temp, action->resourceUri);
OCCapability *capas = action->head;
while (capas != NULL)
{
+ if (remaining < (strlen(capas->capability)
+ + 1 + strlen(capas->status)))
+ {
+ res = OC_STACK_ERROR;
+ goto exit;
+ }
+
strcat(temp, capas->capability);
remaining -= strlen(capas->capability);
strcat(temp, "=");
remaining--;
strcat(temp, capas->status);
- remaining -= strlen(capas->capability);
+ remaining -= strlen(capas->status);
capas = capas->next;
if (capas != NULL)
{
+ if (remaining < 1)
+ {
+ res = OC_STACK_ERROR;
+ goto exit;
+ }
strcat(temp, "|");
}
}
action = action->next;
if (action != NULL)
{
+ if (remaining < strlen(ACTION_DELIMITER))
+ {
+ res = OC_STACK_ERROR;
+ goto exit;
+ }
strcat(temp, ACTION_DELIMITER);
remaining--;
}
}
- *desc = (char *) OICMalloc(1024 - remaining);
+ *desc = OICStrdup(temp);
VARIFY_POINTER_NULL(*desc, res, exit);
- strcpy(*desc, temp);
return OC_STACK_OK;
exit:
OCFREE(*desc);
return res;
-
}
OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
{
(void)context;
(void)clientResponse;
- OC_LOG(INFO, TAG, PCF("Entering BuildActionJSON"));
+ OC_LOG(INFO, TAG, "Entering ActionSetCB");
ClientRequestInfo *info = GetClientRequestInfo(clientRequstList, handle);
if (info)
{
- int idx;
+ OCEntityHandlerResponse response = { 0 };
- unsigned char *responseJson = NULL;
- // TODO: Figure out what this does, change implementation
- //responseJson = (unsigned char *) OICMalloc(
- // (unsigned int) (strlen((char *) clientResponse->resJSONPayload)
- // + 1));
+ response.ehResult = OC_EH_OK;
- if( responseJson == NULL )
+ if(NULL == clientResponse->payload)
+ {
+ OC_LOG(ERROR, TAG, "Error sending response");
return OC_STACK_DELETE_TRANSACTION;
+ }
- // We need the body of response.
- // Copy the body from the response
- // TODO: Taken out
- //strcpy((char *) responseJson,
- // ((char *) clientResponse->resJSONPayload + OC_JSON_PREFIX_LEN));
- //idx = strlen((char *) responseJson) - OC_JSON_SUFFIX_LEN;
- // And insert NULL at the end of body.
- (responseJson[idx]) = 0;
-
- OCEntityHandlerResponse response = { 0 };
- response.ehResult = OC_EH_OK;
- // TODO: Removing payload size, waht goes here?
- // response.payload = (char*)responseJson;
- //response.payloadSize = (unsigned int) strlen((char *) responseJson) + 1;
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = info->ehRequest;
+ response.resourceHandle = info->collResource;
+ response.payload = clientResponse->payload;
+ response.numSendVendorSpecificHeaderOptions = 0;
+ memset(response.sendVendorSpecificHeaderOptions, 0,
+ sizeof response.sendVendorSpecificHeaderOptions);
+ memset(response.resourceUri, 0, sizeof response.resourceUri);
+ // Indicate that response is NOT in a persistent buffer
response.persistentBufferFlag = 0;
- response.requestHandle = (OCRequestHandle) info->ehRequest;
- response.resourceHandle = (OCResourceHandle) info->collResource;
- OCDoResponse(&response);
+ // Send the response
+ if (OCDoResponse(&response) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "Error sending response");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
RemoveClientRequestInfo(&clientRequstList, info);
OCFREE(info)
- OCFREE(responseJson)
}
return OC_STACK_KEEP_TRANSACTION;
char *jsonStr;
uint16_t jsonLen;
- OC_LOG(INFO, TAG, PCF("Entering BuildActionJSON"));
+ OC_LOG(INFO, TAG, "Entering BuildActionJSON");
json = cJSON_CreateObject();
cJSON_AddItemToObject(json, "rep", body = cJSON_CreateObject());
return ret;
}
+OCPayload* BuildActionCBOR(OCAction* action)
+{
+ OCRepPayload* payload = OCRepPayloadCreate();
+
+ if (!payload)
+ {
+ OC_LOG(INFO, TAG, "Failed to create put payload object");
+ return NULL;
+ }
+
+ OCCapability* pointerCapa = action->head;
+ while (pointerCapa)
+ {
+ OCRepPayloadSetPropString(payload, pointerCapa->capability, pointerCapa->status);
+ pointerCapa = pointerCapa->next;
+ }
+
+ return (OCPayload*) payload;
+}
+
unsigned int GetNumOfTargetResource(OCAction *actionset)
{
int numOfResource = 0;
return numOfResource;
}
+OCStackResult SendAction(OCDoHandle *handle, OCServerRequest* requestHandle, const char *targetUri,
+ OCPayload *payload)
+{
-#define DEFAULT_CONTEXT_VALUE 0x99
+ OCCallbackData cbData;
+ cbData.cb = &ActionSetCB;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
+ cbData.cd = NULL;
-OCStackResult SendAction(OCDoHandle *handle, const char *targetUri,
- const unsigned char *action)
-{
- (void)handle;
- (void)targetUri;
- (void)action;
- // TODO: disabled since this is no longer compatible
- return OC_STACK_NOTIMPL;
+ return OCDoResource(handle, OC_REST_PUT, targetUri, &requestHandle->devAddr,
+ payload, CT_ADAPTER_IP, OC_NA_QOS, &cbData, NULL, 0);
}
OCStackResult DoAction(OCResource* resource, OCActionSet* actionset,
OCServerRequest* requestHandle)
{
OCStackResult result = OC_STACK_ERROR;
+
+ if( NULL == actionset->head)
+ {
+ return result;
+ }
+
OCAction *pointerAction = actionset->head;
while (pointerAction != NULL)
{
- unsigned char actionDesc[MAX_RESPONSE_LENGTH] = { 0 };
- unsigned char* actionDescPtr = actionDesc;
- uint16_t remaining = MAX_RESPONSE_LENGTH;
+ OCPayload* payload;
+ payload = BuildActionCBOR(pointerAction);
- strncpy((char *) actionDescPtr, (const char *) OC_JSON_PREFIX,
- strlen((const char *) OC_JSON_PREFIX) + 1);
- BuildActionJSON(pointerAction, actionDescPtr, &remaining);
- strncat((char *) actionDescPtr, (const char *) OC_JSON_SUFFIX,
- strlen((const char *) OC_JSON_SUFFIX));
+ if(payload == NULL)
+ {
+ return result;
+ }
ClientRequestInfo *info = (ClientRequestInfo *) OICMalloc(
sizeof(ClientRequestInfo));
info->collResource = resource;
info->ehRequest = requestHandle;
- result = SendAction(&info->required, pointerAction->resourceUri,
- actionDescPtr);
+ result = SendAction(&info->required, info->ehRequest, pointerAction->resourceUri,
+ payload);
+
if (result != OC_STACK_OK)
{
OICFree(info);
void DoScheduledGroupAction()
{
- OC_LOG(INFO, TAG, PCF("DoScheduledGroupAction Entering..."));
+ OC_LOG(INFO, TAG, "DoScheduledGroupAction Entering...");
ScheduledResourceInfo* info = GetScheduledResource(scheduleResourceList);
if (info == NULL)
{
- OC_LOG(INFO, TAG, PCF("Target resource is NULL"));
+ OC_LOG(INFO, TAG, "Target resource is NULL");
goto exit;
}
else if (info->resource == NULL)
{
- OC_LOG(INFO, TAG, PCF("Target resource is NULL"));
+ OC_LOG(INFO, TAG, "Target resource is NULL");
goto exit;
}
else if (info->actionset == NULL)
{
- OC_LOG(INFO, TAG, PCF("Target ActionSet is NULL"));
+ OC_LOG(INFO, TAG, "Target ActionSet is NULL");
goto exit;
}
else if (info->ehRequest == NULL)
{
- OC_LOG(INFO, TAG, PCF("Target ActionSet is NULL"));
+ OC_LOG(INFO, TAG, "Target ActionSet is NULL");
goto exit;
}
#ifndef WITH_ARDUINO
if (schedule)
{
- OC_LOG(INFO, TAG, PCF("Building New Call Info."));
+ OC_LOG(INFO, TAG, "Building New Call Info.");
memset(schedule, 0, sizeof(ScheduledResourceInfo));
if (info->actionset->timesteps > 0)
&schedule->timer_id,
&DoScheduledGroupAction);
- OC_LOG(INFO, TAG, PCF("Reregisteration."));
+ OC_LOG(INFO, TAG, "Reregisteration.");
#ifndef WITH_ARDUINO
pthread_mutex_unlock(&lock);
#endif
return;
}
-OCStackResult BuildCollectionGroupActionJSONResponse(
+OCStackResult BuildCollectionGroupActionCBORResponse(
OCMethod method/*OCEntityHandlerFlag flag*/, OCResource *resource,
OCEntityHandlerRequest *ehRequest)
{
OCStackResult stackRet = OC_STACK_ERROR;
- OC_LOG(INFO, TAG, PCF("Group Action is requested."));
- // if (stackRet == OC_STACK_OK)
- {
- char *doWhat = NULL;
- char *details = NULL;
-
- size_t bufferLength = 0;
- unsigned char buffer[MAX_RESPONSE_LENGTH] = { 0 };
+ OC_LOG(INFO, TAG, "Group Action is requested.");
- OCResource * collResource = (OCResource *) ehRequest->resource;
+ char *doWhat = NULL;
+ char *details = NULL;
- char *jsonResponse;
+ stackRet = ExtractKeyValueFromRequest(ehRequest, &doWhat, &details);
- stackRet = OC_STACK_NOTIMPL;
- // TODO: Fix?
- //stackRet = ExtractKeyValueFromRequest((char *) ehRequest->reqJSONPayload,
- // &doWhat, &details);
-
- if(stackRet != OC_STACK_OK)
- {
- OC_LOG_V(ERROR, TAG, "ExtractKeyValueFromRequest failed: %d", stackRet);
- return stackRet;
- }
+ if(stackRet != OC_STACK_OK)
+ {
+ OC_LOG_V(ERROR, TAG, "ExtractKeyValueFromRequest failed: %d", stackRet);
+ return stackRet;
+ }
- stackRet = OC_STACK_ERROR;
+ stackRet = OC_STACK_ERROR;
- cJSON *json;
- cJSON *format;
+ if (method == OC_REST_PUT)
+ {
+ OC_LOG(INFO, TAG, "Group Action[PUT].");
- if (method == OC_REST_PUT)
+ if (strcmp(doWhat, ACTIONSET) == 0)
{
- json = cJSON_CreateObject();
- cJSON_AddStringToObject(json, "href", resource->uri);
- cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
-
- OC_LOG(INFO, TAG, PCF("Group Action[PUT]."));
+ OCActionSet *actionSet = NULL;
+ stackRet = BuildActionSetFromString(&actionSet, details);
- if (strcmp(doWhat, ACTIONSET) == 0)
+ if(stackRet == OC_STACK_OK)
{
- OCActionSet *actionSet = NULL;
- stackRet = BuildActionSetFromString(&actionSet, details);
-
- if(stackRet == OC_STACK_OK)
+ if (actionSet != NULL)
{
- if (actionSet != NULL)
+ stackRet = AddActionSet(&resource->actionsetHead,
+ actionSet);
+ if (stackRet == OC_STACK_ERROR)
{
- stackRet = AddActionSet(&resource->actionsetHead,
- actionSet);
- if (stackRet == OC_STACK_ERROR)
+ if(actionSet != NULL)
{
- if(actionSet != NULL)
- {
- DeleteActionSet( &actionSet );
- }
- OC_LOG(INFO, TAG, PCF("Duplicated ActionSet "));
+ DeleteActionSet( &actionSet );
}
+ OC_LOG(INFO, TAG, "Duplicated ActionSet ");
}
}
else
{
stackRet = OC_STACK_ERROR;
+ goto exit;
}
+ }
+ else
+ {
+ stackRet = OC_STACK_ERROR;
+ }
+ }
+ else if (strcmp(doWhat, DELETE_ACTIONSET) == 0)
+ {
+ if (FindAndDeleteActionSet(&resource, details) == OC_STACK_OK)
+ {
+ stackRet = OC_STACK_OK;
}
- else if (strcmp(doWhat, DELETE_ACTIONSET) == 0)
+ else
{
- if (FindAndDeleteActionSet(&resource, details) == OC_STACK_OK)
- {
- stackRet = OC_STACK_OK;
- }
- else
- {
- stackRet = OC_STACK_ERROR;
- }
+ stackRet = OC_STACK_ERROR;
}
+ }
- jsonResponse = cJSON_Print(json);
- cJSON_Delete(json);
+ OCRepPayload* payload = OCRepPayloadCreate();
- OICStrcat((char*)buffer, sizeof(buffer), jsonResponse);
+ if(!payload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to allocate Payload");
+ stackRet = OC_STACK_ERROR;
+ }
+ else
+ {
+ OCEntityHandlerResponse response = { 0 };
- bufferLength = strlen((const char *) buffer);
- if (bufferLength > 0)
+ if(stackRet == OC_STACK_OK)
+ response.ehResult = OC_EH_OK;
+ else
+ response.ehResult = OC_EH_ERROR;
+
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = ehRequest->requestHandle;
+ response.resourceHandle = ehRequest->resource;
+ response.payload = (OCPayload*) payload;
+ response.numSendVendorSpecificHeaderOptions = 0;
+ memset(response.sendVendorSpecificHeaderOptions, 0,
+ sizeof response.sendVendorSpecificHeaderOptions);
+ memset(response.resourceUri, 0, sizeof response. resourceUri);
+ // Indicate that response is NOT in a persistent buffer
+ response.persistentBufferFlag = 0;
+ response.ehResult = (stackRet == OC_STACK_OK)?OC_EH_OK:OC_EH_ERROR;
+
+ // Send the response
+ if (OCDoResponse(&response) != OC_STACK_OK)
{
- OCEntityHandlerResponse response = { 0 };
- if(stackRet == OC_STACK_OK)
- response.ehResult = OC_EH_OK;
- else
- response.ehResult = OC_EH_ERROR;
- // TODO: Fix
- //response.payload = (char*)buffer;
- //response.payloadSize = bufferLength + 1;
- response.persistentBufferFlag = 0;
- response.requestHandle =
- (OCRequestHandle) ehRequest->requestHandle;
- response.resourceHandle = (OCResourceHandle) collResource;
- stackRet = OCDoResponse(&response);
+ OC_LOG(ERROR, TAG, "Error sending response");
+ stackRet = OC_STACK_ERROR;
}
}
+ }
+ else if (method == OC_REST_POST)
+ {
+ OCActionSet *actionset = NULL;
- if (method == OC_REST_POST)
+ OCRepPayload* payload = OCRepPayloadCreate();
+ OCRepPayloadSetUri(payload, resource->uri);
+
+ if ((strcmp(doWhat, DO_ACTION) == 0)
+ || (strcmp(doWhat, "DoScheduledAction") == 0))
{
- OCActionSet *actionset = NULL;
+ char *pActionsetName = NULL;
+ long int delay = -1;
- json = cJSON_CreateObject();
- cJSON_AddStringToObject(json, "href", resource->uri);
+ if (strcmp(doWhat, "DoScheduledAction") == 0)
+ {
+ stackRet = ExtractActionSetNameAndDelaytime(details,
+ &pActionsetName, &delay);
- if ((strcmp(doWhat, DO_ACTION) == 0)
- || (strcmp(doWhat, "DoScheduledAction") == 0))
+ OCFREE(details)
+ details = pActionsetName;
+ }
+ else
{
- char *pActionsetName = NULL;
- long int delay = -1;
+ stackRet = OC_STACK_OK;
+ }
- if (strcmp(doWhat, "DoScheduledAction") == 0)
+ if (stackRet == OC_STACK_OK)
+ {
+ if (GetActionSet(details, resource->actionsetHead,
+ &actionset) != OC_STACK_OK)
{
- stackRet = ExtractActionSetNameAndDelaytime(details,
- &pActionsetName, &delay);
-
- OCFREE(details)
- details = pActionsetName;
+ OC_LOG(INFO, TAG, "ERROR");
+ stackRet = OC_STACK_ERROR;
}
- else
+
+ if (actionset == NULL)
{
- stackRet = OC_STACK_OK;
+ OC_LOG(INFO, TAG, "Cannot Find ActionSet");
+ stackRet = OC_STACK_ERROR;
}
-
- if (stackRet == OC_STACK_OK)
+ else
{
- if (GetActionSet(details, resource->actionsetHead,
- &actionset) != OC_STACK_OK)
- {
- OC_LOG(INFO, TAG, PCF("ERROR"));
- stackRet = OC_STACK_ERROR;
- }
-
- if (actionset == NULL)
+ OC_LOG(INFO, TAG, "Group Action[POST].");
+ if (actionset->type == NONE)
{
- OC_LOG(INFO, TAG, PCF("Cannot Find ActionSet"));
- stackRet = OC_STACK_ERROR;
+ OC_LOG_V(INFO, TAG, "Execute ActionSet : %s",
+ actionset->actionsetName);
+ unsigned int num = GetNumOfTargetResource(
+ actionset->head);
+
+ ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler =
+ HandleAggregateResponse;
+ ((OCServerRequest *) ehRequest->requestHandle)->numResponses =
+ num + 1;
+
+ DoAction(resource, actionset,
+ (OCServerRequest*) ehRequest->requestHandle);
+ stackRet = OC_STACK_OK;
}
else
{
- OC_LOG(INFO, TAG, PCF("Group Action[POST]."));
- if (actionset->type == NONE)
- {
- OC_LOG_V(INFO, TAG, "Execute ActionSet : %s",
- actionset->actionsetName);
- unsigned int num = GetNumOfTargetResource(
- actionset->head);
-
- ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler =
- HandleAggregateResponse;
- ((OCServerRequest *) ehRequest->requestHandle)->numResponses =
- num + 1;
-
- DoAction(resource, actionset,
- (OCServerRequest*) ehRequest->requestHandle);
- stackRet = OC_STACK_OK;
- }
- else
- {
- OC_LOG_V(INFO, TAG, "Execute Scheduled ActionSet : %s",
- actionset->actionsetName);
+ OC_LOG_V(INFO, TAG, "Execute Scheduled ActionSet : %s",
+ actionset->actionsetName);
+
+ delay =
+ (delay == -1 ? actionset->timesteps : delay);
- delay =
- (delay == -1 ? actionset->timesteps : delay);
+ ScheduledResourceInfo *schedule;
+ schedule = (ScheduledResourceInfo *) OICMalloc(
+ sizeof(ScheduledResourceInfo));
- ScheduledResourceInfo *schedule;
- schedule = (ScheduledResourceInfo *) OICMalloc(
+ if (schedule)
+ {
+ OC_LOG(INFO, TAG, "Building New Call Info.");
+ memset(schedule, 0,
sizeof(ScheduledResourceInfo));
- if (schedule)
+ schedule->resource = resource;
+ schedule->actionset = actionset;
+ schedule->ehRequest =
+ (OCServerRequest*) ehRequest->requestHandle;
+
+ if (delay > 0)
+ {
+ OC_LOG_V(INFO, TAG, "delay_time is %lf seconds.",
+ actionset->timesteps);
+
+ schedule->time = registerTimer(delay,
+ &schedule->timer_id,
+ &DoScheduledGroupAction);
+
+ AddScheduledResource(&scheduleResourceList,
+ schedule);
+ stackRet = OC_STACK_OK;
+ }
+ else
{
- OC_LOG(INFO, TAG, PCF("Building New Call Info."));
- memset(schedule, 0,
- sizeof(ScheduledResourceInfo));
-
- schedule->resource = resource;
- schedule->actionset = actionset;
- schedule->ehRequest =
- (OCServerRequest*) ehRequest->requestHandle;
-
- if (delay > 0)
- {
- OC_LOG_V(INFO, TAG, "delay_time is %lf seconds.",
- actionset->timesteps);
-
- schedule->time = registerTimer(delay,
- &schedule->timer_id,
- &DoScheduledGroupAction);
-
- AddScheduledResource(&scheduleResourceList,
- schedule);
- stackRet = OC_STACK_OK;
- }
- else
- {
- stackRet = OC_STACK_ERROR;
- }
+ stackRet = OC_STACK_ERROR;
}
}
}
}
}
- else if (strcmp(doWhat, "CancelAction") == 0)
- {
- ScheduledResourceInfo *info =
- GetScheduledResourceByActionSetName(scheduleResourceList, details);
+ }
+ else if (strcmp(doWhat, "CancelAction") == 0)
+ {
+ ScheduledResourceInfo *info =
+ GetScheduledResourceByActionSetName(scheduleResourceList, details);
- if(info != NULL)
- {
- unregisterTimer(info->timer_id);
+ if(info != NULL)
+ {
+ unregisterTimer(info->timer_id);
- RemoveScheduledResource(&scheduleResourceList, info);
- stackRet = OC_STACK_OK;
- }
- else
- {
- stackRet = OC_STACK_ERROR;
- }
+ RemoveScheduledResource(&scheduleResourceList, info);
+ stackRet = OC_STACK_OK;
}
+ else
+ {
+ stackRet = OC_STACK_ERROR;
+ }
+ }
- else if (strcmp(doWhat, GET_ACTIONSET) == 0)
+ else if (strcmp(doWhat, GET_ACTIONSET) == 0)
+ {
+ char *plainText = NULL;
+ OCActionSet *actionset = NULL;
+
+ GetActionSet(details, resource->actionsetHead, &actionset);
+ if (actionset != NULL)
{
- char *plainText = NULL;
- OCActionSet *actionset = NULL;
+ BuildStringFromActionSet(actionset, &plainText);
- cJSON_AddItemToObject(json, "rep", format =
- cJSON_CreateObject());
- GetActionSet(details, resource->actionsetHead, &actionset);
- if (actionset != NULL)
+ if (plainText != NULL)
{
- BuildStringFromActionSet(actionset, &plainText);
-
- if (plainText != NULL)
- {
- cJSON_AddStringToObject(format, ACTIONSET, plainText);
- }
- OICFree(plainText);
- stackRet = OC_STACK_OK;
+ OCRepPayloadSetPropString(payload, ACTIONSET, plainText);
}
+ OICFree(plainText);
+ stackRet = OC_STACK_OK;
}
+ }
-
- jsonResponse = cJSON_Print(json);
- cJSON_Delete(json);
-
- OICStrcat((char*)buffer, sizeof(buffer), jsonResponse);
-
- bufferLength = strlen((const char *) buffer);
- if (bufferLength > 0)
+ if(!payload)
+ {
+ OC_LOG(ERROR, TAG, "Failed to allocate Payload");
+ stackRet = OC_STACK_ERROR;
+ }
+ else
+ {
+ OCEntityHandlerResponse response = { 0 };
+ if(stackRet == OC_STACK_OK)
+ response.ehResult = OC_EH_OK;
+ else
+ response.ehResult = OC_EH_ERROR;
+
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = ehRequest->requestHandle;
+ response.resourceHandle = ehRequest->resource;
+ response.payload = (OCPayload*) payload;
+ response.numSendVendorSpecificHeaderOptions = 0;
+ memset(response.sendVendorSpecificHeaderOptions, 0,
+ sizeof response.sendVendorSpecificHeaderOptions);
+ memset(response.resourceUri, 0, sizeof response.resourceUri);
+ // Indicate that response is NOT in a persistent buffer
+ response.persistentBufferFlag = 0;
+ response.ehResult = (stackRet == OC_STACK_OK)?OC_EH_OK:OC_EH_ERROR;
+
+ // Send the response
+ if (OCDoResponse(&response) != OC_STACK_OK)
{
- OCEntityHandlerResponse response = { 0 };
- if(stackRet == OC_STACK_OK)
- response.ehResult = OC_EH_OK;
- else
- response.ehResult = OC_EH_ERROR;
- // TODO: Implement
- //response.payload = (char *)buffer;
- //response.payloadSize = bufferLength + 1;
- response.persistentBufferFlag = 0;
- response.requestHandle =
- (OCRequestHandle) ehRequest->requestHandle;
- response.resourceHandle = (OCResourceHandle) collResource;
- stackRet = OCDoResponse(&response);
+ OC_LOG(ERROR, TAG, "Error sending response");
+ stackRet = OC_STACK_ERROR;
}
}
-
- OCFREE(doWhat)
- OCFREE(details)
}
+exit:
+
+ OCFREE(doWhat)
+ OCFREE(details)
+
return stackRet;
}
+
#include "ocstackinternal.h"
#include <string.h>
-#define PCF(str) ((PROGMEM const char *)(F(str)))
-
-PROGMEM const char TAG[] = "Arduino";
+#define TAG "Arduino"
static OCUri SERVICE_URI = "coap://127.0.0.1:5683/";
#if 0 // Turn off logger test stuff
void EXPECT_EQ(int a, int b) {
if (a == b) {
- OC_LOG(INFO, TAG, PCF("PASS"));
+ OC_LOG(INFO, TAG, ("PASS"));
} else {
- OC_LOG(ERROR, TAG, PCF("FAIL"));
+ OC_LOG(ERROR, TAG, ("FAIL"));
}
}
void EXPECT_STREQ(const char *a, const char *b) {
if (strcmp(a, b) == 0) {
- OC_LOG(INFO, TAG, PCF("PASS"));
+ OC_LOG(INFO, TAG, ("PASS"));
} else {
- OC_LOG(ERROR, TAG, PCF("FAIL"));
+ OC_LOG(ERROR, TAG, ("FAIL"));
}
}
//-----------------------------------------------------------------------------
#endif
extern "C" void asyncDoResourcesCallback(OCStackResult result, OCRepresentationHandle representation) {
- OC_LOG(INFO, TAG, PCF("Entering asyncDoResourcesCallback"));
+ OC_LOG(INFO, TAG, ("Entering asyncDoResourcesCallback"));
EXPECT_EQ(OC_STACK_OK, result);
OCResource *resource = (OCResource *)representation;
}
void test0() {
- OC_LOG(INFO, TAG, PCF("test0"));
+ OC_LOG(INFO, TAG, ("test0"));
EXPECT_EQ(OC_STACK_OK, OCInit(0, 5683, OC_SERVER));
}
void test1() {
- OC_LOG(INFO, TAG, PCF("test1"));
+ OC_LOG(INFO, TAG, ("test1"));
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 0, OC_SERVER));
}
void test2() {
- OC_LOG(INFO, TAG, PCF("test2"));
+ OC_LOG(INFO, TAG, ("test2"));
EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER));
}
void test3() {
- OC_LOG(INFO, TAG, PCF("test3"));
+ OC_LOG(INFO, TAG, ("test3"));
EXPECT_EQ(OC_STACK_ERROR, OCInit(0, 0, (OCMode)10));
}
void test4() {
- OC_LOG(INFO, TAG, PCF("test4"));
+ OC_LOG(INFO, TAG, ("test4"));
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER));
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER));
}
void test5() {
- OC_LOG(INFO, TAG, PCF("test5"));
+ OC_LOG(INFO, TAG, ("test5"));
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback), NULL, 0);
EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI));
}
void test6() {
- OC_LOG(INFO, TAG, PCF("test6"));
+ OC_LOG(INFO, TAG, ("test6"));
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
EXPECT_EQ(OC_STACK_OK, OCStop());
EXPECT_EQ(OC_STACK_ERROR, OCStop());
}
void test7() {
- OC_LOG(INFO, TAG, PCF("test7"));
+ OC_LOG(INFO, TAG, ("test7"));
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback), NULL, 0);
EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0));
static uint8_t ETHERNET_MAC[] = {0x90, 0xA2, 0xDA, 0x0F, 0x2B, 0x72 };
-#define TAG PCF("ocserver")
+#define TAG ("ocserver")
void ocInitialize () {
- OC_LOG(DEBUG, TAG, PCF("IP addr is:"));
+ OC_LOG(DEBUG, TAG, ("IP addr is:"));
OC_LOG_BUFFER(INFO, TAG, (uint8_t*)ipAddr, sizeof(ipAddr));
delay(2000);
OCInit (NULL, 0, OC_SERVER);
#include <ocstack.h>
#include <logger.h>
-#define TAG PCF("occlient")
+#define TAG ("occlient")
int gQuitFlag = 0;
#include <ocstack.h>
#include <logger.h>
-#define TAG PCF("ocserver")
+#define TAG ("ocserver")
int gQuitFlag = 0;
OCStackResult createLightResource();
//-----------------------------------------------------------------------------
static const char TAG[] = "TestHarness";
+char gDeviceUUID[] = "myDeviceUUID";
+char gManufacturerName[] = "myName";
+char gTooLongManufacturerName[] = "extremelylongmanufacturername";
+char gManufacturerUrl[] = "www.foooooooooooooooo.baaaaaaaaaaaaar";
+
std::chrono::seconds const SHORT_TEST_TIMEOUT = std::chrono::seconds(5);
//-----------------------------------------------------------------------------
// Callback functions
//-----------------------------------------------------------------------------
-extern "C" OCStackApplicationResult asyncDoResourcesCallback(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+extern "C" OCStackApplicationResult asyncDoResourcesCallback(void* ctx,
+ OCDoHandle /*handle*/, OCClientResponse * clientResponse)
{
OC_LOG(INFO, TAG, "Entering asyncDoResourcesCallback");
//-----------------------------------------------------------------------------
// Entity handler
//-----------------------------------------------------------------------------
-OCEntityHandlerResult entityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest,
- void* callbackParam)
+OCEntityHandlerResult entityHandler(OCEntityHandlerFlag /*flag*/,
+ OCEntityHandlerRequest * /*entityHandlerRequest*/,
+ void* /*callbackParam*/)
{
OC_LOG(INFO, TAG, "Entering entityHandler");
itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER));
- OCPlatformInfo info = {};
- info.platformID = (char *) "platform_id";
- info.manufacturerName = (char *) "manufac_name";
-
+ OCPlatformInfo info =
+ {
+ gDeviceUUID,
+ gManufacturerName,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
EXPECT_EQ(OC_STACK_OK, OCSetPlatformInfo(info));
EXPECT_EQ(OC_STACK_OK, OCStop());
}
itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER));
- OCPlatformInfo info = {};
- info.manufacturerName = (char *) "manufac_name";
+ OCPlatformInfo info =
+ {
+ 0,
+ gDeviceUUID,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSetPlatformInfo(info));
EXPECT_EQ(OC_STACK_OK, OCStop());
itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER));
- OCPlatformInfo info = {};
- info.platformID = (char *) "platform_id";
+ OCPlatformInfo info =
+ {
+ gDeviceUUID,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSetPlatformInfo(info));
EXPECT_EQ(OC_STACK_OK, OCStop());
itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER));
- OCPlatformInfo info = {};
- info.platformID = (char *) "platform_id";
+ OCPlatformInfo info =
+ {
+ gDeviceUUID,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
info.manufacturerName = (char *) "";
EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSetPlatformInfo(info));
itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER));
- OCPlatformInfo info = {};
- info.platformID = (char *) "platform_id";
- info.manufacturerName = (char *) "extremelylongmanufacturername";
+ OCPlatformInfo info =
+ {
+ gDeviceUUID,
+ gTooLongManufacturerName,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSetPlatformInfo(info));
EXPECT_EQ(OC_STACK_OK, OCStop());
{
itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER));
-
- OCPlatformInfo info = {};
- info.platformID = (char *) "platform_id";
- info.manufacturerName = (char *) "extremelylongmanufacturername";
- info.manufacturerUrl = (char *)"www.foooooooooooooooo.baaaaaaaaaaaaar";
+ OCPlatformInfo info =
+ {
+ gDeviceUUID,
+ gManufacturerName,
+ gManufacturerUrl,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ };
EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSetPlatformInfo(info));
EXPECT_EQ(OC_STACK_OK, OCStop());
}
-
TEST(StackDiscovery, DISABLED_DoResourceDeviceDiscovery)
{
itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
{
std::cout << "Got a response from get from the " << resourceName << std::endl;
std::cout << "Get ID is "<<getId<<" and resource URI is " << resource->uri() << std::endl;
+ std::cout << "Get eCode is "<< eCode << std::endl;
printHeaderOptions(headerOptions);
//Callback function to handle response for deleteResource call.
void deleteResponse(const std::string& resourceName, const HeaderOptions& headerOptions,
- const int eCode, OCResource::Ptr resource, int deleteId)
+ const int /*eCode*/, OCResource::Ptr resource, int deleteId)
{
std::cout << "Got a response from delete from the "<< resourceName << std::endl;
std::cout << "Delete ID is "<<deleteId<<" and resource URI is "<<resource->uri()<<std::endl;
}
// callback handler on PUT request
-void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onPut(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
{
if(eCode == SUCCESS_RESPONSE)
{
}
// Callback handler on GET request
-void onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onGet(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
{
if(eCode == SUCCESS_RESPONSE)
{
return ehResult;
}
-int main(int argc, char* argv[1])
+int main(int /*argc*/, char** /*argv[1]*/)
{
// Create PlatformConfig object
PlatformConfig cfg {
}
}
-void onGet(const HeaderOptions& opt, const OCRepresentation &rep, const int eCode)
+void onGet(const HeaderOptions& /*opt*/, const OCRepresentation &rep, const int /*eCode*/)
{
// printf("onGet\n");
cv.notify_one();
}
-void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onPut(const HeaderOptions& /*headerOptions*/,
+ const OCRepresentation& /*rep*/, const int /*eCode*/)
{
printf("\nonPut\n");
}
-void onPost(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onPost(const HeaderOptions& /*headerOptions*/,
+ const OCRepresentation& rep, const int /*eCode*/)
{
printf("\nonPost\n");
return isReady;
}
-int main(int argc, char* argv[])
+int main(int /*argc*/, char** /*argv[]*/)
{
ostringstream requestURI;
requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=a.collection";
}
-int main(int argc, char* argv[])
+int main(int /*argc*/, char** /*argv[]*/)
{
// Create PlatformConfig object
PlatformConfig cfg {
"doxm": {
"oxm": [0],
"oxmsel": 0,
+ "sct": 1,
"owned": true,
"deviceid": "MjIyMjIyMjIyMjIyMjIyMg==",
"ownr": "MjIyMjIyMjIyMjIyMjIyMg=="
"doxm": {
"oxm": [0],
"oxmsel": 0,
+ "sct": 1,
"owned": true,
"deviceid": "MTExMTExMTExMTExMTExMQ==",
"ownr": "MjIyMjIyMjIyMjIyMjIyMg=="
// Create the instance of the resource class (in this case instance of class 'LightResource').
LightResource myLightResource;
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> /*request*/)
{
cout << "\tIn Server CPP entity handler:\n";
return OC_EH_OK;
}
// callback handler on GET request
-void onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onGet(const HeaderOptions& /*headerOptions*/,
+ const OCRepresentation& rep, const int eCode)
{
if(eCode == SUCCESS_RESPONSE)
{
}
}
-void onGet1(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onGet1(const HeaderOptions& /*headerOptions*/,
+ const OCRepresentation& rep, const int eCode)
{
if(eCode == SUCCESS_RESPONSE)
{
}
// callback handler on PUT request
-void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onPut(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
{
if(eCode == SUCCESS_RESPONSE)
{
return ++oc;
}
-void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep,
+void onObserve(const HeaderOptions /*headerOptions*/, const OCRepresentation& rep,
const int& eCode, const int& sequenceNumber)
{
try
std::cout << "\tpower: " << mylight.m_power << std::endl;
std::cout << "\tname: " << mylight.m_name << std::endl;
- if(observe_count() > 10)
+ if(observe_count() == 11)
{
std::cout<<"Cancelling Observe..."<<std::endl;
OCStackResult result = curResource->cancelObserve();
}
-void onPost2(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onPost2(const HeaderOptions& /*headerOptions*/,
+ const OCRepresentation& rep, const int eCode)
{
try
{
}
-void onPost(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onPost(const HeaderOptions& /*headerOptions*/,
+ const OCRepresentation& rep, const int eCode)
{
try
{
}
// callback handler on PUT request
-void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onPut(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
{
try
{
}
// Callback handler on GET request
-void onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onGet(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
{
try
{
}
}
-static FILE* client_open(const char *path, const char *mode)
+static FILE* client_open(const char* /*path*/, const char *mode)
{
return fopen("./oic_svr_db_client.json", mode);
}
return ++oc;
}
-void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep,
+void onObserve(const HeaderOptions /*headerOptions*/, const OCRepresentation& rep,
const int& eCode, const int& sequenceNumber)
{
if(eCode == SUCCESS_RESPONSE)
std::cout << "\tpower: " << mylight.m_power << std::endl;
std::cout << "\tname: " << mylight.m_name << std::endl;
- if(observe_count() > 10)
+ if(observe_count() == 11)
{
std::cout<<"Cancelling Observe..."<<std::endl;
OCStackResult result = curResource->cancelObserve(OC::QualityOfService::HighQos);
}
}
-void onPost2(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onPost2(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
{
if(eCode == SUCCESS_RESPONSE)
{
}
}
-void onPost(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onPost(const HeaderOptions& /*headerOptions*/,
+ const OCRepresentation& rep, const int eCode)
{
if(eCode == SUCCESS_RESPONSE)
{
}
// callback handler on PUT request
-void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onPut(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
{
if(eCode == SUCCESS_RESPONSE)
{
}
// Callback handler on GET request
-void onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+void onGet(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)
{
if(eCode == SUCCESS_RESPONSE)
{
class ClientWorker
{
private:
- void putResourceInfo(const HeaderOptions& headerOptions,
- const OCRepresentation rep, const OCRepresentation rep2, const int eCode)
+ void putResourceInfo(const HeaderOptions& /*headerOptions*/,
+ const OCRepresentation rep, const OCRepresentation /*rep2*/, const int eCode)
{
std::cout << "In PutResourceInfo" << std::endl;
}
}
- void getResourceInfo(const HeaderOptions& headerOptions, const OCRepresentation rep,
+ void getResourceInfo(const HeaderOptions& /*headerOptions*/, const OCRepresentation rep,
const int eCode)
{
std::cout << "In getResourceInfo" << std::endl;
std::cout << " 4 - Non-secure resource, GET slow response, notify all observers\n";
}
-static FILE* client_open(const char *path, const char *mode)
+static FILE* client_open(const char* /*path*/, const char *mode)
{
return fopen("./oic_svr_db_server.json", mode);
}
public:
/// Constructor
- LightResource(PlatformConfig& cfg)
+ LightResource(PlatformConfig& /*cfg*/)
:m_name("John's light"), m_state(false), m_power(0), m_lightUri("/a/light") {
// Initialize representation
m_lightRep.setUri(m_lightUri);
}
};
-void putResourceInfo(const HeaderOptions& headerOptions,
- const OCRepresentation rep, const OCRepresentation rep2, const int eCode)
+void putResourceInfo(const HeaderOptions& /*headerOptions*/,
+ const OCRepresentation rep, const OCRepresentation /*rep2*/, const int eCode)
{
bool m_isFoo = false;
int m_barCount = 0;
}
}
-void getResourceInfo(std::shared_ptr<OCResource> resource, const HeaderOptions& headerOptions,
+void getResourceInfo(std::shared_ptr<OCResource> resource, const HeaderOptions& /*headerOptions*/,
const OCRepresentation rep,
const int eCode)
{
cv.wait(lock);
}
-int main(int argc, char* argv[])
+int main(int /*argc*/, char** /*argv[]*/)
{
requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.foo";
{
Server,
Client,
- Both
+ Both,
+ Gateway /**< Client server mode along with routing capabilities.*/
};
/**
namespace OC
{
/**
- * @brief: This namespace contains the main entrance/functionality of the product.
+ * This namespace contains the main entrance/functionality of the product.
* It may be used with OC::OCPlatform::functionName. To set a custom configuration,
* the implementer must make a call to OCPlatform::Configure before the first usage
* of a function in this namespace.
{
/**
* API for overwriting the default configuration of the OCPlatform object.
- * Note: Any calls made to this AFTER the first call to OCPlatform::Instance
+ * @note Any calls made to this AFTER the first call to OCPlatform::Instance
* will have no affect
*/
void Configure(const PlatformConfig& config);
* @param OCResourceHandle resource handle of the resource
* @param QualityOfService the quality of communication
*
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: This API is for server side only.
- * NOTE: OCResourceHandle is defined in ocstack.h.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK if success.
+ * @note This API is for server side only.
+ * @note OCResourceHandle is defined in ocstack.h
+ * @note OCStackResult is defined in ocstack.h.
+ * @see notifyAllObservers(OCResourceHandle)
+ * @see notifyAllObservers(OCResourceHandle, QualityOfService)
*/
OCStackResult notifyAllObservers(OCResourceHandle resourceHandle);
OCStackResult notifyAllObservers(OCResourceHandle resourceHandle, QualityOfService QoS);
* resource change.
* @param QualityOfService the quality of communication
*
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- *
- * NOTE: This API is for server side only.
- * NOTE: OCResourceHandle is defined in ocstack.h.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK if success.
+ * @note This API is for server side only.
+ * @note OCResourceHandle is defined in ocstack.h.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult notifyListOfObservers(
OCResourceHandle resourceHandle,
/**
* API for Service and Resource Discovery.
- * NOTE: This API applies to client side only.
+ * @note This API applies to client side only.
*
- * @param host - Host IP Address of a service to direct resource discovery query. If null or
+ * @param host Host IP Address of a service to direct resource discovery query. If null or
* empty, performs multicast resource discovery query
- * @param resourceURI - name of the resource. If null or empty, performs search for all
+ * @param resourceURI name of the resource. If null or empty, performs search for all
* resource names
- * @param connectivityType - @ref OCConnectivityType type of connectivity indicating the
+ * @param connectivityType ::OCConnectivityType type of connectivity indicating the
* interface. Example: OC_WIFI, OC_ETHERNET, OC_ALL
- * @param handler - Handles callbacks, success states and failure states.
+ * @param resourceHandler Handles callbacks, success states and failure states.
*
* Four modes of discovery defined as follows:
* (NULL/Empty, NULL/Empty) - Performs ALL service discovery AND ALL resource
* from a particular service.
* @param QualityOfService the quality of communication
*
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: First parameter 'host' currently represents an IP address. This will change in
+ * @return Returns ::OC_STACK_OK if success.
+ * @note First parameter 'host' currently represents an IP address. This will change in
* future and will refer to endpoint interface so that we can refer to other transports such
* as BTH etc.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult findResource(const std::string& host, const std::string& resourceURI,
OCConnectivityType connectivityType, FindCallback resourceHandler);
* API for Device Discovery
*
*
- * @param host - Host IP Address. If null or empty, Multicast is performed.
- * @param deviceURI - Uri containing address to the virtual device in C Stack
+ * @param host Host IP Address. If null or empty, Multicast is performed.
+ * @param deviceURI Uri containing address to the virtual device in C Stack
("/oic/d")
- * @param connectivityType - @ref OCConnectivityType type of connectivity indicating the
+ * @param connectivityType ::OCConnectivityType type of connectivity indicating the
* interface. Example: OC_WIFI, OC_ETHERNET, OC_ALL
- * @param deviceInfoHandler - device discovery callback
+ * @param deviceInfoHandler device discovery callback
* @param QoS the quality of communication
*
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult getDeviceInfo(const std::string& host, const std::string& deviceURI,
OCConnectivityType connectivityType, FindDeviceCallback deviceInfoHandler);
* API for Platform Discovery
*
*
- * @param host - Host IP Address. If null or empty, Multicast is performed.
- * @param platformURI - Uri containing address to the virtual platform in C Stack
+ * @param host Host IP Address. If null or empty, Multicast is performed.
+ * @param platformURI Uri containing address to the virtual platform in C Stack
("/oic/p")
- * @param connectivityType - @ref OCConnectivityType type of connectivity indicating the
+ * @param connectivityType ::OCConnectivityType type of connectivity indicating the
* interface. Example: OC_WIFI, OC_ETHERNET, OC_ALL
- * @param platformInfoHandler - platform discovery callback
+ * @param platformInfoHandler platform discovery callback
* @param QoS the quality of communication
*
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult getPlatformInfo(const std::string& host, const std::string& platformURI,
OCConnectivityType connectivityType, FindPlatformCallback platformInfoHandler);
/**
* This API registers a resource with the server
- * NOTE: This API applies to server side only.
- *
- * @param resourceHandle - Upon successful registration, resourceHandle will be filled
- * @param resourceURI - The URI of the resource. Example: "a/light". See NOTE below
- * @param resourceTypeName - The resource type. Example: "light"
- * @param resourceInterface - The resource interface (whether it is collection etc).
- * @param entityHandler - entity handler callback.
- * @param resourceProperty - indicates the property of the resource. Defined in ocstack.h.
+ * @note This API applies to server side only.
+ *
+ * @param resourceHandle Upon successful registration, resourceHandle will be filled
+ * @param resourceURI The URI of the resource. Example: "a/light". See NOTE below
+ * @param resourceTypeName The resource type. Example: "light"
+ * @param resourceInterface The resource interface (whether it is collection etc).
+ * @param entityHandler entity handler callback.
+ * @param resourceProperty indicates the property of the resource. Defined in ocstack.h.
* setting resourceProperty as OC_DISCOVERABLE will allow Discovery of this resource
* setting resourceProperty as OC_OBSERVABLE will allow observation
* settings resourceProperty as OC_DISCOVERABLE | OC_OBSERVABLE will allow both discovery and
* observation
*
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: "a/light" is a relative URI.
+ * @return Returns ::OC_STACK_OK if success.
+ * @note "a/light" is a relative URI.
* Above relative URI will be prepended (by core) with a host IP + namespace "oic"
* Therefore, fully qualified URI format would be //HostIP-Address/namespace/relativeURI"
* Example, a relative URI: 'a/light' will result in a fully qualified URI:
* qualified URI OR
* first parameter can take fully qualified URI and core will take that as is for further
* operations
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult registerResource(OCResourceHandle& resourceHandle,
std::string& resourceURI,
/**
* This API registers a resource with the server
- * NOTE: This API applies to server & client side.
+ * @note This API applies to server & client side.
- * @param resourceHandle - Upon successful registration, resourceHandle will be filled
- * @param OCResource - The instance of OCResource that all data filled.
+ * @param resourceHandle Upon successful registration, resourceHandle will be filled
+ * @param OCResource The instance of OCResource that all data filled.
*
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult registerResource(OCResourceHandle& resourceHandle,
const std::shared_ptr< OCResource > resource);
/**
* Register Device Info
*
- * @param deviceInfo - structure containing all the device specific information
- *
- * @return
- * OC_STACK_OK - no errors
- * OC_STACK_ERROR - stack process error
+ * @param deviceInfo structure containing all the device specific information
+ * @return Returns ::OC_STACK_OK if no errors and ::OC_STACK_ERROR in case of stack process error
*/
OCStackResult registerDeviceInfo(const OCDeviceInfo deviceInfo);
/**
* Register Platform Info
*
- * @param platformInfo - structure containing all the platform specific information
- *
- * @return
- * OC_STACK_OK - no errors
- * OC_STACK_ERROR - stack process error
+ * @param platformInfo structure containing all the platform specific information
+ * @return Returns ::OC_STACK_OK if no errors and ::OC_STACK_ERROR in case of stack process error
*/
OCStackResult registerPlatformInfo(const OCPlatformInfo platformInfo);
/**
* Set default device entity handler
*
- * @param entityHandler - entity handler to handle requests for
- * any undefined resources or default actions.
- * if NULL is passed it removes the device default entity handler.
- *
- * @return
- * OC_STACK_OK - no errors
- * OC_STACK_ERROR - stack process error
+ * @param entityHandler entity handler to handle requests for
+ * any undefined resources or default actions.
+ * if NULL is passed it removes the device default entity handler.
+ * @return Returns ::OC_STACK_OK if no errors and ::OC_STACK_ERROR in case of stack process error
*/
OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler);
/**
* This API unregisters a resource with the server
- * NOTE: This API applies to server side only.
+ * @note This API applies to server side only.
*
- * @param resourceHandle - This is the resource handle which we which to unregister from the
+ * @param resourceHandle This is the resource handle which we need to unregister from the
* server
*
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult unregisterResource(const OCResourceHandle& resourceHandle);
/**
* Add a resource to a collection resource.
*
- * @param collectionHandle - handle to the collection resource
- * @param resourceHandle - handle to resource to be added to the collection resource
- *
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.<br>
- * NOTE: OCStackResult is defined in ocstack.h. <br>
- * NOTE: bindResource must be used only after the both collection resource and
- * resource to add under a collections are created and respective handles obtained<br>
- * <b>Example:</b> <br>
- * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
- * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
- * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
- * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
- * Step 3: bindResource(homeResourceHandle, kitchenResourceHandle);<br>
- * At the end of Step 3, resource "a/home" will contain a reference to "a/kitchen".<br>
+ * @param collectionHandle handle to the collection resource
+ * @param resourceHandle handle to resource to be added to the collection resource
+ *
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
+ * @note bindResource must be used only after the both collection resource and
+ * resource to add under a collections are created and respective handles obtained
+ *
+ * @par Example:
+ * -# registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
+ * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * -# registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
+ * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * -# bindResource(homeResourceHandle, kitchenResourceHandle);
+ * @par
+ * At the end of Step 3, resource "a/home" will contain a reference to "a/kitchen".
*/
OCStackResult bindResource(const OCResourceHandle collectionHandle,
const OCResourceHandle resourceHandle);
/**
* Add multiple resources to a collection resource.
*
- * @param collectionHandle - handle to the collection resource
+ * @param collectionHandle handle to the collection resource
* @param addedResourceHandleList reference to list of resource handles to be added to the
* collection resource
*
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
- * NOTE: OCStackResult is defined in ocstack.h. <br>
- * NOTE: bindResources must be used only after the both collection resource and
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
+ * @note bindResources must be used only after the both collection resource and
* list of resources to add under a collection are created and respective handles
- * obtained <br>
- * <b> Example: </b> <br>
- * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
- * homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
- * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
- * kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
- * Step 3: registerResource(roomResourceHandle, "a/room", "room", Link_Interface,
- * roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
- * Step 4: std::vector<OCResourceHandle> rList; rList.push_back(kitchenResourceHandle);
- * rList.push_back(roomResourceHandle);<br>
- * Step 5: bindResource(homeResourceHandle, rList);<br>
+ * obtained.
+ *
+ * @par Example:
+ * -# registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
+ * homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * -# registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
+ * kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * -# registerResource(roomResourceHandle, "a/room", "room", Link_Interface,
+ * roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * -# std::vector<OCResourceHandle> rList; rList.push_back(kitchenResourceHandle);
+ * rList.push_back(roomResourceHandle);
+ * -# bindResource(homeResourceHandle, rList);
+ * @par
* At the end of Step 5, resource "a/home" will contain a references to "a/kitchen" and
- * "a/room" <br>
+ * "a/room"
*/
OCStackResult bindResources(const OCResourceHandle collectionHandle,
const std::vector<OCResourceHandle>& addedResourceHandleList);
/**
* Unbind a resource from a collection resource.
*
- * @param collectionHandle - handle to the collection resource
+ * @param collectionHandle handle to the collection resource
* @param resourceHandle resource handle to be unbound from the collection resource
*
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
- * NOTE: OCStackResult is defined in ocstack.h.<br>
- * NOTE: unbindResource must be used only after the both collection resource and
- * resource to unbind from a collection are created and respective handles obtained<br>
- * <b> Example </b> <br>
- * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
- * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
- * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
- * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
- * Step 3: bindResource(homeResourceHandle, kitchenResourceHandle);<br>
- * Step 4: unbindResource(homeResourceHandle, kitchenResourceHandle);<br>
- * At the end of Step 4, resource "a/home" will no longer reference "a/kitchen". <br>
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
+ * @note unbindResource must be used only after the both collection resource and
+ * resource to unbind from a collection are created and respective handles obtained
+ *
+ * @par Example:
+ * -# registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
+ * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * -# registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
+ * entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * -# bindResource(homeResourceHandle, kitchenResourceHandle);
+ * -# unbindResource(homeResourceHandle, kitchenResourceHandle);
+ * @par
+ * At the end of Step 4, resource "a/home" will no longer reference "a/kitchen".
*/
OCStackResult unbindResource(const OCResourceHandle collectionHandle,
const OCResourceHandle resourceHandle);
/**
* Unbind resources from a collection resource.
*
- * @param collectionHandle - handle to the collection resource
+ * @param collectionHandle handle to the collection resource
* @param resourceHandleList List of resource handles to be unbound from the collection
* resource
*
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
- *
- * NOTE: OCStackResult is defined in ocstack.h.<br>
- * NOTE: unbindResources must be used only after the both collection resource and
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
+ * @note unbindResources must be used only after the both collection resource and
* list of resources resource to unbind from a collection are created and respective handles
- * obtained. <br>
- * <b>Example</b> <br>
- * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
- * homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
- * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
- * kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
- * Step 3: registerResource(roomResourceHandle, "a/room", "room", Link_Interface,
- * roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
- * Step 4: std::vector<OCResourceHandle> rList; rList.push_back(kitchenResourceHandle);
- * rList.push_back(roomResourceHandle);<br>
- * Step 5: bindResource(homeResourceHandle, rList);<br>
- * Step 6: unbindResources(homeResourceHandle, rList);<br>
+ * obtained.
+ *
+ * @par Example:
+ * -# registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
+ * homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * -# registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
+ * kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * -# registerResource(roomResourceHandle, "a/room", "room", Link_Interface,
+ * roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+ * -# std::vector<OCResourceHandle> rList; rList.push_back(kitchenResourceHandle);
+ * rList.push_back(roomResourceHandle);
+ * -# bindResource(homeResourceHandle, rList);
+ * -# unbindResources(homeResourceHandle, rList);
+ * @par
* At the end of Step 6, resource "a/home" will no longer reference to "a/kitchen" and
- * "a/room"<br>
+ * "a/room"
*/
OCStackResult unbindResources(const OCResourceHandle collectionHandle,
const std::vector<OCResourceHandle>& resourceHandleList);
/**
* Binds a type to a particular resource
- * @param resourceHandle - handle to the resource
- * @param resourceTypeName - new typename to bind to the resource
-
- * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success <br>
+ * @param resourceHandle handle to the resource
+ * @param resourceTypeName new typename to bind to the resource
+ *
+ * @return Returns ::OC_STACK_OK if success.
*/
OCStackResult bindTypeToResource(const OCResourceHandle& resourceHandle,
const std::string& resourceTypeName);
/**
* Binds an interface to a particular resource
- * @param resourceHandle - handle to the resource
- * @param resourceInterfaceName - new interface to bind to the resource
-
- * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success <br>
+ * @param resourceHandle handle to the resource
+ * @param resourceInterfaceName new interface to bind to the resource
+ *
+ * @return Returns ::OC_STACK_OK if success.
*/
OCStackResult bindInterfaceToResource(const OCResourceHandle& resourceHandle,
const std::string& resourceInterfaceName);
/**
* Start Presence announcements.
*
- * @param ttl - time to live
- * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
- *
- * If ttl is greater than OC_MAX_PRESENCE_TTL_SECONDS, then the ttl will be set to
- * OC_MAX_PRESENCE_TTL_SECONDS.
- *
- * @return OCStackResult - Returns OCSTACK_OK if success <br>
+ * @param ttl time to live
+ * @par
+ * If ttl is '0', then the default stack value will be used (60 Seconds).
+ * If ttl is greater than OC_MAX_PRESENCE_TTL_SECONDS, then the ttl will be set to
+ * OC_MAX_PRESENCE_TTL_SECONDS.
+ * @par
+ * @return Returns ::OC_STACK_OK if success.
*
* Server can call this function when it comes online for the
* first time, or when it comes back online from offline mode,
/**
* Stop Presence announcements.
*
- * @return OCStackResult - Returns OCSTACK_OK if success <br>
+ * @return Returns ::OC_STACK_OK if success.
*
* Server can call this function when it is terminating,
* going offline, or when going away from network.
* every time a server adds/removes/alters a resource, starts or is intentionally
* stopped (potentially more to be added later).
*
- * @param presenceHandle - a handle object that can be used to identify this subscription
+ * @param presenceHandle a handle object that can be used to identify this subscription
* request. It can be used to unsubscribe from these events in the future.
* It will be set upon successful return of this method.
- * @param host - The IP address/addressable name of the server to subscribe to.
+ * @param host The IP address/addressable name of the server to subscribe to.
* This should be in the format coap://address:port
- * @param connectivityType - @ref OCConnectivityType type of connectivity indicating the
+ * @param connectivityType ::OCConnectivityType type of connectivity indicating the
* interface. Example: OC_WIFI, OC_ETHERNET, OC_ALL
- * @param resourceType - a resource type specified as a filter for subscription callbacks.
- * @param presenceHandler - callback function that will receive notifications/subscription
+ * @param resourceType a resource type specified as a filter for subscription callbacks.
+ * @param presenceHandler callback function that will receive notifications/subscription
* events
*
- * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success <br>
+ * @return Returns ::OC_STACK_OK if success.
*/
OCStackResult subscribePresence(OCPresenceHandle& presenceHandle, const std::string& host,
OCConnectivityType connectivityType, SubscribeCallback presenceHandler);
* you may for a short time still receive events from the server since it may take time
* for the unsubscribe to take effect.
*
- * @param presenceHandle - the handle object provided by the subscribePresence call that
+ * @param presenceHandle the handle object provided by the subscribePresence call that
* identifies this subscription.
*
- * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success <br>
+ * @return Returns ::OC_STACK_OK if success.
*/
OCStackResult unsubscribePresence(OCPresenceHandle presenceHandle);
* to be a Client or Client/Server. Otherwise, this will return an empty
* shared ptr.
*
- * @param host - a string containing a resolvable host address of the server
+ * @param host a string containing a resolvable host address of the server
* holding the resource. Currently this should be in the format
* coap://address:port, though in the future, we expect this to
* change to //address:port
*
- * @param uri - the rest of the resource's URI that will permit messages to be
+ * @param uri the rest of the resource's URI that will permit messages to be
* properly routed. Example: /a/light
*
- * @param connectivityType - @ref OCConnectivityType type of connectivity indicating the
+ * @param connectivityType ::OCConnectivityType type of connectivity indicating the
* interface. Example: OC_WIFI, OC_ETHERNET, OC_ALL
*
- * @param isObservable - a boolean containing whether the resource supports observation
+ * @param isObservable a boolean containing whether the resource supports observation
*
- * @param resourceTypes - a collection of resource types implemented by the resource
+ * @param resourceTypes a collection of resource types implemented by the resource
*
- * @param interfaces - a collection of interfaces that the resource supports/implements
- * @return OCResource::Ptr - a shared pointer to the new resource object
+ * @param interfaces a collection of interfaces that the resource supports/implements
+ * @return OCResource::Ptr a shared pointer to the new resource object
*/
OCResource::Ptr constructResourceObject(const std::string& host,
const std::string& uri,
/**
* Allows application entity handler to send response to an incoming request.
*
- * @param pResponse - OCResourceResponse pointer that will permit to set values related
- * to resource response. <br>
- * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success <br>
+ * @param pResponse OCResourceResponse pointer that will permit to set values related
+ * to resource response.
+ *
+ * @return Returns ::OC_STACK_OK if success.
*/
OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
}
/**
* API for Device Discovery
*
- * @param host - Host IP Address. If null or empty, Multicast is performed.
- * @param resourceURI - Uri containing address to the virtual device in C Stack
+ * @param host Host IP Address. If null or empty, Multicast is performed.
+ * @param deviceURI Uri containing address to the virtual device in C Stack
* ("/oic/d")
- *
+ * @param deviceInfoHandler device discovery callback
* @param QualityOfService the quality of communication
- *
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult getDeviceInfo(const std::string& host, const std::string& deviceURI,
FindDeviceCallback deviceInfoHandler);
/**
* API for Platform Discovery
*
- * @param host - Host IP Address. If null or empty, Multicast is performed.
- * @param resourceURI - Uri containing address to the virtual platform in C Stack
+ * @param host Host IP Address. If null or empty, Multicast is performed.
+ * @param platformURI Uri containing address to the virtual platform in C Stack
* ("/oic/p")
- *
+ * @param platformInfoHandler platform discovery callback
* @param QualityOfService the quality of communication
- *
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult getPlatformInfo(const std::string& host, const std::string& platformURI,
FindPlatformCallback platformInfoHandler);
/**
* This API registers a resource with the server
- * NOTE: This API applies to server side only.
+ * @note This API applies to server side only.
*
- * @param resourceHandle - Upon successful registration, resourceHandle will be filled
- * @param resourceURI - The URI of the resource. Example: "a/light". See NOTE below
- * @param resourceTypeName - The resource type. Example: "light"
- * @param resourceInterface - The resource interface (whether it is collection etc).
- * @param entityHandler - entity handler callback.
- * @param resourceProperty - indicates the property of the resource. Defined in ocstack.h.
+ * @param resourceHandle Upon successful registration, resourceHandle will be filled
+ * @param resourceURI The URI of the resource. Example: "a/light". See NOTE below
+ * @param resourceTypeName The resource type. Example: "light"
+ * @param resourceInterface The resource interface (whether it is collection etc).
+ * @param entityHandler entity handler callback.
+ * @param resourceProperty indicates the property of the resource. Defined in ocstack.h.
* setting resourceProperty as OC_DISCOVERABLE will allow Discovery of this resource
* setting resourceProperty as OC_OBSERVABLE will allow observation
* settings resourceProperty as OC_DISCOVERABLE | OC_OBSERVABLE will allow both discovery
* and observation
*
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: "a/light" is a relative URI.
+ * @return Returns ::OC_STACK_OK if success.
+ * @note "a/light" is a relative URI.
* Above relative URI will be prepended (by core) with a host IP + namespace "oc"
* Therefore, fully qualified URI format would be //HostIP-Address/namespace/relativeURI"
* Example, a relative URI: 'a/light' will result in a fully qualified URI:
* qualified URI OR
* first parameter can take fully qualified URI and core will take that as is for further
* operations
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult registerResource(OCResourceHandle& resourceHandle,
std::string& resourceURI,
/**
* This API registers all the device specific information
*
- * @param OCDeviceInfo - Structure containing all the device related information
+ * @param deviceInfo Structure containing all the device related information
*
- * @return OCStackResult return value of the API. Returns OC_STACK_OK if success
- *
- * Note: OCDeviceInfo is defined in OCStack.h
+ * @return Returns ::OC_STACK_OK if success
+ * @note OCDeviceInfo is defined in OCStack.h
*/
OCStackResult registerDeviceInfo(const OCDeviceInfo deviceInfo);
/**
* This API registers all the platform specific information
*
- * @param OCPlatformInfo - Structure containing all the platform related information
- *
- * @return OCStackResult return value of the API. Returns OC_STACK_OK if success
+ * @param platformInfo Structure containing all the platform related information
*
- * Note: OCPlatformInfo is defined in OCStack.h
+ * @return Returns ::OC_STACK_OK if success
+ * @note OCPlatformInfo is defined in OCStack.h
*/
OCStackResult registerPlatformInfo(const OCPlatformInfo platformInfo);
const std::vector<std::string>& interfaces);
OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
+ std::weak_ptr<std::recursive_mutex> csdkLock();
+
private:
PlatformConfig m_cfg;
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 _OCPROVISIONINGMANAGER_CXX_H
+#define _OCPROVISIONINGMANAGER_CXX_H
+
+#include <thread>
+
+#include "pinoxmcommon.h"
+#include "ocprovisioningmanager.h"
+#include "OCApi.h"
+#include "OCPlatform_impl.h"
+
+namespace OC
+{
+ class OCSecureResource;
+
+ typedef std::vector<std::shared_ptr<OCSecureResource>> DeviceList_t;
+ typedef std::vector<OicUuid_t> UuidList_t;
+ typedef std::vector<OCProvisionResult_t> PMResultList_t;
+ typedef std::function<void(PMResultList_t *result, int hasError)> ResultCallBack;
+
+ struct ProvisionContext
+ {
+ ResultCallBack callback;
+ ProvisionContext(ResultCallBack cb) : callback(cb){}
+ };
+
+ /**
+ * @brief: This class is for credential's to be set to devices.
+ * The types supported are
+ * 0: no security mode
+ * 1: symmetric pair-wise key
+ * 2: symmetric group key
+ * 4: asymmetric key
+ * 8: signed asymmetric key (aka certificate)
+ * 16: PIN /password
+ */
+ class Credential
+ {
+ OicSecCredType_t type;
+ size_t keySize;
+ public:
+ Credential() = default;
+ Credential(OicSecCredType_t type, size_t size) : type(type), keySize(size)
+ {}
+
+ OicSecCredType_t getCredentialType() const
+ {
+ return type;
+ }
+
+ size_t getCredentialKeySize() const
+ {
+ return keySize;
+ }
+
+ void setCredentialType(OicSecCredType_t type)
+ {
+ this->type = type;
+ }
+
+ void setCredentialKeySize(size_t keySize)
+ {
+ this->keySize = keySize;
+ }
+ };
+
+ class OCSecure
+ {
+ public:
+ /**
+ * The API is responsible for initializaton of the provisioning manager. It will load
+ * provisioning database which have owned device's list and their linked status.
+ *
+ * @param[in] dbPath file path of the sqlite3 db
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ static OCStackResult provisionInit(const std::string& dbPath);
+
+ /**
+ * API is responsible for discovery of devices in it's subnet. It will list
+ * all the device in subnet which are not yet owned.
+ *
+ * @param[in] timeout Timeout in seconds, time util which function will listen to
+ * responses from client before returning the list of devices.
+ * @param[out] list List of candidate devices to be provisioned
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ static OCStackResult discoverUnownedDevices(unsigned short timeout,
+ DeviceList_t &list);
+
+ /**
+ * API is responsible for discovery of devices in it's subnet. It will list
+ * all the device in subnet which are already owned by calling provioning client
+ *
+ * @param[in] timeout Timeout in seconds, time util which function will listen to
+ * responses from client before returning the list of devices.
+ * @param[out] list List of owned devices
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ static OCStackResult discoverOwnedDevices(unsigned short timeout,
+ DeviceList_t &list);
+
+ /**
+ * API for registering Ownershipt transfer methods for a particular transfer Type
+ *
+ * @param[in] oxm Ownership transfer method
+ * @param[in] callbackData Methods for ownership transfer
+ * @param[in] InputPinCallback Method to input pin for verification
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ static OCStackResult setOwnerTransferCallbackData(OicSecOxm_t oxm,
+ OTMCallbackData_t* callbackData, InputPinCallback inputPin);
+
+ /**
+ * API to get status of all the devices in current subnet. The status include endpoint
+ * information and doxm information which can be extracted duing owned and unowned
+ * discovery. Along with this information, API will provide information about
+ * devices' status.
+ * Device can have following states
+ * - ON/OFF: Device is switched on or off.
+ *
+ * @param[in] timeout waitime for the API.
+ * @param[out] pOwnedDevList list of owned devices.
+ * @param[out] pUnownedDevList list of unowned devices.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ static OCStackResult getDevInfoFromNetwork(unsigned short timeout,
+ DeviceList_t &ownedDevList,
+ DeviceList_t &unownedDevList);
+
+ };
+
+ /**
+ * This class represents a Secure virtual Device, which can be provisioned by the
+ * provisioning client.
+ */
+ class OCSecureResource
+ {
+ private:
+ std::weak_ptr<std::recursive_mutex> m_csdkLock;
+ OCProvisionDev_t *devPtr; // pointer to device.
+
+ public:
+ OCSecureResource();
+ OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock, OCProvisionDev_t *dPtr);
+
+ ~OCSecureResource();
+
+ /**
+ * API to provision credentials between two devices and ACLs for the devices who
+ * act as a server.
+ *
+ * @param[in] cred Type of credentials & key size to be provisioned to the device.
+ * @param[in] acl1 ACL for device 1. If this is not required set NULL.
+ * @param[in] device2 Second device to be provsioned.
+ * @param[in] acl2 ACL for device 2. If this is not required set NULL.
+ * @param[in] resultCallback Callback will be called when provisioning request recieves
+ * a response from first resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult provisionPairwiseDevices(const Credential &cred, const OicSecAcl_t* acl1,
+ const OCSecureResource &device2, const OicSecAcl_t* acl2,
+ ResultCallBack resultCallback);
+
+ /**
+ * API to do ownership transfer for un-owned device.
+ *
+ * @param[in] resultCallback Result callback function to be invoked when
+ * ownership transfer finished.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult doOwnershipTransfer(ResultCallBack resultCallback);
+
+ /**
+ * API to send ACL information to resource.
+ *
+ * @param[in] acl ACL to provision.
+ * @param[in] resultCallback callback will be called when provisioning request
+ * recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult provisionACL(const OicSecAcl_t* acl,
+ ResultCallBack resultCallback);
+
+ /**
+ * API to provision credential to devices.
+ *
+ * @param[in] cred Type of credentials to be provisioned to the device.
+ * @param[in] device2 Second device' instance,respresenting resourceto be provsioned.
+ * @param[in] resultCallback callback will be called when provisioning request recieves
+ * a response from first resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult provisionCredentials(const Credential &cred,
+ const OCSecureResource &device2,
+ ResultCallBack resultCallback);
+
+ /*
+ * API to remove the credential & relasionship between the two devices.
+ *
+ * @param[in] pTargetDev2 second device information to be unlinked.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * device unlink is finished.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult unlinkDevices(const OCSecureResource &device2,
+ ResultCallBack resultCallback);
+
+ /*
+ * API to remove device credential from all devices in subnet.
+ *
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * credential revocation is finished.
+ * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device
+ * discovery.(seconds)
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult removeDevice(unsigned short waitTimeForOwnedDeviceDiscovery,
+ ResultCallBack resultCallback);
+
+ /**
+ * This method is used to get linked devices' IDs.
+ *
+ * @param[out] uuidList information about the list of linked devices' uuids.
+ * @param[out] numOfDevices total number of linked devices.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult getLinkedDevices(UuidList_t &uuidList);
+
+ /**
+ * API to get the DeviceID of this resource
+ */
+ std::string getDeviceID();
+
+ OCProvisionDev_t* getDevPtr()const;
+
+ /**
+ * This function returns the Device's IP addr.
+ */
+ std::string getDevAddr();
+
+ /**
+ * This function returns the Device's Status
+ */
+ int getDeviceStatus();
+
+ /**
+ * This function provides the OWNED status of the device.
+ */
+ bool getOwnedStatus();
+
+ private:
+ /**
+ * Common callback wrapper, which will be called from OC-APIs.
+ */
+ static void callbackWrapper(void* ctx, int nOfRes,
+ OCProvisionResult_t *arr, bool hasError);
+
+ void validateSecureResource();
+ };
+
+}
+#endif //_OCPROVISIONINGMANAGER_CXX_H
class OCRepresentation
{
public:
+ friend bool operator==(const OC::OCRepresentation&, const OC::OCRepresentation&);
// Note: Implementation of all constructors and destructors
// are all placed in the same location due to a crash that
// was observed in Android, where merely constructing/destructing
// Enable-if required to prevent conversions to alternate types. This prevents
// ambigious conversions in the case where conversions can include a number of
// types, such as the string constructor.
- template<typename T, typename= typename std::enable_if<
+ template<typename T, typename std::enable_if<
std::is_same<T, int>::value ||
std::is_same<T, double>::value ||
std::is_same<T, bool>::value ||
std::is_same<T, std::vector<OCRepresentation>>::value ||
std::is_same<T, std::vector<std::vector<OCRepresentation>>>::value ||
std::is_same<T, std::vector<std::vector<std::vector<OCRepresentation>>>>::value
- >::type // enable_if
+ , int>::type = 0// enable_if
>
operator T() const
{
return this->getValue<T>();
}
- operator std::nullptr_t() const
+ template<typename T, typename std::enable_if<
+ std::is_same<T, std::nullptr_t>::value
+ , int>::type = 0
+ >
+ operator T() const
{
this->getValue<NullType>();
return nullptr;
* The callback function will be invoked with a map of attribute name and values.
* The callback function will also have the result from this Get operation
* This will have error codes
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult get(const QueryParamsMap& queryParametersMap, GetCallback attributeHandler);
/**
* The callback function will also have the result from this Get operation
* This will have error codes
* @param QoS the quality of communication
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult get(const QueryParamsMap& queryParametersMap, GetCallback attributeHandler,
QualityOfService QoS);
* resource container (list will be empty if not a container)
* The callback function will also have the result from this Get operation. This will
* have error codes
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
- * NOTE: OCStackResult is defined in ocstack.h.<br>
- * <b>Example:</b><br>
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ * @par Example:
* Consider resource "a/home" (with link interface and resource type as home) contains links
* to "a/kitchen" and "a/room".
- * Step 1: get("home", Link_Interface, &onGet)<br>
+ * -# get("home", Link_Interface, &onGet)
+ * @par
* Callback onGet will receive a) Empty attribute map because there are no attributes for
* a/home b) list with
* full URI of "a/kitchen" and "a/room" resources and their properties c) error code for GET
- * operation<br>
- * NOTE: A resource may contain single or multiple resource types. Also, a resource may
- * contain single or multiple interfaces.<br>
+ * operation
+ * @note A resource may contain single or multiple resource types. Also, a resource may
+ * contain single or multiple interfaces.
* Currently, single GET request is allowed to do operate on single resource type or resource
- * interface. In future, a single GET <br>
- * can operate on multiple resource types and interfaces. <br>
- * NOTE: A client can traverse a tree or graph by doing successive GETs on the returned
- * resources at a node.<br>
+ * interface. In future, a single GET
+ * can operate on multiple resource types and interfaces.
+ * @note A client can traverse a tree or graph by doing successive GETs on the returned
+ * resources at a node.
+ *
*/
OCStackResult get(const std::string& resourceType, const std::string& resourceInterface,
const QueryParamsMap& queryParametersMap, GetCallback attributeHandler);
* The callback function will also have the result from this Get operation. This will
* have error codes
* @param QoS the quality of communication
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
- * NOTE: OCStackResult is defined in ocstack.h.<br>
- * <b>Example:</b><br>
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * note OCStackResult is defined in ocstack.h.
+ * @par Example:
* Consider resource "a/home" (with link interface and resource type as home) contains links
* to "a/kitchen" and "a/room".
- * Step 1: get("home", Link_Interface, &onGet)<br>
+ * -# get("home", Link_Interface, &onGet)
+ * @par
* Callback onGet will receive a) Empty attribute map because there are no attributes for
* a/home b) list with
* full URI of "a/kitchen" and "a/room" resources and their properties c) error code for GET
- * operation<br>
- * NOTE: A resource may contain single or multiple resource types. Also, a resource may
- * contain single or multiple interfaces.<br>
+ * operation
+ * @note A resource may contain single or multiple resource types. Also, a resource may
+ * contain single or multiple interfaces.
* Currently, single GET request is allowed to do operate on single resource type or resource
- * interface. In future, a single GET <br>
- * can operate on multiple resource types and interfaces. <br>
- * NOTE: A client can traverse a tree or graph by doing successive GETs on the returned
- * resources at a node.<br>
+ * interface. In future, a single GET
+ * can operate on multiple resource types and interfaces.
+ * @note A client can traverse a tree or graph by doing successive GETs on the returned
+ * resources at a node.
+ *
*/
OCStackResult get(const std::string& resourceType, const std::string& resourceInterface,
const QueryParamsMap& queryParametersMap, GetCallback attributeHandler,
/**
* Function to set the representation of a resource (via PUT)
+ *
* @param representation which can either have all the attribute names and values
(which will represent entire state of the resource) or a
* set of attribute names and values which needs to be modified
* This will have error codes
* @param queryParametersMap map which can have the query parameter name and value
* @param attributeHandler attribute handler
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
*/
OCStackResult put(const OCRepresentation& representation,
const QueryParamsMap& queryParametersMap, PutCallback attributeHandler);
/**
* Function to set the representation of a resource (via PUT)
+ *
* @param representation which can either have all the attribute names and values
(which will represent entire state of the resource) or a
* set of attribute names and values which needs to be modified
* @param queryParametersMap map which can have the query parameter name and value
* @param attributeHandler attribute handler
* @param QoS the quality of communication
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
*/
OCStackResult put(const OCRepresentation& representation,
const QueryParamsMap& queryParametersMap, PutCallback attributeHandler,
/**
* Function to set the attributes of a resource (via PUT)
+ *
* @param resourceType resource type of the resource to operate on
* @param resourceInterface interface type of the resource to operate on
* @param representation representation of the resource
* and values
* (which will represent entire state of the resource) or a
* set of attribute names and values which needs to be modified
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
- * NOTE: OCStackResult is defined in ocstack.h. <br>
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
*/
OCStackResult put(const std::string& resourceType, const std::string& resourceInterface,
const OCRepresentation& representation, const QueryParamsMap& queryParametersMap,
* (which will represent entire state of the resource) or a
* set of attribute names and values which needs to be modified
* @param QoS the quality of communication
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
- * NOTE: OCStackResult is defined in ocstack.h. <br>
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
*/
OCStackResult put(const std::string& resourceType, const std::string& resourceInterface,
const OCRepresentation& representation, const QueryParamsMap& queryParametersMap,
/**
* Function to post on a resource
+ *
* @param representation which can either have all the attribute names and values
* (which will represent entire state of the resource) or a
* set of attribute names and values which needs to be modified
* This will have error codes
* @param queryParametersMap map which can have the query parameter name and value
* @param attributeHandler attribute handler
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult post(const OCRepresentation& representation,
const QueryParamsMap& queryParametersMap, PostCallback attributeHandler);
/**
* Function to post on a resource
+ *
* @param representation which can either have all the attribute names and values
* (which will represent entire state of the resource) or a
* set of attribute names and values which needs to be modified
* @param queryParametersMap map which can have the query parameter name and value
* @param attributeHandler attribute handler
* @param QoS the quality of communication
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult post(const OCRepresentation& representation,
const QueryParamsMap& queryParametersMap, PostCallback attributeHandler,
/**
* Function to post on a resource
+ *
* @param resourceType resource type of the resource to operate on
* @param resourceInterface interface type of the resource to operate on
* @param representation representation of the resource
* and values
* (which will represent entire state of the resource) or a
* set of attribute names and values which needs to be modified
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
- * NOTE: OCStackResult is defined in ocstack.h. <br>
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
*/
OCStackResult post(const std::string& resourceType, const std::string& resourceInterface,
const OCRepresentation& representation, const QueryParamsMap& queryParametersMap,
PostCallback attributeHandler);
/**
* Function to post on a resource
+ *
* @param resourceType resource type of the resource to operate on
* @param resourceInterface interface type of the resource to operate on
* @param representation representation of the resource
* (which will represent entire state of the resource) or a
* set of attribute names and values which needs to be modified
* @param QoS the quality of communication
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
- * NOTE: OCStackResult is defined in ocstack.h. <br>
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
*/
OCStackResult post(const std::string& resourceType, const std::string& resourceInterface,
const OCRepresentation& representation, const QueryParamsMap& queryParametersMap,
/**
* Function to perform DELETE operation
+ *
* @param deleteHandler handles callback
* The callback function will have headerOptions and result from this Delete
* operation. This will have error codes
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
*/
OCStackResult deleteResource(DeleteCallback deleteHandler);
OCStackResult deleteResource(DeleteCallback deleteHandler, QualityOfService QoS);
/**
* Function to set observation on the resource
+ *
* @param observeType allows the client to specify how it wants to observe.
* @param queryParametersMap map which can have the query parameter name and value
* @param observeHandler handles callback
* The callback function will be invoked with a map of attribute name and values.
* The callback function will also have the result from this observe operation
* This will have error codes
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
*/
OCStackResult observe(ObserveType observeType, const QueryParamsMap& queryParametersMap,
ObserveCallback observeHandler);
/**
* Function to set observation on the resource
+ *
* @param observeType allows the client to specify how it wants to observe.
* @param queryParametersMap map which can have the query parameter name and value
* @param observeHandler handles callback
* The callback function will also have the result from this observe operation
* This will have error codes
* @param qos the quality of communication
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
*/
OCStackResult observe(ObserveType observeType, const QueryParamsMap& queryParametersMap,
ObserveCallback observeHandler, QualityOfService qos);
/**
* Function to cancel the observation on the resource
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
- * NOTE: OCStackResult is defined in ocstack.h.
+ *
+ * @return Returns ::OC_STACK_OK on success, some other value upon failure.
+ * @note OCStackResult is defined in ocstack.h.
+ *
*/
OCStackResult cancelObserve();
OCStackResult cancelObserve(QualityOfService qos);
* @param headerOptions std::vector where header information(header optionID and optionData
* is passed
*
- * NOTE: Once the headers information is set, it will be applicable to GET, PUT and observe
- * request. <br>
+ * @note Once the headers information is set, it will be applicable to GET, PUT and observe
+ * request.
* setHeaderOptions can be used multiple times if headers need to be modifed by the client.
* Latest headers will be used to send in the request. <br>
- * NOTE: Initial support is only for two headers. If headerMap consists of more than two
+ * @note Initial support is only for two headers. If headerMap consists of more than two
* header options, they will be ignored. <br>
* Use unsetHeaderOptions API to clear the header information.
*/
/**
* Function to get the host address of this resource
* @return std::string host address
- * NOTE: This might or might not be exposed in future due to security concerns
+ * @note This might or might not be exposed in future due to security concerns
*/
std::string host() const;
/**
* Function to get a string representation of the resource's server ID.
* This is unique per- server independent on how it was discovered.
- * Note: The format of the return value is subject to change and will
+ * @note The format of the return value is subject to change and will
* likely change both in size and contents in the future.
*/
std::string sid() const;
static const char INVALID_ATTRIBUTE[] = "Invalid Attribute: ";
static const char INVALID_DEVICE_INFO[] = "Invalid Device Information";
static const char UNAUTHORIZED_REQUEST[] = "Unauthorized Request";
+ static const char PDM_DB_NOT_INITIALIZED[] = "Provisioning DB is not initialized";
+ static const char DUPLICATE_UUID[] = "Duplicate UUID in DB";
+ static const char INCONSISTENT_DB[] = "Data in provisioning DB is inconsistent";
}
#include <string.h>
#include <unistd.h>
-#define TAG PCF("MAIN")
+#define TAG ("MAIN")
static int customLogger = 0;
--- /dev/null
+#******************************************************************
+#
+# 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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Import('env')
+
+ocprovision_env = env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+ocprovision_env.AppendUnique(CPPPATH = [
+ '../include/',
+ '../csdk/stack/include',
+ '../csdk/logger/include',
+ '../oc_logger/include',
+ '../csdk/security/include',
+ '../csdk/security/provisioning/include',
+ '../csdk/security/provisioning/include/oxm',
+ '../csdk/security/provisioning/include/internal'
+ ])
+
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+ ocprovision_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-fPIC'])
+
+if target_os == 'android':
+ ocprovision_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+ ocprovision_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+ ocprovision_env.AppendUnique(LIBS = ['ocspapi', 'octbstack', 'oc_logger', 'boost_thread', 'gnustl_shared', 'log'])
+
+if target_os in ['darwin', 'ios']:
+ ocprovision_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+ ocprovision_env.AppendUnique(LIBS = ['octbstack', 'oc_logger'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+ocprovision_src = [
+ 'src/OCProvisioningManager.cpp'
+ ]
+
+ocprovision = ocprovision_env.StaticLibrary('ocprovision', ocprovision_src)
+ocprovision_env.InstallTarget(ocprovision, 'libocprovision')
+
+if target_os in ['linux']:
+ SConscript('examples/SConscript')
--- /dev/null
+#******************************************************************
+#
+# 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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+##
+# Examples build script
+##
+Import('env')
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+
+examples_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+examples_env.AppendUnique(CPPPATH = [
+ '../../include/',
+ '../../csdk/stack/include',
+ '../../csdk/logger/include',
+ '../../oc_logger/include',
+ '../../csdk/security/include',
+ '../../csdk/security/provisioning/include',
+ '../../csdk/security/provisioning/include/oxm',
+ '../../csdk/security/provisioning/include/internal'
+ ])
+
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+ examples_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+
+ # Note: 'pthread' is in libc for android. On other platform, if use
+ # new gcc(>4.9?) it isn't required, otherwise, it's required
+ if target_os != 'android':
+ examples_env.AppendUnique(LIBS = ['-lpthread'])
+
+examples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+examples_env.AppendUnique(RPATH = [env.get('BUILD_DIR')])
+examples_env.PrependUnique(LIBS = ['ocprovision', 'oc', 'ocpmapi', 'octbstack',
+ 'oc_logger', 'connectivity_abstraction', 'coap'])
+if env.get('SECURED') == '1':
+ examples_env.AppendUnique(LIBS = ['tinydtls'])
+
+if target_os == 'android':
+ examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+ examples_env.AppendUnique(LIBS = ['gnustl_shared'])
+
+ if not env.get('RELEASE'):
+ examples_env.AppendUnique(LIBS = ['log'])
+
+if target_os in ['darwin', 'ios']:
+ examples_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+provisioningclient = examples_env.Program('provisioningclient', 'provisioningclient.cpp')
+
+Alias("examples", [provisioningclient])
+env.AppendTarget('examples')
+
+src_dir = examples_env.get('SRC_DIR')
+svr_db_src_dir = src_dir + '/resource/provisioning/examples/'
+svr_db_build_dir = env.get('BUILD_DIR') +'/resource/provisioning/examples/'
+examples_env.Alias("install", examples_env.Install( svr_db_build_dir,
+ svr_db_src_dir + 'oic_svr_db_client.json'))
--- /dev/null
+{
+ "acl": [
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/res",
+ "/oic/d",
+ "/oic/p",
+ "/oic/res/types/d",
+ "/oic/ad",
+ "/oic/sec/amacl"
+ ],
+ "perms": 2,
+ "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+ },
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/sec/doxm",
+ "/oic/sec/pstat"
+ ],
+ "perms": 2,
+ "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+ }
+ ],
+ "pstat": {
+ "isop": true,
+ "deviceid": "YWRtaW5EZXZpY2VVVUlEMA==",
+ "ch": 0,
+ "cm": 0,
+ "tm": 0,
+ "om": 3,
+ "sm": [3]
+ },
+ "doxm": {
+ "oxm": [0],
+ "oxmsel": 0,
+ "sct": 1,
+ "owned": true,
+ "deviceid": "YWRtaW5EZXZpY2VVVUlEMA==",
+ "ownr": "YWRtaW5EZXZpY2VVVUlEMA=="
+ }
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 <string.h>
+#include <unistd.h>
+#include <string>
+#include <map>
+#include <cstdlib>
+#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "OCProvisioningManager.h"
+#include "oxmjustworks.h"
+#include "oxmrandompin.h"
+
+#define MAX_URI_LENGTH (64)
+#define MAX_PERMISSION_LENGTH (5)
+#define CREATE (1)
+#define READ (2)
+#define UPDATE (4)
+#define DELETE (8)
+#define NOTIFY (16)
+#define DASH '-'
+#define PREDEFINED_TIMEOUT (10)
+#define MAX_OWNED_DEVICE (10)
+#define TAG "provisioningclient"
+
+#define JSON_DB_PATH "./oic_svr_db_client.json"
+#define DEV_STATUS_ON "DEV_STATUS_ON"
+#define DEV_STATUS_OFF "DEV_STATUS_OFF"
+
+#define DISCOVERY_TIMEOUT 5
+
+using namespace OC;
+
+DeviceList_t pUnownedDevList, pOwnedDevList;
+static int transferDevIdx, ask = 1;
+
+static FILE* client_open(const char *UNUSED_PARAM, const char *mode)
+{
+ (void)UNUSED_PARAM;
+ return fopen(JSON_DB_PATH, mode);
+}
+
+void printMenu()
+{
+ std::cout << "\nChoose an option:"<<std::endl;
+ std::cout << " 1. UnOwned Device discovery"<<std::endl;
+ std::cout << " 2. Owned Device discovery"<<std::endl;
+ std::cout << " 3. Ownership transfer"<<std::endl;
+ std::cout << " 4. Provision ACL"<<std::endl;
+ std::cout << " 5. Provision Credentials"<<std::endl;
+ std::cout << " 6. Credential & ACL provisioning b/w two devices"<<std::endl;
+ std::cout << " 7. Unlink Devices"<<std::endl;
+ std::cout << " 8. Remove Device"<<std::endl;
+ std::cout << " 9. Get Linked Devices"<<std::endl;
+ std::cout << " 10. Get Device Status"<<std::endl;
+ std::cout << " 11. Exit loop"<<std::endl;
+}
+
+void moveTransferredDevice()
+{
+ pOwnedDevList.push_back(pUnownedDevList[transferDevIdx]);
+ pUnownedDevList.erase(pUnownedDevList.begin() + transferDevIdx);
+}
+
+void InputPinCB(char* pinBuf, size_t bufSize)
+{
+ if(pinBuf)
+ {
+ std::cout <<"INPUT PIN : ";
+ std::string ptr;
+ std::cin >> ptr;
+ OICStrcpy(pinBuf, bufSize, ptr.c_str());
+ return;
+ }
+}
+
+void printUuid(OicUuid_t uuid)
+{
+ for (int i = 0; i < UUID_LENGTH; i++)
+ {
+ std::cout <<std::hex << uuid.id[i] << " ";
+ }
+ std::cout<<std::endl;
+}
+
+void ownershipTransferCB(PMResultList_t *result, int hasError)
+{
+ if (hasError)
+ {
+ std::cout << "Error!!! in OwnershipTransfer"<<std::endl;
+ }
+ else
+ {
+ std::cout<< "\nTransferred Ownership successfuly for device : ";
+ printUuid(result->at(0).deviceId);
+ delete result;
+
+ moveTransferredDevice();
+ }
+ ask = 1;
+}
+
+void printStatus(int status)
+{
+ static std::map<int, std::string> devStatus = {{1<<0, DEV_STATUS_ON}, {1<<1, DEV_STATUS_OFF}};
+
+ std::cout <<devStatus[status] <<std::endl;
+}
+
+void printDevices(DeviceList_t &list)
+{
+ for (unsigned int i = 0; i < list.size(); i++ )
+ {
+ std::cout << "Device "<< i+1 <<" ID: ";
+ std::cout << list[i]->getDeviceID() << " From IP: ";
+ std::cout << list[i]->getDevAddr() << std::endl;
+ }
+}
+
+/**
+ * Callback function for provisioning ACL, Credentials.
+ *
+ * @param[in] result Result list
+ * @param[in] hasError indicates if the result has error
+ */
+void provisionCB(PMResultList_t *result, int hasError)
+{
+ if (hasError)
+ {
+ std::cout << "Error in provisioning operation!"<<std::endl;
+ }
+ else
+ {
+ std::cout<< "\nReceived provisioning results: ";
+ for (unsigned int i = 0; i < result->size(); i++)
+ {
+ std::cout << "Result is = " << result->at(i).res <<" for device ";
+ printUuid(result->at(i).deviceId);
+ }
+
+ delete result;
+ }
+ printMenu();
+ ask = 1;
+}
+/**
+ *
+ * Ask user with which devices it wants to make further actions.
+ * All possible error checks included.
+ * Default behavior in case if only one options leaves are included too.
+ * Expect that user count devices from 1, f.e. 1st, 2nd, 3rd, etc
+ * Use DeviceList_t instead of devicesCount because of print devices info
+ *
+ * @param[in] list owned devices list.
+ * @param[out] out device number array.
+ * @param[in] count how many device numbers need to read.
+ * @return 0 in case of success and other value otherwise.
+ */
+int readDeviceNumber(DeviceList_t &list, int count, int *out)
+{
+ if (out == NULL || count <= 0)
+ {
+ std::cout << "Error! Please put valid input parameters" << std::endl;
+ return -1;
+ }
+
+ int devicesCount = list.size();
+
+ //Print current list of owned devices
+ std::cout <<"Owned devices, count = " << devicesCount << std::endl;
+ printDevices(list);
+
+ if (devicesCount < count)
+ {
+ std::cout << "You can't proceed with selected action because Owned devices count ( ";
+ std::cout << devicesCount << " ) are less then required devices ( " << count << " ).";
+ std::cout << "You may need to discover devices again" << std::endl;
+ return -2;
+ }
+
+ std::cout << "Select " << count << " device(s) for provisioning" << std::endl;
+
+ for (int curr = 0; curr < count; curr++)
+ {
+ //select last device by default if only 1 option exist
+ //from user's point of view device counting starts from 1,
+ //so 1st, 2nd, 3rd, etc devices
+ if ((curr == count - 1) && (devicesCount == count))
+ {
+ int sum = 0;
+ for (int i = 0; i < curr; i++)
+ {
+ sum += out[i];
+ }
+
+ out[curr] = (count*(count+1))/2 - sum;
+
+ std::cout << "Device " << curr + 1 << " : " << out[curr];
+ std::cout << " - selected automatically (because no other options exist)" << std::endl;
+ break;
+ }
+
+ int choice;
+ std::cout << "Device " << curr + 1 << " : ";
+ std::cin >> choice;
+
+ if (choice < 1 || choice > devicesCount)
+ {
+ std::cout << "Error! You should enter valid device number!" << std::endl;
+ return -3;
+ }
+
+ //check that user doesn't select the same device twice
+ for (int i = 0; i < curr; i++)
+ {
+ if (out[i] == choice)
+ {
+ std::cout << "Error! You cannot select the same device twice!" << std::endl;
+ return -4;
+ }
+ }
+
+ out[curr] = choice;
+ }
+
+ //Users count devices from 1, so 1st, 2nd, 3rd, etc device
+ //But deviceList array start index is 0, so need to decrease all numbers to 1
+ for (int i = 0; i < count; i++) out[i] -= 1;
+
+ return 0;
+}
+
+/**
+ * Perform cleanup for ACL
+ * @param[in] ACL
+ */
+static void deleteACL(OicSecAcl_t *acl)
+{
+ if (acl)
+ {
+ /* Clean Resources */
+ for (unsigned int i = 0; i < (acl)->resourcesLen; i++)
+ {
+ OICFree((acl)->resources[i]);
+ }
+ OICFree((acl)->resources);
+
+ /* Clean Owners */
+ OICFree((acl)->owners);
+
+ /* Clean ACL node itself */
+ /* Required only if acl was created in heap */
+ OICFree((acl));
+ }
+}
+
+/**
+ * Calculate ACL permission from string to bit
+ *
+ * @param[in] temp_psm Input data of ACL permission string
+ * @param[in,out] pms The pointer of ACL permission value
+ * @return 0 on success otherwise -1.
+ */
+static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
+{
+ int i = 0;
+
+ if (NULL == temp_pms || NULL == pms)
+ {
+ return -1;
+ }
+ *pms = 0;
+ while (temp_pms[i] != '\0')
+ {
+ switch (temp_pms[i])
+ {
+ case 'C':
+ {
+ *pms += CREATE;
+ i++;
+ break;
+ }
+ case 'R':
+ {
+ *pms += READ;
+ i++;
+ break;
+ }
+ case 'U':
+ {
+ *pms += UPDATE;
+ i++;
+ break;
+ }
+ case 'D':
+ {
+ *pms += DELETE;
+ i++;
+ break;
+ }
+ case 'N':
+ {
+ *pms += NOTIFY;
+ i++;
+ break;
+ }
+ case '_':
+ {
+ i++;
+ break;
+ }
+ default:
+ {
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Get the ACL property from user
+ *
+ * @param[in] ACL Datastructure to save user inputs
+ * @return 0 on success otherwise -1.
+ */
+static int InputACL(OicSecAcl_t *acl)
+{
+ int ret;
+ char *temp_id, *temp_rsc, *temp_pms;
+
+ printf("******************************************************************************\n");
+ printf("-Set ACL policy for target device\n");
+ printf("******************************************************************************\n");
+ //Set Subject.
+ printf("-URN identifying the subject\n");
+ printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
+ printf("Subject : ");
+ ret = scanf("%19ms", &temp_id);
+
+ if (1 == ret)
+ {
+ for (int i = 0, j = 0; temp_id[i] != '\0'; i++)
+ {
+ if (DASH != temp_id[i])
+ acl->subject.id[j++] = temp_id[i];
+ }
+ OICFree(temp_id);
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+
+ //Set Resource.
+ printf("Num. of Resource : ");
+ ret = scanf("%zu", &acl->resourcesLen);
+ printf("-URI of resource\n");
+ printf("ex)/oic/sh/temp/0 (Max_URI_Length: 64 Byte )\n");
+ acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
+ if (NULL == acl->resources)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ return -1;
+ }
+ for (size_t i = 0; i < acl->resourcesLen; i++)
+ {
+ printf("[%zu]Resource : ", i + 1);
+ ret = scanf("%64ms", &temp_rsc);
+ if (1 != ret)
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+
+ acl->resources[i] = OICStrdup(temp_rsc);
+ OICFree(temp_rsc);
+ if (NULL == acl->resources[i])
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ return -1;
+ }
+ }
+ // Set Permission
+ do
+ {
+ printf("-Set the permission(C,R,U,D,N)\n");
+ printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
+ printf("Permission : ");
+ ret = scanf("%5ms", &temp_pms);
+ if (1 != ret)
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+ ret = CalculateAclPermission(temp_pms, &(acl->permission));
+ OICFree(temp_pms);
+ } while (0 != ret );
+
+ // Set Rowner
+ printf("Num. of Rowner : ");
+ ret = scanf("%zu", &acl->ownersLen);
+ printf("-URN identifying the rowner\n");
+ printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
+ acl->owners = (OicUuid_t *)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
+ if (NULL == acl->owners)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ return -1;
+ }
+ for (size_t i = 0; i < acl->ownersLen; i++)
+ {
+ printf("[%zu]Rowner : ", i + 1);
+ ret = scanf("%19ms", &temp_id);
+ if (1 != ret)
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+
+ for (int k = 0, j = 0; temp_id[k] != '\0'; k++)
+ {
+ if (DASH != temp_id[k])
+ {
+ acl->owners[i].id[j++] = temp_id[k];
+ }
+ }
+ OICFree(temp_id);
+ }
+ return 0;
+}
+
+static int InputCredentials(Credential &cred)
+{
+ int choice;
+
+ do
+ {
+ std::cout << "Select credential type from following values:" << std::endl;
+ std::cout << "1: symmetric pair-wise key" << std::endl;
+ std::cout << "2: symmetric group key" << std::endl;
+ std::cout << "4: asymmetric key" << std::endl;
+ std::cout << "8: signed asymmetric key (aka certificate)" << std::endl;
+ std::cout << "16: PIN /password" << std::endl;
+ std::cout << "Your choice: ";
+
+ std::cin >> choice;
+
+ switch (choice){
+ case 1:
+ cred.setCredentialType(static_cast<OicSecCredType_t>(choice));
+ choice = 0; //validation of the accepted choice.
+ break;
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ std::cout << "selected type is not supported yet" << std::endl;
+ break;
+ default:
+ std::cout << "Error! Please select valid credential type" << std::endl;
+ break;
+ }
+ } while(0 != choice);
+
+ std::cout << "Please enter key size (valid size is 128 or 256) :";
+ std::cin >> choice;
+
+ if(128 == choice)
+ {
+ cred.setCredentialKeySize(OWNER_PSK_LENGTH_128);
+ }
+ else if(256 == choice)
+ {
+ cred.setCredentialKeySize(OWNER_PSK_LENGTH_256);
+ }
+ else
+ {
+ std::cout << "Error! Please enter valid key size!" << std::endl;
+ return -2;
+ }
+
+ return 0;
+}
+
+int main(void)
+{
+ OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
+
+ // Create PlatformConfig object
+ PlatformConfig cfg {
+ OC::ServiceType::InProc,
+ OC::ModeType::Both,
+ "0.0.0.0",
+ 0,
+ OC::QualityOfService::LowQos,
+ &ps
+ };
+
+ OCPlatform::Configure(cfg);
+
+ try
+ {
+ int choice;
+ OicSecAcl_t *acl1 = nullptr, *acl2 = nullptr;
+ if (OCSecure::provisionInit("") != OC_STACK_OK)
+ {
+ std::cout <<"PM Init failed"<< std::endl;
+ return 1;
+ }
+
+ for (int out = 0; !out;)
+ {
+ while (!ask)
+ {
+ sleep(1);
+ }
+
+ if (acl1)
+ {
+ deleteACL(acl1);
+ acl1 = nullptr;
+ }
+
+ if (acl2)
+ {
+ deleteACL(acl2);
+ acl2 = nullptr;
+ }
+
+ printMenu();
+ std::cin >> choice;
+ switch(choice) {
+ case 1:
+ {
+ //Secure resource discovery.
+
+ pUnownedDevList.clear();
+ std::cout << "Started discovery..." <<std::endl;
+ OCStackResult result = OCSecure::discoverUnownedDevices(DISCOVERY_TIMEOUT,
+ pUnownedDevList);
+ if (result != OC_STACK_OK)
+ {
+ std::cout<< "!!Error - UnOwned Discovery failed."<<std::endl;
+ }
+ else if (pUnownedDevList.size())
+ {
+ std::cout <<"Found secure devices, count = " <<
+ pUnownedDevList.size() << std::endl;
+ printDevices(pUnownedDevList);
+ }
+ else
+ {
+ std::cout <<"No Secure devices found"<<std::endl;
+ }
+ break;
+ }
+ case 2:
+ {
+ pOwnedDevList.clear();
+ std::cout << "Started discovery..." <<std::endl;
+ OCStackResult result = OCSecure::discoverOwnedDevices(DISCOVERY_TIMEOUT,
+ pOwnedDevList);
+ if (result != OC_STACK_OK)
+ {
+ std::cout<< "!!Error - Owned Discovery failed."<<std::endl;
+ }
+ else if (pOwnedDevList.size())
+ {
+ std::cout <<"Found owned devices, count = " <<
+ pOwnedDevList.size() << std::endl;
+ printDevices(pOwnedDevList);
+ }
+ else
+ {
+ std::cout <<"No Secure devices found"<<std::endl;
+ }
+ break;
+ }
+ case 3:
+ {
+ unsigned int devNum;
+
+ if (!pUnownedDevList.size())
+ {
+ std::cout <<"There are no more Unowned devices"<<std::endl;
+ break;
+ }
+
+ for (unsigned int i = 0; i < pUnownedDevList.size(); i++ )
+ {
+ std::cout << i+1 << ": "<< pUnownedDevList[i]->getDeviceID();
+ std::cout << " From IP:" << pUnownedDevList[i]->getDevAddr() <<std::endl;
+ }
+
+ std::cout <<"Select device number: "<<std::endl;
+ std::cin >> devNum;
+ if (devNum > pUnownedDevList.size())
+ {
+ std::cout <<"Invalid device number"<<std::endl;
+ break;
+ }
+ transferDevIdx = devNum - 1;
+
+ //register callbacks for JUST WORKS and PIN methods
+ std::cout <<"Registering OTM Methods: 1. JUST WORKS and 2. PIN"<<std::endl;
+
+ {
+ OTMCallbackData_t justWorksCBData;
+ justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+ justWorksCBData.createSecureSessionCB =
+ CreateSecureSessionJustWorksCallback;
+ justWorksCBData.createSelectOxmPayloadCB =
+ CreateJustWorksSelectOxmPayload;
+ justWorksCBData.createOwnerTransferPayloadCB =
+ CreateJustWorksOwnerTransferPayload;
+ OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS,
+ &justWorksCBData, NULL);
+ }
+
+ {
+ OTMCallbackData_t pinBasedCBData;
+ pinBasedCBData.loadSecretCB = InputPinCodeCallback;
+ pinBasedCBData.createSecureSessionCB =
+ CreateSecureSessionRandomPinCallbak;
+ pinBasedCBData.createSelectOxmPayloadCB =
+ CreatePinBasedSelectOxmPayload;
+ pinBasedCBData.createOwnerTransferPayloadCB =
+ CreatePinBasedOwnerTransferPayload;
+ OCSecure::setOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN,
+ &pinBasedCBData, InputPinCB);
+ }
+
+ ask = 0;
+ std::cout << "Transfering ownership for : "<<
+ pUnownedDevList[devNum-1]->getDeviceID()<<std::endl;
+ if (pUnownedDevList[devNum-1]->doOwnershipTransfer(ownershipTransferCB)
+ != OC_STACK_OK)
+ {
+ std::cout<<"OwnershipTransferCallback is failed"<<std::endl;
+ ask = 1;
+ }
+ break;
+ }
+ case 4: //Provision ACL
+ {
+ int index;
+
+ if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
+
+ std::cout << "Provision ACL for : "<<
+ pOwnedDevList[index]->getDeviceID()<< std::endl;
+
+ acl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+ if (NULL == acl1)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ break;
+ }
+
+ std::cout << "Please input ACL for selected device: " << std::endl;
+ if (0 != InputACL(acl1))
+ {
+ break;
+ }
+
+ ask = 0;
+
+ if (pOwnedDevList[index]->provisionACL(acl1, provisionCB) != OC_STACK_OK)
+ {
+ ask = 1;
+ std::cout <<"provisionACL is failed"<< std::endl;
+ }
+ }
+ break;
+ case 5: //Provision Credentials
+ {
+ int devices[2];
+
+ if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
+
+ int first = devices[0];
+ int second = devices[1];
+
+ std::cout << "Provision Credentials to devices: "<<
+ pOwnedDevList[first]->getDeviceID();
+ std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
+
+ Credential cred( NO_SECURITY_MODE ,0);
+ std::cout << "Please input credentials for selected devices: " << std::endl;
+ if (0 != InputCredentials(cred))
+ break;
+
+ ask = 0;
+
+ if (pOwnedDevList[first]->provisionCredentials(cred,
+ *pOwnedDevList[second].get(), provisionCB) != OC_STACK_OK)
+ {
+ ask = 1;
+ std::cout <<"provisionCredentials is failed"<< std::endl;
+ }
+ }
+ break;
+ case 6: //Provision ACL & Creds b/w two devices.
+ {
+ int devices[2];
+
+ if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
+
+ int first = devices[0];
+ int second = devices[1];
+
+ std::cout << "Provision pairwise devices: "<<
+ pOwnedDevList[first]->getDeviceID();
+ std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
+
+ Credential cred( NO_SECURITY_MODE, 0);
+ std::cout << "Please input credentials for selected devices: " << std::endl;
+ if (0 != InputCredentials(cred))
+ break;
+
+ acl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+ if (NULL == acl1)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ break;
+ }
+
+ std::cout << "Please input ACL for selected device: " << std::endl;
+ if (0 != InputACL(acl1))
+ {
+ break;
+ }
+
+ acl2 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+ if (NULL == acl2)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ break;
+ }
+
+ std::cout << "Please input ACL for selected device: " << std::endl;
+ if (0 != InputACL(acl2))
+ {
+ break;
+ }
+
+ ask = 0;
+
+ if (pOwnedDevList[first]->provisionPairwiseDevices(cred, acl1,
+ *pOwnedDevList[second].get(), acl2, provisionCB) != OC_STACK_OK)
+ {
+ ask = 1;
+ std::cout <<"provisionPairwiseDevices is failed"<< std::endl;
+ }
+ }
+ break;
+ case 7: //Unlink Devices
+ {
+ int devices[2];
+
+ if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
+
+ int first = devices[0];
+ int second = devices[1];
+
+ std::cout << "Unlink devices: "<< pOwnedDevList[first]->getDeviceID();
+ std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
+
+ ask = 0;
+
+ if (pOwnedDevList[first]->unlinkDevices(*pOwnedDevList[second].get(),
+ provisionCB) != OC_STACK_OK)
+ {
+ ask = 1;
+ std::cout <<"unlinkDevice is failed"<< std::endl;
+ }
+ break;
+ }
+ case 8: //Remove Device
+ {
+ int index;
+
+ if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
+
+ std::cout << "Remove Device: "<< pOwnedDevList[index]->getDeviceID()<< std::endl;
+
+ ask = 0;
+
+ if (pOwnedDevList[index]->removeDevice(DISCOVERY_TIMEOUT, provisionCB)
+ != OC_STACK_OK)
+ {
+ ask = 1;
+ std::cout <<"removeDevice is failed"<< std::endl;
+ }
+ break;
+ }
+ case 9: //Get Linked devices
+ {
+ UuidList_t linkedUuid;
+ unsigned int devNum;
+
+ if (!pOwnedDevList.size())
+ {
+ std::cout <<"There are no Owned devices yet,"
+ " may need to discover"<<std::endl;
+ break;
+ }
+
+ for (unsigned int i = 0; i < pOwnedDevList.size(); i++ )
+ {
+ std::cout << i+1 << ": "<< pOwnedDevList[i]->getDeviceID() <<" From IP:";
+ std::cout << pOwnedDevList[i]->getDevAddr() <<std::endl;
+ }
+
+ std::cout <<"Select device number: "<<std::endl;
+ std::cin >> devNum;
+ if (devNum > pOwnedDevList.size())
+ {
+ std::cout <<"Invalid device number"<<std::endl;
+ break;
+ }
+
+ if(pOwnedDevList[devNum -1]->getLinkedDevices(linkedUuid) == OC_STACK_OK)
+ {
+ if (!linkedUuid.size())
+ {
+ std::cout <<"No devices are linked to "<<
+ pOwnedDevList[devNum -1]->getDeviceID() << std::endl;
+ }
+ //display the Linked devices (UUIDs)
+ for(unsigned int i = 0; i < linkedUuid.size(); i++)
+ {
+ printUuid(linkedUuid[i]);
+ }
+ }
+ else
+ {
+ std::cout <<"Error! in getLinkedDevices"<<std::endl;
+ }
+ break;
+ }
+ case 10: //Get device' status
+ {
+ DeviceList_t unownedList, ownedList;
+
+ if (OCSecure::getDevInfoFromNetwork(DISCOVERY_TIMEOUT, ownedList,
+ unownedList) == OC_STACK_OK)
+ {
+ std::cout <<"Owned Device' status for" <<std::endl;
+ for (unsigned int i = 0; i < ownedList.size(); i++ )
+ {
+ std::cout << "Device "<<i+1 <<" ID: '";
+ std::cout << ownedList[i]->getDeviceID() << "' From IP: ";
+ std::cout << ownedList[i]->getDevAddr() << " Status: ";
+ printStatus(ownedList[i]->getDeviceStatus());
+ }
+ std::cout <<"\nUnOwned Device' status for" <<std::endl;
+ for (unsigned int i = 0; i < unownedList.size(); i++ )
+ {
+ std::cout << "Device "<<i+1 <<" ID: '";
+ std::cout << unownedList[i]->getDeviceID() << "' From IP: ";
+ std::cout << unownedList[i]->getDevAddr() << " Status: ";
+ printStatus(unownedList[i]->getDeviceStatus());
+ }
+
+ }
+ break;
+ }
+
+ case 11:
+ default:
+ out = 1;
+ break;
+ }
+ }
+ }
+ catch(OCException& e)
+ {
+ oclog() << "Exception in main: "<<e.what();
+ }
+
+ return 0;
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "ocstack.h"
+#include "base64.h"
+#include "OCProvisioningManager.h"
+
+namespace OC
+{
+ OCStackResult OCSecure::provisionInit(const std::string& dbPath)
+ {
+ OCStackResult result;
+ auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCInitPM(dbPath.c_str());
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+ }
+
+ OCStackResult OCSecure::discoverUnownedDevices(unsigned short timeout,
+ DeviceList_t &list)
+ {
+ OCStackResult result;
+ OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
+ auto csdkLock = OCPlatform_impl::Instance().csdkLock();
+ auto cLock = csdkLock.lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCDiscoverUnownedDevices(timeout, &pDevList);
+ if (result == OC_STACK_OK)
+ {
+ // Create DeviceList of OCSecureResource's
+ pCurDev = pDevList;
+ while (pCurDev)
+ {
+ tmp = pCurDev;
+ list.push_back(std::shared_ptr<OCSecureResource>(
+ new OCSecureResource(csdkLock, pCurDev)));
+ pCurDev = pCurDev->next;
+ tmp->next = nullptr;
+ }
+ }
+ else
+ {
+ oclog() <<"Unowned device discovery failed!";
+ }
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+ }
+
+ OCStackResult OCSecure::discoverOwnedDevices(unsigned short timeout,
+ DeviceList_t &list)
+ {
+ OCStackResult result;
+ OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
+ auto csdkLock = OCPlatform_impl::Instance().csdkLock();
+ auto cLock = csdkLock.lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCDiscoverOwnedDevices(timeout, &pDevList);
+ if (result == OC_STACK_OK)
+ {
+ pCurDev = pDevList;
+ while (pCurDev)
+ {
+ tmp = pCurDev;
+ list.push_back(std::shared_ptr<OCSecureResource>(
+ new OCSecureResource(csdkLock, pCurDev)));
+ pCurDev = pCurDev->next;
+ tmp->next = nullptr;
+ }
+ }
+ else
+ {
+ oclog() <<"Owned device discovery failed!";
+ }
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+ }
+
+ OCStackResult OCSecure::setOwnerTransferCallbackData(OicSecOxm_t oxm,
+ OTMCallbackData_t* callbackData, InputPinCallback inputPin)
+ {
+ if(NULL == callbackData || oxm >= OIC_OXM_COUNT)
+ {
+ oclog() <<"Invalid callbackData or OXM type";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ if((OIC_RANDOM_DEVICE_PIN == oxm) && !inputPin)
+ {
+ oclog() <<"for OXM type DEVICE_PIN, inputPin callback can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCSetOwnerTransferCallbackData(oxm, callbackData);
+ if(result == OC_STACK_OK && (OIC_RANDOM_DEVICE_PIN & oxm))
+ {
+ SetInputPinCB(inputPin);
+ }
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+
+ }
+
+ OCStackResult OCSecure::getDevInfoFromNetwork(unsigned short timeout,
+ DeviceList_t &ownedDevList,
+ DeviceList_t &unownedDevList)
+ {
+ OCStackResult result = OC_STACK_OK;
+ OCProvisionDev_t *owned = nullptr, *unowned = nullptr, *tmp = nullptr, *dev = nullptr;
+ auto csdkLock = OCPlatform_impl::Instance().csdkLock();
+ auto cLock = csdkLock.lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+
+ result = OCGetDevInfoFromNetwork(timeout, &owned, &unowned);
+
+ if (result == OC_STACK_OK)
+ {
+ dev = owned;
+ while (dev)
+ {
+ tmp = dev;
+ ownedDevList.push_back(std::shared_ptr<OCSecureResource>(
+ new OCSecureResource(csdkLock, dev)));
+ dev = dev->next;
+ tmp->next = nullptr;
+ }
+
+ dev = unowned;
+ while (dev)
+ {
+ tmp = dev;
+ unownedDevList.push_back(std::shared_ptr<OCSecureResource>(
+ new OCSecureResource(csdkLock, dev)));
+ dev = dev->next;
+ tmp->next = nullptr;
+ }
+ }
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+ }
+
+ void OCSecureResource::callbackWrapper(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+ {
+ PMResultList_t *results = nullptr;
+ ProvisionContext* context = static_cast<ProvisionContext*>(ctx);
+
+ results = new PMResultList_t;
+ for (int i = 0; i < nOfRes; i++)
+ {
+ results->push_back(arr[i]);
+ }
+
+ std::thread exec(context->callback, results, hasError);
+ exec.detach();
+
+ delete context;
+ }
+
+ OCSecureResource::OCSecureResource(): m_csdkLock(std::weak_ptr<std::recursive_mutex>()),
+ devPtr(nullptr)
+ {
+ }
+
+ OCSecureResource::OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock,
+ OCProvisionDev_t *dPtr)
+ :m_csdkLock(csdkLock), devPtr(dPtr)
+ {
+ }
+
+ OCSecureResource::~OCSecureResource()
+ {
+ if(devPtr)
+ {
+ OCDeleteDiscoveredDevices(devPtr);
+ }
+ }
+
+ OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
+ {
+ if(!resultCallback)
+ {
+ oclog() <<"Result callback can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ ProvisionContext* context = new ProvisionContext(resultCallback);
+
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCDoOwnershipTransfer(static_cast<void*>(context),
+ devPtr, &OCSecureResource::callbackWrapper);
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
+ ResultCallBack resultCallback)
+ {
+ if(!resultCallback || !acl)
+ {
+ oclog() <<"Result callback or ACL can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ ProvisionContext* context = new ProvisionContext(resultCallback);
+
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCProvisionACL(static_cast<void*>(context),
+ devPtr, const_cast<OicSecAcl_t*>(acl),
+ &OCSecureResource::callbackWrapper);
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ OCStackResult OCSecureResource::provisionCredentials(const Credential &cred,
+ const OCSecureResource &device2, ResultCallBack resultCallback)
+ {
+ if(!resultCallback)
+ {
+ oclog() << "Result calback can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ ProvisionContext* context = new ProvisionContext(resultCallback);
+
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCProvisionCredentials(static_cast<void*>(context),
+ cred.getCredentialType(),
+ cred.getCredentialKeySize(),
+ devPtr, device2.getDevPtr(),
+ &OCSecureResource::callbackWrapper);
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ OCStackResult OCSecureResource::provisionPairwiseDevices(const Credential &cred,
+ const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2,
+ ResultCallBack resultCallback)
+ {
+ if(!resultCallback)
+ {
+ oclog() << "Result calback can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ ProvisionContext* context = new ProvisionContext(resultCallback);
+
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCProvisionPairwiseDevices(static_cast<void*>(context),
+ cred.getCredentialType(),
+ cred.getCredentialKeySize(),
+ devPtr, const_cast<OicSecAcl_t*>(acl1),
+ device2.getDevPtr(), const_cast<OicSecAcl_t*>(acl2),
+ &OCSecureResource::callbackWrapper);
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2,
+ ResultCallBack resultCallback)
+ {
+ if(!resultCallback)
+ {
+ oclog() << "Result calback can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ ProvisionContext* context = new ProvisionContext(resultCallback);
+
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+
+ result = OCUnlinkDevices(static_cast<void*>(context),
+ devPtr, device2.getDevPtr(), &OCSecureResource::callbackWrapper);
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ OCStackResult OCSecureResource::removeDevice(unsigned short waitTimeForOwnedDeviceDiscovery,
+ ResultCallBack resultCallback)
+ {
+ if(!resultCallback)
+ {
+ oclog() << "Result calback can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ ProvisionContext* context = new ProvisionContext(resultCallback);
+
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+
+ result = OCRemoveDevice(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
+ devPtr, &OCSecureResource::callbackWrapper);
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ OCStackResult OCSecureResource::getLinkedDevices(UuidList_t &uuidList)
+ {
+ OCStackResult result;
+ size_t numOfDevices = -1;
+ auto devUuid = devPtr->doxm->deviceID;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+
+ OCUuidList_t* linkedDevs = nullptr, *tmp = nullptr;
+ result = OCGetLinkedStatus(&devUuid, &linkedDevs, &numOfDevices);
+ if (result == OC_STACK_OK)
+ {
+ for (tmp = linkedDevs; tmp; tmp = tmp->next)
+ {
+ uuidList.push_back(tmp->dev);
+ }
+ OCDeleteUuidList(linkedDevs);
+ }
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ std::string OCSecureResource::getDeviceID()
+ {
+ char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {0,};
+ uint32_t outLen = 0;
+ B64Result b64Ret = B64_OK;
+ std::ostringstream deviceId("");
+
+ validateSecureResource();
+ b64Ret = b64Encode(devPtr->doxm->deviceID.id, sizeof(devPtr->doxm->deviceID.id), base64Buff,
+ sizeof(base64Buff), &outLen);
+
+ if (B64_OK == b64Ret)
+ {
+ deviceId << base64Buff;
+ }
+ return deviceId.str();
+ }
+
+ OCProvisionDev_t* OCSecureResource::getDevPtr() const
+ {
+ return devPtr;
+ }
+
+ std::string OCSecureResource::getDevAddr()
+ {
+ validateSecureResource();
+ std::string ipAddr(devPtr->endpoint.addr);
+ return ipAddr;
+ }
+
+ int OCSecureResource::getDeviceStatus()
+ {
+ validateSecureResource();
+ return (int)devPtr->devStatus;
+ }
+
+ bool OCSecureResource::getOwnedStatus()
+ {
+ validateSecureResource();
+ return devPtr->doxm->owned;
+ }
+
+ void OCSecureResource::validateSecureResource()
+ {
+ if (!devPtr)
+ {
+ throw OCException("Incomplete secure resource", OC_STACK_RESOURCE_ERROR);
+ }
+ }
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 <ocstack.h>
+#include <oic_malloc.h>
+#include <OCApi.h>
+#include <OCPlatform_impl.h>
+#include <oxmjustworks.h>
+#include <oxmrandompin.h>
+#include <OCProvisioningManager.h>
+#include <gtest/gtest.h>
+
+#define TIMEOUT 5
+
+namespace OCProvisioningTest
+{
+ using namespace OC;
+
+ void resultCallback(PMResultList_t *result, int hasError)
+ {
+ (void)result;
+ (void)hasError;
+ }
+
+ TEST(ProvisionInitTest, TestWithEmptyPath)
+ {
+ std::string dbPath("");
+ EXPECT_EQ(OC_STACK_OK, OCSecure::provisionInit(dbPath));
+ }
+
+ TEST(ProvisionInitTest, TestValidPath)
+ {
+ std::string dbPath("./dbPath");
+ EXPECT_EQ(OC_STACK_OK, OCSecure::provisionInit(dbPath));
+ }
+
+ TEST(DiscoveryTest, UnownedDevices)
+ {
+ DeviceList_t list;
+ EXPECT_EQ(OC_STACK_OK, OCSecure::discoverUnownedDevices(TIMEOUT, list));
+ }
+
+ TEST(DiscoveryTest, UnownedDevicesZeroTimeout)
+ {
+ DeviceList_t list;
+ EXPECT_EQ(OC_STACK_OK, OCSecure::discoverUnownedDevices(0, list));
+ }
+
+ TEST(DiscoveryTest, OwnedDevices)
+ {
+ DeviceList_t list;
+ EXPECT_EQ(OC_STACK_OK, OCSecure::discoverOwnedDevices(TIMEOUT, list));
+ }
+
+ TEST(DiscoveryTest, OwnedDevicesZeroTimeout)
+ {
+ DeviceList_t list;
+ EXPECT_EQ(OC_STACK_OK, OCSecure::discoverOwnedDevices(0, list));
+ }
+
+ TEST(OwnershipTest, SetOwnershipTransferCBDataNull)
+ {
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSecure::setOwnerTransferCallbackData(
+ OIC_JUST_WORKS, NULL, NULL));
+ }
+
+ TEST(OwnershipTest, SetOwnershipTransferCBData)
+ {
+ OTMCallbackData_t justWorksCBData;
+ justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+ justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+ justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+ justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+ EXPECT_EQ(OC_STACK_OK, OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS,
+ &justWorksCBData, NULL));
+ }
+
+ TEST(OwnershipTest, SetOwnershipTransferCBDataInvalidType)
+ {
+ OTMCallbackData_t justWorksCBData;
+ justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+ justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+ justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+ justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSecure::setOwnerTransferCallbackData(OIC_OXM_COUNT,
+ &justWorksCBData, NULL));
+ }
+
+ TEST(OwnershipTest, SetOwnershipTransferCBDataNullInputPin)
+ {
+ OTMCallbackData_t pinBasedCBData;
+ pinBasedCBData.loadSecretCB = InputPinCodeCallback;
+ pinBasedCBData.createSecureSessionCB = CreateSecureSessionRandomPinCallbak;
+ pinBasedCBData.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
+ pinBasedCBData.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
+ OTMSetOwnershipTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &pinBasedCBData);
+
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSecure::setOwnerTransferCallbackData(
+ OIC_RANDOM_DEVICE_PIN, &pinBasedCBData, NULL));
+ }
+
+ TEST(OwnershipTest, OwnershipTransferNullCallback)
+ {
+ OCSecureResource device;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, device.doOwnershipTransfer(nullptr));
+ }
+
+ TEST(DeviceInfoTest, DevInfoFromNetwork)
+ {
+ DeviceList_t owned, unowned;
+ EXPECT_EQ(OC_STACK_OK, OCSecure::getDevInfoFromNetwork(TIMEOUT,
+ owned, unowned));
+ }
+
+ TEST(ProvisionAclTest, ProvisionAclTestNullAcl)
+ {
+ OCSecureResource device;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionACL(nullptr, resultCallback));
+ }
+
+ TEST(ProvisionAclTest, ProvisionAclTestNullCallback)
+ {
+ OCSecureResource device;
+ OicSecAcl_t *acl = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionACL(acl, nullptr));
+ OICFree(acl);
+ }
+
+ TEST(ProvisionAclTest, ProvisionAclTestNullCallbackNUllAcl)
+ {
+ OCSecureResource device;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionACL(nullptr, nullptr));
+ }
+
+ TEST(ProvisionCredTest, ProvisionCredTestNullCallback)
+ {
+ OCSecureResource device, dev2;
+ Credential cred;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionCredentials(cred, dev2, nullptr));
+ }
+
+ TEST(ProvisionPairwiseTest, ProvisionPairwiseTestNullCallback)
+ {
+ OCSecureResource device, dev2;
+ Credential cred;
+ OicSecAcl_t *acl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+ OicSecAcl_t *acl2 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionPairwiseDevices(cred, acl1,
+ dev2, acl2, nullptr));
+ OICFree(acl1);
+ OICFree(acl2);
+ }
+
+}
--- /dev/null
+#******************************************************************
+#
+# 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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Import('env')
+import os
+import os.path
+provisiontests_env = env.Clone()
+
+src_dir = provisiontests_env.get('SRC_DIR')
+######################################################################
+# Build flags
+######################################################################
+provisiontests_env.PrependUnique(CPPPATH = [
+ '../../include',
+ '../../oc_logger/include',
+ '../../csdk/stack/include',
+ '../../csdk/security/include',
+ '../../csdk/security/provisioning/include',
+ '../../csdk/security/provisioning/include/oxm',
+ '../../csdk/security/provisioning/include/internal',
+ '../../csdk/stack/include/internal',
+ '../../csdk/connectivity/api',
+ '../../csdk/connectivity/external/inc',
+ '../../csdk/ocsocket/include',
+ '../../csdk/ocrandom/include',
+ '../../csdk/logger/include',
+ '../../../extlibs/gtest/gtest-1.7.0/include',
+ '../../../extlibs/hippomocks-master/HippoMocks',
+ '../../../extlibs/hippomocks-master/HippoMocksTest'
+ ])
+
+provisiontests_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+provisiontests_env.AppendUnique(LIBS = ['-lpthread'])
+provisiontests_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+provisiontests_env.AppendUnique(LIBPATH = [src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs'])
+provisiontests_env.PrependUnique(LIBS = [
+ 'ocprovision',
+ 'oc',
+ 'ocpmapi',
+ 'octbstack',
+ 'oc_logger',
+ 'connectivity_abstraction',
+ 'coap',
+ 'gtest',
+ 'gtest_main',
+ ])
+
+if env.get('SECURED') == '1':
+ provisiontests_env.AppendUnique(LIBS = ['tinydtls'])
+
+if env.get('LOGGING'):
+ provisiontests_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+unittests = provisiontests_env.Program('provisiontests', ['OCProvisioningTest.cpp'])
+
+Alias("provisiontests", [unittests])
+
+env.AppendTarget('provisiontests')
+if env.get('TEST') == '1':
+ target_os = env.get('TARGET_OS')
+ if target_os == 'linux':
+ out_dir = env.get('BUILD_DIR')
+ result_dir = env.get('BUILD_DIR') + '/test_out/'
+ if not os.path.isdir(result_dir):
+ os.makedirs(result_dir)
+ provisiontests_env.AppendENVPath('GTEST_OUTPUT', ['xml:'+ result_dir])
+ provisiontests_env.AppendENVPath('LD_LIBRARY_PATH', [out_dir])
+ provisiontests_env.AppendENVPath('LD_LIBRARY_PATH', ['./extlibs/gtest/gtest-1.7.0/lib/.libs'])
+ ut = provisiontests_env.Command ('ut', None, out_dir + 'resource/provisioning/unittests/provisiontests')
+ AlwaysBuild ('ut')
+
+src_dir = provisiontests_env.get('SRC_DIR')
+svr_db_src_dir = src_dir + '/resource/provisioning/examples/'
+svr_db_build_dir = env.get('BUILD_DIR') +'/resource/provisioning/unittests/'
+provisiontests_env.Alias("install", provisiontests_env.Install( svr_db_build_dir,
+ svr_db_src_dir + 'oic_svr_db_client.json'))
{
initType = OC_CLIENT_SERVER;
}
+ else if (cfg.mode == ModeType::Gateway)
+ {
+ initType = OC_GATEWAY;
+ }
else
{
throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
return OC::Exception::INVALID_REPRESENTATION;
case OC_STACK_UNAUTHORIZED_REQ:
return OC::Exception::UNAUTHORIZED_REQUEST;
+ case OC_STACK_PDM_IS_NOT_INITIALIZED:
+ return OC::Exception::PDM_DB_NOT_INITIALIZED;
+ case OC_STACK_DUPLICATE_UUID:
+ return OC::Exception::DUPLICATE_UUID;
+ case OC_STACK_INCONSISTENT_DB:
+ return OC::Exception::INCONSISTENT_DB;
}
return OC::Exception::UNKNOWN_ERROR;
break;
case ModeType::Both:
+ case ModeType::Gateway:
m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config);
m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config);
break;
return checked_guard(m_server, &IServerWrapper::sendResponse,
pResponse);
}
+
+ std::weak_ptr<std::recursive_mutex> OCPlatform_impl::csdkLock()
+ {
+ return m_csdkLock;
+ }
} //namespace OC
{
root_size_calc<T>();
dimensions[0] = arr.size();
+ dimensions[1] = 0;
+ dimensions[2] = 0;
dimTotal = calcDimTotal(dimensions);
array = (void*)OICMalloc(dimTotal * root_size);
{
root_size_calc<T>();
dimensions[0] = arr.size();
+ dimensions[1] = 0;
+ dimensions[2] = 0;
for(size_t i = 0; i < arr.size(); ++i)
{
dimensions[1] = std::max(dimensions[1], arr[i].size());
{
root_size_calc<T>();
dimensions[0] = arr.size();
+ dimensions[1] = 0;
+ dimensions[2] = 0;
for(size_t i = 0; i < arr.size(); ++i)
{
dimensions[1] = std::max(dimensions[1], arr[i].size());
}
template<>
+ void get_payload_array::copy_to_array(std::string item, void* array, size_t pos)
+ {
+ ((char**)array)[pos] = OICStrdup(item.c_str());
+ }
+
+ template<>
+ void get_payload_array::copy_to_array(std::string& item, void* array, size_t pos)
+ {
+ ((char**)array)[pos] = OICStrdup(item.c_str());
+ }
+
+ template<>
void get_payload_array::copy_to_array(const std::string& item, void* array, size_t pos)
{
((char**)array)[pos] = OICStrdup(item.c_str());
OCRepPayloadSetPropInt(root, val.attrname().c_str(), static_cast<int>(val));
break;
case AttributeType::Double:
- OCRepPayloadSetPropDouble(root, val.attrname().c_str(), val);
+ OCRepPayloadSetPropDouble(root, val.attrname().c_str(),
+ val.getValue<double>());
break;
case AttributeType::Boolean:
- OCRepPayloadSetPropBool(root, val.attrname().c_str(), val);
+ OCRepPayloadSetPropBool(root, val.attrname().c_str(), val.getValue<bool>());
break;
case AttributeType::String:
OCRepPayloadSetPropString(root, val.attrname().c_str(),
}
}
- OCRepPayload* cur = root;
- for(auto& child : this->getChildren())
- {
- cur->next = child.getPayload();
- cur = cur->next;
- }
-
return root;
}
std::string OCRepresentation::payload_array_helper_copy<std::string>(
size_t index, const OCRepPayloadValue* pl)
{
- return std::string(pl->arr.strArray[index]);
+ if (pl->arr.strArray[index])
+ {
+ return std::string(pl->arr.strArray[index]);
+ }
+ else
+ {
+ return std::string{};
+ }
}
template<>
OCRepresentation OCRepresentation::payload_array_helper_copy<OCRepresentation>(
size_t index, const OCRepPayloadValue* pl)
{
OCRepresentation r;
- r.setPayload(pl->arr.objArray[index]);
+ if (pl->arr.objArray[index])
+ {
+ r.setPayload(pl->arr.objArray[index]);
+ }
return r;
}
std::vector<std::vector<T>> val(pl->arr.dimensions[0]);
for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
{
- val[i].reserve(pl->arr.dimensions[1]);
+ val[i].resize(pl->arr.dimensions[1]);
for(size_t j = 0; j < pl->arr.dimensions[1]; ++j)
{
val[i][j] = payload_array_helper_copy<T>(
}
else if (depth == 3)
{
- std::vector<std::vector<std::vector<T>>> val;
+ std::vector<std::vector<std::vector<T>>> val(pl->arr.dimensions[0]);
for(size_t i = 0; i < pl->arr.dimensions[0]; ++i)
{
- val[i].reserve(pl->arr.dimensions[1]);
+ val[i].resize(pl->arr.dimensions[1]);
for(size_t j = 0; j < pl->arr.dimensions[1]; ++j)
{
- val[i][j].reserve(pl->arr.dimensions[2]);
+ val[i][j].resize(pl->arr.dimensions[2]);
for(size_t k = 0; k < pl->arr.dimensions[2]; ++k)
{
val[i][j][k] = payload_array_helper_copy<T>(
static const char COAP[] = "coap://";
static const char COAPS[] = "coaps://";
+
+#ifdef TCP_ADAPTER
+static const char COAP_TCP[] = "coap+tcp://";
+#endif
+
using OC::nil_guard;
using OC::result_guard;
using OC::checked_guard;
const std::vector<std::string>& interfaces)
: m_clientWrapper(clientWrapper), m_uri(uri),
m_resourceId(serverId, m_uri),
- m_devAddr{ OC_DEFAULT_ADAPTER },
+ m_devAddr{ OC_DEFAULT_ADAPTER, OC_DEFAULT_FLAGS, 0, {0}, 0 },
m_isObservable(observable), m_isCollection(false),
m_resourceTypes(resourceTypes), m_interfaces(interfaces),
m_observeHandle(nullptr)
interfaces.empty(), m_clientWrapper.expired(), false, false);
}
+ if (uri.length() == 1 && uri[0] == '/')
+ {
+ throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
+ interfaces.empty(), m_clientWrapper.expired(), false, false);
+ }
+
+ if (uri[0] != '/')
+ {
+ throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
+ interfaces.empty(), m_clientWrapper.expired(), false, false);
+ }
+
// construct the devAddr from the pieces we have
m_devAddr.adapter = static_cast<OCTransportAdapter>(connectivityType >> CT_ADAPTER_SHIFT);
m_devAddr.flags = static_cast<OCTransportFlags>(connectivityType & CT_MASK_FLAGS);
prefix_len = sizeof(COAPS) - 1;
m_devAddr.flags = static_cast<OCTransportFlags>(m_devAddr.flags & OC_SECURE);
}
+#ifdef TCP_ADAPTER
+ else if (host.compare(0, sizeof(COAP_TCP) - 1, COAP_TCP) == 0)
+ {
+ prefix_len = sizeof(COAP_TCP) - 1;
+ m_devAddr.adapter = static_cast<OCTransportAdapter>(m_devAddr.adapter & OC_ADAPTER_TCP);
+ }
+#endif
else
{
throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
m_interfaces.empty(), m_clientWrapper.expired(), false, false);
}
- // removed coap:// or coaps://
+ // removed coap:// or coaps:// or coap+tcp://
std::string host_token = host.substr(prefix_len);
if(host_token[0] == '[')
size_t found = host_token.find(']');
- if(found == std::string::npos)
+ if(found == std::string::npos || found == 0)
{
throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
m_interfaces.empty(), m_clientWrapper.expired(), false, false);
{
size_t found = host_token.find(':');
- if(found == std::string::npos)
+ if(found == std::string::npos || found == 0)
{
throw ResourceInitException(m_uri.empty(), m_resourceTypes.empty(),
m_interfaces.empty(), m_clientWrapper.expired(), false, false);
{
ss << COAPS;
}
+#ifdef TCP_ADAPTER
+ else if (m_devAddr.adapter & OC_ADAPTER_TCP)
+ {
+ ss << COAP_TCP;
+ }
+#endif
else
{
ss << COAP;
oclib_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
oclib_env.AppendUnique(LIBS = ['boost_thread', 'gnustl_shared', 'log'])
+if target_os == 'tizen':
+ oclib_env.AppendUnique(CPPDEFINES = ['__TIZEN__'])
+
######################################################################
# Source files and Targets
######################################################################
oclib_env.InstallTarget(oclib, 'liboc')
oclib_env.UserInstallTargetLib(oclib, 'liboc')
+src_dir = env.get('SRC_DIR')
+
+oclib_env.UserInstallTargetHeader(src_dir + '/resource/include/OCApi.h', 'resource', 'OCApi.h')
+oclib_env.UserInstallTargetHeader(src_dir + '/resource/include/OCPlatform.h', 'resource', 'OCPlatform.h')
+oclib_env.UserInstallTargetHeader(src_dir + '/resource/include/OCRepresentation.h', 'resource', 'OCRepresentation.h')
+oclib_env.UserInstallTargetHeader(src_dir + '/resource/include/OCResource.h', 'resource', 'OCResource.h')
+oclib_env.UserInstallTargetHeader(src_dir + '/resource/include/OCResourceRequest.h', 'resource', 'OCResourceRequest.h')
+oclib_env.UserInstallTargetHeader(src_dir + '/resource/include/OCResourceResponse.h', 'resource', 'OCResourceResponse.h')
+
+# Add Provisioning library
+if target_os in ['linux', 'android'] and env.get('SECURED') == '1':
+ SConscript('../provisioning/SConscript')
# Build Provisioning API unit test
if env.get('SECURED') == '1':
SConscript('csdk/security/provisioning/unittest/SConscript')
+ SConscript('provisioning/unittests/SConscript')
elif target_os == 'darwin':
# Verify that 'google unit test' library is installed. If not,
OC_STACK_PRESENCE_STOPPED,
OC_STACK_PRESENCE_TIMEOUT,
OC_STACK_PRESENCE_DO_NOT_HANDLE,
- OC_STACK_ERROR
+ OC_STACK_ERROR,
+ OC_STACK_PDM_IS_NOT_INITIALIZED,
+ OC_STACK_DUPLICATE_UUID,
+ OC_STACK_INCONSISTENT_DB
};
std::string resultMessages[]=
OC::Exception::PRESENCE_STOPPED,
OC::Exception::PRESENCE_TIMEOUT,
OC::Exception::PRESENCE_NOT_HANDLED,
- OC::Exception::GENERAL_FAULT
+ OC::Exception::GENERAL_FAULT,
+ OC::Exception::PDM_DB_NOT_INITIALIZED,
+ OC::Exception::DUPLICATE_UUID,
+ OC::Exception::INCONSISTENT_DB
};
TEST(OCExceptionTest, ReasonCodeMatches)
{
const std::string gResourceInterface = DEFAULT_INTERFACE;
const uint8_t gResourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
OCResourceHandle resourceHandle;
- //OCPersistent Storage Handlers
- static FILE* client_open(const char *path, const char *mode)
- {
- std::cout << "<===Opening SVR DB file = './oic_svr_db_client.json' with mode = '"<< mode<<"' "<<std::endl;
- return fopen("./oic_svr_db_client.json", mode);
- }
+ //OCPersistent Storage Handlers
+ static FILE* client_open(const char * /*path*/, const char *mode)
+ {
+ std::cout << "<===Opening SVR DB file = './oic_svr_db_client.json' with mode = '" << mode
+ << "' " << std::endl;
+ return fopen("./oic_svr_db_client.json", mode);
+ }
+ OCPersistentStorage gps {client_open, fread, fwrite, fclose, unlink };
+
// Callbacks
- OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
+ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> /*request*/)
{
return OC_EH_OK;
}
- void foundResource(std::shared_ptr<OCResource> resource)
+ void foundResource(std::shared_ptr<OCResource> /*resource*/)
{
}
- void receivedDeviceInfo(const OCRepresentation& rep)
+ void receivedDeviceInfo(const OCRepresentation& /*rep*/)
{
}
- void presenceHandler(OCStackResult result,
- const unsigned int nonce, const std::string& hostAddress)
+ void presenceHandler(OCStackResult /*result*/,
+ const unsigned int /*nonce*/, const std::string& /*hostAddress*/)
{
}
OCResourceHandle RegisterResource(std::string uri, std::string type, std::string iface)
{
- PlatformConfig cfg = {};
+ PlatformConfig cfg
+ { OC::ServiceType::OutOfProc, OC::ModeType::Server, "0.0.0.0", 0,
+ OC::QualityOfService::LowQos, &gps };
OCPlatform::Configure(cfg);
EXPECT_EQ(OC_STACK_OK,OCPlatform::registerResource(
resourceHandle, uri, type,
OCResourceHandle RegisterResource(std::string uri, std::string type)
{
- PlatformConfig cfg = {};
+ PlatformConfig cfg
+ { OC::ServiceType::OutOfProc, OC::ModeType::Server, "0.0.0.0", 0,
+ OC::QualityOfService::LowQos, &gps };
OCPlatform::Configure(cfg);
EXPECT_EQ(OC_STACK_OK, OCPlatform::registerResource(
resourceHandle, uri, type,
OCResourceHandle RegisterResource(std::string uri)
{
- PlatformConfig cfg = {};
+ PlatformConfig cfg
+ { OC::ServiceType::OutOfProc, OC::ModeType::Server, "0.0.0.0", 0,
+ OC::QualityOfService::LowQos, &gps };
OCPlatform::Configure(cfg);
EXPECT_EQ(OC_STACK_OK, OCPlatform::registerResource(
resourceHandle, uri, gResourceTypeName,
TEST(ConfigureTest, ConfigureServerOutProc)
{
- PlatformConfig cfg {
+ PlatformConfig cfg
+ {
OC::ServiceType::OutOfProc,
OC::ModeType::Server,
"0.0.0.0",
0,
- OC::QualityOfService::LowQos
+ OC::QualityOfService::LowQos, &gps
};
std::string uri = "/a/light67";
std::string type = "core.light";
OC::ModeType::Server,
"0.0.0.0",
0,
- OC::QualityOfService::LowQos
+ OC::QualityOfService::LowQos, &gps
};
OCPlatform::Configure(cfg);
std::string uri = "/a/light70";
std::string type = "core.light";
uint8_t gResourceProperty = 0;
- PlatformConfig cfg {
+ PlatformConfig cfg
+ {
OC::ServiceType::InProc,
OC::ModeType::Client,
"0.0.0.0",
0,
- OC::QualityOfService::LowQos
+ OC::QualityOfService::LowQos,
+ &gps
};
- OCPlatform::Configure(cfg);
EXPECT_NO_THROW(OCPlatform::registerResource(
resourceHandle, uri, type,
//PersistentStorageTest
TEST(ConfigureTest, ConfigurePersistentStorage)
{
- OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
- PlatformConfig cfg {
+ PlatformConfig cfg {
OC::ServiceType::InProc,
OC::ModeType::Both,
"0.0.0.0",
0,
OC::QualityOfService::LowQos,
- &ps
+ &gps
};
OCPlatform::Configure(cfg);
EXPECT_NO_THROW(OCPlatform::setDefaultDeviceEntityHandler(nullptr));
//PersistentStorageTest
TEST(ConfigureTest, ConfigureNULLHandlersPersistentStorage)
{
- OCPersistentStorage ps {client_open, nullptr, nullptr, nullptr, nullptr };
PlatformConfig cfg {
OC::ServiceType::InProc,
OC::ModeType::Both,
"0.0.0.0",
0,
OC::QualityOfService::LowQos,
- &ps
+ &gps
};
OCPlatform::Configure(cfg);
EXPECT_NO_THROW(OCPlatform::setDefaultDeviceEntityHandler(nullptr));
OCDeviceInfo deviceInfo;
DuplicateString(&deviceInfo.deviceName, "myDeviceName");
-
EXPECT_EQ(OC_STACK_OK, OCPlatform::registerDeviceInfo(deviceInfo));
EXPECT_NO_THROW(DeleteDeviceInfo(deviceInfo));
}
TEST(RegisterDeviceInfoTest, RegisterDeviceInfoWithEmptyObject)
{
- OCDeviceInfo di = {};
+ OCDeviceInfo di = {0};
EXPECT_ANY_THROW(OCPlatform::registerDeviceInfo(di));
}
--- /dev/null
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <gtest/gtest.h>
+#include <OCApi.h>
+#include <OCRepresentation.h>
+#include <octypes.h>
+#include <ocpayload.h>
+#include <ocpayloadcbor.h>
+#include <oic_malloc.h>
+
+namespace OC
+{
+ bool operator==(const OC::NullType&, const OC::NullType&)
+ {
+ return true;
+ }
+
+ bool operator==(const OC::OCRepresentation& lhs, const OC::OCRepresentation& rhs)
+ {
+ return lhs.getUri() == rhs.getUri() &&
+ lhs.getChildren() == rhs.getChildren() &&
+ lhs.getResourceInterfaces() == rhs.getResourceInterfaces() &&
+ lhs.getResourceTypes() == rhs.getResourceTypes() &&
+ lhs.m_values == rhs.m_values;
+ }
+}
+// these tests validate the OCRepresentation->OCPayload, OCPayload->CBOR,
+// CBOR->OCPayload and OCPayload->OCRepresentation conversions
+namespace OCRepresentationEncodingTest
+{
+
+ static const char uri1[] = "/testuri";
+ static const uint8_t sid1[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
+ static const char devicename1[] = "device name";
+ static const char specver1[] = "spec version";
+ static const char dmver1[] = "data model version";
+ // Device Payloads
+ TEST(DeviceDiscoveryEncoding, Normal)
+ {
+ OCDevicePayload* device = OCDevicePayloadCreate(
+ uri1,
+ sid1,
+ devicename1,
+ specver1,
+ dmver1);
+
+ EXPECT_STREQ(uri1, device->uri);
+ EXPECT_STREQ(devicename1, device->deviceName);
+ EXPECT_STREQ(specver1, device->specVersion);
+ EXPECT_STREQ(dmver1, device->dataModelVersion);
+ EXPECT_EQ(PAYLOAD_TYPE_DEVICE, ((OCPayload*)device)->type);
+
+ for (uint8_t i = 1; i <= sizeof(sid1); ++i)
+ {
+ EXPECT_EQ(i, sid1[i - 1]);
+ }
+
+ uint8_t* cborData;
+ size_t cborSize;
+ OCPayload* parsedDevice;
+ EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)device, &cborData, &cborSize));
+ EXPECT_EQ(OC_STACK_OK, OCParsePayload(&parsedDevice, PAYLOAD_TYPE_DEVICE,
+ cborData, cborSize));
+ OICFree(cborData);
+
+ EXPECT_STREQ(device->uri, ((OCDevicePayload*)parsedDevice)->uri);
+ EXPECT_STREQ(device->deviceName, ((OCDevicePayload*)parsedDevice)->deviceName);
+ EXPECT_STREQ(device->specVersion, ((OCDevicePayload*)parsedDevice)->specVersion);
+ EXPECT_STREQ(device->dataModelVersion, ((OCDevicePayload*)parsedDevice)->dataModelVersion);
+ EXPECT_EQ(device->base.type, ((OCDevicePayload*)parsedDevice)->base.type);
+
+ OCPayloadDestroy((OCPayload*)device);
+
+ OC::MessageContainer mc;
+ mc.setPayload(parsedDevice);
+ EXPECT_EQ(1u, mc.representations().size());
+ const OC::OCRepresentation& r = mc.representations()[0];
+ EXPECT_STREQ(uri1, r.getUri().c_str());
+ EXPECT_STREQ(devicename1, r.getValue<std::string>(OC_RSRVD_DEVICE_NAME).c_str());
+ EXPECT_STREQ(specver1, r.getValue<std::string>(OC_RSRVD_SPEC_VERSION).c_str());
+ EXPECT_STREQ(dmver1, r.getValue<std::string>(OC_RSRVD_DATA_MODEL_VERSION).c_str());
+
+
+ OCPayloadDestroy(parsedDevice);
+ }
+
+ static char pfid1[] = "pfid";
+ static char mfgnm1[] = "mfgnm";
+ static char mfgurl1[] = "mfgurl";
+ static char modelnum1[] = "modelnum";
+ static char dom1[] = "dom";
+ static char pfver1[] = "pfver";
+ static char osver1[] = "osver";
+ static char hwver1[] = "hwver";
+ static char fwver1[] = "fwver";
+ static char url1[] = "url";
+ static char time1[] = "time";
+
+ // Platform Payloads
+ TEST(PlatformDiscoveryEncoding, Normal)
+ {
+ OCPlatformInfo info {pfid1, mfgnm1, mfgurl1, modelnum1, dom1, pfver1, osver1, hwver1,
+ fwver1, url1, time1};
+ OCPlatformPayload* platform = OCPlatformPayloadCreate(uri1, &info);
+ EXPECT_EQ(PAYLOAD_TYPE_PLATFORM, ((OCPayload*)platform)->type);
+ EXPECT_STREQ(uri1, platform->uri);
+ EXPECT_STREQ(pfid1, platform->info.platformID);
+ EXPECT_STREQ(mfgnm1, platform->info.manufacturerName);
+ EXPECT_STREQ(mfgurl1, platform->info.manufacturerUrl);
+ EXPECT_STREQ(modelnum1, platform->info.modelNumber);
+ EXPECT_STREQ(dom1, platform->info.dateOfManufacture);
+ EXPECT_STREQ(pfver1, platform->info.platformVersion);
+ EXPECT_STREQ(osver1, platform->info.operatingSystemVersion);
+ EXPECT_STREQ(hwver1, platform->info.hardwareVersion);
+ EXPECT_STREQ(fwver1, platform->info.firmwareVersion);
+ EXPECT_STREQ(url1, platform->info.supportUrl);
+ EXPECT_STREQ(time1, platform->info.systemTime);
+
+ uint8_t* cborData;
+ size_t cborSize;
+ OCPayload* parsedPlatform;
+ EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)platform, &cborData, &cborSize));
+ EXPECT_EQ(OC_STACK_OK, OCParsePayload(&parsedPlatform, PAYLOAD_TYPE_PLATFORM,
+ cborData, cborSize));
+ OICFree(cborData);
+
+ EXPECT_EQ(platform->base.type, ((OCPlatformPayload*)parsedPlatform)->base.type);
+ OCPlatformPayload* platform2 = (OCPlatformPayload*)parsedPlatform;
+ EXPECT_STREQ(platform->uri, platform2->uri);
+ EXPECT_STREQ(platform->info.platformID, platform2->info.platformID);
+ EXPECT_STREQ(platform->info.manufacturerName, platform->info.manufacturerName);
+ EXPECT_STREQ(platform->info.manufacturerUrl, platform->info.manufacturerUrl);
+ EXPECT_STREQ(platform->info.modelNumber, platform->info.modelNumber);
+ EXPECT_STREQ(platform->info.dateOfManufacture, platform->info.dateOfManufacture);
+ EXPECT_STREQ(platform->info.platformVersion, platform->info.platformVersion);
+ EXPECT_STREQ(platform->info.operatingSystemVersion, platform->info.operatingSystemVersion);
+ EXPECT_STREQ(platform->info.hardwareVersion, platform->info.hardwareVersion);
+ EXPECT_STREQ(platform->info.firmwareVersion, platform->info.firmwareVersion);
+ EXPECT_STREQ(platform->info.supportUrl, platform->info.supportUrl);
+ EXPECT_STREQ(platform->info.systemTime, platform2->info.systemTime);
+
+ OCPayloadDestroy((OCPayload*)platform);
+
+ OC::MessageContainer mc;
+ mc.setPayload(parsedPlatform);
+ EXPECT_EQ(1u, mc.representations().size());
+ const OC::OCRepresentation& r = mc.representations()[0];
+ EXPECT_STREQ(uri1, r.getUri().c_str());
+ EXPECT_STREQ(pfid1, r.getValue<std::string>(OC_RSRVD_PLATFORM_ID).c_str());
+ EXPECT_STREQ(mfgnm1, r.getValue<std::string>(OC_RSRVD_MFG_NAME).c_str());
+ EXPECT_STREQ(mfgurl1, r.getValue<std::string>(OC_RSRVD_MFG_URL).c_str());
+ EXPECT_STREQ(modelnum1, r.getValue<std::string>(OC_RSRVD_MODEL_NUM).c_str());
+ EXPECT_STREQ(dom1, r.getValue<std::string>(OC_RSRVD_MFG_DATE).c_str());
+ EXPECT_STREQ(pfver1, r.getValue<std::string>(OC_RSRVD_PLATFORM_VERSION).c_str());
+ EXPECT_STREQ(osver1, r.getValue<std::string>(OC_RSRVD_OS_VERSION).c_str());
+ EXPECT_STREQ(hwver1, r.getValue<std::string>(OC_RSRVD_HARDWARE_VERSION).c_str());
+ EXPECT_STREQ(fwver1, r.getValue<std::string>(OC_RSRVD_FIRMWARE_VERSION).c_str());
+ EXPECT_STREQ(url1, r.getValue<std::string>(OC_RSRVD_SUPPORT_URL).c_str());
+ EXPECT_STREQ(time1, r.getValue<std::string>(OC_RSRVD_SYSTEM_TIME).c_str());
+
+ OCPayloadDestroy(parsedPlatform);
+ }
+
+ // Representation Payloads
+ TEST(RepresentationEncoding, BaseAttributeTypes)
+ {
+ OC::OCRepresentation startRep;
+ startRep.setNULL("NullAttr");
+ startRep.setValue("IntAttr", 77);
+ startRep.setValue("DoubleAttr", 3.333);
+ startRep.setValue("BoolAttr", true);
+ startRep.setValue("StringAttr", std::string("String attr"));
+ OC::MessageContainer mc1;
+ mc1.addRepresentation(startRep);
+
+ OCRepPayload* cstart = mc1.getPayload();
+ EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
+
+ uint8_t* cborData;
+ size_t cborSize;
+ OCPayload* cparsed;
+ EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
+ EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
+ cborData, cborSize));
+ OCPayloadDestroy((OCPayload*)cstart);
+ OICFree(cborData);
+
+ OC::MessageContainer mc2;
+ mc2.setPayload(cparsed);
+ EXPECT_EQ(1u, mc2.representations().size());
+ const OC::OCRepresentation& r = mc2.representations()[0];
+
+ EXPECT_TRUE(r.isNULL("NullAttr"));
+ EXPECT_EQ(77, r.getValue<int>("IntAttr"));
+ EXPECT_EQ(3.333, r.getValue<double>("DoubleAttr"));
+ EXPECT_EQ(true, r.getValue<bool>("BoolAttr"));
+ EXPECT_STREQ("String attr", r.getValue<std::string>("StringAttr").c_str());
+
+ OCPayloadDestroy(cparsed);
+ }
+
+ TEST(RepresentationEncoding, RepAttribute)
+ {
+ OC::OCRepresentation startRep;
+ OC::OCRepresentation subRep;
+ subRep.setNULL("NullAttr");
+ subRep.setValue("IntAttr", 77);
+ subRep.setValue("DoubleAttr", 3.333);
+ subRep.setValue("BoolAttr", true);
+ subRep.setValue("StringAttr", std::string("String attr"));
+ startRep.setValue("Sub", subRep);
+
+ OC::MessageContainer mc1;
+ mc1.addRepresentation(startRep);
+
+ OCRepPayload* cstart = mc1.getPayload();
+ EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
+
+ uint8_t* cborData;
+ size_t cborSize;
+ OCPayload* cparsed;
+ EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
+ EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
+ cborData, cborSize));
+ OCPayloadDestroy((OCPayload*)cstart);
+ OICFree(cborData);
+
+ OC::MessageContainer mc2;
+ mc2.setPayload(cparsed);
+ EXPECT_EQ(1u, mc2.representations().size());
+ const OC::OCRepresentation& r = mc2.representations()[0];
+
+ OC::OCRepresentation newSubRep = r["Sub"];
+
+ EXPECT_TRUE(newSubRep.isNULL("NullAttr"));
+ EXPECT_EQ(77, newSubRep.getValue<int>("IntAttr"));
+ EXPECT_EQ(3.333, newSubRep.getValue<double>("DoubleAttr"));
+ EXPECT_EQ(true, newSubRep.getValue<bool>("BoolAttr"));
+ EXPECT_STREQ("String attr", newSubRep.getValue<std::string>("StringAttr").c_str());
+ OCPayloadDestroy(cparsed);
+ }
+
+ TEST(RepresentationEncoding, OneDVectors)
+ {
+ // Setup
+ OC::OCRepresentation startRep;
+
+ OC::OCRepresentation subRep1;
+ OC::OCRepresentation subRep2;
+ OC::OCRepresentation subRep3;
+ subRep1.setNULL("NullAttr");
+ subRep1.setValue("IntAttr", 77);
+ subRep2.setValue("DoubleAttr", 3.333);
+ subRep2.setValue("BoolAttr", true);
+ subRep3.setValue("StringAttr", std::string("String attr"));
+
+ std::vector<int> iarr {1,2,3,4,5,6,7,8,9};
+ std::vector<double> darr {1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9};
+ std::vector<bool> barr {false, true, false, false, true, true};
+ std::vector<std::string> strarr {"item1", "item2", "item3", "item4"};
+ std::vector<OC::OCRepresentation> objarr {subRep1, subRep2, subRep3};
+
+ startRep["iarr"] = iarr;
+ startRep["darr"] = darr;
+ startRep["barr"] = barr;
+ startRep["strarr"] = strarr;
+ startRep["objarr"] = objarr;
+
+ // Encode/decode
+ OC::MessageContainer mc1;
+ mc1.addRepresentation(startRep);
+
+ OCRepPayload* cstart = mc1.getPayload();
+ EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
+
+ uint8_t* cborData;
+ size_t cborSize;
+ OCPayload* cparsed;
+ EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
+ EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
+ cborData, cborSize));
+ OCPayloadDestroy((OCPayload*)cstart);
+ OICFree(cborData);
+
+ OC::MessageContainer mc2;
+ mc2.setPayload(cparsed);
+ EXPECT_EQ(1u, mc2.representations().size());
+ const OC::OCRepresentation& r = mc2.representations()[0];
+
+ // Test
+ std::vector<int> iarr2 = r["iarr"];
+ std::vector<double> darr2 = r["darr"];
+ std::vector<bool> barr2 = r["barr"];
+ std::vector<std::string> strarr2 = r["strarr"];
+ std::vector<OC::OCRepresentation> objarr2 = r["objarr"];
+
+ EXPECT_EQ(iarr, iarr2);
+ EXPECT_EQ(darr, darr2);
+ EXPECT_EQ(barr, barr2);
+ EXPECT_EQ(strarr, strarr2);
+ EXPECT_EQ(objarr, objarr2);
+ OCPayloadDestroy(cparsed);
+ }
+
+ TEST(RepresentationEncoding, TwoDVectors)
+ {
+ // Setup
+ OC::OCRepresentation startRep;
+
+ OC::OCRepresentation subRep1;
+ OC::OCRepresentation subRep2;
+ OC::OCRepresentation subRep3;
+ subRep1.setNULL("NullAttr");
+ subRep1.setValue("IntAttr", 77);
+ subRep2.setValue("DoubleAttr", 3.333);
+ subRep2.setValue("BoolAttr", true);
+ subRep3.setValue("StringAttr", std::string("String attr"));
+
+ std::vector<std::vector<int>> iarr {{1,2,3},{4,5,6},{7,8,9}};
+ std::vector<std::vector<double>> darr {{1.1,2.2,3.3},{4.4,5.5,6.6},{7.7,8.8,9.9}};
+ std::vector<std::vector<bool>> barr {{false, true}, {false, false}, {true, true}};
+ std::vector<std::vector<std::string>> strarr {{"item1", "item2"}, {"item3", "item4"}};
+ std::vector<std::vector<OC::OCRepresentation>> objarr
+ {{subRep1, subRep2, subRep3}, {subRep3, subRep2, subRep1}};
+
+ startRep["iarr"] = iarr;
+ startRep["darr"] = darr;
+ startRep["barr"] = barr;
+ startRep["strarr"] = strarr;
+ startRep["objarr"] = objarr;
+
+ // Encode/decode
+ OC::MessageContainer mc1;
+ mc1.addRepresentation(startRep);
+
+ OCRepPayload* cstart = mc1.getPayload();
+ EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
+
+ uint8_t* cborData;
+ size_t cborSize;
+ OCPayload* cparsed;
+ EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
+ EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
+ cborData, cborSize));
+ OCPayloadDestroy((OCPayload*)cstart);
+ OICFree(cborData);
+
+ OC::MessageContainer mc2;
+ mc2.setPayload(cparsed);
+ EXPECT_EQ(1u, mc2.representations().size());
+ const OC::OCRepresentation& r = mc2.representations()[0];
+
+ // Test
+ std::vector<std::vector<int>> iarr2 = r["iarr"];
+ std::vector<std::vector<double>> darr2 = r["darr"];
+ std::vector<std::vector<bool>> barr2 = r["barr"];
+ std::vector<std::vector<std::string>> strarr2 = r["strarr"];
+ std::vector<std::vector<OC::OCRepresentation>> objarr2 = r["objarr"];
+
+ EXPECT_EQ(iarr, iarr2);
+ EXPECT_EQ(darr, darr2);
+ EXPECT_EQ(barr, barr2);
+ EXPECT_EQ(strarr, strarr2);
+ EXPECT_EQ(objarr, objarr2);
+ OCPayloadDestroy(cparsed);
+ }
+
+ TEST(RepresentationEncoding, TwoDVectorsJagged)
+ {
+ // Setup
+ OC::OCRepresentation startRep;
+
+ OC::OCRepresentation subRep1;
+ OC::OCRepresentation subRep2;
+ OC::OCRepresentation subRep3;
+ subRep1.setNULL("NullAttr");
+ subRep1.setValue("IntAttr", 77);
+ subRep2.setValue("DoubleAttr", 3.333);
+ subRep2.setValue("BoolAttr", true);
+ subRep3.setValue("StringAttr", std::string("String attr"));
+
+ std::vector<std::vector<int>> iarr {{1,2,3},{4,6},{7,8,9}};
+ std::vector<std::vector<double>> darr {{1.1,2.2,3.3},{4.4,5.5,6.6},{8.8,9.9}};
+ std::vector<std::vector<bool>> barr {{false, true}, {false}, {true, true}};
+ std::vector<std::vector<std::string>> strarr {{"item1"}, {"item3", "item4"}};
+ std::vector<std::vector<OC::OCRepresentation>> objarr
+ {{subRep1, subRep3}, {subRep3, subRep2, subRep1}};
+
+ startRep["iarr"] = iarr;
+ startRep["darr"] = darr;
+ startRep["barr"] = barr;
+ startRep["strarr"] = strarr;
+ startRep["objarr"] = objarr;
+
+ // Encode/decode
+ OC::MessageContainer mc1;
+ mc1.addRepresentation(startRep);
+
+ OCRepPayload* cstart = mc1.getPayload();
+ EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
+
+ uint8_t* cborData;
+ size_t cborSize;
+ OCPayload* cparsed;
+ EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
+ EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
+ cborData, cborSize));
+ OCPayloadDestroy((OCPayload*)cstart);
+ OICFree(cborData);
+
+ OC::MessageContainer mc2;
+ mc2.setPayload(cparsed);
+ EXPECT_EQ(1u, mc2.representations().size());
+ const OC::OCRepresentation& r = mc2.representations()[0];
+
+ // Test
+ std::vector<std::vector<int>> iarr2 = r["iarr"];
+ std::vector<std::vector<double>> darr2 = r["darr"];
+ std::vector<std::vector<bool>> barr2 = r["barr"];
+ std::vector<std::vector<std::string>> strarr2 = r["strarr"];
+ std::vector<std::vector<OC::OCRepresentation>> objarr2 = r["objarr"];
+
+ // Note: due to the way that the CSDK works, all 2d arrays need to be rectangular.
+ // Since std::vector doesn't require this, items received on the other side end up
+ // being backfilled. This section removes the backfilling
+ iarr2[1].pop_back();
+ darr2[2].pop_back();
+ barr2[1].pop_back();
+ strarr2[0].pop_back();
+ objarr2[0].pop_back();
+
+ EXPECT_EQ(iarr, iarr2);
+ EXPECT_EQ(darr, darr2);
+ EXPECT_EQ(barr, barr2);
+ EXPECT_EQ(strarr, strarr2);
+ EXPECT_EQ(objarr, objarr2);
+ OCPayloadDestroy(cparsed);
+ }
+
+ TEST(RepresentationEncoding, ThreeDVectors)
+ {
+ // Setup
+ OC::OCRepresentation startRep;
+
+ OC::OCRepresentation subRep1;
+ OC::OCRepresentation subRep2;
+ OC::OCRepresentation subRep3;
+ subRep1.setNULL("NullAttr");
+ subRep1.setValue("IntAttr", 77);
+ subRep2.setValue("DoubleAttr", 3.333);
+ subRep2.setValue("BoolAttr", true);
+ subRep3.setValue("StringAttr", std::string("String attr"));
+
+ std::vector<std::vector<std::vector<int>>> iarr
+ {{{1,2,3},{4,5,6}},{{7,8,9},{10,11,12}},{{13,14,15},{16,17,18}}};
+ std::vector<std::vector<std::vector<double>>> darr
+ {{{1.1,2.2,3.3},{4.4,5.5,6.6}},
+ {{7.7,8.7,9.7},{10.7,11.7,12.7}},
+ {{13.7,14.7,15.7},{16.7,17.7,18.7}}};
+ std::vector<std::vector<std::vector<bool>>> barr
+ {{{false, true},{true, false}},{{false, true},{true, false}}};
+ std::vector<std::vector<std::vector<std::string>>> strarr
+ {
+ {{"item1", "item2"},{"item3", "item4"}},
+ {{"item5", "item6"},{"item7", "item8"}},
+ {{"item9", "item10"},{"item11", ""}}
+ };
+ std::vector<std::vector<std::vector<OC::OCRepresentation>>> objarr
+ {
+ {{subRep1, subRep2},{subRep3, subRep1}},
+ {{subRep2, subRep3},{subRep2, subRep1}},
+ {{subRep3, subRep2},{subRep1, subRep2}}
+ };
+
+ startRep["iarr"] = iarr;
+ startRep["darr"] = darr;
+ startRep["barr"] = barr;
+ startRep["strarr"] = strarr;
+ startRep["objarr"] = objarr;
+
+ // Encode/decode
+ OC::MessageContainer mc1;
+ mc1.addRepresentation(startRep);
+
+ OCRepPayload* cstart = mc1.getPayload();
+ EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
+
+ uint8_t* cborData;
+ size_t cborSize;
+ OCPayload* cparsed;
+ EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
+ EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
+ cborData, cborSize));
+ OCPayloadDestroy((OCPayload*)cstart);
+ OICFree(cborData);
+
+ OC::MessageContainer mc2;
+ mc2.setPayload(cparsed);
+ EXPECT_EQ(1u, mc2.representations().size());
+ const OC::OCRepresentation& r = mc2.representations()[0];
+
+ // Test
+ std::vector<std::vector<std::vector<int>>> iarr2 = r["iarr"];
+ std::vector<std::vector<std::vector<double>>> darr2 = r["darr"];
+ std::vector<std::vector<std::vector<bool>>> barr2 = r["barr"];
+ std::vector<std::vector<std::vector<std::string>>> strarr2 = r["strarr"];
+ std::vector<std::vector<std::vector<OC::OCRepresentation>>> objarr2 = r["objarr"];
+
+ EXPECT_EQ(iarr, iarr2);
+ EXPECT_EQ(darr, darr2);
+ EXPECT_EQ(barr, barr2);
+ EXPECT_EQ(strarr, strarr2);
+ EXPECT_EQ(objarr, objarr2);
+ OCPayloadDestroy(cparsed);
+ }
+
+ TEST(RepresentationEncoding, ThreeDVectorsJagged)
+ {
+ // Setup
+ OC::OCRepresentation startRep;
+
+ OC::OCRepresentation subRep1;
+ OC::OCRepresentation subRep2;
+ OC::OCRepresentation subRep3;
+ subRep1.setNULL("NullAttr");
+ subRep1.setValue("IntAttr", 77);
+ subRep2.setValue("DoubleAttr", 3.333);
+ subRep2.setValue("BoolAttr", true);
+ subRep3.setValue("StringAttr", std::string("String attr"));
+
+ std::vector<std::vector<std::vector<int>>> iarr
+ {
+ {{1,2,3},{4,5,6}},
+ {{7,8,9},{10,12}},
+ {{13,14,15},{16,17,18}}
+ };
+ std::vector<std::vector<std::vector<double>>> darr
+ {
+ {{1.1,2.2,3.3},{4.4,5.5,6.6}},
+ {{7.7,8.7,9.7},{10.7,12.7}},
+ {{13.7,14.7,15.7},{16.7,17.7,18.7}}
+ };
+ std::vector<std::vector<std::vector<bool>>> barr
+ {
+ {{false, true},{true}},
+ {{false, true},{true, false}}
+ };
+ std::vector<std::vector<std::vector<std::string>>> strarr
+ {
+ {{"item1", "item2"},{"item3", "item4"}},
+ {{"item5", "item6"},{"item8"}},
+ {{"item9", "item10"},{"item11", ""}}
+ };
+ std::vector<std::vector<std::vector<OC::OCRepresentation>>> objarr
+ {
+ {{subRep1, subRep2},{subRep3, subRep1}},
+ {{subRep2, subRep3},{subRep2}},
+ {{subRep3, subRep2}}
+ };
+
+ startRep["iarr"] = iarr;
+ startRep["darr"] = darr;
+ startRep["barr"] = barr;
+ startRep["strarr"] = strarr;
+ startRep["objarr"] = objarr;
+
+ // Encode/decode
+ OC::MessageContainer mc1;
+ mc1.addRepresentation(startRep);
+
+ OCRepPayload* cstart = mc1.getPayload();
+ EXPECT_EQ(PAYLOAD_TYPE_REPRESENTATION, cstart->base.type);
+
+ uint8_t* cborData;
+ size_t cborSize;
+ OCPayload* cparsed;
+ EXPECT_EQ(OC_STACK_OK, OCConvertPayload((OCPayload*)cstart, &cborData, &cborSize));
+ EXPECT_EQ(OC_STACK_OK, OCParsePayload(&cparsed, PAYLOAD_TYPE_REPRESENTATION,
+ cborData, cborSize));
+ OCPayloadDestroy((OCPayload*)cstart);
+ OICFree(cborData);
+
+ OC::MessageContainer mc2;
+ mc2.setPayload(cparsed);
+ EXPECT_EQ(1u, mc2.representations().size());
+ const OC::OCRepresentation& r = mc2.representations()[0];
+
+ // Test
+ std::vector<std::vector<std::vector<int>>> iarr2 = r["iarr"];
+ std::vector<std::vector<std::vector<double>>> darr2 = r["darr"];
+ std::vector<std::vector<std::vector<bool>>> barr2 = r["barr"];
+ std::vector<std::vector<std::vector<std::string>>> strarr2 = r["strarr"];
+ std::vector<std::vector<std::vector<OC::OCRepresentation>>> objarr2 = r["objarr"];
+
+ // Note: due to the way that the CSDK works, all 3d arrays need to be cuboidal.
+ // Since std::vector doesn't require this, items received on the other side end up
+ // being backfilled. This section removes the backfilling
+ iarr2[1][1].pop_back();
+ darr2[1][1].pop_back();
+ barr2[0][1].pop_back();
+ strarr2[1][1].pop_back();
+ objarr2[1][1].pop_back();
+ objarr2[2].pop_back();
+
+ EXPECT_EQ(iarr, iarr2);
+ EXPECT_EQ(darr, darr2);
+ EXPECT_EQ(barr, barr2);
+ EXPECT_EQ(strarr, strarr2);
+ EXPECT_EQ(objarr, objarr2);
+ OCPayloadDestroy(cparsed);
+ }
+}
EXPECT_ANY_THROW(ConstructResourceObject(std::string(""), std::string("")));
}
+ TEST(ConstructResourceTest, ConstructResourceObjectWithoutCoapScheme)
+ {
+ EXPECT_ANY_THROW(ConstructResourceObject("//192.168.1.2:5000", "/resource"));
+ }
+
TEST(ConstructResourceTest, ConstructResourceObjectWithoutPortNumber)
{
EXPECT_ANY_THROW(ConstructResourceObject("coap://192.168.1.2", "/resource"));
}
+ TEST(ConstructResourceTest, ConstructResourceObjectInvalidHost)
+ {
+ EXPECT_ANY_THROW(ConstructResourceObject("192.168.1.2:5000", "/resource"));
+ }
+
+ TEST(ConstructResourceTest, ConstructResourceObjectInvalidHost2)
+ {
+ EXPECT_ANY_THROW(ConstructResourceObject("coap://:5000", "/resource"));
+ }
+
+ TEST(ConstructResourceTest, ConstructResourceObjectInvalidUri)
+ {
+ EXPECT_ANY_THROW(ConstructResourceObject("coap://192.168.1.2:5000", "/"));
+ }
+
+ TEST(ConstructResourceTest, ConstructResourceObjectInvalidUri2)
+ {
+ EXPECT_ANY_THROW(ConstructResourceObject("coap://192.168.1.2:5000", "resource"));
+ }
+
TEST(ResourceGetTest, DISABLED_ResourceGetForValidUri)
{
OCResource::Ptr resource = ConstructResourceObject("coap://192.168.1.2:5000", "/resource");
unittests = unittests_env.Program('unittests', ['ConstructResourceTest.cpp',
'OCPlatformTest.cpp',
'OCRepresentationTest.cpp',
+ 'OCRepresentationEncodingTest.cpp',
'OCResourceTest.cpp',
'OCExceptionTest.cpp',
'OCResourceResponseTest.cpp',
target_os = env.get('TARGET_OS')
-if target_os not in ['arduino','darwin','ios']:
+if target_os not in ['arduino','darwin']:
# Build things manager project
SConscript('things-manager/SConscript')
# Build protocol plugin project
# protocol-plugin use 'inotify', this feature isn't support by MAC OSX
- if target_os not in ['darwin', 'ios']:
+ if target_os not in ['darwin', 'ios', 'android']:
SConscript('protocol-plugin/SConscript')
# Build notification manager project
- if target_os not in ['android', 'tizen']:
- SConscript('notification-manager/SConscript')
-
+ SConscript('notification-manager/SConscript')
+
# Build resource-encapsulation project
- if target_os not in ['android', 'tizen']:
+ if target_os not in ['tizen']:
SConscript('resource-encapsulation/SConscript')
# Build resource directory project
if env.get('WITH_RD') == '1':
SConscript('resource-directory/SConscript')
-#else:
-# SConscript('notification-manager/SampleApp/arduino/SConscript')
extern "C" {
#endif // __cplusplus
-#define HOSTING_TAG PCF("Hosting")
+#define HOSTING_TAG "Hosting"
/**
* Start resource hosting.
va_start(args, format);
vsnprintf(buffer, sizeof buffer - 1, format, args);
va_end(args);
- OCLog(level, PCF("Hosting"), buffer);
+ OCLog(level, "Hosting", buffer);
}
HostingObject::HostingObject()
void ResourceHosting::requestDiscovery(std::string address)
{
std::string host = address;
- std::string uri = OC_RSRVD_WELL_KNOWN_URI + std::string("?rt=") + HOSTING_RESOURSE_TYPE;
RCSAddress rcsAddress = RCSAddress::unicast(host);
- discoveryManager->discoverResource(rcsAddress, uri, pDiscoveryCB);
+ discoveryManager->discoverResourceByType(rcsAddress, OC_RSRVD_WELL_KNOWN_URI,
+ HOSTING_RESOURSE_TYPE, pDiscoveryCB);
}
void ResourceHosting::discoverHandler(RemoteObjectPtr remoteResource)
notificationsdk = notimgr_env.StaticLibrary('NotificationManager', notimgr_src)
notimgr_env.InstallTarget(notificationsdk, 'libResouceHosting')
+notimgr_env.UserInstallTargetHeader('NotificationManager/include/hosting.h', 'service/notification-manager', 'hosting.h')
# Go to build sample apps
SConscript('SampleApp/SConscript')
C-Pluff, a plug-in framework for C
Copyright 2007 Johannes Lehtinen
-
+
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
when running the configure script.
./configure --prefix=/usr
-
+
The default installation prefix is /usr/local. More help on available
configuration options is available using the --help option.
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*-----------------------------------------------------------------------*/
-// Basic command line input functionality
+// Basic command line input functionality
#include <stdio.h>
#include <string.h>
CP_HIDDEN char *cmdline_input(const char *prompt) {
static char cmdline[CMDLINE_SIZE];
int i, success = 0;
-
+
do {
fputs(prompt, stdout);
if (fgets(cmdline, CMDLINE_SIZE, stdin) == NULL) {
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*-----------------------------------------------------------------------*/
-// GNU readline based command line input
+// GNU readline based command line input
#include <stdio.h>
#include <stdlib.h>
static char *cp_console_compl_flagsgen(const char *text, int state) {
static int counter;
static int textlen;
-
+
if (!state) {
counter = 0;
textlen = strlen(text);
static char *cp_console_compl_loggen(const char *text, int state) {
static int counter;
static int textlen;
-
+
if (!state) {
counter = 0;
textlen = strlen(text);
static char *cp_console_compl_plugingen(const char *text, int state) {
static int counter;
static int textlen;
-
+
if (!state) {
counter = 0;
textlen = strlen(text);
int cs, ce;
char **matches = NULL;
- // Search for start and end of command
+ // Search for start and end of command
for (cs = 0; cs < start && isspace(rl_line_buffer[cs]); cs++);
for (ce = cs; ce <= start && !isspace(rl_line_buffer[ce]); ce++);
-
+
// If no command entered yet, use command completion
if (ce >= start) {
matches = rl_completion_matches(text, cp_console_compl_cmdgen);
rl_attempted_completion_over = 1;
}
-
+
// Otherwise check if known command and complete accordingly
else {
int j = 0;
CP_HIDDEN char *cmdline_input(const char *prompt) {
static char *cmdline = NULL;
-
- // Free previously returned command line, if any
+
+ // Free previously returned command line, if any
if (cmdline != NULL) {
free(cmdline);
cmdline = NULL;
}
-
- // Obtain new command line and record it for history
+
+ // Obtain new command line and record it for history
cmdline = readline(prompt);
if (cmdline != NULL && *cmdline != '\0') {
add_history(cmdline);
}
-
+
return cmdline;
}
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*-----------------------------------------------------------------------*/
-// Core console logic
+// Core console logic
#ifdef HAVE_CONFIG_H
#include <config.h>
* Function declarations
* ----------------------------------------------------------------------*/
-// Function declarations for command implementations
+// Function declarations for command implementations
static void cmd_help(int argc, char *argv[]);
static void cmd_set_log_level(int argc, char *argv[]);
static void cmd_register_pcollection(int argc, char *argv[]);
/// The plug-in context
CP_HIDDEN cp_context_t *context;
-/// The available commands
+/// The available commands
CP_HIDDEN const command_info_t commands[] = {
{ "help", N_("displays available commands"), cmd_help, CPC_COMPL_NONE },
{ "set-log-level", N_("sets the displayed log level"), cmd_set_log_level, CPC_COMPL_LOG_LEVEL },
{ NULL, NULL, NULL, CPC_COMPL_NONE }
};
-/// The available load flags
+/// The available load flags
CP_HIDDEN const flag_info_t load_flags[] = {
{ "upgrade", N_("enables upgrades of installed plug-ins"), CP_SP_UPGRADE },
{ "stop-all-on-upgrade", N_("stops all plug-ins on first upgrade"), CP_SP_STOP_ALL_ON_UPGRADE },
* Returns the number of elements and the pointer to argument table including
* command and arguments. The argument table is valid until the next call
* to this function.
- *
+ *
* @param cmdline the command line to be parsed
* @param argv pointer to the argument table is stored here
* @return the number of command line elements, or -1 on failure
static int cmdline_parse(char *cmdline, char **argv[]) {
static char *sargv[16];
int i, argc;
-
+
for (i = 0; isspace(cmdline[i]); i++);
for (argc = 0; cmdline[i] != '\0' && argc < 16; argc++) {
sargv[argc] = cmdline + i;
}
static void cmd_exit(int argc, char *argv[]) {
-
+
// Uninitialize input
cmdline_destroy();
-
- // Destroy C-Pluff framework
+
+ // Destroy C-Pluff framework
cp_destroy();
-
- // Exit program
+
+ // Exit program
exit(0);
}
static void cmd_help(int argc, char *argv[]) {
int i;
-
+
fputs(_("The following commands are available:\n"), stdout);
for (i = 0; commands[i].name != NULL; i++) {
printf(" %s - %s\n", commands[i].name, _(commands[i].description));
level = _("ERROR");
break;
default:
- /* TRANSLATORS: A tag for unknown severity level. */
+ /* TRANSLATORS: A tag for unknown severity level. */
level = _("UNKNOWN");
break;
}
static void cmd_set_log_level(int argc, char *argv[]) {
if (argc != 2) {
- /* TRANSLATORS: Usage instructions for setting log level */
+ /* TRANSLATORS: Usage instructions for setting log level */
printf(_("Usage: %s <level>\n"), argv[0]);
} else {
int i;
-
+
for (i = 0; log_levels[i].name != NULL; i++) {
if (!strcmp(argv[1], log_levels[i].name)) {
break;
cp_unregister_logger(context, logger);
}
/* TRANSLATORS: The first %s is the log level name and the second the localized log level description. */
- printf(_("Using display log level %s (%s).\n"), log_levels[i].name, _(log_levels[i].description));
+ printf(_("Using display log level %s (%s).\n"), log_levels[i].name, _(log_levels[i].description));
}
}
}
static void cmd_register_pcollection(int argc, char *argv[]) {
cp_status_t status;
-
+
if (argc != 2) {
/* TRANSLATORS: Usage instructions for registering a plug-in collection */
printf(_("Usage: %s <path>\n"), argv[0]);
static void cmd_load_plugin(int argc, char *argv[]) {
cp_plugin_info_t *plugin;
cp_status_t status;
-
+
if (argc != 2) {
/* TRANSLATORS: Usage instructios for loading a plug-in */
printf(_("Usage: %s <path>\n"), argv[0]);
} else if ((plugin = cp_load_plugin_descriptor(context, argv[1], &status)) == NULL) {
api_failed("cp_load_plugin_descriptor", status);
} else if ((status = cp_install_plugin(context, plugin)) != CP_OK) {
- api_failed("cp_install_plugin", status);
+ api_failed("cp_install_plugin", status);
cp_release_info(context, plugin);
} else {
printf(_("Installed plug-in %s.\n"), plugin->identifier);
int flags = 0;
cp_status_t status;
int i;
-
- // Set flags
+
+ // Set flags
for (i = 1; i < argc; i++) {
int j;
-
+
for (j = 0; load_flags[j].name != NULL; j++) {
if (!strcmp(argv[i], load_flags[j].name)) {
flags |= load_flags[j].value;
return;
}
}
-
+
if ((status = cp_scan_plugins(context, flags)) != CP_OK) {
api_failed("cp_scan_plugins", status);
return;
};
static struct str_list_entry_t *str_list = NULL;
-
+
static char *str_or_null(const char *str) {
if (str != NULL) {
char *s = malloc((strlen(str) + 3) * sizeof(char));
static void strcat_quote_xml(char *dst, const char *src, int is_attr) {
char c;
-
+
while (*dst != '\0')
dst++;
do {
static int strlen_quoted_xml(const char *str,int is_attr) {
int len = 0;
int i;
-
+
for (i = 0; str[i] != '\0'; i++) {
switch (str[i]) {
case '&':
rs += strlen_quoted_xml(ce->atts[2*i + 1], 1);
rs += 4;
}
-
+
// Allocate buffer
if ((buffer = malloc(rs * sizeof(char))) == NULL) {
fputs(_("Memory allocation failed.\n"), stderr);
abort();
}
-
+
// Create the string
for (i = 0; i < indent; i++) {
buffer[i] = ' ';
cp_plugin_info_t *plugin;
cp_status_t status;
int i;
-
+
if (argc != 2) {
/* TRANSLATORS: Usage instructions for showing plug-in information */
printf(_("Usage: %s <plugin>\n"), argv[0]);
for (i = 0; ext_points[i] != NULL; i++) {
printf(format,
ext_points[i]->identifier,
- ext_points[i]->name != NULL ? ext_points[i]->name : "");
+ ext_points[i]->name != NULL ? ext_points[i]->name : "");
}
cp_release_info(context, ext_points);
- }
+ }
}
static void cmd_findResourcebyType(int argc, char *argv[]){
}
}
cp_release_info(context, extensions);
- }
+ }
}
static char **argv_dup(int argc, char *argv[]) {
char **dup;
int i;
-
+
if ((dup = malloc((argc + 1) * sizeof(char *))) == NULL) {
return NULL;
}
static void cmd_start_plugin(int argc, char *argv[]) {
cp_status_t status;
-
+
if (argc != 2) {
/* TRANSLATORS: Usage instructions for starting a plug-in */
printf(_("Usage: %s <plugin>\n"), argv[0]);
}
static void cmd_run_plugins_step(int argc, char *argv[]) {
-
+
if (argc != 1) {
/* TRANSLATORS: Usage instructions for running one plug-in run function */
printf(_("Usage: %s\n"), argv[0]);
static void cmd_stop_plugin(int argc, char *argv[]) {
cp_status_t status;
-
+
if (argc != 2) {
/* TRANSLATORS: Usage instructions for stopping a plug-in */
printf(_("Usage: %s <plugin>\n"), argv[0]);
static void cmd_uninstall_plugin(int argc, char *argv[]) {
cp_status_t status;
-
+
if (argc != 2) {
/* TRANSLATORS: Usage instructions for uninstalling a plug-in */
printf(_("Usage: %s <plugin>\n"), argv[0]);
setlocale(LC_ALL, "");
#endif
- // Initialize C-Pluff library
+ // Initialize C-Pluff library
if ((status = cp_init()) != CP_OK) {
api_failed("cp_init", status);
exit(1);
}
-
- // Set gettext domain
+
+ // Set gettext domain
#ifdef HAVE_GETTEXT
textdomain(PACKAGE);
#endif
- // Display startup information
+ // Display startup information
printf(
/* TRANSLATORS: This is a version string displayed on startup. */
_("C-Pluff Console, version %s\n"), PACKAGE_VERSION);
cp_register_logger(context, logger, NULL, log_levels[1].level);
printf(_("Using display log level %s (%s).\n"), log_levels[1].name, _(log_levels[1].description));
- // Command line loop
+ // Command line loop
fputs(_("Type \"help\" for help on available commands.\n"), stdout);
cmdline_init();
-
+
/* TRANSLATORS: This is the input prompt for cpluff-console. */
prompt = _("C-Pluff Console > ");
-
+
while (1) {
char *cmdline;
int argc;
char **argv;
-
- // Get command line
+
+ // Get command line
cmdline = cmdline_input(prompt);
if (cmdline == NULL) {
putchar('\n');
cmdline = "exit";
}
-
- // Parse command line
+
+ // Parse command line
argc = cmdline_parse(cmdline, &argv);
if (argc <= 0) {
continue;
}
-
- // Choose command
+
+ // Choose command
for (i = 0; commands[i].name != NULL; i++) {
if (!strcmp(argv[0], commands[i].name)) {
commands[i].implementation(argc, argv);
Readline Library meaning that you have to comply with the conditions of
the GNU General Public License when distributing it in binary form.
</p>
-
+
<h2 id="cpluff-license">C-Pluff license</h2>
<p>
C-Pluff, a plug-in framework for C<br/>
feedback, ideas and thoughts about such platform directly to the
<a href="mailto:johannes.lehtinen@iki.fi">author</a>.
</p>
-
+
<h2 id="structure">Architecture</h2>
<p>
The plug-in architecture supported by C-Pluff is presented in the
<a name="l00020"></a>00020 <span class="comment"> * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE</span>
<a name="l00021"></a>00021 <span class="comment"> * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</span>
<a name="l00022"></a>00022 <span class="comment"> *-----------------------------------------------------------------------*/</span>
-<a name="l00023"></a>00023
+<a name="l00023"></a>00023
<a name="l00033"></a>00033 <span class="preprocessor">#ifndef CPLUFF_H_</span>
<a name="l00034"></a>00034 <span class="preprocessor"></span><span class="preprocessor">#define CPLUFF_H_</span>
<a name="l00035"></a>00035 <span class="preprocessor"></span>
<a name="l00041"></a>00041 <span class="preprocessor">#include <<a class="code" href="cpluffdef_8h.html">cpluffdef.h</a>></span>
-<a name="l00042"></a>00042
+<a name="l00042"></a>00042
<a name="l00043"></a>00043 <span class="preprocessor">#ifdef __cplusplus</span>
<a name="l00044"></a>00044 <span class="preprocessor"></span><span class="keyword">extern</span> <span class="stringliteral">"C"</span> {
<a name="l00045"></a>00045 <span class="preprocessor">#endif </span><span class="comment">/*__cplusplus*/</span>
-<a name="l00046"></a>00046
-<a name="l00047"></a>00047
+<a name="l00046"></a>00046
+<a name="l00047"></a>00047
<a name="l00048"></a>00048 <span class="comment">/* ------------------------------------------------------------------------</span>
<a name="l00049"></a>00049 <span class="comment"> * Defines</span>
<a name="l00050"></a>00050 <span class="comment"> * ----------------------------------------------------------------------*/</span>
-<a name="l00051"></a>00051
+<a name="l00051"></a>00051
<a name="l00060"></a>00060 <span class="preprocessor">#ifndef CP_C_API</span>
<a name="l00061"></a><a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">00061</a> <span class="preprocessor"></span><span class="preprocessor">#define CP_C_API CP_IMPORT</span>
<a name="l00062"></a>00062 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
<a name="l00063"></a>00063 <span class="preprocessor"></span>
-<a name="l00064"></a>00064
-<a name="l00073"></a>00073
+<a name="l00064"></a>00064
+<a name="l00073"></a>00073
<a name="l00078"></a><a class="code" href="group__cScanFlags.html#g1d4b72334d60f1401e6616da54e4d6f1">00078</a> <span class="preprocessor">#define CP_SP_UPGRADE 0x01</span>
<a name="l00079"></a>00079 <span class="preprocessor"></span>
<a name="l00084"></a><a class="code" href="group__cScanFlags.html#g72cdcd1181d60fd3caf5d0e0dd59c33c">00084</a> <span class="preprocessor">#define CP_SP_STOP_ALL_ON_UPGRADE 0x02</span>
<a name="l00102"></a>00102 <span class="comment">/* ------------------------------------------------------------------------</span>
<a name="l00103"></a>00103 <span class="comment"> * Data types</span>
<a name="l00104"></a>00104 <span class="comment"> * ----------------------------------------------------------------------*/</span>
-<a name="l00105"></a>00105
+<a name="l00105"></a>00105
<a name="l00122"></a>00122 <span class="comment">/* Enumerations */</span>
-<a name="l00123"></a>00123
+<a name="l00123"></a>00123
<a name="l00133"></a><a class="code" href="group__cEnums.html#gd6a8106d281ffa4b1f43fe8e3effc7da">00133</a> <span class="keyword">enum</span> <a class="code" href="group__cEnums.html#gd6a8106d281ffa4b1f43fe8e3effc7da">cp_status_t</a> {
-<a name="l00134"></a>00134
+<a name="l00134"></a>00134
<a name="l00139"></a>00139 <a class="code" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da5ffbe0fe80af75e699e4b04909912f7a">CP_OK</a> = 0,
-<a name="l00140"></a>00140
+<a name="l00140"></a>00140
<a name="l00142"></a>00142 <a class="code" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dac4e31e28c38ba325fa7169da1a233950">CP_ERR_RESOURCE</a>,
-<a name="l00143"></a>00143
+<a name="l00143"></a>00143
<a name="l00145"></a>00145 <a class="code" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da6418acb9f17c3a00ea350684bff9782e">CP_ERR_UNKNOWN</a>,
-<a name="l00146"></a>00146
+<a name="l00146"></a>00146
<a name="l00148"></a>00148 <a class="code" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da2993572d373d8cc61f9655c10fbeefa5">CP_ERR_IO</a>,
-<a name="l00149"></a>00149
+<a name="l00149"></a>00149
<a name="l00151"></a>00151 <a class="code" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dadc486f602f89493e882cde6a364de0b7">CP_ERR_MALFORMED</a>,
-<a name="l00152"></a>00152
+<a name="l00152"></a>00152
<a name="l00154"></a>00154 <a class="code" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dab07cfdc96a5dbc3a3e359bae2534c9d2">CP_ERR_CONFLICT</a>,
-<a name="l00155"></a>00155
+<a name="l00155"></a>00155
<a name="l00157"></a>00157 <a class="code" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da068a07ac79fdc33dc0c47d14c37005f6">CP_ERR_DEPENDENCY</a>,
-<a name="l00158"></a>00158
+<a name="l00158"></a>00158
<a name="l00160"></a>00160 <a class="code" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dae9eb8fc6b508a70eae974760d8be07aa">CP_ERR_RUNTIME</a>
-<a name="l00161"></a>00161
+<a name="l00161"></a>00161
<a name="l00162"></a>00162 };
-<a name="l00163"></a>00163
+<a name="l00163"></a>00163
<a name="l00175"></a><a class="code" href="group__cEnums.html#gd517a8088e2ed89fda71251d9c7b3252">00175</a> <span class="keyword">enum</span> <a class="code" href="group__cEnums.html#gd517a8088e2ed89fda71251d9c7b3252">cp_plugin_state_t</a> {
-<a name="l00176"></a>00176
+<a name="l00176"></a>00176
<a name="l00181"></a>00181 <a class="code" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b325290eacd4f02fb7d65eaf68f7251a99689">CP_PLUGIN_UNINSTALLED</a>,
-<a name="l00182"></a>00182
+<a name="l00182"></a>00182
<a name="l00190"></a>00190 <a class="code" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32521c91e4bef84a1d924456fb268a1d848b">CP_PLUGIN_INSTALLED</a>,
-<a name="l00191"></a>00191
+<a name="l00191"></a>00191
<a name="l00202"></a>00202 <a class="code" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b325275596c790e344583d117d3c6bb4252bd">CP_PLUGIN_RESOLVED</a>,
-<a name="l00203"></a>00203
+<a name="l00203"></a>00203
<a name="l00213"></a>00213 <a class="code" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32522c6ca0c8d90c3acb01e336ce1711540c">CP_PLUGIN_STARTING</a>,
-<a name="l00214"></a>00214
+<a name="l00214"></a>00214
<a name="l00224"></a>00224 <a class="code" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32525aafd09bec81bb2bedfd7bfc8643051c">CP_PLUGIN_STOPPING</a>,
-<a name="l00225"></a>00225
+<a name="l00225"></a>00225
<a name="l00230"></a>00230 <a class="code" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b3252953ad85aee24006f4a5079bfca73eb9f">CP_PLUGIN_ACTIVE</a>
-<a name="l00231"></a>00231
+<a name="l00231"></a>00231
<a name="l00232"></a>00232 };
-<a name="l00233"></a>00233
+<a name="l00233"></a>00233
<a name="l00241"></a><a class="code" href="group__cEnums.html#g952725f83949f4eb486c390c4ff72aeb">00241</a> <span class="keyword">enum</span> <a class="code" href="group__cEnums.html#g952725f83949f4eb486c390c4ff72aeb">cp_log_severity_t</a> {
-<a name="l00242"></a>00242
+<a name="l00242"></a>00242
<a name="l00244"></a>00244 <a class="code" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aeb22e3ccb1789e1f0ea3b35e1682fe8af8">CP_LOG_DEBUG</a>,
-<a name="l00245"></a>00245
+<a name="l00245"></a>00245
<a name="l00247"></a>00247 <a class="code" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aebcdb069d62e546b005ae6a81e6cdb0333">CP_LOG_INFO</a>,
-<a name="l00248"></a>00248
+<a name="l00248"></a>00248
<a name="l00250"></a>00250 <a class="code" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aeb26a8a8c987042689e5018e481d235ee0">CP_LOG_WARNING</a>,
-<a name="l00251"></a>00251
+<a name="l00251"></a>00251
<a name="l00253"></a>00253 <a class="code" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aebd99d2bd1dbae181f9a41e90e6bf8d14e">CP_LOG_ERROR</a>
-<a name="l00254"></a>00254
+<a name="l00254"></a>00254
<a name="l00255"></a>00255 };
-<a name="l00256"></a>00256
+<a name="l00256"></a>00256
<a name="l00260"></a>00260 <span class="comment">/* Typedefs */</span>
-<a name="l00261"></a>00261
-<a name="l00268"></a>00268
+<a name="l00261"></a>00261
+<a name="l00268"></a>00268
<a name="l00281"></a><a class="code" href="group__cTypedefsOpaque.html#gcb1aa0619dcefa746383c5e0833b62e7">00281</a> <span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="group__cTypedefsOpaque.html#gcb1aa0619dcefa746383c5e0833b62e7">cp_context_t</a> cp_context_t;
-<a name="l00282"></a>00282
-<a name="l00291"></a>00291
+<a name="l00282"></a>00282
+<a name="l00291"></a>00291
<a name="l00293"></a><a class="code" href="group__cTypedefsShorthand.html#gc552cbab3bf4b5a2b62a1420521383ad">00293</a> <span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="structcp__plugin__info__t.html">cp_plugin_info_t</a> <a class="code" href="group__cTypedefsShorthand.html#gc552cbab3bf4b5a2b62a1420521383ad">cp_plugin_info_t</a>;
-<a name="l00294"></a>00294
+<a name="l00294"></a>00294
<a name="l00296"></a><a class="code" href="group__cTypedefsShorthand.html#g1da07ec69dd85c103a4dd8d8e8bc9018">00296</a> <span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="structcp__plugin__import__t.html">cp_plugin_import_t</a> <a class="code" href="group__cTypedefsShorthand.html#g1da07ec69dd85c103a4dd8d8e8bc9018">cp_plugin_import_t</a>;
-<a name="l00297"></a>00297
+<a name="l00297"></a>00297
<a name="l00299"></a><a class="code" href="group__cTypedefsShorthand.html#g4a19f7af87165d59dd82866006a96424">00299</a> <span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="structcp__ext__point__t.html">cp_ext_point_t</a> <a class="code" href="group__cTypedefsShorthand.html#g4a19f7af87165d59dd82866006a96424">cp_ext_point_t</a>;
-<a name="l00300"></a>00300
+<a name="l00300"></a>00300
<a name="l00302"></a><a class="code" href="group__cTypedefsShorthand.html#gea86d23c48f7335c3b710b9a3af2bf89">00302</a> <span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="structcp__extension__t.html">cp_extension_t</a> <a class="code" href="group__cTypedefsShorthand.html#gea86d23c48f7335c3b710b9a3af2bf89">cp_extension_t</a>;
-<a name="l00303"></a>00303
+<a name="l00303"></a>00303
<a name="l00305"></a><a class="code" href="group__cTypedefsShorthand.html#ge8a837c613935f505e66734c567ed700">00305</a> <span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="structcp__cfg__element__t.html">cp_cfg_element_t</a> <a class="code" href="group__cTypedefsShorthand.html#ge8a837c613935f505e66734c567ed700">cp_cfg_element_t</a>;
-<a name="l00306"></a>00306
+<a name="l00306"></a>00306
<a name="l00308"></a><a class="code" href="group__cTypedefsShorthand.html#gca5d98d242f7c005f04b00bf77d1882e">00308</a> <span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="structcp__plugin__runtime__t.html">cp_plugin_runtime_t</a> <a class="code" href="group__cTypedefsShorthand.html#gca5d98d242f7c005f04b00bf77d1882e">cp_plugin_runtime_t</a>;
-<a name="l00309"></a>00309
+<a name="l00309"></a>00309
<a name="l00311"></a><a class="code" href="group__cTypedefsShorthand.html#g53b128f964c24169c758a0c60248d602">00311</a> <span class="keyword">typedef</span> <span class="keyword">enum</span> <a class="code" href="group__cEnums.html#gd6a8106d281ffa4b1f43fe8e3effc7da">cp_status_t</a> <a class="code" href="group__cEnums.html#gd6a8106d281ffa4b1f43fe8e3effc7da">cp_status_t</a>;
-<a name="l00312"></a>00312
+<a name="l00312"></a>00312
<a name="l00314"></a><a class="code" href="group__cTypedefsShorthand.html#g026780097ccf13e9896f2d4759aa642e">00314</a> <span class="keyword">typedef</span> <span class="keyword">enum</span> <a class="code" href="group__cEnums.html#gd517a8088e2ed89fda71251d9c7b3252">cp_plugin_state_t</a> <a class="code" href="group__cEnums.html#gd517a8088e2ed89fda71251d9c7b3252">cp_plugin_state_t</a>;
-<a name="l00315"></a>00315
+<a name="l00315"></a>00315
<a name="l00317"></a><a class="code" href="group__cTypedefsShorthand.html#gfa3a21d1af3332cab04867d6f1b0b076">00317</a> <span class="keyword">typedef</span> <span class="keyword">enum</span> <a class="code" href="group__cEnums.html#g952725f83949f4eb486c390c4ff72aeb">cp_log_severity_t</a> <a class="code" href="group__cEnums.html#g952725f83949f4eb486c390c4ff72aeb">cp_log_severity_t</a>;
-<a name="l00318"></a>00318
-<a name="l00327"></a>00327
+<a name="l00318"></a>00318
+<a name="l00327"></a>00327
<a name="l00344"></a><a class="code" href="group__cTypedefsFuncs.html#g24fde3d7324169d8448700123aa97c7a">00344</a> <span class="keyword">typedef</span> void (*<a class="code" href="group__cTypedefsFuncs.html#g24fde3d7324169d8448700123aa97c7a">cp_plugin_listener_func_t</a>)(<span class="keyword">const</span> <span class="keywordtype">char</span> *plugin_id, cp_plugin_state_t old_state, cp_plugin_state_t new_state, <span class="keywordtype">void</span> *user_data);
-<a name="l00345"></a>00345
+<a name="l00345"></a>00345
<a name="l00358"></a><a class="code" href="group__cTypedefsFuncs.html#ga53e481fd552856aff67d8584f7e5614">00358</a> <span class="keyword">typedef</span> void (*<a class="code" href="group__cTypedefsFuncs.html#ga53e481fd552856aff67d8584f7e5614">cp_logger_func_t</a>)(cp_log_severity_t severity, <span class="keyword">const</span> <span class="keywordtype">char</span> *msg, <span class="keyword">const</span> <span class="keywordtype">char</span> *apid, <span class="keywordtype">void</span> *user_data);
-<a name="l00359"></a>00359
+<a name="l00359"></a>00359
<a name="l00369"></a><a class="code" href="group__cTypedefsFuncs.html#g91b11fd391854d0854cfde0779f8d707">00369</a> <span class="keyword">typedef</span> void (*<a class="code" href="group__cTypedefsFuncs.html#g91b11fd391854d0854cfde0779f8d707">cp_fatal_error_func_t</a>)(<span class="keyword">const</span> <span class="keywordtype">char</span> *msg);
-<a name="l00370"></a>00370
+<a name="l00370"></a>00370
<a name="l00381"></a><a class="code" href="group__cTypedefsFuncs.html#gf55fb990664aaa069e72a8fa4da20034">00381</a> <span class="keyword">typedef</span> int (*<a class="code" href="group__cTypedefsFuncs.html#gf55fb990664aaa069e72a8fa4da20034">cp_run_func_t</a>)(<span class="keywordtype">void</span> *plugin_data);
-<a name="l00382"></a>00382
+<a name="l00382"></a>00382
<a name="l00386"></a>00386 <span class="comment">/* Data structures */</span>
-<a name="l00387"></a>00387
+<a name="l00387"></a>00387
<a name="l00396"></a><a class="code" href="structcp__plugin__info__t.html">00396</a> <span class="keyword">struct </span><a class="code" href="group__cTypedefsShorthand.html#gc552cbab3bf4b5a2b62a1420521383ad">cp_plugin_info_t</a> {
-<a name="l00397"></a>00397
+<a name="l00397"></a>00397
<a name="l00405"></a><a class="code" href="structcp__plugin__info__t.html#f5351a0143adaf16c64b881aee01d893">00405</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__plugin__info__t.html#f5351a0143adaf16c64b881aee01d893">identifier</a>;
-<a name="l00406"></a>00406
+<a name="l00406"></a>00406
<a name="l00413"></a><a class="code" href="structcp__plugin__info__t.html#5ac083a645d964373f022d03df4849c8">00413</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__plugin__info__t.html#5ac083a645d964373f022d03df4849c8">name</a>;
-<a name="l00414"></a>00414
+<a name="l00414"></a>00414
<a name="l00420"></a><a class="code" href="structcp__plugin__info__t.html#56abfaab87c46691c1ef3ad0df23e864">00420</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__plugin__info__t.html#56abfaab87c46691c1ef3ad0df23e864">version</a>;
-<a name="l00421"></a>00421
+<a name="l00421"></a>00421
<a name="l00429"></a><a class="code" href="structcp__plugin__info__t.html#8bf76789248b4737d6a9a1175ceadca5">00429</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__plugin__info__t.html#8bf76789248b4737d6a9a1175ceadca5">provider_name</a>;
-<a name="l00430"></a>00430
+<a name="l00430"></a>00430
<a name="l00438"></a><a class="code" href="structcp__plugin__info__t.html#bfb5abdafe1c5db02dcd2922b32be4e6">00438</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__plugin__info__t.html#bfb5abdafe1c5db02dcd2922b32be4e6">plugin_path</a>;
-<a name="l00439"></a>00439
+<a name="l00439"></a>00439
<a name="l00451"></a><a class="code" href="structcp__plugin__info__t.html#80147b4cbaeac68ad7a02dfe9c732e43">00451</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__plugin__info__t.html#80147b4cbaeac68ad7a02dfe9c732e43">abi_bw_compatibility</a>;
-<a name="l00452"></a>00452
+<a name="l00452"></a>00452
<a name="l00465"></a><a class="code" href="structcp__plugin__info__t.html#a0db42bb2a075c5804c0aeecfab567d8">00465</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__plugin__info__t.html#a0db42bb2a075c5804c0aeecfab567d8">api_bw_compatibility</a>;
-<a name="l00466"></a>00466
+<a name="l00466"></a>00466
<a name="l00475"></a><a class="code" href="structcp__plugin__info__t.html#8b1942a723f6a68c9afad9e52b7e78d1">00475</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__plugin__info__t.html#8b1942a723f6a68c9afad9e52b7e78d1">req_cpluff_version</a>;
-<a name="l00476"></a>00476
+<a name="l00476"></a>00476
<a name="l00478"></a><a class="code" href="structcp__plugin__info__t.html#bca19d2e4af3752ceb056d638321b894">00478</a> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="structcp__plugin__info__t.html#bca19d2e4af3752ceb056d638321b894">num_imports</a>;
-<a name="l00479"></a>00479
+<a name="l00479"></a>00479
<a name="l00484"></a><a class="code" href="structcp__plugin__info__t.html#e03a6d473f95a77ad6de9d43610f8d39">00484</a> <a class="code" href="group__cTypedefsShorthand.html#g1da07ec69dd85c103a4dd8d8e8bc9018">cp_plugin_import_t</a> *<a class="code" href="structcp__plugin__info__t.html#e03a6d473f95a77ad6de9d43610f8d39">imports</a>;
-<a name="l00485"></a>00485
+<a name="l00485"></a>00485
<a name="l00493"></a><a class="code" href="structcp__plugin__info__t.html#e466145debd47625f99bbc780e8950ed">00493</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__plugin__info__t.html#e466145debd47625f99bbc780e8950ed">runtime_lib_name</a>;
-<a name="l00494"></a>00494
+<a name="l00494"></a>00494
<a name="l00501"></a><a class="code" href="structcp__plugin__info__t.html#3291d0de7ca4bbe510950be556641856">00501</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__plugin__info__t.html#3291d0de7ca4bbe510950be556641856">runtime_funcs_symbol</a>;
-<a name="l00502"></a>00502
+<a name="l00502"></a>00502
<a name="l00504"></a><a class="code" href="structcp__plugin__info__t.html#845440eb771d52a4b271bfbd48fcb7ec">00504</a> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="structcp__plugin__info__t.html#845440eb771d52a4b271bfbd48fcb7ec">num_ext_points</a>;
-<a name="l00505"></a>00505
+<a name="l00505"></a>00505
<a name="l00511"></a><a class="code" href="structcp__plugin__info__t.html#8299ae4ef53289492911a1334494e405">00511</a> <a class="code" href="group__cTypedefsShorthand.html#g4a19f7af87165d59dd82866006a96424">cp_ext_point_t</a> *<a class="code" href="structcp__plugin__info__t.html#8299ae4ef53289492911a1334494e405">ext_points</a>;
-<a name="l00512"></a>00512
+<a name="l00512"></a>00512
<a name="l00514"></a><a class="code" href="structcp__plugin__info__t.html#5774f2b85864891690291909ecbbf819">00514</a> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="structcp__plugin__info__t.html#5774f2b85864891690291909ecbbf819">num_extensions</a>;
-<a name="l00515"></a>00515
+<a name="l00515"></a>00515
<a name="l00521"></a><a class="code" href="structcp__plugin__info__t.html#2288d4af96da6699b7a2c8b747bd42dc">00521</a> <a class="code" href="group__cTypedefsShorthand.html#gea86d23c48f7335c3b710b9a3af2bf89">cp_extension_t</a> *<a class="code" href="structcp__plugin__info__t.html#2288d4af96da6699b7a2c8b747bd42dc">extensions</a>;
-<a name="l00522"></a>00522
+<a name="l00522"></a>00522
<a name="l00523"></a>00523 };
-<a name="l00524"></a>00524
+<a name="l00524"></a>00524
<a name="l00530"></a><a class="code" href="structcp__plugin__import__t.html">00530</a> <span class="keyword">struct </span><a class="code" href="group__cTypedefsShorthand.html#g1da07ec69dd85c103a4dd8d8e8bc9018">cp_plugin_import_t</a> {
-<a name="l00531"></a>00531
+<a name="l00531"></a>00531
<a name="l00536"></a><a class="code" href="structcp__plugin__import__t.html#29da905aeb4da90dae48b2aa19f5cc62">00536</a> <span class="keywordtype">char</span> *plugin_id;
-<a name="l00537"></a>00537
+<a name="l00537"></a>00537
<a name="l00546"></a><a class="code" href="structcp__plugin__import__t.html#56abfaab87c46691c1ef3ad0df23e864">00546</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__plugin__import__t.html#56abfaab87c46691c1ef3ad0df23e864">version</a>;
-<a name="l00547"></a>00547
+<a name="l00547"></a>00547
<a name="l00557"></a><a class="code" href="structcp__plugin__import__t.html#69b1249c974e922ecdd066c43dc91f88">00557</a> <span class="keywordtype">int</span> <a class="code" href="structcp__plugin__import__t.html#69b1249c974e922ecdd066c43dc91f88">optional</a>;
<a name="l00558"></a>00558 };
-<a name="l00559"></a>00559
+<a name="l00559"></a>00559
<a name="l00566"></a><a class="code" href="structcp__ext__point__t.html">00566</a> <span class="keyword">struct </span><a class="code" href="group__cTypedefsShorthand.html#g4a19f7af87165d59dd82866006a96424">cp_ext_point_t</a> {
-<a name="l00567"></a>00567
+<a name="l00567"></a>00567
<a name="l00573"></a><a class="code" href="structcp__ext__point__t.html#e498b24942e6fdd73ce6c22505549680">00573</a> <a class="code" href="group__cTypedefsShorthand.html#gc552cbab3bf4b5a2b62a1420521383ad">cp_plugin_info_t</a> *<a class="code" href="structcp__ext__point__t.html#e498b24942e6fdd73ce6c22505549680">plugin</a>;
-<a name="l00574"></a>00574
+<a name="l00574"></a>00574
<a name="l00580"></a>00580 <span class="keywordtype">char</span> *local_id;
-<a name="l00581"></a>00581
+<a name="l00581"></a>00581
<a name="l00587"></a><a class="code" href="structcp__ext__point__t.html#f5351a0143adaf16c64b881aee01d893">00587</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__ext__point__t.html#f5351a0143adaf16c64b881aee01d893">identifier</a>;
-<a name="l00588"></a>00588
+<a name="l00588"></a>00588
<a name="l00595"></a><a class="code" href="structcp__ext__point__t.html#5ac083a645d964373f022d03df4849c8">00595</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__ext__point__t.html#5ac083a645d964373f022d03df4849c8">name</a>;
-<a name="l00596"></a>00596
+<a name="l00596"></a>00596
<a name="l00603"></a><a class="code" href="structcp__ext__point__t.html#2370171ff78694fa0871fd845ab3ad6f">00603</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__ext__point__t.html#2370171ff78694fa0871fd845ab3ad6f">schema_path</a>;
<a name="l00604"></a>00604 };
-<a name="l00605"></a>00605
+<a name="l00605"></a>00605
<a name="l00611"></a><a class="code" href="structcp__extension__t.html">00611</a> <span class="keyword">struct </span><a class="code" href="group__cTypedefsShorthand.html#gea86d23c48f7335c3b710b9a3af2bf89">cp_extension_t</a> {
-<a name="l00612"></a>00612
+<a name="l00612"></a>00612
<a name="l00618"></a><a class="code" href="structcp__extension__t.html#e498b24942e6fdd73ce6c22505549680">00618</a> <a class="code" href="group__cTypedefsShorthand.html#gc552cbab3bf4b5a2b62a1420521383ad">cp_plugin_info_t</a> *<a class="code" href="structcp__extension__t.html#e498b24942e6fdd73ce6c22505549680">plugin</a>;
-<a name="l00619"></a>00619
+<a name="l00619"></a>00619
<a name="l00625"></a><a class="code" href="structcp__extension__t.html#9fe304775bea17eeba3c3fd734d1e4bc">00625</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__extension__t.html#9fe304775bea17eeba3c3fd734d1e4bc">ext_point_id</a>;
-<a name="l00626"></a>00626
+<a name="l00626"></a>00626
<a name="l00632"></a><a class="code" href="structcp__extension__t.html#eb234b64f623fd6c2bcbbc98bacb99ce">00632</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__extension__t.html#eb234b64f623fd6c2bcbbc98bacb99ce">local_id</a>;
-<a name="l00633"></a>00633
+<a name="l00633"></a>00633
<a name="l00639"></a><a class="code" href="structcp__extension__t.html#f5351a0143adaf16c64b881aee01d893">00639</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__extension__t.html#f5351a0143adaf16c64b881aee01d893">identifier</a>;
-<a name="l00640"></a>00640
+<a name="l00640"></a>00640
<a name="l00647"></a><a class="code" href="structcp__extension__t.html#5ac083a645d964373f022d03df4849c8">00647</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__extension__t.html#5ac083a645d964373f022d03df4849c8">name</a>;
-<a name="l00648"></a>00648
+<a name="l00648"></a>00648
<a name="l00655"></a><a class="code" href="structcp__extension__t.html#a745fad14a2300fd48e55c33f580f91b">00655</a> <a class="code" href="group__cTypedefsShorthand.html#ge8a837c613935f505e66734c567ed700">cp_cfg_element_t</a> *<a class="code" href="structcp__extension__t.html#a745fad14a2300fd48e55c33f580f91b">configuration</a>;
<a name="l00656"></a>00656 };
-<a name="l00657"></a>00657
+<a name="l00657"></a>00657
<a name="l00667"></a><a class="code" href="structcp__cfg__element__t.html">00667</a> <span class="keyword">struct </span><a class="code" href="group__cTypedefsShorthand.html#ge8a837c613935f505e66734c567ed700">cp_cfg_element_t</a> {
-<a name="l00668"></a>00668
+<a name="l00668"></a>00668
<a name="l00673"></a><a class="code" href="structcp__cfg__element__t.html#5ac083a645d964373f022d03df4849c8">00673</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__cfg__element__t.html#5ac083a645d964373f022d03df4849c8">name</a>;
-<a name="l00674"></a>00674
+<a name="l00674"></a>00674
<a name="l00676"></a><a class="code" href="structcp__cfg__element__t.html#b6eced8675261543cd28efea6c7a0fa4">00676</a> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="structcp__cfg__element__t.html#b6eced8675261543cd28efea6c7a0fa4">num_atts</a>;
-<a name="l00677"></a>00677
+<a name="l00677"></a>00677
<a name="l00682"></a><a class="code" href="structcp__cfg__element__t.html#719b3d0c1369478044ce59dc2f207c21">00682</a> <span class="keywordtype">char</span> **<a class="code" href="structcp__cfg__element__t.html#719b3d0c1369478044ce59dc2f207c21">atts</a>;
-<a name="l00683"></a>00683
+<a name="l00683"></a>00683
<a name="l00689"></a><a class="code" href="structcp__cfg__element__t.html#4e9aec275e566b978a3ccb4e043d8c61">00689</a> <span class="keywordtype">char</span> *<a class="code" href="structcp__cfg__element__t.html#4e9aec275e566b978a3ccb4e043d8c61">value</a>;
-<a name="l00690"></a>00690
+<a name="l00690"></a>00690
<a name="l00692"></a><a class="code" href="structcp__cfg__element__t.html#8c99879f94f30ed01e0b76847ab11237">00692</a> <a class="code" href="group__cTypedefsShorthand.html#ge8a837c613935f505e66734c567ed700">cp_cfg_element_t</a> *<a class="code" href="structcp__cfg__element__t.html#8c99879f94f30ed01e0b76847ab11237">parent</a>;
-<a name="l00693"></a>00693
+<a name="l00693"></a>00693
<a name="l00695"></a><a class="code" href="structcp__cfg__element__t.html#589d64202487f78e3cc30dd2e04c5201">00695</a> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="structcp__cfg__element__t.html#589d64202487f78e3cc30dd2e04c5201">index</a>;
-<a name="l00696"></a>00696
+<a name="l00696"></a>00696
<a name="l00698"></a><a class="code" href="structcp__cfg__element__t.html#b7c9e81d106b95f54ff71b9096ba5dc6">00698</a> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="structcp__cfg__element__t.html#b7c9e81d106b95f54ff71b9096ba5dc6">num_children</a>;
-<a name="l00699"></a>00699
+<a name="l00699"></a>00699
<a name="l00704"></a><a class="code" href="structcp__cfg__element__t.html#3c4e4c4df68a11f898566c3f90bcd534">00704</a> <a class="code" href="group__cTypedefsShorthand.html#ge8a837c613935f505e66734c567ed700">cp_cfg_element_t</a> *<a class="code" href="structcp__cfg__element__t.html#3c4e4c4df68a11f898566c3f90bcd534">children</a>;
<a name="l00705"></a>00705 };
-<a name="l00706"></a>00706
+<a name="l00706"></a>00706
<a name="l00734"></a><a class="code" href="structcp__plugin__runtime__t.html">00734</a> <span class="keyword">struct </span><a class="code" href="group__cTypedefsShorthand.html#gca5d98d242f7c005f04b00bf77d1882e">cp_plugin_runtime_t</a> {
-<a name="l00735"></a>00735
+<a name="l00735"></a>00735
<a name="l00753"></a>00753 <span class="keywordtype">void</span> *(*create)(cp_context_t *ctx);
-<a name="l00754"></a>00754
+<a name="l00754"></a>00754
<a name="l00775"></a>00775 int (*<a class="code" href="structcp__plugin__runtime__t.html#5a6c64e5d2467d67cf4dd2498639b490">start</a>)(<span class="keywordtype">void</span> *data);
-<a name="l00776"></a>00776
+<a name="l00776"></a>00776
<a name="l00800"></a>00800 void (*<a class="code" href="structcp__plugin__runtime__t.html#ede7dc51a6d9f47d0e21445dc952d5d4">stop</a>)(<span class="keywordtype">void</span> *data);
-<a name="l00801"></a>00801
+<a name="l00801"></a>00801
<a name="l00814"></a>00814 void (*<a class="code" href="structcp__plugin__runtime__t.html#cc37619ea5a3ff4e39e53b9ce0e7ed4f">destroy</a>)(<span class="keywordtype">void</span> *data);
-<a name="l00815"></a>00815
+<a name="l00815"></a>00815
<a name="l00816"></a>00816 };
-<a name="l00817"></a>00817
+<a name="l00817"></a>00817
<a name="l00821"></a>00821 <span class="comment">/* ------------------------------------------------------------------------</span>
<a name="l00822"></a>00822 <span class="comment"> * Function declarations</span>
<a name="l00823"></a>00823 <span class="comment"> * ----------------------------------------------------------------------*/</span>
-<a name="l00824"></a>00824
-<a name="l00844"></a>00844
+<a name="l00824"></a>00824
+<a name="l00844"></a>00844
<a name="l00851"></a>00851 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keyword">const</span> <span class="keywordtype">char</span> *<a class="code" href="group__cFuncsFrameworkInfo.html#g5783cc2485fb87c487b524c2d0fcd702">cp_get_version</a>(<span class="keywordtype">void</span>) <a class="code" href="group__cDefinesGCCAttributes.html#g97e63f6bd1007545853c6ab4d0271e43">CP_GCC_PURE</a>;
-<a name="l00852"></a>00852
+<a name="l00852"></a>00852
<a name="l00860"></a>00860 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> const <span class="keywordtype">char</span> *<a class="code" href="group__cFuncsFrameworkInfo.html#gd44dbf4f97f511f9f4df3f9fdbe6e865">cp_get_host_type</a>(<span class="keywordtype">void</span>) CP_GCC_PURE;
-<a name="l00861"></a>00861
-<a name="l00874"></a>00874
+<a name="l00861"></a>00861
+<a name="l00874"></a>00874
<a name="l00885"></a>00885 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsInit.html#gc794f61edbd896327fabddad2b3d2fd5">cp_set_fatal_error_handler</a>(<a class="code" href="group__cTypedefsFuncs.html#g91b11fd391854d0854cfde0779f8d707">cp_fatal_error_func_t</a> error_handler);
-<a name="l00886"></a>00886
+<a name="l00886"></a>00886
<a name="l00902"></a>00902 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_status_t <a class="code" href="group__cFuncsInit.html#gc72ffd50777c3e898dae661c67b04ba9">cp_init</a>(<span class="keywordtype">void</span>);
-<a name="l00903"></a>00903
+<a name="l00903"></a>00903
<a name="l00914"></a>00914 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsInit.html#g8dfbe51a3b7f23368a4ddf0d9987180e">cp_destroy</a>(<span class="keywordtype">void</span>);
-<a name="l00915"></a>00915
-<a name="l00933"></a>00933
+<a name="l00915"></a>00915
+<a name="l00933"></a>00933
<a name="l00947"></a>00947 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_context_t * <a class="code" href="group__cFuncsContext.html#g7d239c4fc07cf7d3095a20900444ad62">cp_create_context</a>(cp_status_t *status);
-<a name="l00948"></a>00948
+<a name="l00948"></a>00948
<a name="l00956"></a>00956 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsContext.html#g754ff895992fab0aae81a09c727e5868">cp_destroy_context</a>(cp_context_t *ctx) <a class="code" href="group__cDefinesGCCAttributes.html#gca94f5f75abdc0d1c78572d95305c800">CP_GCC_NONNULL</a>(1);
-<a name="l00957"></a>00957
+<a name="l00957"></a>00957
<a name="l00970"></a>00970 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_status_t <a class="code" href="group__cFuncsContext.html#g998d8350e64a129101f9da687ff5713b">cp_register_pcollection</a>(cp_context_t *ctx, const <span class="keywordtype">char</span> *dir) CP_GCC_NONNULL(1, 2);
-<a name="l00971"></a>00971
+<a name="l00971"></a>00971
<a name="l00981"></a>00981 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsContext.html#g59817fdae1aeb28dbc7d3dcfc5568c15">cp_unregister_pcollection</a>(cp_context_t *ctx, const <span class="keywordtype">char</span> *dir) CP_GCC_NONNULL(1, 2);
-<a name="l00982"></a>00982
+<a name="l00982"></a>00982
<a name="l00990"></a>00990 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsContext.html#g0473208ccfde69e0c57ec1f2b4789781">cp_unregister_pcollections</a>(cp_context_t *ctx) CP_GCC_NONNULL(1);
-<a name="l00991"></a>00991
-<a name="l01004"></a>01004
+<a name="l00991"></a>00991
+<a name="l01004"></a>01004
<a name="l01020"></a>01020 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_status_t <a class="code" href="group__cFuncsLogging.html#g5f6962ee1b09d60d9b98d25adfd55cff">cp_register_logger</a>(cp_context_t *ctx, <a class="code" href="group__cTypedefsFuncs.html#ga53e481fd552856aff67d8584f7e5614">cp_logger_func_t</a> logger, <span class="keywordtype">void</span> *user_data, cp_log_severity_t min_severity) CP_GCC_NONNULL(1, 2);
-<a name="l01021"></a>01021
+<a name="l01021"></a>01021
<a name="l01028"></a>01028 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsLogging.html#g206e88cf84739ff2a0ee6e6925ca5ed8">cp_unregister_logger</a>(cp_context_t *ctx, <a class="code" href="group__cTypedefsFuncs.html#ga53e481fd552856aff67d8584f7e5614">cp_logger_func_t</a> logger) CP_GCC_NONNULL(1, 2);
-<a name="l01029"></a>01029
+<a name="l01029"></a>01029
<a name="l01037"></a>01037 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsLogging.html#g6227362eb74ed67ad53ec20e40b9b7bf">cp_log</a>(cp_context_t *ctx, cp_log_severity_t severity, const <span class="keywordtype">char</span> *msg) CP_GCC_NONNULL(1, 3);
-<a name="l01038"></a>01038
+<a name="l01038"></a>01038
<a name="l01046"></a>01046 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">int</span> <a class="code" href="group__cFuncsLogging.html#g16486c754d76d388e0f4c205668c7187">cp_is_logged</a>(cp_context_t *ctx, cp_log_severity_t severity) CP_GCC_NONNULL(1);
-<a name="l01047"></a>01047
-<a name="l01059"></a>01059
+<a name="l01047"></a>01047
+<a name="l01059"></a>01059
<a name="l01076"></a>01076 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <a class="code" href="group__cTypedefsShorthand.html#gc552cbab3bf4b5a2b62a1420521383ad">cp_plugin_info_t</a> * <a class="code" href="group__cFuncsPlugin.html#gcb92588ad3b48dab5e9487698f6ef437">cp_load_plugin_descriptor</a>(cp_context_t *ctx, const <span class="keywordtype">char</span> *path, cp_status_t *status) CP_GCC_NONNULL(1, 2);
-<a name="l01077"></a>01077
+<a name="l01077"></a>01077
<a name="l01094"></a>01094 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_status_t <a class="code" href="group__cFuncsPlugin.html#gc862fd9be2bad2e0dfaafa6216ad34d4">cp_install_plugin</a>(cp_context_t *ctx, <a class="code" href="group__cTypedefsShorthand.html#gc552cbab3bf4b5a2b62a1420521383ad">cp_plugin_info_t</a> *pi) CP_GCC_NONNULL(1, 2);
-<a name="l01095"></a>01095
+<a name="l01095"></a>01095
<a name="l01119"></a>01119 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_status_t <a class="code" href="group__cFuncsPlugin.html#ga9603cd8d153b0ce192ac7b6e56779af">cp_scan_plugins</a>(cp_context_t *ctx, <span class="keywordtype">int</span> flags) CP_GCC_NONNULL(1);
-<a name="l01120"></a>01120
+<a name="l01120"></a>01120
<a name="l01133"></a>01133 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_status_t <a class="code" href="group__cFuncsPlugin.html#g2456b7740351c2530376ffb3a5ab7d92">cp_start_plugin</a>(cp_context_t *ctx, const <span class="keywordtype">char</span> *<span class="keywordtype">id</span>) CP_GCC_NONNULL(1, 2);
-<a name="l01134"></a>01134
+<a name="l01134"></a>01134
<a name="l01147"></a>01147 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_status_t <a class="code" href="group__cFuncsPlugin.html#g7bdc861d480c6c9addafbb0f481323fa">cp_stop_plugin</a>(cp_context_t *ctx, const <span class="keywordtype">char</span> *<span class="keywordtype">id</span>) CP_GCC_NONNULL(1, 2);
-<a name="l01148"></a>01148
+<a name="l01148"></a>01148
<a name="l01154"></a>01154 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsPlugin.html#g4dec7d61518adfa01da3f2892eaea20a">cp_stop_plugins</a>(cp_context_t *ctx) CP_GCC_NONNULL(1);
-<a name="l01155"></a>01155
+<a name="l01155"></a>01155
<a name="l01164"></a>01164 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_status_t <a class="code" href="group__cFuncsPlugin.html#g2249552dc67bb7893f81babee4a27454">cp_uninstall_plugin</a>(cp_context_t *ctx, const <span class="keywordtype">char</span> *<span class="keywordtype">id</span>) CP_GCC_NONNULL(1, 2);
-<a name="l01165"></a>01165
+<a name="l01165"></a>01165
<a name="l01172"></a>01172 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsPlugin.html#g01a607d9ae7f9fdb7e91a1845b0e5e99">cp_uninstall_plugins</a>(cp_context_t *ctx) CP_GCC_NONNULL(1);
-<a name="l01173"></a>01173
-<a name="l01186"></a>01186
+<a name="l01173"></a>01173
+<a name="l01186"></a>01186
<a name="l01200"></a>01200 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <a class="code" href="group__cTypedefsShorthand.html#gc552cbab3bf4b5a2b62a1420521383ad">cp_plugin_info_t</a> * <a class="code" href="group__cFuncsPluginInfo.html#g4aba19886c68b2a3c1508c3b66110c12">cp_get_plugin_info</a>(cp_context_t *ctx, const <span class="keywordtype">char</span> *<span class="keywordtype">id</span>, cp_status_t *status) CP_GCC_NONNULL(1);
-<a name="l01201"></a>01201
+<a name="l01201"></a>01201
<a name="l01214"></a>01214 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <a class="code" href="group__cTypedefsShorthand.html#gc552cbab3bf4b5a2b62a1420521383ad">cp_plugin_info_t</a> ** <a class="code" href="group__cFuncsPluginInfo.html#g015373cf40c08ea4a346a1bac5656fb1">cp_get_plugins_info</a>(cp_context_t *ctx, cp_status_t *status, <span class="keywordtype">int</span> *num) CP_GCC_NONNULL(1);
-<a name="l01215"></a>01215
+<a name="l01215"></a>01215
<a name="l01228"></a>01228 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <a class="code" href="group__cTypedefsShorthand.html#g4a19f7af87165d59dd82866006a96424">cp_ext_point_t</a> ** <a class="code" href="group__cFuncsPluginInfo.html#g5fb5797d8d84e03275070666dc60a02d">cp_get_ext_points_info</a>(cp_context_t *ctx, cp_status_t *status, <span class="keywordtype">int</span> *num) CP_GCC_NONNULL(1);
-<a name="l01229"></a>01229
+<a name="l01229"></a>01229
<a name="l01243"></a>01243 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <a class="code" href="group__cTypedefsShorthand.html#gea86d23c48f7335c3b710b9a3af2bf89">cp_extension_t</a> ** <a class="code" href="group__cFuncsPluginInfo.html#gc4321531959bb053be7698139b0ae168">cp_get_extensions_info</a>(cp_context_t *ctx, const <span class="keywordtype">char</span> *extpt_id, cp_status_t *status, <span class="keywordtype">int</span> *num) CP_GCC_NONNULL(1);
-<a name="l01244"></a>01244
+<a name="l01244"></a>01244
<a name="l01255"></a>01255 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsPluginInfo.html#gbac266df43a4850cf43224aa7b863942">cp_release_info</a>(cp_context_t *ctx, <span class="keywordtype">void</span> *info) CP_GCC_NONNULL(1, 2);
-<a name="l01256"></a>01256
+<a name="l01256"></a>01256
<a name="l01265"></a>01265 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_plugin_state_t <a class="code" href="group__cFuncsPluginInfo.html#g926489fc366d412cd272ec4bfefe22e5">cp_get_plugin_state</a>(cp_context_t *ctx, const <span class="keywordtype">char</span> *<span class="keywordtype">id</span>) CP_GCC_NONNULL(1, 2);
-<a name="l01266"></a>01266
+<a name="l01266"></a>01266
<a name="l01280"></a>01280 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_status_t <a class="code" href="group__cFuncsPluginInfo.html#ge9930a241e859e9eb07e36981ef7077a">cp_register_plistener</a>(cp_context_t *ctx, <a class="code" href="group__cTypedefsFuncs.html#g24fde3d7324169d8448700123aa97c7a">cp_plugin_listener_func_t</a> listener, <span class="keywordtype">void</span> *user_data) CP_GCC_NONNULL(1, 2);
-<a name="l01281"></a>01281
+<a name="l01281"></a>01281
<a name="l01289"></a>01289 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsPluginInfo.html#g2cd49b8752e8971b569ae3e39b41723e">cp_unregister_plistener</a>(cp_context_t *ctx, <a class="code" href="group__cTypedefsFuncs.html#g24fde3d7324169d8448700123aa97c7a">cp_plugin_listener_func_t</a> listener) CP_GCC_NONNULL(1, 2);
-<a name="l01290"></a>01290
+<a name="l01290"></a>01290
<a name="l01304"></a>01304 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <a class="code" href="group__cTypedefsShorthand.html#ge8a837c613935f505e66734c567ed700">cp_cfg_element_t</a> * <a class="code" href="group__cFuncsPluginInfo.html#g9868077c72df950607e2698153d593d1">cp_lookup_cfg_element</a>(<a class="code" href="group__cTypedefsShorthand.html#ge8a837c613935f505e66734c567ed700">cp_cfg_element_t</a> *base, const <span class="keywordtype">char</span> *path) CP_GCC_PURE CP_GCC_NONNULL(1, 2);
-<a name="l01305"></a>01305
+<a name="l01305"></a>01305
<a name="l01322"></a>01322 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">char</span> * <a class="code" href="group__cFuncsPluginInfo.html#g13f5121ab21951d59d3c6b985ed6adcd">cp_lookup_cfg_value</a>(<a class="code" href="group__cTypedefsShorthand.html#ge8a837c613935f505e66734c567ed700">cp_cfg_element_t</a> *base, const <span class="keywordtype">char</span> *path) CP_GCC_PURE CP_GCC_NONNULL(1, 2);
-<a name="l01323"></a>01323
-<a name="l01351"></a>01351
+<a name="l01323"></a>01323
+<a name="l01351"></a>01351
<a name="l01365"></a>01365 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_status_t <a class="code" href="group__cFuncsPluginExec.html#g357c45e87ff896e8541fe3758b19a035">cp_run_function</a>(cp_context_t *ctx, <a class="code" href="group__cTypedefsFuncs.html#gf55fb990664aaa069e72a8fa4da20034">cp_run_func_t</a> runfunc) CP_GCC_NONNULL(1, 2);
-<a name="l01366"></a>01366
+<a name="l01366"></a>01366
<a name="l01376"></a>01376 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsPluginExec.html#g4668727a5b1c9f0531f6d5dc77fa9f9f">cp_run_plugins</a>(cp_context_t *ctx) CP_GCC_NONNULL(1);
-<a name="l01377"></a>01377
+<a name="l01377"></a>01377
<a name="l01389"></a>01389 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">int</span> <a class="code" href="group__cFuncsPluginExec.html#g7e212bc93d6588fc09995f310548c929">cp_run_plugins_step</a>(cp_context_t *ctx) CP_GCC_NONNULL(1);
-<a name="l01390"></a>01390
+<a name="l01390"></a>01390
<a name="l01405"></a>01405 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsPluginExec.html#g9233fa8a46e408044030d2d767f1fda4">cp_set_context_args</a>(cp_context_t *ctx, <span class="keywordtype">char</span> **argv) CP_GCC_NONNULL(1, 2);
-<a name="l01406"></a>01406
+<a name="l01406"></a>01406
<a name="l01418"></a>01418 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">char</span> **<a class="code" href="group__cFuncsPluginExec.html#g08929433446b28f8fce8b8beae0e742a">cp_get_context_args</a>(cp_context_t *ctx, <span class="keywordtype">int</span> *argc) CP_GCC_NONNULL(1);
-<a name="l01419"></a>01419
-<a name="l01432"></a>01432
+<a name="l01419"></a>01419
+<a name="l01432"></a>01432
<a name="l01445"></a>01445 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> cp_status_t <a class="code" href="group__cFuncsSymbols.html#g9d128b52c0ffe2d4215026fe59f9abeb">cp_define_symbol</a>(cp_context_t *ctx, const <span class="keywordtype">char</span> *name, <span class="keywordtype">void</span> *ptr) CP_GCC_NONNULL(1, 2, 3);
-<a name="l01446"></a>01446
+<a name="l01446"></a>01446
<a name="l01477"></a>01477 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> *<a class="code" href="group__cFuncsSymbols.html#g8bc3b7fcf4f4ed414837f5a3998d46b7">cp_resolve_symbol</a>(cp_context_t *ctx, const <span class="keywordtype">char</span> *<span class="keywordtype">id</span>, const <span class="keywordtype">char</span> *name, cp_status_t *status) CP_GCC_NONNULL(1, 2, 3);
-<a name="l01478"></a>01478
+<a name="l01478"></a>01478
<a name="l01488"></a>01488 <a class="code" href="group__cDefines.html#g4a0b99de58335624b91476b9cf1c4404">CP_C_API</a> <span class="keywordtype">void</span> <a class="code" href="group__cFuncsSymbols.html#g150629125a61ac9fa4e2095b0d9c7e57">cp_release_symbol</a>(cp_context_t *ctx, const <span class="keywordtype">void</span> *ptr) CP_GCC_NONNULL(1, 2);
-<a name="l01489"></a>01489
+<a name="l01489"></a>01489
<a name="l01493"></a>01493 <span class="preprocessor">#ifdef __cplusplus</span>
<a name="l01494"></a>01494 <span class="preprocessor"></span>}
<a name="l01495"></a>01495 <span class="preprocessor">#endif </span><span class="comment">/*__cplusplus*/</span>
-<a name="l01496"></a>01496
+<a name="l01496"></a>01496
<a name="l01497"></a>01497 <span class="preprocessor">#endif </span><span class="comment">/*CPLUFF_H_*/</span>
</pre></div><hr size="1">
<p class="footer">
<li><a href="globals.html"><span>Globals</span></a></li>
</ul></div>
<h1>cpluff.h File Reference</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-C-Pluff C API header file.
+C-Pluff C API header file.
<p>
-The elements declared here constitute the C-Pluff C API. To use the API include this file and link the main program and plug-in runtime libraries with the C-Pluff C library. In addition to local declarations, this file also includes <a class="el" href="cpluffdef_8h.html">cpluffdef.h</a> header file for defines common to C and C++ API.
+The elements declared here constitute the C-Pluff C API. To use the API include this file and link the main program and plug-in runtime libraries with the C-Pluff C library. In addition to local declarations, this file also includes <a class="el" href="cpluffdef_8h.html">cpluffdef.h</a> header file for defines common to C and C++ API.
<p>
<p>
<tr><td class="mdescLeft"> </td><td class="mdescRight">A run function registered by a plug-in to perform work. <a href="group__cTypedefsFuncs.html#gf55fb990664aaa069e72a8fa4da20034"></a><br></td></tr>
<tr><td colspan="2"><br><h2>Enumerations</h2></td></tr>
<tr><td class="memItemLeft" nowrap align="right" valign="top">enum </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cEnums.html#gd6a8106d281ffa4b1f43fe8e3effc7da">cp_status_t</a> { <br>
- <a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da5ffbe0fe80af75e699e4b04909912f7a">CP_OK</a> = 0,
-<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dac4e31e28c38ba325fa7169da1a233950">CP_ERR_RESOURCE</a>,
-<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da6418acb9f17c3a00ea350684bff9782e">CP_ERR_UNKNOWN</a>,
-<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da2993572d373d8cc61f9655c10fbeefa5">CP_ERR_IO</a>,
+ <a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da5ffbe0fe80af75e699e4b04909912f7a">CP_OK</a> = 0,
+<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dac4e31e28c38ba325fa7169da1a233950">CP_ERR_RESOURCE</a>,
+<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da6418acb9f17c3a00ea350684bff9782e">CP_ERR_UNKNOWN</a>,
+<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da2993572d373d8cc61f9655c10fbeefa5">CP_ERR_IO</a>,
<br>
- <a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dadc486f602f89493e882cde6a364de0b7">CP_ERR_MALFORMED</a>,
-<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dab07cfdc96a5dbc3a3e359bae2534c9d2">CP_ERR_CONFLICT</a>,
-<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da068a07ac79fdc33dc0c47d14c37005f6">CP_ERR_DEPENDENCY</a>,
+ <a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dadc486f602f89493e882cde6a364de0b7">CP_ERR_MALFORMED</a>,
+<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dab07cfdc96a5dbc3a3e359bae2534c9d2">CP_ERR_CONFLICT</a>,
+<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da068a07ac79fdc33dc0c47d14c37005f6">CP_ERR_DEPENDENCY</a>,
<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dae9eb8fc6b508a70eae974760d8be07aa">CP_ERR_RUNTIME</a>
<br>
}</td></tr>
<tr><td class="mdescLeft"> </td><td class="mdescRight">An enumeration of status codes returned by API functions. <a href="group__cEnums.html#gd6a8106d281ffa4b1f43fe8e3effc7da">More...</a><br></td></tr>
<tr><td class="memItemLeft" nowrap align="right" valign="top">enum </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cEnums.html#gd517a8088e2ed89fda71251d9c7b3252">cp_plugin_state_t</a> { <br>
- <a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b325290eacd4f02fb7d65eaf68f7251a99689">CP_PLUGIN_UNINSTALLED</a>,
-<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32521c91e4bef84a1d924456fb268a1d848b">CP_PLUGIN_INSTALLED</a>,
-<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b325275596c790e344583d117d3c6bb4252bd">CP_PLUGIN_RESOLVED</a>,
-<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32522c6ca0c8d90c3acb01e336ce1711540c">CP_PLUGIN_STARTING</a>,
+ <a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b325290eacd4f02fb7d65eaf68f7251a99689">CP_PLUGIN_UNINSTALLED</a>,
+<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32521c91e4bef84a1d924456fb268a1d848b">CP_PLUGIN_INSTALLED</a>,
+<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b325275596c790e344583d117d3c6bb4252bd">CP_PLUGIN_RESOLVED</a>,
+<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32522c6ca0c8d90c3acb01e336ce1711540c">CP_PLUGIN_STARTING</a>,
<br>
- <a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32525aafd09bec81bb2bedfd7bfc8643051c">CP_PLUGIN_STOPPING</a>,
+ <a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32525aafd09bec81bb2bedfd7bfc8643051c">CP_PLUGIN_STOPPING</a>,
<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b3252953ad85aee24006f4a5079bfca73eb9f">CP_PLUGIN_ACTIVE</a>
<br>
}</td></tr>
<tr><td class="mdescLeft"> </td><td class="mdescRight">An enumeration of possible plug-in states. <a href="group__cEnums.html#gd517a8088e2ed89fda71251d9c7b3252">More...</a><br></td></tr>
-<tr><td class="memItemLeft" nowrap align="right" valign="top">enum </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cEnums.html#g952725f83949f4eb486c390c4ff72aeb">cp_log_severity_t</a> { <a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aeb22e3ccb1789e1f0ea3b35e1682fe8af8">CP_LOG_DEBUG</a>,
-<a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aebcdb069d62e546b005ae6a81e6cdb0333">CP_LOG_INFO</a>,
-<a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aeb26a8a8c987042689e5018e481d235ee0">CP_LOG_WARNING</a>,
+<tr><td class="memItemLeft" nowrap align="right" valign="top">enum </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cEnums.html#g952725f83949f4eb486c390c4ff72aeb">cp_log_severity_t</a> { <a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aeb22e3ccb1789e1f0ea3b35e1682fe8af8">CP_LOG_DEBUG</a>,
+<a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aebcdb069d62e546b005ae6a81e6cdb0333">CP_LOG_INFO</a>,
+<a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aeb26a8a8c987042689e5018e481d235ee0">CP_LOG_WARNING</a>,
<a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aebd99d2bd1dbae181f9a41e90e6bf8d14e">CP_LOG_ERROR</a>
}</td></tr>
<a name="l00020"></a>00020 <span class="comment"> * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE</span>
<a name="l00021"></a>00021 <span class="comment"> * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</span>
<a name="l00022"></a>00022 <span class="comment"> *-----------------------------------------------------------------------*/</span>
-<a name="l00023"></a>00023
+<a name="l00023"></a>00023
<a name="l00030"></a>00030 <span class="preprocessor">#ifndef CPLUFFDEF_H_</span>
<a name="l00031"></a>00031 <span class="preprocessor"></span><span class="preprocessor">#define CPLUFFDEF_H_</span>
<a name="l00032"></a>00032 <span class="preprocessor"></span>
-<a name="l00033"></a>00033
+<a name="l00033"></a>00033
<a name="l00034"></a>00034 <span class="comment">/* ------------------------------------------------------------------------</span>
<a name="l00035"></a>00035 <span class="comment"> * Version information</span>
<a name="l00036"></a>00036 <span class="comment"> * ----------------------------------------------------------------------*/</span>
-<a name="l00037"></a>00037
-<a name="l00047"></a>00047
+<a name="l00037"></a>00037
+<a name="l00047"></a>00047
<a name="l00053"></a><a class="code" href="group__versionInfo.html#gec8f38d724eaff6c28e96f355e0a6a85">00053</a> <span class="preprocessor">#define CP_VERSION "0.1.3"</span>
<a name="l00054"></a>00054 <span class="preprocessor"></span>
<a name="l00059"></a><a class="code" href="group__versionInfo.html#gc02132b57a51a1c26ff6fb11dc046c04">00059</a> <span class="preprocessor">#define CP_VERSION_MAJOR 0</span>
<a name="l00070"></a>00070 <span class="comment">/* ------------------------------------------------------------------------</span>
<a name="l00071"></a>00071 <span class="comment"> * Symbol visibility</span>
<a name="l00072"></a>00072 <span class="comment"> * ----------------------------------------------------------------------*/</span>
-<a name="l00073"></a>00073
-<a name="l00102"></a>00102
+<a name="l00073"></a>00073
+<a name="l00102"></a>00102
<a name="l00137"></a>00137 <span class="preprocessor">#if defined(_WIN32)</span>
<a name="l00138"></a>00138 <span class="preprocessor"></span><span class="preprocessor"># define CP_EXPORT __declspec(dllexport)</span>
<a name="l00139"></a>00139 <span class="preprocessor"></span><span class="preprocessor"># define CP_IMPORT extern __declspec(dllimport)</span>
<a name="l00154"></a>00154 <span class="comment">/* ------------------------------------------------------------------------</span>
<a name="l00155"></a>00155 <span class="comment"> * GCC attributes</span>
<a name="l00156"></a>00156 <span class="comment"> * ----------------------------------------------------------------------*/</span>
-<a name="l00157"></a>00157
-<a name="l00168"></a>00168
+<a name="l00157"></a>00157
+<a name="l00168"></a>00168
<a name="l00187"></a>00187 <span class="preprocessor">#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)</span>
<a name="l00188"></a>00188 <span class="preprocessor"></span><span class="preprocessor">#define CP_GCC_PURE __attribute__((pure))</span>
<a name="l00189"></a>00189 <span class="preprocessor"></span><span class="preprocessor">#else</span>
<li><a href="globals.html"><span>Globals</span></a></li>
</ul></div>
<h1>cpluffdef.h File Reference</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-Common defines shared by C-Pluff C and C++ APIs.
+Common defines shared by C-Pluff C and C++ APIs.
<p>
-This file is automatically included by the top level C and C++ API header files. There should be no need to include it explicitly.
+This file is automatically included by the top level C and C++ API header files. There should be no need to include it explicitly.
<p>
<p>
<li><a href="pages.html"><span>Related Pages</span></a></li>
</ul></div>
<h1>Defines</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-Preprocessor defines.
+Preprocessor defines.
<p>
<p>
<div class="memdoc">
<p>
-Marks a symbol declaration to be part of the C-Pluff C API.
+Marks a symbol declaration to be part of the C-Pluff C API.
<p>
-This macro declares the symbol to be imported from the C-Pluff library.
+This macro declares the symbol to be imported from the C-Pluff library.
</div>
</div><p>
<hr size="1">
<small>
[<a class="el" href="group__cDefines.html">Defines</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-These macros conditionally define GCC attributes for declarations.
+These macros conditionally define GCC attributes for declarations.
<p>
-They are used in C-Pluff API declarations to enable better optimization and error checking when using GCC. In non-GCC platforms they have empty values.
+They are used in C-Pluff API declarations to enable better optimization and error checking when using GCC. In non-GCC platforms they have empty values.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-Declares a function as pure function having no side effects.
+Declares a function as pure function having no side effects.
<p>
-This attribute is supported in GCC since version 2.96. Such functions can be subject to common subexpression elimination and loop optimization.
+This attribute is supported in GCC since version 2.96. Such functions can be subject to common subexpression elimination and loop optimization.
</div>
</div><p>
<a class="anchor" name="gca94f5f75abdc0d1c78572d95305c800"></a><!-- doxytag: member="cpluffdef.h::CP_GCC_NONNULL" ref="gca94f5f75abdc0d1c78572d95305c800" args="(...)" -->
<div class="memdoc">
<p>
-Specifies that some pointer arguments to a function should have non-NULL values.
+Specifies that some pointer arguments to a function should have non-NULL values.
<p>
-Takes a variable length list of argument indexes as arguments. This attribute is supported in GCC since version 3.3. It can be used for enhanced error checking and some optimizations.
+Takes a variable length list of argument indexes as arguments. This attribute is supported in GCC since version 3.3. It can be used for enhanced error checking and some optimizations.
</div>
</div><p>
<hr size="1">
<li><a href="pages.html"><span>Related Pages</span></a></li>
</ul></div>
<h1>Enumerations</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-Constant value enumerations.
+Constant value enumerations.
<p>
<p>
<tr><td></td></tr>
<tr><td colspan="2"><br><h2>Enumerations</h2></td></tr>
<tr><td class="memItemLeft" nowrap align="right" valign="top">enum </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cEnums.html#gd6a8106d281ffa4b1f43fe8e3effc7da">cp_status_t</a> { <br>
- <a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da5ffbe0fe80af75e699e4b04909912f7a">CP_OK</a> = 0,
-<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dac4e31e28c38ba325fa7169da1a233950">CP_ERR_RESOURCE</a>,
-<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da6418acb9f17c3a00ea350684bff9782e">CP_ERR_UNKNOWN</a>,
-<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da2993572d373d8cc61f9655c10fbeefa5">CP_ERR_IO</a>,
+ <a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da5ffbe0fe80af75e699e4b04909912f7a">CP_OK</a> = 0,
+<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dac4e31e28c38ba325fa7169da1a233950">CP_ERR_RESOURCE</a>,
+<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da6418acb9f17c3a00ea350684bff9782e">CP_ERR_UNKNOWN</a>,
+<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da2993572d373d8cc61f9655c10fbeefa5">CP_ERR_IO</a>,
<br>
- <a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dadc486f602f89493e882cde6a364de0b7">CP_ERR_MALFORMED</a>,
-<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dab07cfdc96a5dbc3a3e359bae2534c9d2">CP_ERR_CONFLICT</a>,
-<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da068a07ac79fdc33dc0c47d14c37005f6">CP_ERR_DEPENDENCY</a>,
+ <a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dadc486f602f89493e882cde6a364de0b7">CP_ERR_MALFORMED</a>,
+<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dab07cfdc96a5dbc3a3e359bae2534c9d2">CP_ERR_CONFLICT</a>,
+<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da068a07ac79fdc33dc0c47d14c37005f6">CP_ERR_DEPENDENCY</a>,
<a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dae9eb8fc6b508a70eae974760d8be07aa">CP_ERR_RUNTIME</a>
<br>
}</td></tr>
<tr><td class="mdescLeft"> </td><td class="mdescRight">An enumeration of status codes returned by API functions. <a href="group__cEnums.html#gd6a8106d281ffa4b1f43fe8e3effc7da">More...</a><br></td></tr>
<tr><td class="memItemLeft" nowrap align="right" valign="top">enum </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cEnums.html#gd517a8088e2ed89fda71251d9c7b3252">cp_plugin_state_t</a> { <br>
- <a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b325290eacd4f02fb7d65eaf68f7251a99689">CP_PLUGIN_UNINSTALLED</a>,
-<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32521c91e4bef84a1d924456fb268a1d848b">CP_PLUGIN_INSTALLED</a>,
-<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b325275596c790e344583d117d3c6bb4252bd">CP_PLUGIN_RESOLVED</a>,
-<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32522c6ca0c8d90c3acb01e336ce1711540c">CP_PLUGIN_STARTING</a>,
+ <a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b325290eacd4f02fb7d65eaf68f7251a99689">CP_PLUGIN_UNINSTALLED</a>,
+<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32521c91e4bef84a1d924456fb268a1d848b">CP_PLUGIN_INSTALLED</a>,
+<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b325275596c790e344583d117d3c6bb4252bd">CP_PLUGIN_RESOLVED</a>,
+<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32522c6ca0c8d90c3acb01e336ce1711540c">CP_PLUGIN_STARTING</a>,
<br>
- <a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32525aafd09bec81bb2bedfd7bfc8643051c">CP_PLUGIN_STOPPING</a>,
+ <a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b32525aafd09bec81bb2bedfd7bfc8643051c">CP_PLUGIN_STOPPING</a>,
<a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b3252953ad85aee24006f4a5079bfca73eb9f">CP_PLUGIN_ACTIVE</a>
<br>
}</td></tr>
<tr><td class="mdescLeft"> </td><td class="mdescRight">An enumeration of possible plug-in states. <a href="group__cEnums.html#gd517a8088e2ed89fda71251d9c7b3252">More...</a><br></td></tr>
-<tr><td class="memItemLeft" nowrap align="right" valign="top">enum </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cEnums.html#g952725f83949f4eb486c390c4ff72aeb">cp_log_severity_t</a> { <a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aeb22e3ccb1789e1f0ea3b35e1682fe8af8">CP_LOG_DEBUG</a>,
-<a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aebcdb069d62e546b005ae6a81e6cdb0333">CP_LOG_INFO</a>,
-<a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aeb26a8a8c987042689e5018e481d235ee0">CP_LOG_WARNING</a>,
+<tr><td class="memItemLeft" nowrap align="right" valign="top">enum </td><td class="memItemRight" valign="bottom"><a class="el" href="group__cEnums.html#g952725f83949f4eb486c390c4ff72aeb">cp_log_severity_t</a> { <a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aeb22e3ccb1789e1f0ea3b35e1682fe8af8">CP_LOG_DEBUG</a>,
+<a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aebcdb069d62e546b005ae6a81e6cdb0333">CP_LOG_INFO</a>,
+<a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aeb26a8a8c987042689e5018e481d235ee0">CP_LOG_WARNING</a>,
<a class="el" href="group__cEnums.html#gg952725f83949f4eb486c390c4ff72aebd99d2bd1dbae181f9a41e90e6bf8d14e">CP_LOG_ERROR</a>
}</td></tr>
<div class="memdoc">
<p>
-An enumeration of status codes returned by API functions.
+An enumeration of status codes returned by API functions.
<p>
Most of the interface functions return a status code. The returned status code either indicates successful completion of the operation or some specific kind of error. Some functions do not return a status code because they never fail. <dl compact><dt><b>Enumerator: </b></dt><dd>
<table border="0" cellspacing="2" cellpadding="0">
<div class="memdoc">
<p>
-An enumeration of possible plug-in states.
+An enumeration of possible plug-in states.
<p>
Plug-in states are controlled by <a class="el" href="group__cFuncsPlugin.html">plug-in management functions</a>. Plug-in states can be observed by <a class="el" href="group__cFuncsPluginInfo.html#ge9930a241e859e9eb07e36981ef7077a">registering</a> a <a class="el" href="group__cTypedefsFuncs.html#g24fde3d7324169d8448700123aa97c7a">plug-in listener function</a> or by calling <a class="el" href="group__cFuncsPluginInfo.html#g926489fc366d412cd272ec4bfefe22e5">cp_get_plugin_state</a>.<p>
<dl class="see" compact><dt><b>See also:</b></dt><dd>cp_plugin_listener_t <p>
<dl compact><dt><b>Enumerator: </b></dt><dd>
<table border="0" cellspacing="2" cellpadding="0">
<tr><td valign="top"><em><a class="anchor" name="ggd517a8088e2ed89fda71251d9c7b325290eacd4f02fb7d65eaf68f7251a99689"></a><!-- doxytag: member="CP_PLUGIN_UNINSTALLED" ref="ggd517a8088e2ed89fda71251d9c7b325290eacd4f02fb7d65eaf68f7251a99689" args="" -->CP_PLUGIN_UNINSTALLED</em> </td><td>
-Plug-in is not installed.
+Plug-in is not installed.
<p>
No plug-in information has been loaded. </td></tr>
<tr><td valign="top"><em><a class="anchor" name="ggd517a8088e2ed89fda71251d9c7b32521c91e4bef84a1d924456fb268a1d848b"></a><!-- doxytag: member="CP_PLUGIN_INSTALLED" ref="ggd517a8088e2ed89fda71251d9c7b32521c91e4bef84a1d924456fb268a1d848b" args="" -->CP_PLUGIN_INSTALLED</em> </td><td>
-Plug-in is installed.
+Plug-in is installed.
<p>
At this stage the plug-in information has been loaded but its dependencies to other plug-ins has not yet been resolved. The plug-in runtime has not been loaded yet. The extension points and extensions provided by the plug-in have been registered. </td></tr>
<tr><td valign="top"><em><a class="anchor" name="ggd517a8088e2ed89fda71251d9c7b325275596c790e344583d117d3c6bb4252bd"></a><!-- doxytag: member="CP_PLUGIN_RESOLVED" ref="ggd517a8088e2ed89fda71251d9c7b325275596c790e344583d117d3c6bb4252bd" args="" -->CP_PLUGIN_RESOLVED</em> </td><td>
-Plug-in dependencies have been resolved.
+Plug-in dependencies have been resolved.
<p>
At this stage it has been verified that the dependencies of the plug-in are satisfied and the plug-in runtime has been loaded but it is not active (it has not been started or it has been stopped). Plug-in is resolved when a dependent plug-in is being resolved or before the plug-in is started. Plug-in is put back to installed stage if its dependencies are being uninstalled. </td></tr>
<tr><td valign="top"><em><a class="anchor" name="ggd517a8088e2ed89fda71251d9c7b32522c6ca0c8d90c3acb01e336ce1711540c"></a><!-- doxytag: member="CP_PLUGIN_STARTING" ref="ggd517a8088e2ed89fda71251d9c7b32522c6ca0c8d90c3acb01e336ce1711540c" args="" -->CP_PLUGIN_STARTING</em> </td><td>
-Plug-in is starting.
+Plug-in is starting.
<p>
The plug-in has been resolved and the start function (if any) of the plug-in runtime is about to be called. A plug-in is started when explicitly requested by the main program or when a dependent plug-in is about to be started or when a dynamic symbol defined by the plug-in is being resolved. This state is omitted and the state changes directly from resolved to active if the plug-in runtime does not define a start function. </td></tr>
<tr><td valign="top"><em><a class="anchor" name="ggd517a8088e2ed89fda71251d9c7b32525aafd09bec81bb2bedfd7bfc8643051c"></a><!-- doxytag: member="CP_PLUGIN_STOPPING" ref="ggd517a8088e2ed89fda71251d9c7b32525aafd09bec81bb2bedfd7bfc8643051c" args="" -->CP_PLUGIN_STOPPING</em> </td><td>
-Plug-in is stopping.
+Plug-in is stopping.
<p>
The stop function (if any) of the plug-in runtime is about to be called. A plug-in is stopped if the start function fails or when stopping is explicitly requested by the main program or when its dependencies are being stopped. This state is omitted and the state changes directly from active to resolved if the plug-in runtime does not define a stop function. </td></tr>
<tr><td valign="top"><em><a class="anchor" name="ggd517a8088e2ed89fda71251d9c7b3252953ad85aee24006f4a5079bfca73eb9f"></a><!-- doxytag: member="CP_PLUGIN_ACTIVE" ref="ggd517a8088e2ed89fda71251d9c7b3252953ad85aee24006f4a5079bfca73eb9f" args="" -->CP_PLUGIN_ACTIVE</em> </td><td>
<div class="memdoc">
<p>
-An enumeration of possible message severities for framework logging.
+An enumeration of possible message severities for framework logging.
<p>
These constants are used when passing a log message to a <a class="el" href="group__cTypedefsFuncs.html#ga53e481fd552856aff67d8584f7e5614">logger function</a> and when <a class="el" href="group__cFuncsLogging.html#g5f6962ee1b09d60d9b98d25adfd55cff">registering</a> a logger function. <dl compact><dt><b>Enumerator: </b></dt><dd>
<table border="0" cellspacing="2" cellpadding="0">
<li><a href="pages.html"><span>Related Pages</span></a></li>
</ul></div>
<h1>Functions</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-C API functions.
+C API functions.
<p>
-The C-Pluff C API functions and any data exposed by them are generally thread-safe if the library has been compiled with multi-threading support. The <a class="el" href="group__cFuncsInit.html">framework initialization functions</a> are exceptions, they are not thread-safe.
+The C-Pluff C API functions and any data exposed by them are generally thread-safe if the library has been compiled with multi-threading support. The <a class="el" href="group__cFuncsInit.html">framework initialization functions</a> are exceptions, they are not thread-safe.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<small>
[<a class="el" href="group__cFuncs.html">Functions</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-These functions are used to manage plug-in contexts from the main program perspective.
+These functions are used to manage plug-in contexts from the main program perspective.
<p>
-They are not intended to be used by a plug-in runtime. From the main program perspective a plug-in context is a container for installed plug-ins. There can be several plug-in context instances if there are several independent sets of plug-ins. However, different plug-in contexts are not very isolated from each other in practice because the global symbols exported by a plug-in runtime in one context are visible to all plug-ins in all context instances.
+They are not intended to be used by a plug-in runtime. From the main program perspective a plug-in context is a container for installed plug-ins. There can be several plug-in context instances if there are several independent sets of plug-ins. However, different plug-in contexts are not very isolated from each other in practice because the global symbols exported by a plug-in runtime in one context are visible to all plug-ins in all context instances.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-Creates a new plug-in context which can be used as a container for plug-ins.
+Creates a new plug-in context which can be used as a container for plug-ins.
<p>
Plug-ins are loaded and installed into a specific context. The main program may have more than one plug-in context but the plug-ins that interact with each other should be placed in the same context. The resources associated with the context are released by calling <a class="el" href="group__cFuncsContext.html#g754ff895992fab0aae81a09c727e5868">cp_destroy_context</a> when the context is not needed anymore. Remaining contexts are automatically destroyed when the plug-in framework is destroyed.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Destroys the specified plug-in context and releases the associated resources.
+Destroys the specified plug-in context and releases the associated resources.
<p>
Stops and uninstalls all plug-ins in the context. The context must not be accessed after calling this function.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Registers a plug-in collection with a plug-in context.
+Registers a plug-in collection with a plug-in context.
<p>
A plug-in collection is a directory that has plug-ins as its immediate subdirectories. The plug-in context will scan the directory when <a class="el" href="group__cFuncsPlugin.html#ga9603cd8d153b0ce192ac7b6e56779af">cp_scan_plugins</a> is called. Returns <a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da5ffbe0fe80af75e699e4b04909912f7a">CP_OK</a> if the directory has already been registered. A plug-in collection can be unregistered using <a class="el" href="group__cFuncsContext.html#g59817fdae1aeb28dbc7d3dcfc5568c15">cp_unregister_pcollection</a> or <a class="el" href="group__cFuncsContext.html#g0473208ccfde69e0c57ec1f2b4789781">cp_unregister_pcollections</a>.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Unregisters a previously registered plug-in collection from a plug-in context.
+Unregisters a previously registered plug-in collection from a plug-in context.
<p>
Plug-ins already loaded from the collection are not affected. Does nothing if the directory has not been registered. Plug-in collections can be registered using <a class="el" href="group__cFuncsContext.html#g998d8350e64a129101f9da687ff5713b">cp_register_pcollection</a>.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Unregisters all plug-in collections from a plug-in context.
+Unregisters all plug-in collections from a plug-in context.
<p>
Plug-ins already loaded are not affected. Plug-in collections can be registered using <a class="el" href="group__cFuncsContext.html#g998d8350e64a129101f9da687ff5713b">cp_register_pcollection</a>.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<small>
[<a class="el" href="group__cFuncs.html">Functions</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-These functions can be used to query runtime information about the linked in C-Pluff implementation.
+These functions can be used to query runtime information about the linked in C-Pluff implementation.
<p>
-They may be used by the main program or by a plug-in runtime.
+They may be used by the main program or by a plug-in runtime.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-Returns the release version string of the linked in C-Pluff implementation.
+Returns the release version string of the linked in C-Pluff implementation.
<p>
<dl class="return" compact><dt><b>Returns:</b></dt><dd>the C-Pluff release version string </dd></dl>
<div class="memdoc">
<p>
-Returns the canonical host type associated with the linked in C-Pluff implementation.
+Returns the canonical host type associated with the linked in C-Pluff implementation.
<p>
A multi-platform installation manager could use this information to determine what plug-in versions to install.<p>
<dl class="return" compact><dt><b>Returns:</b></dt><dd>the canonical host type </dd></dl>
<small>
[<a class="el" href="group__cFuncs.html">Functions</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-These functions are used for framework initialization.
+These functions are used for framework initialization.
<p>
-They are intended to be used by the main program. These functions are not thread safe.
+They are intended to be used by the main program. These functions are not thread safe.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-Sets the fatal error handler called on non-recoverable errors.
+Sets the fatal error handler called on non-recoverable errors.
<p>
The default error handler prints the error message out to standard error and aborts the program. If the user specified error handler returns then the framework will abort the program. Setting NULL error handler will restore the default handler. This function is not thread-safe and it should be called before initializing the framework to catch all fatal errors.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Initializes the plug-in framework.
+Initializes the plug-in framework.
<p>
This function must be called by the main program before calling any other plug-in framework functions except <a class="el" href="group__cFuncsFrameworkInfo.html">framework information</a> functions and <a class="el" href="group__cFuncsInit.html#gc794f61edbd896327fabddad2b3d2fd5">cp_set_fatal_error_handler</a>. This function may be called several times but it is not thread-safe. Library resources should be released by calling <a class="el" href="group__cFuncsInit.html#g8dfbe51a3b7f23368a4ddf0d9987180e">cp_destroy</a> when the framework is not needed anymore.<p>
-Additionally, to enable localization support, the main program should set the current locale using<div class="fragment"><pre class="fragment"> setlocale(LC_ALL, <span class="stringliteral">""</span>)
+Additionally, to enable localization support, the main program should set the current locale using<div class="fragment"><pre class="fragment"> setlocale(LC_ALL, <span class="stringliteral">""</span>)
</pre></div> before calling this function.<p>
<dl class="return" compact><dt><b>Returns:</b></dt><dd><a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7da5ffbe0fe80af75e699e4b04909912f7a">CP_OK</a> (zero) on success or error code on failure </dd></dl>
<div class="memdoc">
<p>
-Destroys the plug-in framework and releases the resources used by it.
+Destroys the plug-in framework and releases the resources used by it.
<p>
-The plug-in framework is only destroyed after this function has been called as many times as <a class="el" href="group__cFuncsInit.html#gc72ffd50777c3e898dae661c67b04ba9">cp_init</a>. This function is not thread-safe. Plug-in framework functions other than <a class="el" href="group__cFuncsInit.html#gc72ffd50777c3e898dae661c67b04ba9">cp_init</a>, cp_get_framework_info and <a class="el" href="group__cFuncsInit.html#gc794f61edbd896327fabddad2b3d2fd5">cp_set_fatal_error_handler</a> must not be called after the plug-in framework has been destroyed. All contexts are destroyed and all data references returned by the framework become invalid.
+The plug-in framework is only destroyed after this function has been called as many times as <a class="el" href="group__cFuncsInit.html#gc72ffd50777c3e898dae661c67b04ba9">cp_init</a>. This function is not thread-safe. Plug-in framework functions other than <a class="el" href="group__cFuncsInit.html#gc72ffd50777c3e898dae661c67b04ba9">cp_init</a>, cp_get_framework_info and <a class="el" href="group__cFuncsInit.html#gc794f61edbd896327fabddad2b3d2fd5">cp_set_fatal_error_handler</a> must not be called after the plug-in framework has been destroyed. All contexts are destroyed and all data references returned by the framework become invalid.
</div>
</div><p>
<hr size="1">
<small>
[<a class="el" href="group__cFuncs.html">Functions</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-These functions can be used to receive and emit log messages related to a particular plug-in context.
+These functions can be used to receive and emit log messages related to a particular plug-in context.
<p>
-They can be used by the main program or by a plug-in runtime.
+They can be used by the main program or by a plug-in runtime.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-Registers a logger with a plug-in context or updates the settings of a registered logger.
+Registers a logger with a plug-in context or updates the settings of a registered logger.
<p>
The logger will receive selected log messages. If the specified logger is not yet known, a new logger registration is made, otherwise the settings for the existing logger are updated. The logger can be unregistered using <a class="el" href="group__cFuncsLogging.html#g206e88cf84739ff2a0ee6e6925ca5ed8">cp_unregister_logger</a> and it is automatically unregistered when the registering plug-in is stopped or when the context is destroyed.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Removes a logger registration.
+Removes a logger registration.
<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<table border="0" cellspacing="2" cellpadding="0">
<div class="memdoc">
<p>
-Emits a new log message.
+Emits a new log message.
<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<table border="0" cellspacing="2" cellpadding="0">
<div class="memdoc">
<p>
-Returns whether a message of the specified severity would get logged.
+Returns whether a message of the specified severity would get logged.
<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<table border="0" cellspacing="2" cellpadding="0">
<small>
[<a class="el" href="group__cFuncs.html">Functions</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-These functions can be used to manage plug-ins.
+These functions can be used to manage plug-ins.
<p>
-They are intended to be used by the main program.
+They are intended to be used by the main program.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-Loads a plug-in descriptor from the specified plug-in installation path and returns information about the plug-in.
+Loads a plug-in descriptor from the specified plug-in installation path and returns information about the plug-in.
<p>
The plug-in descriptor is validated during loading. Possible loading errors are reported via the specified plug-in context. The plug-in is not installed to the context. If operation fails or the descriptor is invalid then NULL is returned. The caller must release the returned information by calling cp_release_plugin_info when it does not need the information anymore, typically after installing the plug-in. The returned plug-in information must not be modified.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Installs the plug-in described by the specified plug-in information structure to the specified plug-in context.
+Installs the plug-in described by the specified plug-in information structure to the specified plug-in context.
<p>
The plug-in information must have been loaded using <a class="el" href="group__cFuncsPlugin.html#gcb92588ad3b48dab5e9487698f6ef437">cp_load_plugin_descriptor</a> with the same plug-in context. The installation fails on <a class="el" href="group__cEnums.html#ggd6a8106d281ffa4b1f43fe8e3effc7dab07cfdc96a5dbc3a3e359bae2534c9d2">CP_ERR_CONFLICT</a> if the context already has an installed plug-in with the same plug-in identifier. Installation also fails if the plug-in tries to install an extension point which conflicts with an already installed extension point. The plug-in information must not be modified but it is safe to call cp_release_plugin_info after the plug-in has been installed.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Scans for plug-ins in the registered plug-in directories, installing new plug-ins and upgrading installed plug-ins.
+Scans for plug-ins in the registered plug-in directories, installing new plug-ins and upgrading installed plug-ins.
<p>
This function can be used to initially load the plug-ins and to later rescan for new plug-ins.<p>
When several versions of the same plug-in is available the most recent version will be installed. The upgrade behavior depends on the specified <a class="el" href="group__cScanFlags.html">flags</a>. If <a class="el" href="group__cScanFlags.html#g1d4b72334d60f1401e6616da54e4d6f1">CP_SP_UPGRADE</a> is set then upgrades to installed plug-ins are allowed. The old version is unloaded and the new version installed instead. If <a class="el" href="group__cScanFlags.html#g72cdcd1181d60fd3caf5d0e0dd59c33c">CP_SP_STOP_ALL_ON_UPGRADE</a> is set then all active plug-ins are stopped if any plug-ins are to be upgraded. If <a class="el" href="group__cScanFlags.html#gb5996fbc57c7ec3bb538bc80a3ebfc40">CP_SP_STOP_ALL_ON_INSTALL</a> is set then all active plug-ins are stopped if any plug-ins are to be installed or upgraded. Finally, if <a class="el" href="group__cScanFlags.html#g7ca04507561932ae293e81c3636768b7">CP_SP_RESTART_ACTIVE</a> is set all currently active plug-ins will be restarted after the changes (if they were stopped).<p>
<div class="memdoc">
<p>
-Starts a plug-in.
+Starts a plug-in.
<p>
Also starts any imported plug-ins. If the plug-in is already starting then this function blocks until the plug-in has started or failed to start. If the plug-in is already active then this function returns immediately. If the plug-in is stopping then this function blocks until the plug-in has stopped and then starts the plug-in.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Stops a plug-in.
+Stops a plug-in.
<p>
First stops any dependent plug-ins that are currently active. Then stops the specified plug-in. If the plug-in is already stopping then this function blocks until the plug-in has stopped. If the plug-in is already stopped then this function returns immediately. If the plug-in is starting then this function blocks until the plug-in has started (or failed to start) and then stops the plug-in.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Stops all active plug-ins.
+Stops all active plug-ins.
<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<table border="0" cellspacing="2" cellpadding="0">
<div class="memdoc">
<p>
-Uninstalls the specified plug-in.
+Uninstalls the specified plug-in.
<p>
The plug-in is first stopped if it is active. Then uninstalls the plug-in and any dependent plug-ins.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Uninstalls all plug-ins.
+Uninstalls all plug-ins.
<p>
All plug-ins are first stopped and then uninstalled.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<small>
[<a class="el" href="group__cFuncs.html">Functions</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-These functions support a plug-in controlled execution model.
+These functions support a plug-in controlled execution model.
<p>
Started plug-ins can use <a class="el" href="group__cFuncsPluginExec.html#g357c45e87ff896e8541fe3758b19a035">cp_run_function</a> to register <a class="el" href="group__cTypedefsFuncs.html#gf55fb990664aaa069e72a8fa4da20034">a run function</a> which is called when the main program calls <a class="el" href="group__cFuncsPluginExec.html#g4668727a5b1c9f0531f6d5dc77fa9f9f">cp_run_plugins</a> or <a class="el" href="group__cFuncsPluginExec.html#g7e212bc93d6588fc09995f310548c929">cp_run_plugins_step</a>. A run function should do a finite chunk of work and then return telling whether there is more work to be done. A run function is automatically unregistered when the plug-in is stopped. Run functions make it possible for plug-ins to control the flow of execution or they can be used as a coarse way of task switching if there is no multi-threading support.<p>
The C-Pluff distribution includes a generic main program, cpluff-loader, which only acts as a plug-in loader. It loads and starts up the specified plug-ins, passing any additional startup arguments to them and then just calls run functions of the plug-ins. This makes it is possible to put all the application specific logic in plug-ins. Application does not necessarily need a main program of its own.<p>
-It is also safe, from framework perspective, to call these functions from multiple threads. Run functions may then be executed in parallel threads.
+It is also safe, from framework perspective, to call these functions from multiple threads. Run functions may then be executed in parallel threads.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-Registers a new run function.
+Registers a new run function.
<p>
The plug-in instance data pointer is given to the run function as a parameter. The run function must return zero if it has finished its work or non-zero if it should be called again later. The run function is unregistered when it returns zero. Plug-in framework functions stopping the registering plug-in must not be called from within a run function. This function does nothing if the specified run function is already registered for the calling plug-in instance.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Runs the started plug-ins as long as there is something to run.
+Runs the started plug-ins as long as there is something to run.
<p>
This function calls repeatedly run functions registered by started plug-ins until there are no more active run functions. This function is normally called by a thin main proram, a loader, which loads plug-ins, starts some plug-ins and then passes control over to the started plug-ins.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Runs one registered run function.
+Runs one registered run function.
<p>
This function calls one active run function registered by a started plug-in. When the run function returns this function also returns and passes control back to the main program. The return value can be used to determine whether there are any active run functions left. This function does nothing if there are no active registered run functions.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Sets startup arguments for the specified plug-in context.
+Sets startup arguments for the specified plug-in context.
<p>
Like for usual C main functions, the first argument is expected to be the name of the program being executed or an empty string and the argument array should be terminated by NULL entry. If the main program is about to pass startup arguments to plug-ins it should call this function before starting any plug-ins in the context. The arguments are not copied and the caller is responsible for keeping the argument data available once the arguments have been set until the context is destroyed. Plug-ins can access the startup arguments using <a class="el" href="group__cFuncsPluginExec.html#g08929433446b28f8fce8b8beae0e742a">cp_get_context_args</a>.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Returns the startup arguments associated with the specified plug-in context.
+Returns the startup arguments associated with the specified plug-in context.
<p>
This function is intended to be used by a plug-in runtime. Startup arguments are set by the main program using <a class="el" href="group__cFuncsPluginExec.html#g9233fa8a46e408044030d2d767f1fda4">cp_set_context_args</a>. The returned argument count is zero and the array pointer is NULL if no arguments have been set.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<small>
[<a class="el" href="group__cFuncs.html">Functions</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-These functions can be used to query information about the installed plug-ins, extension points and extensions or to listen for plug-in state changes.
+These functions can be used to query information about the installed plug-ins, extension points and extensions or to listen for plug-in state changes.
<p>
-They may be used by the main program or by a plug-in runtime.
+They may be used by the main program or by a plug-in runtime.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-Returns static information about the specified plug-in.
+Returns static information about the specified plug-in.
<p>
The returned information must not be modified and the caller must release the information by calling <a class="el" href="group__cFuncsPluginInfo.html#gbac266df43a4850cf43224aa7b863942">cp_release_info</a> when the information is not needed anymore. When a plug-in runtime calls this function it may pass NULL as the identifier to get information about the plug-in itself.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Returns static information about the installed plug-ins.
+Returns static information about the installed plug-ins.
<p>
The returned information must not be modified and the caller must release the information by calling <a class="el" href="group__cFuncsPluginInfo.html#gbac266df43a4850cf43224aa7b863942">cp_release_info</a> when the information is not needed anymore.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Returns static information about the currently installed extension points.
+Returns static information about the currently installed extension points.
<p>
The returned information must not be modified and the caller must release the information by calling <a class="el" href="group__cFuncsPluginInfo.html#gbac266df43a4850cf43224aa7b863942">cp_release_info</a> when the information is not needed anymore.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Returns static information about the currently installed extension points.
+Returns static information about the currently installed extension points.
<p>
The returned information must not be modified and the caller must release the information by calling <a class="el" href="group__cFuncsPluginInfo.html#gbac266df43a4850cf43224aa7b863942">cp_release_info</a> when the information is not needed anymore.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Releases a previously obtained reference counted information object.
+Releases a previously obtained reference counted information object.
<p>
The documentation for functions returning such information refers to this function. The information must not be accessed after it has been released. The framework uses reference counting to deallocate the information when it is not in use anymore.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Returns the current state of the specified plug-in.
+Returns the current state of the specified plug-in.
<p>
Returns <a class="el" href="group__cEnums.html#ggd517a8088e2ed89fda71251d9c7b325290eacd4f02fb7d65eaf68f7251a99689">CP_PLUGIN_UNINSTALLED</a> if the specified plug-in identifier is unknown.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Registers a plug-in listener with a plug-in context.
+Registers a plug-in listener with a plug-in context.
<p>
The listener is called synchronously immediately after a plug-in state change. There can be several listeners registered with the same context. A plug-in listener can be unregistered using <a class="el" href="group__cFuncsPluginInfo.html#g2cd49b8752e8971b569ae3e39b41723e">cp_unregister_plistener</a> and it is automatically unregistered when the registering plug-in is stopped or when the context is destroyed.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Removes a plug-in listener from a plug-in context.
+Removes a plug-in listener from a plug-in context.
<p>
Does nothing if the specified listener was not registered.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Traverses a configuration element tree and returns the specified element.
+Traverses a configuration element tree and returns the specified element.
<p>
The target element is specified by a base element and a relative path from the base element to the target element. The path includes element names separated by slash '/'. Two dots ".." can be used to designate a parent element. Returns NULL if the specified element does not exist. If there are several subelements with the same name, this function chooses the first one when traversing the tree.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Traverses a configuration element tree and returns the value of the specified element or attribute.
+Traverses a configuration element tree and returns the value of the specified element or attribute.
<p>
The target element or attribute is specified by a base element and a relative path from the base element to the target element or attributes. The path includes element names separated by slash '/'. Two dots ".." can be used to designate a parent element. The path may end with '@' followed by an attribute name to select an attribute. Returns NULL if the specified element or attribute does not exist or does not have a value. If there are several subelements with the same name, this function chooses the first one when traversing the tree.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<small>
[<a class="el" href="group__cFuncs.html">Functions</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-These functions can be used to dynamically access symbols exported by the plug-ins.
+These functions can be used to dynamically access symbols exported by the plug-ins.
<p>
-They are intended to be used by a plug-in runtime or by the main program.
+They are intended to be used by a plug-in runtime or by the main program.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-Defines a context specific symbol.
+Defines a context specific symbol.
<p>
If a plug-in has symbols which have a plug-in instance specific value then the plug-in should define those symbols when it is started. The defined symbols are cleared automatically when the plug-in instance is stopped. Symbols can not be redefined.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-Resolves a symbol provided by the specified plug-in.
+Resolves a symbol provided by the specified plug-in.
<p>
The plug-in is started automatically if it is not already active. The symbol may be context specific or global. The framework first looks for a context specific symbol and then falls back to resolving a global symbol exported by the plug-in runtime library. The symbol can be released using <a class="el" href="group__cFuncsSymbols.html#g150629125a61ac9fa4e2095b0d9c7e57">cp_release_symbol</a> when it is not needed anymore. Pointers obtained from this function must not be passed on to other plug-ins or the main program.<p>
When a plug-in runtime calls this function the plug-in framework creates a dynamic dependency from the symbol using plug-in to the symbol defining plug-in. The symbol using plug-in is stopped automatically if the symbol defining plug-in is about to be stopped. If the symbol using plug-in does not explicitly release the symbol then it is automatically released after a call to the stop function. It is not safe to refer to a dynamically resolved symbol in the stop function except to release it using <a class="el" href="group__cFuncsSymbols.html#g150629125a61ac9fa4e2095b0d9c7e57">cp_release_symbol</a>.<p>
<div class="memdoc">
<p>
-Releases a previously obtained symbol.
+Releases a previously obtained symbol.
<p>
The pointer must not be used after the symbol has been released. The symbol is released only after as many calls to this function as there have been for <a class="el" href="group__cFuncsSymbols.html#g8bc3b7fcf4f4ed414837f5a3998d46b7">cp_resolve_symbol</a> for the same plug-in and symbol.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<small>
[<a class="el" href="group__cDefines.html">Defines</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-These constants can be orred together for the flags parameter of <a class="el" href="group__cFuncsPlugin.html#ga9603cd8d153b0ce192ac7b6e56779af">cp_scan_plugins</a>.
+These constants can be orred together for the flags parameter of <a class="el" href="group__cFuncsPlugin.html#ga9603cd8d153b0ce192ac7b6e56779af">cp_scan_plugins</a>.
<p>
<p>
<div class="memdoc">
<p>
-This flag enables upgrades of installed plug-ins by unloading the old version and installing the new version.
+This flag enables upgrades of installed plug-ins by unloading the old version and installing the new version.
<p>
</div>
<div class="memdoc">
<p>
-This flag causes all plug-ins to be stopped before any plug-ins are to be upgraded.
+This flag causes all plug-ins to be stopped before any plug-ins are to be upgraded.
<p>
</div>
<div class="memdoc">
<p>
-This flag causes all plug-ins to be stopped before any plugins are to be installed (also if new version is to be installed as part of an upgrade).
+This flag causes all plug-ins to be stopped before any plugins are to be installed (also if new version is to be installed as part of an upgrade).
<p>
</div>
<div class="memdoc">
<p>
-Setting this flag causes the currently active plug-ins to be restarted after all changes to the plug-ins have been made (if they were stopped).
+Setting this flag causes the currently active plug-ins to be restarted after all changes to the plug-ins have been made (if they were stopped).
<p>
</div>
<li><a href="pages.html"><span>Related Pages</span></a></li>
</ul></div>
<h1>Data structures</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-Data structure definitions.
+Data structure definitions.
<p>
<p>
<li><a href="pages.html"><span>Related Pages</span></a></li>
</ul></div>
<h1>Typedefs</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-Typedefs of various kind.
+Typedefs of various kind.
<p>
<p>
<small>
[<a class="el" href="group__cTypedefs.html">Typedefs</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-Typedefs for client supplied callback functions.
+Typedefs for client supplied callback functions.
<p>
<p>
<div class="memdoc">
<p>
-A listener function called synchronously after a plugin state change.
+A listener function called synchronously after a plugin state change.
<p>
The function should return promptly. <a class="el" href="group__cFuncsInit.html">Library initialization</a>, <a class="el" href="group__cFuncsContext.html">plug-in context management</a>, <a class="el" href="group__cFuncsPlugin.html">plug-in management</a>, listener registration (<a class="el" href="group__cFuncsPluginInfo.html#ge9930a241e859e9eb07e36981ef7077a">cp_register_plistener</a> and <a class="el" href="group__cFuncsPluginInfo.html#g2cd49b8752e8971b569ae3e39b41723e">cp_unregister_plistener</a>) and <a class="el" href="group__cFuncsSymbols.html">dynamic symbol</a> functions must not be called from within a plug-in listener invocation. Listener functions are registered using <a class="el" href="group__cFuncsPluginInfo.html#ge9930a241e859e9eb07e36981ef7077a">cp_register_plistener</a>.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-A logger function called to log selected plug-in framework messages.
+A logger function called to log selected plug-in framework messages.
<p>
The messages may be localized. Plug-in framework API functions must not be called from within a logger function invocation. In a multi-threaded environment logger function invocations are serialized by the framework. Logger functions are registered using <a class="el" href="group__cFuncsLogging.html#g5f6962ee1b09d60d9b98d25adfd55cff">cp_register_logger</a>.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-A fatal error handler for handling unrecoverable errors.
+A fatal error handler for handling unrecoverable errors.
<p>
If the error handler returns then the framework aborts the program. Plug-in framework API functions must not be called from within a fatal error handler invocation. The fatal error handler function is set using <a class="el" href="group__cFuncsInit.html#gc794f61edbd896327fabddad2b3d2fd5">cp_set_fatal_error_handler</a>.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<div class="memdoc">
<p>
-A run function registered by a plug-in to perform work.
+A run function registered by a plug-in to perform work.
<p>
The run function should perform a finite chunk of work and it should return a non-zero value if there is more work to be done. Run functions are registered using <a class="el" href="group__cFuncsPluginExec.html#g357c45e87ff896e8541fe3758b19a035">cp_run_function</a> and the usage is discussed in more detail in the <a class="el" href="group__cFuncsPluginExec.html">serial execution</a> section.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
<small>
[<a class="el" href="group__cTypedefs.html">Typedefs</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-Opaque data type definitions.
+Opaque data type definitions.
<p>
<p>
<div class="memdoc">
<p>
-A plug-in context represents the co-operation environment of a set of plug-ins from the perspective of a particular participating plug-in or the perspective of the main program.
+A plug-in context represents the co-operation environment of a set of plug-ins from the perspective of a particular participating plug-in or the perspective of the main program.
<p>
-It is used as an opaque handle to the shared resources but the framework also uses the context to identify the plug-in or the main program invoking framework functions. Therefore a plug-in should not generally expose its context instance to other plug-ins or the main program and neither should the main program expose its context instance to plug-ins. The main program creates plug-in contexts using <a class="el" href="group__cFuncsContext.html#g7d239c4fc07cf7d3095a20900444ad62">cp_create_context</a> and plug-ins receive their plug-in contexts via <a class="el" href="structcp__plugin__runtime__t.html#f193bb8481e4b6aeab275fa5908a9af9">cp_plugin_runtime_t::create</a>.
+It is used as an opaque handle to the shared resources but the framework also uses the context to identify the plug-in or the main program invoking framework functions. Therefore a plug-in should not generally expose its context instance to other plug-ins or the main program and neither should the main program expose its context instance to plug-ins. The main program creates plug-in contexts using <a class="el" href="group__cFuncsContext.html#g7d239c4fc07cf7d3095a20900444ad62">cp_create_context</a> and plug-ins receive their plug-in contexts via <a class="el" href="structcp__plugin__runtime__t.html#f193bb8481e4b6aeab275fa5908a9af9">cp_plugin_runtime_t::create</a>.
</div>
</div><p>
<hr size="1">
<small>
[<a class="el" href="group__cTypedefs.html">Typedefs</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-Shorthand type names for structs and enumerations.
+Shorthand type names for structs and enumerations.
<p>
<p>
<div class="memdoc">
<p>
-A type for <a class="el" href="structcp__plugin__info__t.html">cp_plugin_info_t</a> structure.
+A type for <a class="el" href="structcp__plugin__info__t.html">cp_plugin_info_t</a> structure.
<p>
</div>
<div class="memdoc">
<p>
-A type for <a class="el" href="structcp__plugin__import__t.html">cp_plugin_import_t</a> structure.
+A type for <a class="el" href="structcp__plugin__import__t.html">cp_plugin_import_t</a> structure.
<p>
</div>
<div class="memdoc">
<p>
-A type for <a class="el" href="structcp__ext__point__t.html">cp_ext_point_t</a> structure.
+A type for <a class="el" href="structcp__ext__point__t.html">cp_ext_point_t</a> structure.
<p>
</div>
<div class="memdoc">
<p>
-A type for <a class="el" href="structcp__extension__t.html">cp_extension_t</a> structure.
+A type for <a class="el" href="structcp__extension__t.html">cp_extension_t</a> structure.
<p>
</div>
<div class="memdoc">
<p>
-A type for <a class="el" href="structcp__cfg__element__t.html">cp_cfg_element_t</a> structure.
+A type for <a class="el" href="structcp__cfg__element__t.html">cp_cfg_element_t</a> structure.
<p>
</div>
<div class="memdoc">
<p>
-A type for <a class="el" href="structcp__plugin__runtime__t.html">cp_plugin_runtime_t</a> structure.
+A type for <a class="el" href="structcp__plugin__runtime__t.html">cp_plugin_runtime_t</a> structure.
<p>
</div>
<div class="memdoc">
<p>
-A type for cp_status_t enumeration.
+A type for cp_status_t enumeration.
<p>
</div>
<div class="memdoc">
<p>
-A type for cp_plugin_state_t enumeration.
+A type for cp_plugin_state_t enumeration.
<p>
</div>
<div class="memdoc">
<p>
-A type for cp_log_severity_t enumeration.
+A type for cp_log_severity_t enumeration.
<p>
</div>
<small>
[<a class="el" href="group__cDefines.html">Defines</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-Macros for controlling inter-module symbol visibility and linkage.
+Macros for controlling inter-module symbol visibility and linkage.
<p>
These macros have platform specific values. <a class="el" href="group__symbolVisibility.html#ga2e3768d73167e12c2330e4b96bcbd70">CP_EXPORT</a>, <a class="el" href="group__symbolVisibility.html#gb44eb8224723b45a1c909177bdd7bc32">CP_IMPORT</a> and <a class="el" href="group__symbolVisibility.html#gf58571664980e1a0d2b0bee413296492">CP_HIDDEN</a> can be reused by plug-in implementations for better portability. The complexity is mostly due to Windows DLL exports and imports.<p>
<a class="anchor" name="symbolVisibilityExample"></a> Each module should usually define its own macro to declare API symbols with <a class="el" href="group__symbolVisibility.html#ga2e3768d73167e12c2330e4b96bcbd70">CP_EXPORT</a> and <a class="el" href="group__symbolVisibility.html#gb44eb8224723b45a1c909177bdd7bc32">CP_IMPORT</a> as necessary. For example, a mobule could define a macro <code>MY_API</code> in the API header file as follows.<p>
<span class="preprocessor"></span><span class="preprocessor"> # define MY_API CP_IMPORT</span>
<span class="preprocessor"> #endif</span>
</pre></div><p>
-By default the API symbols would then be marked for import which is correct when client modules are including the API header file. When compiling the module itself the option <code>-DMY_API=CP_EXPORT</code> would be passed to the compiler to override the API header file and to mark the API symbols for export. The overriding definition could also be included in module source files or in an internal header file before including the API header file.
+By default the API symbols would then be marked for import which is correct when client modules are including the API header file. When compiling the module itself the option <code>-DMY_API=CP_EXPORT</code> would be passed to the compiler to override the API header file and to mark the API symbols for export. The overriding definition could also be included in module source files or in an internal header file before including the API header file.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-Declares a symbol to be exported for inter-module usage.
+Declares a symbol to be exported for inter-module usage.
<p>
-When compiling the module which defines the symbol this macro should be placed at the start of the symbol declaration to ensure that the symbol is exported to other modules. However, when compiling other modules the declaration of the symbol should start with <a class="el" href="group__symbolVisibility.html#gb44eb8224723b45a1c909177bdd7bc32">CP_IMPORT</a>. See <a class="el" href="group__symbolVisibility.html#symbolVisibilityExample">the example</a> of how to do this.
+When compiling the module which defines the symbol this macro should be placed at the start of the symbol declaration to ensure that the symbol is exported to other modules. However, when compiling other modules the declaration of the symbol should start with <a class="el" href="group__symbolVisibility.html#gb44eb8224723b45a1c909177bdd7bc32">CP_IMPORT</a>. See <a class="el" href="group__symbolVisibility.html#symbolVisibilityExample">the example</a> of how to do this.
</div>
</div><p>
<a class="anchor" name="gb44eb8224723b45a1c909177bdd7bc32"></a><!-- doxytag: member="cpluffdef.h::CP_IMPORT" ref="gb44eb8224723b45a1c909177bdd7bc32" args="" -->
<div class="memdoc">
<p>
-Declares a symbol to be imported from another module.
+Declares a symbol to be imported from another module.
<p>
-When compiling a module which uses the symbol this macro should be placed at the start of the symbol declaration to ensure that the symbol is imported from the defining module. However, when compiling the defining module the declaration of the symbol should start with <a class="el" href="group__symbolVisibility.html#ga2e3768d73167e12c2330e4b96bcbd70">CP_EXPORT</a>. See <a class="el" href="group__symbolVisibility.html#symbolVisibilityExample">the example</a> of how to do this.
+When compiling a module which uses the symbol this macro should be placed at the start of the symbol declaration to ensure that the symbol is imported from the defining module. However, when compiling the defining module the declaration of the symbol should start with <a class="el" href="group__symbolVisibility.html#ga2e3768d73167e12c2330e4b96bcbd70">CP_EXPORT</a>. See <a class="el" href="group__symbolVisibility.html#symbolVisibilityExample">the example</a> of how to do this.
</div>
</div><p>
<a class="anchor" name="gf58571664980e1a0d2b0bee413296492"></a><!-- doxytag: member="cpluffdef.h::CP_HIDDEN" ref="gf58571664980e1a0d2b0bee413296492" args="" -->
<div class="memdoc">
<p>
-Declares a symbol hidden from other modules.
+Declares a symbol hidden from other modules.
<p>
-This macro should be placed at the start of the symbol declaration to hide the symbol from other modules (if supported by the platform). This macro is not intended to be used with symbols declared as "static" which are already internal to the object file. Some platforms do not support hiding of symbols and therefore unique prefixes should be used for global symbols internal to the module even when they are declared using this macro.
+This macro should be placed at the start of the symbol declaration to hide the symbol from other modules (if supported by the platform). This macro is not intended to be used with symbols declared as "static" which are already internal to the object file. Some platforms do not support hiding of symbols and therefore unique prefixes should be used for global symbols internal to the module even when they are declared using this macro.
</div>
</div><p>
<hr size="1">
<small>
[<a class="el" href="group__cDefines.html">Defines</a>]</small>
</h1><hr><a name="_details"></a><h2>Detailed Description</h2>
-C-Pluff version information.
+C-Pluff version information.
<p>
-Notice that this version information is static version information included in header files. The macros introduced here can be used for compile time checks.
+Notice that this version information is static version information included in header files. The macros introduced here can be used for compile time checks.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-The C-Pluff release version string.
+The C-Pluff release version string.
<p>
-This string identifies a specific version of the C-Pluff distribution. Compile time software compatibility checks should use <a class="el" href="group__versionInfo.html#gc02132b57a51a1c26ff6fb11dc046c04">CP_VERSION_MAJOR</a> and <a class="el" href="group__versionInfo.html#g015d989acd6a013e84ea8696953172a8">CP_VERSION_MINOR</a> instead.
+This string identifies a specific version of the C-Pluff distribution. Compile time software compatibility checks should use <a class="el" href="group__versionInfo.html#gc02132b57a51a1c26ff6fb11dc046c04">CP_VERSION_MAJOR</a> and <a class="el" href="group__versionInfo.html#g015d989acd6a013e84ea8696953172a8">CP_VERSION_MINOR</a> instead.
</div>
</div><p>
<a class="anchor" name="gc02132b57a51a1c26ff6fb11dc046c04"></a><!-- doxytag: member="cpluffdef.h::CP_VERSION_MAJOR" ref="gc02132b57a51a1c26ff6fb11dc046c04" args="" -->
<div class="memdoc">
<p>
-The major version number component of the release version.
+The major version number component of the release version.
<p>
-This is an integer.
+This is an integer.
</div>
</div><p>
<a class="anchor" name="g015d989acd6a013e84ea8696953172a8"></a><!-- doxytag: member="cpluffdef.h::CP_VERSION_MINOR" ref="g015d989acd6a013e84ea8696953172a8" args="" -->
<div class="memdoc">
<p>
-The minor version number component of the release version.
+The minor version number component of the release version.
<p>
-This is an integer.
+This is an integer.
</div>
</div><p>
<hr size="1">
<<a href="#pluginDescPluginRequires" class="code">requires</a>>
<<a href="#pluginDescPluginReqCP" class="code">c-pluff</a> version=<span class="charliteral">"0.1"</span>/>
<<a href="#pluginDescPluginReqImport" class="code">import</a> plugin=<span class="charliteral">"org.c-pluff.util"</span> version=<span class="charliteral">"0.2"</span>/>
- <<a href="#pluginDescPluginReqImport" class="code">import</a> plugin=<span class="charliteral">"org.c-pluff.extra"</span> optional=<span class="charliteral">"true"</span>/>
+ <<a href="#pluginDescPluginReqImport" class="code">import</a> plugin=<span class="charliteral">"org.c-pluff.extra"</span> optional=<span class="charliteral">"true"</span>/>
</<a href="#pluginDescPluginRequires" class="code">requires</a>>
<<a href="#pluginDescPluginRuntime" class="code">runtime</a> library=<span class="charliteral">"libruntime"</span> funcs=<span class="charliteral">"org_cpluff_example_funcs"</span>/>
<<a href="#pluginDescPluginEP" class="code">extension-point</a> id=<span class="charliteral">"editors"</span> name=<span class="charliteral">"Text Editors"</span> schema=<span class="charliteral">"editors_schema.xsd"</span>/>
[<a class="el" href="group__cStructs.html">Data structures</a>]</small>
</h1><!-- doxytag: class="cp_cfg_element_t" -->Collaboration diagram for cp_cfg_element_t:<p><center><img src="structcp__cfg__element__t__coll__graph.png" border="0" usemap="#cp__cfg__element__t__coll__map" alt="Collaboration graph"></center>
<center><font size="2">[<a href="graph_legend.html">legend</a>]</font></center><hr><a name="_details"></a><h2>Detailed Description</h2>
-A configuration element contains configuration information for an extension.
+A configuration element contains configuration information for an extension.
<p>
-Utility functions <a class="el" href="group__cFuncsPluginInfo.html#g9868077c72df950607e2698153d593d1">cp_lookup_cfg_element</a> and <a class="el" href="group__cFuncsPluginInfo.html#g13f5121ab21951d59d3c6b985ed6adcd">cp_lookup_cfg_value</a> can be used for traversing the tree of configuration elements. Pointer to the root configuration element is stored at <a class="el" href="structcp__extension__t.html#a745fad14a2300fd48e55c33f580f91b">cp_extension_t::configuration</a> and others are contained as <a class="el" href="structcp__cfg__element__t.html#3c4e4c4df68a11f898566c3f90bcd534">children</a> of parent elements.
+Utility functions <a class="el" href="group__cFuncsPluginInfo.html#g9868077c72df950607e2698153d593d1">cp_lookup_cfg_element</a> and <a class="el" href="group__cFuncsPluginInfo.html#g13f5121ab21951d59d3c6b985ed6adcd">cp_lookup_cfg_value</a> can be used for traversing the tree of configuration elements. Pointer to the root configuration element is stored at <a class="el" href="structcp__extension__t.html#a745fad14a2300fd48e55c33f580f91b">cp_extension_t::configuration</a> and others are contained as <a class="el" href="structcp__cfg__element__t.html#3c4e4c4df68a11f898566c3f90bcd534">children</a> of parent elements.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-The name of the configuration element.
+The name of the configuration element.
<p>
-This corresponds to the name of the element in a plug-in descriptor.
+This corresponds to the name of the element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="b6eced8675261543cd28efea6c7a0fa4"></a><!-- doxytag: member="cp_cfg_element_t::num_atts" ref="b6eced8675261543cd28efea6c7a0fa4" args="" -->
<div class="memdoc">
<p>
-Number of attribute name, value pairs in the <a class="el" href="structcp__cfg__element__t.html#719b3d0c1369478044ce59dc2f207c21">atts</a> array.
+Number of attribute name, value pairs in the <a class="el" href="structcp__cfg__element__t.html#719b3d0c1369478044ce59dc2f207c21">atts</a> array.
<p>
</div>
<div class="memdoc">
<p>
-An array of pointers to alternating attribute names and values.
+An array of pointers to alternating attribute names and values.
<p>
-Attribute values can be localized.
+Attribute values can be localized.
</div>
</div><p>
<a class="anchor" name="4e9aec275e566b978a3ccb4e043d8c61"></a><!-- doxytag: member="cp_cfg_element_t::value" ref="4e9aec275e566b978a3ccb4e043d8c61" args="" -->
<div class="memdoc">
<p>
-An optional value of this configuration element.
+An optional value of this configuration element.
<p>
-NULL if not available. The value can be localized. This corresponds to the text contents of the element in a plug-in descriptor.
+NULL if not available. The value can be localized. This corresponds to the text contents of the element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="8c99879f94f30ed01e0b76847ab11237"></a><!-- doxytag: member="cp_cfg_element_t::parent" ref="8c99879f94f30ed01e0b76847ab11237" args="" -->
<div class="memdoc">
<p>
-A pointer to the parent element or NULL if this is a root element.
+A pointer to the parent element or NULL if this is a root element.
<p>
</div>
<div class="memdoc">
<p>
-The index of this element among its siblings (0-based).
+The index of this element among its siblings (0-based).
<p>
</div>
<div class="memdoc">
<p>
-Number of children in the <a class="el" href="structcp__cfg__element__t.html#3c4e4c4df68a11f898566c3f90bcd534">children</a> array.
+Number of children in the <a class="el" href="structcp__cfg__element__t.html#3c4e4c4df68a11f898566c3f90bcd534">children</a> array.
<p>
</div>
<div class="memdoc">
<p>
-An array of <a class="el" href="structcp__cfg__element__t.html#b7c9e81d106b95f54ff71b9096ba5dc6">num_children</a> childrens of this element.
+An array of <a class="el" href="structcp__cfg__element__t.html#b7c9e81d106b95f54ff71b9096ba5dc6">num_children</a> childrens of this element.
<p>
-These correspond to child elements in a plug-in descriptor.
+These correspond to child elements in a plug-in descriptor.
</div>
</div><p>
<hr>The documentation for this struct was generated from the following file:<ul>
<area href="structcp__plugin__import__t.html" shape="rect" coords="156,7,306,31" alt="">
</map>
<center><font size="2">[<a href="graph_legend.html">legend</a>]</font></center><hr><a name="_details"></a><h2>Detailed Description</h2>
-Extension point structure captures information about an extension point.
+Extension point structure captures information about an extension point.
<p>
-Extension point structures are contained in <a class="el" href="structcp__plugin__info__t.html#8299ae4ef53289492911a1334494e405">cp_plugin_info_t::ext_points</a>.
+Extension point structures are contained in <a class="el" href="structcp__plugin__info__t.html#8299ae4ef53289492911a1334494e405">cp_plugin_info_t::ext_points</a>.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-A pointer to plug-in information containing this extension point.
+A pointer to plug-in information containing this extension point.
<p>
-This reverse pointer is provided to make it easy to get information about the plug-in which is hosting a particular extension point.
+This reverse pointer is provided to make it easy to get information about the plug-in which is hosting a particular extension point.
</div>
</div><p>
<a class="anchor" name="f5351a0143adaf16c64b881aee01d893"></a><!-- doxytag: member="cp_ext_point_t::identifier" ref="f5351a0143adaf16c64b881aee01d893" args="" -->
<div class="memdoc">
<p>
-The unique identifier of the extension point.
+The unique identifier of the extension point.
<p>
-This is automatically constructed by concatenating the identifier of the host plug-in and the local identifier of the extension point.
+This is automatically constructed by concatenating the identifier of the host plug-in and the local identifier of the extension point.
</div>
</div><p>
<a class="anchor" name="5ac083a645d964373f022d03df4849c8"></a><!-- doxytag: member="cp_ext_point_t::name" ref="5ac083a645d964373f022d03df4849c8" args="" -->
<div class="memdoc">
<p>
-An optional extension point name.
+An optional extension point name.
<p>
-NULL if not available. The extension point name is intended for display purposes only and the value can be localized. This corresponds to the <em>name</em> attribute of an <em>extension-point</em> element in a plug-in descriptor.
+NULL if not available. The extension point name is intended for display purposes only and the value can be localized. This corresponds to the <em>name</em> attribute of an <em>extension-point</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="2370171ff78694fa0871fd845ab3ad6f"></a><!-- doxytag: member="cp_ext_point_t::schema_path" ref="2370171ff78694fa0871fd845ab3ad6f" args="" -->
<div class="memdoc">
<p>
-An optional path to the extension schema definition.
+An optional path to the extension schema definition.
<p>
-NULL if not available. The path is relative to the plug-in directory. This corresponds to the <em>schema</em> attribute of an <em>extension-point</em> element in a plug-in descriptor.
+NULL if not available. The path is relative to the plug-in directory. This corresponds to the <em>schema</em> attribute of an <em>extension-point</em> element in a plug-in descriptor.
</div>
</div><p>
<hr>The documentation for this struct was generated from the following file:<ul>
<area href="structcp__cfg__element__t.html" shape="rect" coords="184,13,323,37" alt="">
</map>
<center><font size="2">[<a href="graph_legend.html">legend</a>]</font></center><hr><a name="_details"></a><h2>Detailed Description</h2>
-Extension structure captures information about an extension.
+Extension structure captures information about an extension.
<p>
-Extension structures are contained in <a class="el" href="structcp__plugin__info__t.html#2288d4af96da6699b7a2c8b747bd42dc">cp_plugin_info_t::extensions</a>.
+Extension structures are contained in <a class="el" href="structcp__plugin__info__t.html#2288d4af96da6699b7a2c8b747bd42dc">cp_plugin_info_t::extensions</a>.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-A pointer to plug-in information containing this extension.
+A pointer to plug-in information containing this extension.
<p>
-This reverse pointer is provided to make it easy to get information about the plug-in which is hosting a particular extension.
+This reverse pointer is provided to make it easy to get information about the plug-in which is hosting a particular extension.
</div>
</div><p>
<a class="anchor" name="9fe304775bea17eeba3c3fd734d1e4bc"></a><!-- doxytag: member="cp_extension_t::ext_point_id" ref="9fe304775bea17eeba3c3fd734d1e4bc" args="" -->
<div class="memdoc">
<p>
-The unique identifier of the extension point this extension is attached to.
+The unique identifier of the extension point this extension is attached to.
<p>
-This corresponds to the <em>point</em> attribute of an <em>extension</em> element in a plug-in descriptor.
+This corresponds to the <em>point</em> attribute of an <em>extension</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="eb234b64f623fd6c2bcbbc98bacb99ce"></a><!-- doxytag: member="cp_extension_t::local_id" ref="eb234b64f623fd6c2bcbbc98bacb99ce" args="" -->
<div class="memdoc">
<p>
-An optional local identifier uniquely identifying the extension within the host plug-in.
+An optional local identifier uniquely identifying the extension within the host plug-in.
<p>
-NULL if not available. This corresponds to the <em>id</em> attribute of an <em>extension</em> element in a plug-in descriptor.
+NULL if not available. This corresponds to the <em>id</em> attribute of an <em>extension</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="f5351a0143adaf16c64b881aee01d893"></a><!-- doxytag: member="cp_extension_t::identifier" ref="f5351a0143adaf16c64b881aee01d893" args="" -->
<div class="memdoc">
<p>
-An optional unique identifier of the extension.
+An optional unique identifier of the extension.
<p>
-NULL if not available. This is automatically constructed by concatenating the identifier of the host plug-in and the local identifier of the extension.
+NULL if not available. This is automatically constructed by concatenating the identifier of the host plug-in and the local identifier of the extension.
</div>
</div><p>
<a class="anchor" name="5ac083a645d964373f022d03df4849c8"></a><!-- doxytag: member="cp_extension_t::name" ref="5ac083a645d964373f022d03df4849c8" args="" -->
<div class="memdoc">
<p>
-An optional extension name.
+An optional extension name.
<p>
-NULL if not available. The extension name is intended for display purposes only and the value can be localized. This corresponds to the <em>name</em> attribute of an <em>extension</em> element in a plug-in descriptor.
+NULL if not available. The extension name is intended for display purposes only and the value can be localized. This corresponds to the <em>name</em> attribute of an <em>extension</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="a745fad14a2300fd48e55c33f580f91b"></a><!-- doxytag: member="cp_extension_t::configuration" ref="a745fad14a2300fd48e55c33f580f91b" args="" -->
<div class="memdoc">
<p>
-Extension configuration starting with the extension element.
+Extension configuration starting with the extension element.
<p>
-This includes extension configuration information as a tree of configuration elements. These correspond to the <em>extension</em> element and its contents in a plug-in descriptor.
+This includes extension configuration information as a tree of configuration elements. These correspond to the <em>extension</em> element and its contents in a plug-in descriptor.
</div>
</div><p>
<hr>The documentation for this struct was generated from the following file:<ul>
<small>
[<a class="el" href="group__cStructs.html">Data structures</a>]</small>
</h1><!-- doxytag: class="cp_plugin_import_t" --><hr><a name="_details"></a><h2>Detailed Description</h2>
-Information about plug-in import.
+Information about plug-in import.
<p>
-Plug-in import structures are contained in <a class="el" href="structcp__plugin__info__t.html#e03a6d473f95a77ad6de9d43610f8d39">cp_plugin_info_t::imports</a>.
+Plug-in import structures are contained in <a class="el" href="structcp__plugin__info__t.html#e03a6d473f95a77ad6de9d43610f8d39">cp_plugin_info_t::imports</a>.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-The identifier of the imported plug-in.
+The identifier of the imported plug-in.
<p>
-This corresponds to the <em>plugin</em> attribute of the <em>import</em> element in a plug-in descriptor.
+This corresponds to the <em>plugin</em> attribute of the <em>import</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="56abfaab87c46691c1ef3ad0df23e864"></a><!-- doxytag: member="cp_plugin_import_t::version" ref="56abfaab87c46691c1ef3ad0df23e864" args="" -->
<div class="memdoc">
<p>
-An optional version requirement.
+An optional version requirement.
<p>
-NULL if no version requirement. This is the version of the imported plug-in the importing plug-in was compiled against. Any version of the imported plug-in that is backwards compatible with this version fulfills the requirement. This corresponds to the <em>if-version</em> attribute of the <em>import</em> element in a plug-in descriptor.
+NULL if no version requirement. This is the version of the imported plug-in the importing plug-in was compiled against. Any version of the imported plug-in that is backwards compatible with this version fulfills the requirement. This corresponds to the <em>if-version</em> attribute of the <em>import</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="69b1249c974e922ecdd066c43dc91f88"></a><!-- doxytag: member="cp_plugin_import_t::optional" ref="69b1249c974e922ecdd066c43dc91f88" args="" -->
<div class="memdoc">
<p>
-Is this import optional.
+Is this import optional.
<p>
-1 for optional and 0 for mandatory import. An optional import causes the imported plug-in to be started if it is available but does not stop the importing plug-in from starting if the imported plug-in is not available. If the imported plug-in is available but the API version conflicts with the API version requirement then the importing plug-in fails to start. This corresponds to the <em>optional</em> attribute of the <em>import</em> element in a plug-in descriptor.
+1 for optional and 0 for mandatory import. An optional import causes the imported plug-in to be started if it is available but does not stop the importing plug-in from starting if the imported plug-in is not available. If the imported plug-in is available but the API version conflicts with the API version requirement then the importing plug-in fails to start. This corresponds to the <em>optional</em> attribute of the <em>import</em> element in a plug-in descriptor.
</div>
</div><p>
<hr>The documentation for this struct was generated from the following file:<ul>
<area href="structcp__plugin__import__t.html" shape="rect" coords="268,7,418,31" alt="">
</map>
<center><font size="2">[<a href="graph_legend.html">legend</a>]</font></center><hr><a name="_details"></a><h2>Detailed Description</h2>
-Plug-in information structure captures information about a plug-in.
+Plug-in information structure captures information about a plug-in.
<p>
-This information can be loaded from a plug-in descriptor using <a class="el" href="group__cFuncsPlugin.html#gcb92588ad3b48dab5e9487698f6ef437">cp_load_plugin_descriptor</a>. Information about installed plug-ins can be obtained using <a class="el" href="group__cFuncsPluginInfo.html#g4aba19886c68b2a3c1508c3b66110c12">cp_get_plugin_info</a> and <a class="el" href="group__cFuncsPluginInfo.html#g015373cf40c08ea4a346a1bac5656fb1">cp_get_plugins_info</a>. This structure corresponds to the <em>plugin</em> element in a plug-in descriptor.
+This information can be loaded from a plug-in descriptor using <a class="el" href="group__cFuncsPlugin.html#gcb92588ad3b48dab5e9487698f6ef437">cp_load_plugin_descriptor</a>. Information about installed plug-ins can be obtained using <a class="el" href="group__cFuncsPluginInfo.html#g4aba19886c68b2a3c1508c3b66110c12">cp_get_plugin_info</a> and <a class="el" href="group__cFuncsPluginInfo.html#g015373cf40c08ea4a346a1bac5656fb1">cp_get_plugins_info</a>. This structure corresponds to the <em>plugin</em> element in a plug-in descriptor.
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-The obligatory unique identifier of the plugin.
+The obligatory unique identifier of the plugin.
<p>
-A recommended way to generate identifiers is to use domain name service (DNS) prefixes (for example, org.cpluff.ExamplePlugin) to avoid naming conflicts. This corresponds to the <em>id</em> attribute of the <em>plugin</em> element in a plug-in descriptor.
+A recommended way to generate identifiers is to use domain name service (DNS) prefixes (for example, org.cpluff.ExamplePlugin) to avoid naming conflicts. This corresponds to the <em>id</em> attribute of the <em>plugin</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="5ac083a645d964373f022d03df4849c8"></a><!-- doxytag: member="cp_plugin_info_t::name" ref="5ac083a645d964373f022d03df4849c8" args="" -->
<div class="memdoc">
<p>
-An optional plug-in name.
+An optional plug-in name.
<p>
-NULL if not available. The plug-in name is intended only for display purposes and the value can be localized. This corresponds to the <em>name</em> attribute of the <em>plugin</em> element in a plug-in descriptor.
+NULL if not available. The plug-in name is intended only for display purposes and the value can be localized. This corresponds to the <em>name</em> attribute of the <em>plugin</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="56abfaab87c46691c1ef3ad0df23e864"></a><!-- doxytag: member="cp_plugin_info_t::version" ref="56abfaab87c46691c1ef3ad0df23e864" args="" -->
<div class="memdoc">
<p>
-An optional release version string.
+An optional release version string.
<p>
-NULL if not available. This corresponds to the <em>version</em> attribute of the <em>plugin</em> element in a plug-in descriptor.
+NULL if not available. This corresponds to the <em>version</em> attribute of the <em>plugin</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="8bf76789248b4737d6a9a1175ceadca5"></a><!-- doxytag: member="cp_plugin_info_t::provider_name" ref="8bf76789248b4737d6a9a1175ceadca5" args="" -->
<div class="memdoc">
<p>
-An optional provider name.
+An optional provider name.
<p>
-NULL if not available. This is the name of the author or the organization providing the plug-in. The provider name is intended only for display purposes and the value can be localized. This corresponds to the <em>provider-name</em> attribute of the <em>plugin</em> element in a plug-in descriptor.
+NULL if not available. This is the name of the author or the organization providing the plug-in. The provider name is intended only for display purposes and the value can be localized. This corresponds to the <em>provider-name</em> attribute of the <em>plugin</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="bfb5abdafe1c5db02dcd2922b32be4e6"></a><!-- doxytag: member="cp_plugin_info_t::plugin_path" ref="bfb5abdafe1c5db02dcd2922b32be4e6" args="" -->
<div class="memdoc">
<p>
-Path of the plugin directory or NULL if not known.
+Path of the plugin directory or NULL if not known.
<p>
-This is the (absolute or relative) path to the plug-in directory containing plug-in data and the plug-in runtime library. The value corresponds to the path specified to <a class="el" href="group__cFuncsPlugin.html#gcb92588ad3b48dab5e9487698f6ef437">cp_load_plugin_descriptor</a> when loading the plug-in.
+This is the (absolute or relative) path to the plug-in directory containing plug-in data and the plug-in runtime library. The value corresponds to the path specified to <a class="el" href="group__cFuncsPlugin.html#gcb92588ad3b48dab5e9487698f6ef437">cp_load_plugin_descriptor</a> when loading the plug-in.
</div>
</div><p>
<a class="anchor" name="80147b4cbaeac68ad7a02dfe9c732e43"></a><!-- doxytag: member="cp_plugin_info_t::abi_bw_compatibility" ref="80147b4cbaeac68ad7a02dfe9c732e43" args="" -->
<div class="memdoc">
<p>
-Optional ABI compatibility information.
+Optional ABI compatibility information.
<p>
-NULL if not available. This is the earliest version of the plug-in interface the current interface is backwards compatible with when it comes to the application binary interface (ABI) of the plug-in. That is, plug-in clients compiled against any plug-in interface version from <em>abi_bw_compatibility</em> to <a class="el" href="structcp__plugin__info__t.html#56abfaab87c46691c1ef3ad0df23e864">version</a> (inclusive) can use the current version of the plug-in binary. This describes binary or runtime compatibility. The value corresponds to the <em>abi-compatibility</em> attribute of the <em>backwards-compatibility</em> element in a plug-in descriptor.
+NULL if not available. This is the earliest version of the plug-in interface the current interface is backwards compatible with when it comes to the application binary interface (ABI) of the plug-in. That is, plug-in clients compiled against any plug-in interface version from <em>abi_bw_compatibility</em> to <a class="el" href="structcp__plugin__info__t.html#56abfaab87c46691c1ef3ad0df23e864">version</a> (inclusive) can use the current version of the plug-in binary. This describes binary or runtime compatibility. The value corresponds to the <em>abi-compatibility</em> attribute of the <em>backwards-compatibility</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="a0db42bb2a075c5804c0aeecfab567d8"></a><!-- doxytag: member="cp_plugin_info_t::api_bw_compatibility" ref="a0db42bb2a075c5804c0aeecfab567d8" args="" -->
<div class="memdoc">
<p>
-Optional API compatibility information.
+Optional API compatibility information.
<p>
-NULL if not available. This is the earliest version of the plug-in interface the current interface is backwards compatible with when it comes to the application programming interface (API) of the plug-in. That is, plug-in clients written for any plug-in interface version from <em>api_bw_compatibility</em> to <a class="el" href="structcp__plugin__info__t.html#56abfaab87c46691c1ef3ad0df23e864">version</a> (inclusive) can be compiled against the current version of the plug-in API. This describes source or build time compatibility. The value corresponds to the <em>api-compatibility</em> attribute of the <em>backwards-compatibility</em> element in a plug-in descriptor.
+NULL if not available. This is the earliest version of the plug-in interface the current interface is backwards compatible with when it comes to the application programming interface (API) of the plug-in. That is, plug-in clients written for any plug-in interface version from <em>api_bw_compatibility</em> to <a class="el" href="structcp__plugin__info__t.html#56abfaab87c46691c1ef3ad0df23e864">version</a> (inclusive) can be compiled against the current version of the plug-in API. This describes source or build time compatibility. The value corresponds to the <em>api-compatibility</em> attribute of the <em>backwards-compatibility</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="8b1942a723f6a68c9afad9e52b7e78d1"></a><!-- doxytag: member="cp_plugin_info_t::req_cpluff_version" ref="8b1942a723f6a68c9afad9e52b7e78d1" args="" -->
<div class="memdoc">
<p>
-Optional C-Pluff version requirement.
+Optional C-Pluff version requirement.
<p>
-NULL if not available. This is the version of the C-Pluff implementation the plug-in was compiled against. It is used to determine the compatibility of the plug-in runtime and the linked in C-Pluff implementation. Any C-Pluff version that is backwards compatible on binary level with the specified version fulfills the requirement.
+NULL if not available. This is the version of the C-Pluff implementation the plug-in was compiled against. It is used to determine the compatibility of the plug-in runtime and the linked in C-Pluff implementation. Any C-Pluff version that is backwards compatible on binary level with the specified version fulfills the requirement.
</div>
</div><p>
<a class="anchor" name="bca19d2e4af3752ceb056d638321b894"></a><!-- doxytag: member="cp_plugin_info_t::num_imports" ref="bca19d2e4af3752ceb056d638321b894" args="" -->
<div class="memdoc">
<p>
-Number of import entries in the <a class="el" href="structcp__plugin__info__t.html#e03a6d473f95a77ad6de9d43610f8d39">imports</a> array.
+Number of import entries in the <a class="el" href="structcp__plugin__info__t.html#e03a6d473f95a77ad6de9d43610f8d39">imports</a> array.
<p>
</div>
<div class="memdoc">
<p>
-An array of <a class="el" href="structcp__plugin__info__t.html#bca19d2e4af3752ceb056d638321b894">num_imports</a> import entries.
+An array of <a class="el" href="structcp__plugin__info__t.html#bca19d2e4af3752ceb056d638321b894">num_imports</a> import entries.
<p>
-These correspond to <em>import</em> elements in a plug-in descriptor.
+These correspond to <em>import</em> elements in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="e466145debd47625f99bbc780e8950ed"></a><!-- doxytag: member="cp_plugin_info_t::runtime_lib_name" ref="e466145debd47625f99bbc780e8950ed" args="" -->
<div class="memdoc">
<p>
-The base name of the plug-in runtime library, or NULL if none.
+The base name of the plug-in runtime library, or NULL if none.
<p>
-A platform specific prefix (for example, "lib") and an extension (for example, ".dll" or ".so") may be added to the base name. This corresponds to the <em>library</em> attribute of the <em>runtime</em> element in a plug-in descriptor.
+A platform specific prefix (for example, "lib") and an extension (for example, ".dll" or ".so") may be added to the base name. This corresponds to the <em>library</em> attribute of the <em>runtime</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="3291d0de7ca4bbe510950be556641856"></a><!-- doxytag: member="cp_plugin_info_t::runtime_funcs_symbol" ref="3291d0de7ca4bbe510950be556641856" args="" -->
<div class="memdoc">
<p>
-The symbol pointing to the plug-in runtime function information or NULL if none.
+The symbol pointing to the plug-in runtime function information or NULL if none.
<p>
-The symbol with this name should point to an instance of <a class="el" href="structcp__plugin__runtime__t.html">cp_plugin_runtime_t</a> structure. This corresponds to the <em>funcs</em> attribute of the <em>runtime</em> element in a plug-in descriptor.
+The symbol with this name should point to an instance of <a class="el" href="structcp__plugin__runtime__t.html">cp_plugin_runtime_t</a> structure. This corresponds to the <em>funcs</em> attribute of the <em>runtime</em> element in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="845440eb771d52a4b271bfbd48fcb7ec"></a><!-- doxytag: member="cp_plugin_info_t::num_ext_points" ref="845440eb771d52a4b271bfbd48fcb7ec" args="" -->
<div class="memdoc">
<p>
-Number of extension points in <a class="el" href="structcp__plugin__info__t.html#8299ae4ef53289492911a1334494e405">ext_points</a> array.
+Number of extension points in <a class="el" href="structcp__plugin__info__t.html#8299ae4ef53289492911a1334494e405">ext_points</a> array.
<p>
</div>
<div class="memdoc">
<p>
-An array of <a class="el" href="structcp__plugin__info__t.html#845440eb771d52a4b271bfbd48fcb7ec">num_ext_points</a> extension points provided by this plug-in.
+An array of <a class="el" href="structcp__plugin__info__t.html#845440eb771d52a4b271bfbd48fcb7ec">num_ext_points</a> extension points provided by this plug-in.
<p>
-These correspond to <em>extension-point</em> elements in a plug-in descriptor.
+These correspond to <em>extension-point</em> elements in a plug-in descriptor.
</div>
</div><p>
<a class="anchor" name="5774f2b85864891690291909ecbbf819"></a><!-- doxytag: member="cp_plugin_info_t::num_extensions" ref="5774f2b85864891690291909ecbbf819" args="" -->
<div class="memdoc">
<p>
-Number of extensions in <a class="el" href="structcp__plugin__info__t.html#2288d4af96da6699b7a2c8b747bd42dc">extensions</a> array.
+Number of extensions in <a class="el" href="structcp__plugin__info__t.html#2288d4af96da6699b7a2c8b747bd42dc">extensions</a> array.
<p>
</div>
<div class="memdoc">
<p>
-An array of <a class="el" href="structcp__plugin__info__t.html#5774f2b85864891690291909ecbbf819">num_extensions</a> extensions provided by this plug-in.
+An array of <a class="el" href="structcp__plugin__info__t.html#5774f2b85864891690291909ecbbf819">num_extensions</a> extensions provided by this plug-in.
<p>
-These correspond to <em>extension</em> elements in a plug-in descriptor.
+These correspond to <em>extension</em> elements in a plug-in descriptor.
</div>
</div><p>
<hr>The documentation for this struct was generated from the following file:<ul>
<small>
[<a class="el" href="group__cStructs.html">Data structures</a>]</small>
</h1><!-- doxytag: class="cp_plugin_runtime_t" --><hr><a name="_details"></a><h2>Detailed Description</h2>
-Container for plug-in runtime information.
+Container for plug-in runtime information.
<p>
A plug-in runtime defines a static instance of this structure to pass information to the plug-in framework. The plug-in framework then uses the information to create and control plug-in instances. The symbol pointing to the runtime information instance is named by the <em>funcs</em> attribute of the <em>runtime</em> element in a plug-in descriptor.<p>
The following graph displays how these functions are used to control the state of the plug-in instance.<p>
<area href="structcp__plugin__runtime__t.html#ede7dc51a6d9f47d0e21445dc952d5d4" shape="rect" coords="268,52,276,60" alt="">
</map>
</div>
-
+
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td></td></tr>
<div class="memdoc">
<p>
-An initialization function called to create a new plug-in runtime instance.
+An initialization function called to create a new plug-in runtime instance.
<p>
The initialization function initializes and returns an opaque plug-in instance data pointer which is then passed on to other control functions. This data pointer should be used to access plug-in instance specific data. For example, the context reference must be stored as part of plug-in instance data if the plug-in runtime needs it. On failure, the function must return NULL.<p>
C-pluff API functions must not be called from within a create function invocation and symbols from imported plug-ins must not be used because they may not available yet.<p>
<div class="memdoc">
<p>
-A start function called to start a plug-in instance.
+A start function called to start a plug-in instance.
<p>
The start function must return zero (CP_OK) on success and non-zero on failure. If the start fails then the stop function (if any) is called to clean up plug-in state. <a class="el" href="group__cFuncsInit.html">Library initialization</a>, <a class="el" href="group__cFuncsContext.html">plug-in context management</a> and <a class="el" href="group__cFuncsPlugin.html">plug-in management</a> functions must not be called from within a start function invocation. The start function pointer can be NULL if the plug-in runtime does not have a start function.<p>
The start function implementation should set up plug-in and return promptly. If there is further work to be done then a plug-in can start a thread or register a run function using <a class="el" href="group__cFuncsPluginExec.html#g357c45e87ff896e8541fe3758b19a035">cp_run_function</a>. Symbols from imported plug-ins are guaranteed to be available for the start function.<p>
<div class="memdoc">
<p>
-A stop function called to stop a plugin instance.
+A stop function called to stop a plugin instance.
<p>
This function must cease all plug-in runtime activities. <a class="el" href="group__cFuncsInit.html">Library initialization</a>, <a class="el" href="group__cFuncsContext.html">plug-in context management</a>, <a class="el" href="group__cFuncsPlugin.html">plug-in management</a> functions, <a class="el" href="group__cFuncsPluginExec.html#g357c45e87ff896e8541fe3758b19a035">cp_run_function</a> and <a class="el" href="group__cFuncsSymbols.html#g8bc3b7fcf4f4ed414837f5a3998d46b7">cp_resolve_symbol</a> must not be called from within a stop function invocation. The stop function pointer can be NULL if the plug-in runtime does not have a stop function. It is guaranteed that no run functions registered by the plug-in are called simultaneously or after the call to the stop function.<p>
The stop function should release any external resources hold by the plug-in. Dynamically resolved symbols are automatically released and dynamically defined symbols and registered run functions are automatically unregistered after the call to stop function. Resolved external symbols are still available for the stop function and symbols provided by the plug-in should remain available after the call to stop function (although functionality might be limited). Final cleanup can be safely done in the destroy function.<p>
<div class="memdoc">
<p>
-A destroy function called to destroy a plug-in instance.
+A destroy function called to destroy a plug-in instance.
<p>
This function should release any plug-in instance data. The plug-in is stopped before this function is called. C-Pluff API functions must not be called from within a destroy function invocation and symbols from imported plug-ins must not be used because they may not be available anymore. Correspondingly, it is guaranteed that the symbols provided by the plug-in are not used by other plug-ins when destroy function has been called.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
/sbin/init: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
for GNU/Linux 2.4.1, dynamically linked (uses shared libs), for
GNU/Linux 2.4.1, stripped
-
+
$ file COPYRIGHT.txt
COPYRIGHT.txt: ASCII English text
C-Pluff Loader, version 0.1.0
C-Pluff Library, version 0.1.0 for i686-pc-linux-gnu
/tmp/testdir: directory
-
+
$ cpfile /tmp/test.foo
C-Pluff Loader, version 0.1.0
C-Pluff Library, version 0.1.0 for i686-pc-linux-gnu
/tmp/test.foo: unknown file type
-
+
$ cpfile /tmp/test.c
C-Pluff Loader, version 0.1.0
C-Pluff Library, version 0.1.0 for i686-pc-linux-gnu
$ cpfile -q /tmp/test.c
/tmp/test.c: C source file
-
+
$ cpfile -vv /tmp/test.c
C-Pluff Loader, version 0.1.0
C-Pluff Library, version 0.1.0 for i686-pc-linux-gnu
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libcore.la: $(libcore_la_OBJECTS) $(libcore_la_DEPENDENCIES) $(EXTRA_libcore_la_DEPENDENCIES)
+libcore.la: $(libcore_la_OBJECTS) $(libcore_la_DEPENDENCIES) $(EXTRA_libcore_la_DEPENDENCIES)
$(libcore_la_LINK) -rpath $(plugindir) $(libcore_la_OBJECTS) $(libcore_la_LIBADD) $(LIBS)
mostlyclean-compile:
/** Plug-in instance data */
struct plugin_data_t {
-
+
/** The plug-in context */
cp_context_t *ctx;
-
+
/** Number of registered classifiers */
int num_classifiers;
-
+
/** An array of registered classifiers */
- registered_classifier_t *classifiers;
+ registered_classifier_t *classifiers;
};
/** Registered classifier information */
struct registered_classifier_t {
-
+
/** The priority of the classifier */
int priority;
-
+
/** The classifier data */
classifier_t *classifier;
};
for (i = 1; argv[i] != NULL; i++) {
int j;
int classified = 0;
-
+
// Print file name
printf("%s: ", argv[i]);
-
+
// Try classifiers in order of descending priority
for (j = 0; !classified && j < data->num_classifiers; j++) {
classifier_t *cl
= data->classifiers[j].classifier;
-
+
classified = cl->classify(cl->data, argv[i]);
}
-
+
// Check if unknown file
if (!classified) {
fputs("unknown file type\n", stdout);
}
}
-
+
// All done
return 0;
-}
+}
/**
* Creates a new plug-in instance.
int num_cl_exts;
cp_status_t status;
int i;
-
+
// Obtain list of registered classifiers
cl_exts = cp_get_extensions_info(
data->ctx,
&num_cl_exts
);
if (cl_exts == NULL) {
-
+
// An error occurred and framework logged it
return status;
}
-
+
// Allocate memory for classifier information, if any
if (num_cl_exts > 0) {
data->classifiers = malloc(
num_cl_exts * sizeof(registered_classifier_t)
);
if (data->classifiers == NULL) {
-
+
// Memory allocation failed
cp_log(data->ctx, CP_LOG_ERROR,
"Insufficient memory for classifier list.");
return CP_ERR_RESOURCE;
}
- }
-
+ }
+
/* Resolve classifier functions. This will implicitly start
* plug-ins providing the classifiers. */
for (i = 0; i < num_cl_exts; i++) {
const char *str;
int pri;
classifier_t *cl;
-
+
// Get the classifier function priority
str = cp_lookup_cfg_value(
cl_exts[i]->configuration, "@priority"
);
if (str == NULL) {
-
+
// Classifier is missing mandatory priority
cp_log(data->ctx, CP_LOG_ERROR,
"Ignoring classifier without priority.");
continue;
}
pri = atoi(str);
-
+
// Resolve classifier data pointer
str = cp_lookup_cfg_value(
cl_exts[i]->configuration, "@classifier");
if (str == NULL) {
-
+
// Classifier symbol name is missing
cp_log(data->ctx, CP_LOG_ERROR,
"Ignoring classifier without symbol name.");
NULL
);
if (cl == NULL) {
-
+
// Could not resolve classifier symbol
cp_log(data->ctx, CP_LOG_ERROR,
"Ignoring classifier which could not be resolved.");
continue;
}
-
+
// Add classifier to the list of registered classifiers
data->classifiers[data->num_classifiers].priority = pri;
data->classifiers[data->num_classifiers].classifier = cl;
data->num_classifiers++;
}
-
+
// Release extension information
cp_release_info(data->ctx, cl_exts);
-
+
// Sort registered classifiers according to priority
if (data->num_classifiers > 1) {
qsort(data->classifiers,
sizeof(registered_classifier_t),
(int (*)(const void *, const void *)) comp_classifiers);
}
-
+
// Register run function to do the real work
cp_run_function(data->ctx, run);
-
+
// Successfully started
return CP_OK;
}
static void stop(void *d) {
plugin_data_t *data = d;
int i;
-
+
// Release classifier data, if any
if (data->classifiers != NULL) {
-
+
// Release classifier pointers
for (i = 0; i < data->num_classifiers; i++) {
cp_release_symbol(
data->ctx, data->classifiers[i].classifier
);
}
-
+
// Free local data
free(data->classifiers);
data->classifiers = NULL;
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libextension.la: $(libextension_la_OBJECTS) $(libextension_la_DEPENDENCIES) $(EXTRA_libextension_la_DEPENDENCIES)
+libextension.la: $(libextension_la_OBJECTS) $(libextension_la_DEPENDENCIES) $(EXTRA_libextension_la_DEPENDENCIES)
$(libextension_la_LINK) -rpath $(plugindir) $(libextension_la_OBJECTS) $(libextension_la_LIBADD) $(LIBS)
mostlyclean-compile:
cp_extension_t **exts;
const char *type = NULL;
int i;
-
+
// Go through all extensions registered at the extension point
exts = cp_get_extensions_info(ctx, "org.c-pluff.examples.cpfile.extension.file-types", NULL, NULL);
if (exts == NULL) {
}
for (i = 0; type == NULL && exts[i] != NULL; i++) {
int j;
-
+
// Go through all file types provided by the extension
for (j = 0; type == NULL && j < exts[i]->configuration->num_children; j++) {
cp_cfg_element_t *elem = exts[i]->configuration->children + j;
const char *desc = NULL;
-
+
if (strcmp(elem->name, "file-type") == 0
&& (desc = cp_lookup_cfg_value(elem, "@description")) != NULL
&& (is_of_type(path, elem))) {
}
}
}
-
+
// Release extension information
cp_release_info(ctx, exts);
-
+
// Print file type if recognized, otherwise try other classifiers
if (type != NULL) {
fputs(type, stdout);
static int is_of_type(const char *path, const cp_cfg_element_t *type) {
int i;
int iot = 0;
-
+
/* Go through all extensions specified for the type */
for (i = 0; !iot && i < type->num_children; i++) {
cp_cfg_element_t *ee = type->children + i;
const char *ext;
-
+
iot = (strcmp(ee->name, "file-extension") == 0
&& (ext = cp_lookup_cfg_value(ee, "@ext")) != NULL
&& strlen(path) >= strlen(ext)
&& strcmp(path + (strlen(path) - strlen(ext)), ext) == 0);
}
-
+
return iot;
}
*/
static void *create(cp_context_t *ctx) {
classifier_t *cl;
-
+
cl = malloc(sizeof(classifier_t));
if (cl != NULL) {
cl->data = ctx;
static int start(void *d) {
classifier_t *cl = d;
cp_context_t *ctx = cl->data;
-
+
return cp_define_symbol(ctx, "cp_ex_cpfile_extension_classifier", cl);
}
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libspecial.la: $(libspecial_la_OBJECTS) $(libspecial_la_DEPENDENCIES) $(EXTRA_libspecial_la_DEPENDENCIES)
+libspecial.la: $(libspecial_la_OBJECTS) $(libspecial_la_DEPENDENCIES) $(EXTRA_libspecial_la_DEPENDENCIES)
$(libspecial_la_LINK) -rpath $(plugindir) $(libspecial_la_OBJECTS) $(libspecial_la_LIBADD) $(LIBS)
mostlyclean-compile:
#ifdef STAT
struct stat s;
const char *type;
-
+
// Stat the file
if (STAT(path, &s)) {
fflush(stdout);
perror("stat failed");
-
+
// No point for other classifiers to classify this
return 1;
}
-
+
// Check if this is a special file
if ((s.st_mode & S_IFMT) == S_IFDIR) {
type = "directory";
type = "symbolic link";
#endif
} else {
-
+
// Did not recognize it, let other plug-ins try
return 0;
}
-
+
// Print recognized file type
fputs(type, stdout);
putchar('\n');
}
/*
- * Compute a shift amount from a given table size
+ * Compute a shift amount from a given table size
*/
static hash_val_t compute_mask(hashcount_t size)
* hash->shift is equal to hash_val_t_bit, an illegal shift value.
* Also, other things could go wrong, such as hash->lowmark becoming zero.
* 2. Looping over each pair of sister chains, the low_chain is set to
- * point to the head node of the chain in the lower half of the table,
+ * point to the head node of the chain in the lower half of the table,
* and high_chain points to the head node of the sister in the upper half.
* 3. The intent here is to compute a pointer to the last node of the
* lower chain into the low_tail variable. If this chain is empty,
clear_table(hash); /* 8 */
assert (hash_verify(hash));
return hash;
- }
+ }
free(hash);
}
* 2. The user supplied array of pointers hopefully contains nchains nodes.
* 3. See note 7. in hash_create().
* 4. We must dynamically compute the mask from the given power of two table
- * size.
+ * size.
* 5. The user supplied table can't be assumed to contain null pointers,
* so we reset it here.
*/
/*
* Reset the hash scanner so that the next element retrieved by
- * hash_scan_next() shall be the first element on the first non-empty chain.
+ * hash_scan_next() shall be the first element on the first non-empty chain.
* Notes:
* 1. Locate the first non empty chain.
* 2. If an empty chain is found, remember which one it is and set the next
/*
* Retrieve the next node from the hash table, and update the pointer
- * for the next invocation of hash_scan_next().
+ * for the next invocation of hash_scan_next().
* Notes:
* 1. Remember the next pointer in a temporary value so that it can be
* returned.
* 3. If the table is dynamic and the load factor is already at >= 2,
* grow the table.
* 4. We take the bottom N bits of the hash value to derive the chain index,
- * where N is the base 2 logarithm of the size of the hash table.
+ * where N is the base 2 logarithm of the size of the hash table.
*/
CP_HIDDEN void hash_insert(hash_t *hash, hnode_t *node, const void *key)
* Notes:
* 1. We hash the key and keep the entire hash value. As an optimization, when
* we descend down the chain, we can compare hash values first and only if
- * hash values match do we perform a full key comparison.
+ * hash values match do we perform a full key comparison.
* 2. To locate the chain from among 2^N chains, we look at the lower N bits of
* the hash value by anding them with the current mask.
* 3. Looping through the chain, we compare the stored hash value inside each
* 1. The node must belong to this hash table, and its key must not have
* been tampered with.
* 2. If this deletion will take the node count below the low mark, we
- * shrink the table now.
+ * shrink the table now.
* 3. Determine which chain the node belongs to, and fetch the pointer
* to the first node in this chain.
* 4. If the node being deleted is the first node in the chain, then
assert (hptr->next == node);
hptr->next = node->next;
}
-
+
hash->nodecount--;
assert (hash_verify(hash));
if (hptr == node) {
hash->table[chain] = node->next;
} else {
- while (hptr->next != node)
+ while (hptr->next != node)
hptr = hptr->next;
hptr->next = node->next;
}
-
+
hash->nodecount--;
assert (hash_verify(hash));
node->next = NULL;
}
/*
- * Initialize a client-supplied node
+ * Initialize a client-supplied node
*/
CP_HIDDEN hnode_t *hnode_init(hnode_t *hnode, void *data)
static int tokenize(char *string, ...)
{
- char **tokptr;
+ char **tokptr;
va_list arglist;
int tokcount = 0;
}
/*
- * Free all of the nodes of a list. The list must contain only
+ * Free all of the nodes of a list. The list must contain only
* dynamically allocated nodes. After this call, the list
* is empty.
*/
/*
* Borrow a node from a node pool. Returns a null pointer if the pool
- * is exhausted.
+ * is exhausted.
*/
CP_HIDDEN lnode_t *lnode_borrow(lnodepool_t *pool, void *data)
assert (first != list_nil(source)); /* oops, last before first! */
moved++;
}
-
+
/* assert no overflows */
assert (source->nodecount - moved <= source->nodecount);
assert (dest->nodecount + moved >= dest->nodecount);
first = first->next;
moved++;
}
-
+
/* assert no overflows */
assert (source->nodecount - moved <= source->nodecount);
assert (dest->nodecount + moved >= dest->nodecount);
while (middle--)
node = lnode_next(node);
-
+
list_transfer(&extra, list, node);
list_sort(list, compare);
list_sort(&extra, compare);
list_merge(list, &extra, compare);
- }
+ }
assert (list_is_sorted(list, compare));
}
if (compare(lnode_get(node), key) == 0)
return node;
}
-
+
return 0;
}
/*
* Return 1 if the list is full, 0 otherwise
- * Permitted only on bounded lists.
+ * Permitted only on bounded lists.
*/
CP_HIDDEN int list_isfull(list_t *list)
}
/*
- * Retrieve the node's successor. If there is no successor,
+ * Retrieve the node's successor. If there is no successor,
* NULL is returned.
*/
if (count != 0 || node != nil)
return 0;
-
+
return 1;
}
static int tokenize(char *string, ...)
{
- char **tokptr;
+ char **tokptr;
va_list arglist;
int tokcount = 0;
}
val = dupstring(tok1);
ln = lnode_create(val);
-
+
if (!val || !ln) {
puts("allocation failure");
if (ln)
free(val);
break;
}
-
+
list_append(l, ln);
break;
case 'd':
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libcpluff.la: $(libcpluff_la_OBJECTS) $(libcpluff_la_DEPENDENCIES) $(EXTRA_libcpluff_la_DEPENDENCIES)
+libcpluff.la: $(libcpluff_la_OBJECTS) $(libcpluff_la_DEPENDENCIES) $(EXTRA_libcpluff_la_DEPENDENCIES)
$(libcpluff_la_LINK) -rpath $(libdir) $(libcpluff_la_OBJECTS) $(libcpluff_la_LIBADD) $(LIBS)
mostlyclean-compile:
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* Function definitions
* ----------------------------------------------------------------------*/
-// Generic
+// Generic
static void free_plugin_env(cp_plugin_env_t *env) {
assert(env != NULL);
-
+
// Free environment data
if (env->plugin_listeners != NULL) {
cpi_unregister_plisteners(env->plugin_listeners, NULL);
assert(list_isempty(env->run_funcs));
list_destroy(env->run_funcs);
}
-
- // Destroy mutex
+
+ // Destroy mutex
#ifdef CP_THREADS
if (env->mutex != NULL) {
cpi_destroy_mutex(env->mutex);
CP_HIDDEN void cpi_free_context(cp_context_t *context) {
assert(context != NULL);
-
+
// Free environment if this is the client program context
if (context->plugin == NULL && context->env != NULL) {
free_plugin_env(context->env);
}
-
+
// Destroy symbol lists
if (context->resolved_symbols != NULL) {
assert(hash_isempty(context->resolved_symbols));
}
// Free context
- free(context);
+ free(context);
}
CP_HIDDEN cp_context_t * cpi_new_context(cp_plugin_t *plugin, cp_plugin_env_t *env, cp_status_t *error) {
cp_context_t *context = NULL;
cp_status_t status = CP_OK;
-
+
assert(env != NULL);
assert(error != NULL);
-
+
do {
-
+
// Allocate memory for the context
if ((context = malloc(sizeof(cp_context_t))) == NULL) {
status = CP_ERR_RESOURCE;
break;
}
-
+
// Initialize context
context->plugin = plugin;
context->env = env;
context->resolved_symbols = NULL;
context->symbol_providers = NULL;
-
+
} while (0);
-
+
// Free context on error
if (status != CP_OK && context != NULL) {
free(context);
context = NULL;
}
-
+
*error = status;
return context;
}
// Initialize internal state
do {
-
+
// Allocate memory for the plug-in environment
if ((env = malloc(sizeof(cp_plugin_env_t))) == NULL) {
status = CP_ERR_RESOURCE;
break;
}
-
+
// Initialize plug-in environment
memset(env, 0, sizeof(cp_plugin_env_t));
#ifdef CP_THREADS
status = CP_ERR_RESOURCE;
break;
}
-
+
// Create the plug-in context
if ((context = cpi_new_context(NULL, env, &status)) == NULL) {
break;
}
if (status == CP_OK) {
lnode_t *node;
-
+
if ((node = lnode_create(context)) == NULL) {
status = CP_ERR_RESOURCE;
} else {
}
}
cpi_unlock_framework();
-
+
} while (0);
-
- // Release resources on failure
+
+ // Release resources on failure
if (status != CP_OK) {
if (env != NULL) {
free_plugin_env(env);
context = NULL;
}
- // Return the final status
+ // Return the final status
if (error != NULL) {
*error = status;
}
-
- // Return the context (or NULL on failure)
+
+ // Return the context (or NULL on failure)
return context;
}
cpi_lock_framework();
if (contexts != NULL) {
lnode_t *node;
-
+
if ((node = list_find(contexts, context, cpi_comp_ptr)) != NULL) {
list_delete(contexts, node);
lnode_destroy(node);
}
cpi_unlock_framework();
- // Unload all plug-ins
+ // Unload all plug-ins
cp_uninstall_plugins(context);
// Release remaining information objects
cpi_release_infos(context);
-
+
// Free context
cpi_free_context(context);
}
cpi_lock_framework();
if (contexts != NULL) {
lnode_t *node;
-
+
while ((node = list_last(contexts)) != NULL) {
cpi_unlock_framework();
cp_destroy_context(lnode_get(node));
}
-// Plug-in directories
+// Plug-in directories
CP_C_API cp_status_t cp_register_pcollection(cp_context_t *context, const char *dir) {
char *d = NULL;
lnode_t *node = NULL;
cp_status_t status = CP_OK;
-
+
CHECK_NOT_NULL(context);
CHECK_NOT_NULL(dir);
-
+
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_ANY, __func__);
do {
-
- // Check if directory has already been registered
+
+ // Check if directory has already been registered
if (list_find(context->env->plugin_dirs, dir, (int (*)(const void *, const void *)) strcmp) != NULL) {
break;
}
-
- // Allocate resources
+
+ // Allocate resources
d = malloc(sizeof(char) * (strlen(dir) + 1));
node = lnode_create(d);
if (d == NULL || node == NULL) {
status = CP_ERR_RESOURCE;
break;
}
-
- // Register directory
+
+ // Register directory
strcpy(d, dir);
list_append(context->env->plugin_dirs, node);
-
+
} while (0);
// Report error or success
}
cpi_unlock_context(context);
- // Release resources on failure
- if (status != CP_OK) {
+ // Release resources on failure
+ if (status != CP_OK) {
if (d != NULL) {
free(d);
}
lnode_destroy(node);
}
}
-
+
return status;
}
CP_C_API void cp_unregister_pcollection(cp_context_t *context, const char *dir) {
char *d;
lnode_t *node;
-
+
CHECK_NOT_NULL(context);
CHECK_NOT_NULL(dir);
-
+
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_ANY, __func__);
node = list_find(context->env->plugin_dirs, dir, (int (*)(const void *, const void *)) strcmp);
CP_C_API void cp_set_context_args(cp_context_t *ctx, char **argv) {
int argc;
-
+
CHECK_NOT_NULL(ctx);
CHECK_NOT_NULL(argv);
for (argc = 0; argv[argc] != NULL; argc++);
CP_C_API char **cp_get_context_args(cp_context_t *ctx, int *argc) {
char **argv;
-
+
CHECK_NOT_NULL(ctx);
cpi_lock_context(ctx);
if (argc != NULL) {
}
-// Locking
+// Locking
#if defined(CP_THREADS) || !defined(NDEBUG)
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
/** @file
* Core framework functions
- */
+ */
#include <stdio.h>
#include <stdlib.h>
* Variables
* ----------------------------------------------------------------------*/
-/// Number of initializations
+/// Number of initializations
static int initialized = 0;
#ifdef CP_THREADS
#endif
-/// Fatal error handler, or NULL for default
+/// Fatal error handler, or NULL for default
static cp_fatal_error_func_t fatal_error_handler = NULL;
CP_C_API cp_status_t cp_init(void) {
cp_status_t status = CP_OK;
-
+
// Initialize if necessary
do {
if (!initialized) {
}
initialized++;
} while (0);
-
+
// Rollback on failure
if (status != CP_OK) {
reset();
}
-
+
return status;
}
CP_HIDDEN void cpi_fatalf(const char *msg, ...) {
va_list params;
char fmsg[256];
-
- // Format message
+
+ // Format message
assert(msg != NULL);
va_start(params, msg);
vsnprintf(fmsg, sizeof(fmsg), msg, params);
} else {
fprintf(stderr, _("C-Pluff: FATAL ERROR: %s\n"), fmsg);
}
-
- // Abort if still alive
+
+ // Abort if still alive
abort();
}
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
/** @file
* Logging functions
- */
+ */
#include <stdio.h>
#include <stdlib.h>
/// Contains information about installed loggers
typedef struct logger_t {
-
+
/// Pointer to logger
cp_logger_func_t logger;
-
+
/// Pointer to registering plug-in or NULL for the main program
cp_plugin_t *plugin;
-
+
/// User data pointer
void *user_data;
-
+
/// Minimum severity
cp_log_severity_t min_severity;
-
+
/// Selected environment or NULL
cp_plugin_env_t *env_selection;
} logger_t;
static void update_logging_limits(cp_context_t *context) {
lnode_t *node;
int nms = CP_LOG_NONE;
-
+
node = list_first(context->env->loggers);
while (node != NULL) {
logger_t *lh = lnode_get(node);
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_LOGGER, __func__);
do {
-
+
// Check if logger already exists and allocate new holder if necessary
l.logger = logger;
if ((node = list_find(context->env->loggers, &l, comp_logger)) == NULL) {
} else {
lh = lnode_get(node);
}
-
+
// Initialize or update the logger holder
lh->user_data = user_data;
lh->min_severity = min_severity;
-
+
// Update global limits
update_logging_limits(context);
-
+
} while (0);
// Report error
if (status == CP_ERR_RESOURCE) {
- cpi_error(context, N_("Logger could not be registered due to insufficient memory."));
+ cpi_error(context, N_("Logger could not be registered due to insufficient memory."));
} else if (cpi_is_logged(context, CP_LOG_DEBUG)) {
char owner[64];
/* TRANSLATORS: %s is the context owner */
CP_C_API void cp_unregister_logger(cp_context_t *context, cp_logger_func_t logger) {
logger_t l;
lnode_t *node;
-
+
CHECK_NOT_NULL(context);
CHECK_NOT_NULL(logger);
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_LOGGER, __func__);
-
+
l.logger = logger;
if ((node = list_find(context->env->loggers, &l, comp_logger)) != NULL) {
logger_t *lh = lnode_get(node);
lnode_t *node;
const char *apid = NULL;
- assert(cpi_is_context_locked(context));
+ assert(cpi_is_context_locked(context));
if (context->env->in_logger_invocation) {
cpi_fatalf(_("Encountered a recursive logging request within a logger invocation."));
}
CP_HIDDEN void cpi_logf(cp_context_t *context, cp_log_severity_t severity, const char *msg, ...) {
char buffer[256];
va_list va;
-
+
assert(context != NULL);
assert(msg != NULL);
assert(severity >= CP_LOG_DEBUG && severity <= CP_LOG_ERROR);
-
+
va_start(va, msg);
vsnprintf(buffer, sizeof(buffer), _(msg), va);
va_end(va);
CP_C_API int cp_is_logged(cp_context_t *context, cp_log_severity_t severity) {
int is_logged;
-
+
CHECK_NOT_NULL(context);
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_LOGGER, __func__);
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
static void assert_processed_zero(cp_context_t *context) {
hscan_t scan;
hnode_t *node;
-
+
hash_scan_begin(&scan, context->env->plugins);
while ((node = hash_scan_next(&scan)) != NULL) {
cp_plugin_t *plugin = hnode_get(node);
static void unregister_extensions(cp_context_t *context, cp_plugin_info_t *plugin) {
int i;
-
+
for (i = 0; i < plugin->num_ext_points; i++) {
cp_ext_point_t *ep = plugin->ext_points + i;
hnode_t *hnode;
-
+
if ((hnode = hash_lookup(context->env->ext_points, ep->identifier)) != NULL
&& hnode_get(hnode) == ep) {
hash_delete_free(context->env->ext_points, hnode);
for (i = 0; i < plugin->num_extensions; i++) {
cp_extension_t *e = plugin->extensions + i;
hnode_t *hnode;
-
+
if ((hnode = hash_lookup(context->env->extensions, e->ext_point_id)) != NULL) {
list_t *el = hnode_get(hnode);
lnode_t *lnode = list_first(el);
-
+
while (lnode != NULL) {
lnode_t *nn = list_next(el, lnode);
if (lnode_get(lnode) == e) {
lnode = nn;
}
if (list_isempty(el)) {
- char *epid = (char *) hnode_getkey(hnode);
+ char *epid = (char *) hnode_getkey(hnode);
hash_delete_free(context->env->extensions, hnode);
free(epid);
list_destroy(el);
CHECK_NOT_NULL(context);
CHECK_NOT_NULL(plugin);
-
+
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_ANY, __func__);
do {
-
- // Check that there is no conflicting plug-in already loaded
+
+ // Check that there is no conflicting plug-in already loaded
if (hash_lookup(context->env->plugins, plugin->identifier) != NULL) {
cpi_errorf(context,
- N_("Plug-in %s could not be installed because a plug-in with the same identifier is already installed."),
+ N_("Plug-in %s could not be installed because a plug-in with the same identifier is already installed."),
plugin->identifier);
status = CP_ERR_CONFLICT;
break;
// Increase usage count for the plug-in descriptor
cpi_use_info(context, plugin);
- // Allocate space for the plug-in state
+ // Allocate space for the plug-in state
if ((rp = malloc(sizeof(cp_plugin_t))) == NULL) {
status = CP_ERR_RESOURCE;
break;
}
-
- // Initialize plug-in state
+
+ // Initialize plug-in state
memset(rp, 0, sizeof(cp_plugin_t));
rp->context = NULL;
rp->plugin = plugin;
status = CP_ERR_RESOURCE;
break;
}
-
+
// Register extension points
for (i = 0; status == CP_OK && i < plugin->num_ext_points; i++) {
cp_ext_point_t *ep = plugin->ext_points + i;
hnode_t *hnode;
-
+
if ((hnode = hash_lookup(context->env->ext_points, ep->identifier)) != NULL) {
cpi_errorf(context, N_("Plug-in %s could not be installed because extension point %s conflicts with an already installed extension point."), plugin->identifier, ep->identifier);
status = CP_ERR_CONFLICT;
status = CP_ERR_RESOURCE;
}
}
-
+
// Register extensions
for (i = 0; status == CP_OK && i < plugin->num_extensions; i++) {
cp_extension_t *e = plugin->extensions + i;
hnode_t *hnode;
lnode_t *lnode;
list_t *el;
-
+
if ((hnode = hash_lookup(context->env->extensions, e->ext_point_id)) == NULL) {
char *epid;
if ((el = list_create(LISTCOUNT_T_MAX)) != NULL
if (status != CP_OK) {
break;
}
-
- // Plug-in installed
+
+ // Plug-in installed
event.plugin_id = plugin->identifier;
event.old_state = CP_PLUGIN_UNINSTALLED;
event.new_state = rp->state;
/**
* Unresolves the plug-in runtime information.
- *
+ *
* @param plugin the plug-in to unresolve
*/
static void unresolve_plugin_runtime(cp_plugin_t *plugin) {
plugin->context = NULL;
}
- // Close plug-in runtime library
+ // Close plug-in runtime library
plugin->runtime_funcs = NULL;
if (plugin->runtime_lib != NULL) {
DLCLOSE(plugin->runtime_lib);
plugin->runtime_lib = NULL;
- }
+ }
}
/**
* Loads and resolves the plug-in runtime library and initialization functions.
- *
+ *
* @param context the plug-in context
* @param plugin the plugin
* @return CP_OK (zero) on success or error code on failure
char *rlpath = NULL;
int rlpath_len;
cp_status_t status = CP_OK;
-
+
assert(plugin->runtime_lib == NULL);
if (plugin->plugin->runtime_lib_name == NULL) {
return CP_OK;
}
-
+
do {
int ppath_len, lname_len;
int cpluff_compatibility = 1;
-
+
// Check C-Pluff compatibility
if (plugin->plugin->req_cpluff_version != NULL) {
#ifdef CP_ABI_COMPATIBILITY
rlpath[ppath_len] = CP_FNAMESEP_CHAR;
strcpy(rlpath + ppath_len + 1, plugin->plugin->runtime_lib_name);
strcpy(rlpath + ppath_len + 1 + lname_len, CP_SHREXT);
-
- // Open the plug-in runtime library
+
+ // Open the plug-in runtime library
plugin->runtime_lib = DLOPEN(rlpath);
if (plugin->runtime_lib == NULL) {
const char *error = DLERROR();
status = CP_ERR_RUNTIME;
break;
}
-
+
// Resolve plug-in functions
if (plugin->plugin->runtime_funcs_symbol != NULL) {
plugin->runtime_funcs = (cp_plugin_runtime_t *) DLSYM(plugin->runtime_lib, plugin->plugin->runtime_funcs_symbol);
}
} while (0);
-
- // Release resources
+
+ // Release resources
free(rlpath);
if (status != CP_OK) {
unresolve_plugin_runtime(plugin);
}
-
+
return status;
}
/**
* Resolves the specified plug-in import into a plug-in pointer. Does not
* try to resolve the imported plug-in.
- *
+ *
* @param context the plug-in context
* @param plugin the plug-in being resolved
* @param import the plug-in import to resolve
cp_plugin_t *ip = NULL;
hnode_t *node;
- // Lookup the plug-in
+ // Lookup the plug-in
node = hash_lookup(context->env->plugins, import->plugin_id);
if (node != NULL) {
ip = hnode_get(node);
}
-
+
// Check plug-in version
if (ip != NULL
&& import->version != NULL
*ipptr = NULL;
return CP_ERR_DEPENDENCY;
}
-
+
// Check if missing mandatory plug-in
if (ip == NULL && !import->optional) {
cpi_errorf(context,
/**
* Resolves the specified plug-in and its dependencies while leaving plug-ins
* with circular dependencies in a preliminarily resolved state.
- *
+ *
* @param context the plug-in context
* @param plugin the plug-in
* @return CP_OK (zero) or CP_OK_PRELIMINARY or an error code
if (plugin->state >= CP_PLUGIN_RESOLVED) {
return CP_OK;
}
-
+
// Check for dependency loops
if (plugin->processed) {
return CP_OK_PRELIMINARY;
for (i = 0; i < plugin->plugin->num_imports; i++) {
cp_plugin_t *ip;
int s;
-
+
if ((node = lnode_create(NULL)) == NULL) {
status = CP_ERR_RESOURCE;
break;
if (status != CP_OK) {
break;
}
-
+
// Resolve this plug-in
assert(plugin->state == CP_PLUGIN_INSTALLED);
if ((i = resolve_plugin_runtime(context, plugin)) != CP_OK) {
error_reported = 1;
break;
}
-
+
// Notify event listeners and update state if completely resolved
if (status == CP_OK) {
cpi_plugin_event_t event;
-
+
plugin->processed = 0;
event.plugin_id = plugin->plugin->identifier;
event.old_state = plugin->state;
if (status == CP_ERR_RESOURCE && !error_reported) {
cpi_errorf(context, N_("Plug-in %s could not be resolved because of insufficient memory."), plugin->plugin->identifier);
}
-
+
return status;
}
/**
* Recursively commits the resolving process for the specified plug-in and
* its dependencies.
- *
+ *
* @param context the plug-in context
* @param plugin the plug-in
*/
static void resolve_plugin_commit_rec(cp_context_t *context, cp_plugin_t *plugin) {
-
+
// Check if already committed
if (!plugin->processed) {
return;
}
plugin->processed = 0;
-
+
// Commit if only preliminarily resolved
if (plugin->state < CP_PLUGIN_RESOLVED) {
cpi_plugin_event_t event;
resolve_plugin_commit_rec(context, (cp_plugin_t *) lnode_get(node));
node = list_next(plugin->imported, node);
}
-
+
// Notify event listeners and update state
event.plugin_id = plugin->plugin->identifier;
event.old_state = plugin->state;
event.new_state = plugin->state = CP_PLUGIN_RESOLVED;
- cpi_deliver_event(context, &event);
+ cpi_deliver_event(context, &event);
}
}
/**
* Recursively cleans up the specified plug-in and its dependencies after
* a failed resolving attempt.
- *
+ *
* @param plugin the plug-in
*/
static void resolve_plugin_failed_rec(cp_plugin_t *plugin) {
-
+
// Check if already cleaned up
if (!plugin->processed) {
return;
}
plugin->processed = 0;
-
+
// Clean up if only preliminarily resolved
if (plugin->state < CP_PLUGIN_RESOLVED) {
lnode_t *node;
// Recursively clean up depedencies
while ((node = list_first(plugin->imported)) != NULL) {
cp_plugin_t *ip = lnode_get(node);
-
+
resolve_plugin_failed_rec(ip);
cpi_ptrset_remove(ip->importing, plugin);
list_delete(plugin->imported, node);
/**
* Resolves the specified plug-in and its dependencies.
- *
+ *
* @param context the plug-in context
* @param plugin the plug-in to be resolved
* @return CP_OK (zero) on success or an error code on failure
*/
static int resolve_plugin(cp_context_t *context, cp_plugin_t *plugin) {
cp_status_t status;
-
+
if ((status = resolve_plugin_prel_rec(context, plugin)) == CP_OK || status == CP_OK_PRELIMINARY) {
status = CP_OK;
resolve_plugin_commit_rec(context, plugin);
* Starts the plug-in runtime of the specified plug-in. This function does
* not consider dependencies and assumes that the plug-in is resolved but
* not yet started.
- *
+ *
* @param context the plug-in context
* @param plugin the plug-in
* @return CP_OK (zero) on success or an error code on failure
event.plugin_id = plugin->plugin->identifier;
do {
- // Allocate space for the list node
+ // Allocate space for the list node
node = lnode_create(plugin);
if (node == NULL) {
status = CP_ERR_RESOURCE;
break;
}
-
+
// Set up plug-in instance
if (plugin->runtime_funcs != NULL) {
break;
}
}
-
+
// Start plug-in
if (plugin->runtime_funcs->start != NULL) {
int s;
-
- // About to start the plug-in
+
+ // About to start the plug-in
event.old_state = plugin->state;
event.new_state = plugin->state = CP_PLUGIN_STARTING;
cpi_deliver_event(context, &event);
-
+
// Start the plug-in
context->env->in_start_func_invocation++;
s = plugin->runtime_funcs->start(plugin->plugin_data);
context->env->in_start_func_invocation--;
if (s != CP_OK) {
-
- // Roll back plug-in state
+
+ // Roll back plug-in state
if (plugin->runtime_funcs->stop != NULL) {
- // Update state
+ // Update state
event.old_state = plugin->state;
event.new_state = plugin->state = CP_PLUGIN_STOPPING;
cpi_deliver_event(context, &event);
-
+
// Call stop function
context->env->in_stop_func_invocation++;
plugin->runtime_funcs->stop(plugin->plugin_data);
context->env->in_stop_func_invocation--;
}
-
+
// Destroy plug-in object
context->env->in_destroy_func_invocation++;
plugin->runtime_funcs->destroy(plugin->plugin_data);
context->env->in_destroy_func_invocation--;
-
+
status = CP_ERR_RUNTIME;
break;
}
}
}
-
- // Plug-in active
+
+ // Plug-in active
list_append(context->env->started_plugins, node);
event.old_state = plugin->state;
event.new_state = plugin->state = CP_PLUGIN_ACTIVE;
cpi_deliver_event(context, &event);
-
+
} while (0);
// Release resources and roll back plug-in state on failure
break;
default:
break;
- }
-
+ }
+
return status;
}
char *msg;
int msgsize;
lnode_t *node;
-
+
// Take the message base
if (dynamic) {
msgbase = N_("Detected a runtime plug-in dependency loop: %s");
} else {
msgbase = N_("Detected a static plug-in dependency loop: %s");
}
-
+
// Calculate the required message space
msgsize = 0;
msgsize += strlen(plugin->plugin->identifier);
/**
* Starts the specified plug-in and its dependencies.
- *
+ *
* @param context the plug-in context
* @param plugin the plug-in
* @param importing stack of importing plug-ins
static int start_plugin_rec(cp_context_t *context, cp_plugin_t *plugin, list_t *importing) {
cp_status_t status = CP_OK;
lnode_t *node;
-
+
// Check if already started or starting
if (plugin->state == CP_PLUGIN_ACTIVE) {
return CP_OK;
return CP_OK;
}
assert(plugin->state == CP_PLUGIN_RESOLVED);
-
+
// Check for dependency loops
if (cpi_ptrset_contains(importing, plugin)) {
warn_dependency_loop(context, plugin, importing, 0);
node = list_first(plugin->imported);
while (node != NULL) {
cp_plugin_t *ip = lnode_get(node);
-
+
if ((status = start_plugin_rec(context, ip, importing)) != CP_OK) {
break;
}
node = list_next(plugin->imported, node);
}
cpi_ptrset_remove(importing, plugin);
-
+
// Start up this plug-in
if (status == CP_OK) {
status = start_plugin_runtime(context, plugin);
CP_HIDDEN cp_status_t cpi_start_plugin(cp_context_t *context, cp_plugin_t *plugin) {
cp_status_t status;
-
+
if ((status = resolve_plugin(context, plugin)) == CP_OK) {
list_t *importing = list_create(LISTCOUNT_T_MAX);
if (importing != NULL) {
CHECK_NOT_NULL(context);
CHECK_NOT_NULL(id);
- // Look up and start the plug-in
+ // Look up and start the plug-in
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_ANY, __func__);
node = hash_lookup(context->env->plugins, id);
/**
* Stops the plug-in runtime of the specified plug-in. This function does
* not consider dependencies and assumes that the plug-in is active.
- *
+ *
* @param context the plug-in context
* @param plugin the plug-in
*/
static void stop_plugin_runtime(cp_context_t *context, cp_plugin_t *plugin) {
cpi_plugin_event_t event;
-
+
// Destroy plug-in instance
event.plugin_id = plugin->plugin->identifier;
if (plugin->context != NULL) {
-
+
// Wait until possible run functions have stopped
cpi_stop_plugin_run(plugin);
// Stop the plug-in
if (plugin->runtime_funcs->stop != NULL) {
- // About to stop the plug-in
+ // About to stop the plug-in
event.old_state = plugin->state;
event.new_state = plugin->state = CP_PLUGIN_STOPPING;
cpi_deliver_event(context, &event);
-
- // Invoke stop function
+
+ // Invoke stop function
context->env->in_stop_func_invocation++;
plugin->runtime_funcs->stop(plugin->plugin_data);
context->env->in_stop_func_invocation--;
cpi_unregister_loggers(plugin->context->env->loggers, plugin);
// Unregister all plug-in listeners
- cpi_unregister_plisteners(plugin->context->env->plugin_listeners, plugin);
+ cpi_unregister_plisteners(plugin->context->env->plugin_listeners, plugin);
// Release resolved symbols
if (plugin->context->resolved_symbols != NULL) {
hscan_t scan;
hnode_t *node;
const void *ptr;
-
+
hash_scan_begin(&scan, plugin->context->resolved_symbols);
node = hash_scan_next(&scan);
ptr = hnode_getkey(node);
if (plugin->defined_symbols != NULL) {
hscan_t scan;
hnode_t *node;
-
+
hash_scan_begin(&scan, plugin->defined_symbols);
while ((node = hash_scan_next(&scan)) != NULL) {
char *n = (char *) hnode_getkey(node);
hash_destroy(plugin->defined_symbols);
plugin->defined_symbols = NULL;
}
-
+
}
-
- // Plug-in stopped
+
+ // Plug-in stopped
cpi_ptrset_remove(context->env->started_plugins, plugin);
event.old_state = plugin->state;
event.new_state = plugin->state = CP_PLUGIN_RESOLVED;
/**
* Stops the plug-in and all plug-ins depending on it.
- *
+ *
* @param context the plug-in context
* @param plugin the plug-in
*/
static void stop_plugin_rec(cp_context_t *context, cp_plugin_t *plugin) {
lnode_t *node;
-
+
// Check if already stopped
if (plugin->state < CP_PLUGIN_ACTIVE) {
return;
}
-
+
// Check for dependency loops
if (plugin->processed) {
return;
}
plugin->processed = 1;
-
+
// Stop the depending plug-ins
node = list_first(plugin->importing);
while (node != NULL) {
assert(plugin->state == CP_PLUGIN_ACTIVE);
stop_plugin_runtime(context, plugin);
assert(plugin->state < CP_PLUGIN_ACTIVE);
-
+
// Clear processed flag
plugin->processed = 0;
}
CHECK_NOT_NULL(context);
CHECK_NOT_NULL(id);
- // Look up and stop the plug-in
+ // Look up and stop the plug-in
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_ANY, __func__);
node = hash_lookup(context->env->plugins, id);
CP_C_API void cp_stop_plugins(cp_context_t *context) {
lnode_t *node;
-
+
CHECK_NOT_NULL(context);
-
- // Stop the active plug-ins in the reverse order they were started
+
+ // Stop the active plug-ins in the reverse order they were started
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_ANY, __func__);
while ((node = list_last(context->env->started_plugins)) != NULL) {
static void unresolve_plugin_rec(cp_context_t *context, cp_plugin_t *plugin) {
lnode_t *node;
cpi_plugin_event_t event;
-
+
// Check if already unresolved
if (plugin->state < CP_PLUGIN_RESOLVED) {
return;
}
assert(plugin->state == CP_PLUGIN_RESOLVED);
-
+
// Clear the list of imported plug-ins (also breaks dependency loops)
while ((node = list_first(plugin->imported)) != NULL) {
cp_plugin_t *ip = lnode_get(node);
-
+
cpi_ptrset_remove(ip->importing, plugin);
list_delete(plugin->imported, node);
lnode_destroy(node);
while ((node = list_first(plugin->importing)) != NULL) {
unresolve_plugin_rec(context, lnode_get(node));
}
-
+
// Unresolve this plug-in
unresolve_plugin_runtime(plugin);
event.plugin_id = plugin->plugin->identifier;
/**
* Unresolves a plug-in.
- *
+ *
* @param context the plug-in context
* @param plug-in the plug-in to be unresolved
*/
CP_HIDDEN void cpi_free_plugin(cp_plugin_info_t *plugin) {
int i;
-
+
assert(plugin != NULL);
free(plugin->name);
free(plugin->identifier);
/**
* Frees any memory allocated for a registered plug-in.
- *
+ *
* @param context the plug-in context
* @param plugin the plug-in to be freed
*/
// Release plug-in information
cpi_release_info(context, plugin->plugin);
- // Release data structures
+ // Release data structures
if (plugin->importing != NULL) {
assert(list_isempty(plugin->importing));
list_destroy(plugin->importing);
/**
* Uninstalls a plug-in associated with the specified hash node.
- *
+ *
* @param context the plug-in context
* @param node the hash node of the plug-in to be uninstalled
*/
static void uninstall_plugin(cp_context_t *context, hnode_t *node) {
cp_plugin_t *plugin;
cpi_plugin_event_t event;
-
- // Check if already uninstalled
+
+ // Check if already uninstalled
plugin = (cp_plugin_t *) hnode_get(node);
if (plugin->state <= CP_PLUGIN_UNINSTALLED) {
// TODO: Is this possible state?
return;
}
-
- // Make sure the plug-in is not in resolved state
+
+ // Make sure the plug-in is not in resolved state
unresolve_plugin(context, plugin);
assert(plugin->state == CP_PLUGIN_INSTALLED);
- // Plug-in uninstalled
+ // Plug-in uninstalled
event.plugin_id = plugin->plugin->identifier;
event.old_state = plugin->state;
event.new_state = plugin->state = CP_PLUGIN_UNINSTALLED;
cpi_deliver_event(context, &event);
-
+
// Unregister extension objects
unregister_extensions(context, plugin->plugin);
- // Unregister the plug-in
+ // Unregister the plug-in
hash_delete_free(context->env->plugins, node);
// Free the plug-in data structures
CHECK_NOT_NULL(context);
CHECK_NOT_NULL(id);
- // Look up and unload the plug-in
+ // Look up and unload the plug-in
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_ANY, __func__);
node = hash_lookup(context->env->plugins, id);
CP_C_API void cp_uninstall_plugins(cp_context_t *context) {
hscan_t scan;
hnode_t *node;
-
+
CHECK_NOT_NULL(context);
-
+
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_ANY, __func__);
cp_stop_plugins(context);
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
typedef struct info_resource_t {
/// Pointer to the resource
- void *resource;
+ void *resource;
/// Usage count for the resource
int usage_count;
-
+
/// Deallocation function
cpi_dealloc_func_t dealloc_func;
-
+
} info_resource_t;
/// A plug-in listener registration
typedef struct el_holder_t {
-
+
/// The plug-in listener
cp_plugin_listener_func_t plugin_listener;
-
+
/// The registering plug-in or NULL for the client program
cp_plugin_t *plugin;
-
+
/// Associated user data
void *user_data;
-
+
} el_holder_t;
break;
}
} while (0);
-
+
// Report success
if (status == CP_OK) {
cpi_debugf(context, _("An information object at address %p was registered."), res);
- }
-
+ }
+
// Release resources on failure
if (status != CP_OK) {
if (ir != NULL) {
free(ir);
}
}
-
+
return status;
}
CP_HIDDEN void cpi_use_info(cp_context_t *context, void *res) {
hnode_t *node;
-
+
assert(context != NULL);
assert(res != NULL);
assert(cpi_is_context_locked(context));
CP_HIDDEN void cpi_release_info(cp_context_t *context, void *info) {
hnode_t *node;
-
+
assert(context != NULL);
assert(info != NULL);
assert(cpi_is_context_locked(context));
CP_HIDDEN void cpi_release_infos(cp_context_t *context) {
hscan_t scan;
hnode_t *node;
-
+
hash_scan_begin(&scan, context->env->infos);
while ((node = hash_scan_next(&scan)) != NULL) {
- info_resource_t *ir = hnode_get(node);
+ info_resource_t *ir = hnode_get(node);
cpi_lock_context(context);
cpi_errorf(context, _("An unreleased information object was encountered at address %p with reference count %d when destroying the associated plug-in context. Not releasing the object."), ir->resource, ir->usage_count);
cpi_unlock_context(context);
cpi_fatalf(_("The plug-in identifier argument to cp_get_plugin_info must not be NULL when the main program calls it."));
}
- // Look up the plug-in and return information
+ // Look up the plug-in and return information
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_LOGGER, __func__);
do {
-
+
// Lookup plug-in information
if (id != NULL) {
if ((node = hash_lookup(context->env->plugins, id)) == NULL) {
static void dealloc_plugins_info(cp_context_t *context, cp_plugin_info_t **plugins) {
int i;
-
+
assert(context != NULL);
assert(plugins != NULL);
for (i = 0; plugins[i] != NULL; i++) {
cp_plugin_info_t **plugins = NULL;
int i, n;
cp_status_t status = CP_OK;
-
+
CHECK_NOT_NULL(context);
-
+
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_LOGGER, __func__);
do {
hscan_t scan;
hnode_t *node;
-
- // Allocate space for pointer array
+
+ // Allocate space for pointer array
n = hash_count(context->env->plugins);
if ((plugins = malloc(sizeof(cp_plugin_info_t *) * (n + 1))) == NULL) {
status = CP_ERR_RESOURCE;
break;
}
-
- // Get plug-in information structures
+
+ // Get plug-in information structures
hash_scan_begin(&scan, context->env->plugins);
i = 0;
while ((node = hash_scan_next(&scan)) != NULL) {
cp_plugin_t *rp = hnode_get(node);
-
+
assert(i < n);
cpi_use_info(context, rp->plugin);
plugins[i] = rp->plugin;
i++;
}
plugins[i] = NULL;
-
+
// Register the array
status = cpi_register_info(context, plugins, (void (*)(cp_context_t *, void *)) dealloc_plugins_info);
-
+
} while (0);
// Report error
}
cpi_unlock_context(context);
- // Release resources on error
+ // Release resources on error
if (status != CP_OK) {
if (plugins != NULL) {
dealloc_plugins_info(context, plugins);
plugins = NULL;
}
}
-
+
assert(status != CP_OK || n == 0 || plugins[n - 1] != NULL);
if (error != NULL) {
*error = status;
CP_C_API cp_plugin_state_t cp_get_plugin_state(cp_context_t *context, const char *id) {
cp_plugin_state_t state = CP_PLUGIN_UNINSTALLED;
hnode_t *hnode;
-
+
CHECK_NOT_NULL(context);
CHECK_NOT_NULL(id);
-
- // Look up the plug-in state
+
+ // Look up the plug-in state
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_LOGGER, __func__);
if ((hnode = hash_lookup(context->env->plugins, id)) != NULL) {
static void dealloc_ext_points_info(cp_context_t *context, cp_ext_point_t **ext_points) {
int i;
-
+
assert(context != NULL);
assert(ext_points != NULL);
for (i = 0; ext_points[i] != NULL; i++) {
cp_ext_point_t **ext_points = NULL;
int i, n;
cp_status_t status = CP_OK;
-
+
CHECK_NOT_NULL(context);
-
+
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_LOGGER, __func__);
do {
hscan_t scan;
hnode_t *node;
-
- // Allocate space for pointer array
+
+ // Allocate space for pointer array
n = hash_count(context->env->ext_points);
if ((ext_points = malloc(sizeof(cp_ext_point_t *) * (n + 1))) == NULL) {
status = CP_ERR_RESOURCE;
break;
}
-
- // Get extension point information structures
+
+ // Get extension point information structures
hash_scan_begin(&scan, context->env->ext_points);
i = 0;
while ((node = hash_scan_next(&scan)) != NULL) {
cp_ext_point_t *ep = hnode_get(node);
-
+
assert(i < n);
cpi_use_info(context, ep->plugin);
ext_points[i] = ep;
i++;
}
ext_points[i] = NULL;
-
+
// Register the array
status = cpi_register_info(context, ext_points, (void (*)(cp_context_t *, void *)) dealloc_ext_points_info);
-
+
} while (0);
-
+
// Report error
if (status != CP_OK) {
cpi_error(context, N_("Extension point information could not be returned due to insufficient memory."));
}
cpi_unlock_context(context);
-
- // Release resources on error
+
+ // Release resources on error
if (status != CP_OK) {
if (ext_points != NULL) {
dealloc_ext_points_info(context, ext_points);
ext_points = NULL;
}
}
-
+
assert(status != CP_OK || n == 0 || ext_points[n - 1] != NULL);
if (error != NULL) {
*error = status;
static void dealloc_extensions_info(cp_context_t *context, cp_extension_t **extensions) {
int i;
-
+
assert(context != NULL);
assert(extensions != NULL);
for (i = 0; extensions[i] != NULL; i++) {
cp_extension_t **extensions = NULL;
int i, n;
cp_status_t status = CP_OK;
-
+
CHECK_NOT_NULL(context);
-
+
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_LOGGER, __func__);
do {
}
} else {
hscan_t scan;
-
+
n = 0;
hash_scan_begin(&scan, context->env->extensions);
while ((hnode = hash_scan_next(&scan)) != NULL) {
n += list_count((list_t *) hnode_get(hnode));
}
}
-
- // Allocate space for pointer array
+
+ // Allocate space for pointer array
if ((extensions = malloc(sizeof(cp_extension_t *) * (n + 1))) == NULL) {
status = CP_ERR_RESOURCE;
break;
}
-
+
// Get extension information structures
if (extpt_id != NULL) {
i = 0;
if ((hnode = hash_lookup(context->env->extensions, extpt_id)) != NULL) {
list_t *el = hnode_get(hnode);
lnode_t *lnode;
-
+
lnode = list_first(el);
while (lnode != NULL) {
cp_extension_t *e = lnode_get(lnode);
-
+
assert(i < n);
cpi_use_info(context, e->plugin);
extensions[i] = e;
}
}
extensions[i] = NULL;
- } else {
+ } else {
hash_scan_begin(&scan, context->env->extensions);
i = 0;
while ((hnode = hash_scan_next(&scan)) != NULL) {
list_t *el = hnode_get(hnode);
lnode_t *lnode;
-
+
lnode = list_first(el);
while (lnode != NULL) {
cp_extension_t *e = lnode_get(lnode);
-
+
assert(i < n);
cpi_use_info(context, e->plugin);
extensions[i] = e;
}
}
extensions[i] = NULL;
-
+
// Register the array
status = cpi_register_info(context, extensions, (void (*)(cp_context_t *, void *)) dealloc_extensions_info);
-
+
} while (0);
-
+
// Report error
if (status != CP_OK) {
cpi_error(context, N_("Extension information could not be returned due to insufficient memory."));
}
cpi_unlock_context(context);
-
- // Release resources on error
+
+ // Release resources on error
if (status != CP_OK) {
if (extensions != NULL) {
dealloc_extensions_info(context, extensions);
extensions = NULL;
}
}
-
+
assert(status != CP_OK || n == 0 || extensions[n - 1] != NULL);
if (error != NULL) {
*error = status;
}
-// Plug-in listeners
+// Plug-in listeners
/**
* Compares plug-in listener holders.
- *
+ *
* @param h1 the first holder to be compared
* @param h2 the second holder to be compared
* @return zero if the holders point to the same function, otherwise non-zero
static int comp_el_holder(const void *h1, const void *h2) {
const el_holder_t *plh1 = h1;
const el_holder_t *plh2 = h2;
-
+
return (plh1->plugin_listener != plh2->plugin_listener);
}
/**
* Processes a node by delivering the specified event to the associated
* plug-in listener.
- *
+ *
* @param list the list being processed
* @param node the node being processed
* @param event the event
/**
* Processes a node by unregistering the associated plug-in listener.
- *
+ *
* @param list the list being processed
* @param node the node being processed
* @param plugin plugin whose listeners are to be unregistered or NULL for all
CHECK_NOT_NULL(context);
CHECK_NOT_NULL(listener);
-
+
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_LOGGER | CPI_CF_LISTENER, __func__);
if ((holder = malloc(sizeof(el_holder_t))) != NULL) {
free(holder);
}
}
-
+
// Report error or success
if (status != CP_OK) {
cpi_error(context, _("A plug-in listener could not be registered due to insufficient memory."));
cpi_debugf(context, N_("%s registered a plug-in listener."), cpi_context_owner(context, owner, sizeof(owner)));
}
cpi_unlock_context(context);
-
+
return status;
}
CP_C_API void cp_unregister_plistener(cp_context_t *context, cp_plugin_listener_func_t listener) {
el_holder_t holder;
lnode_t *node;
-
+
CHECK_NOT_NULL(context);
holder.plugin_listener = listener;
cpi_lock_context(context);
static cp_cfg_element_t * lookup_cfg_element(cp_cfg_element_t *base, const char *path, int len) {
int start = 0;
-
+
CHECK_NOT_NULL(base);
CHECK_NOT_NULL(path);
-
+
// Traverse the path
while (base != NULL && path[start] != '\0' && (len == -1 || start < len)) {
int end = start;
} else {
int i;
int found = 0;
-
+
for (i = 0; !found && i < base->num_children; i++) {
cp_cfg_element_t *e = base->children + i;
if (end - start == strlen(e->name)
CP_C_API char * cp_lookup_cfg_value(cp_cfg_element_t *base, const char *path) {
cp_cfg_element_t *e;
const char *attr;
-
+
CHECK_NOT_NULL(base);
CHECK_NOT_NULL(path);
-
+
if ((attr = strrchr(path, '@')) == NULL) {
e = lookup_cfg_element(base, path, -1);
} else {
return e->value;
} else {
int i;
-
+
for (i = 0; i < e->num_atts; i++) {
if (!strcmp(attr, e->atts[2*i])) {
return e->atts[2*i + 1];
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* Constants
* ----------------------------------------------------------------------*/
-/// XML parser buffer size (in bytes)
+/// XML parser buffer size (in bytes)
#define CP_XML_PARSER_BUFFER_SIZE 4096
-/// Initial configuration element value size
+/// Initial configuration element value size
#define CP_CFG_ELEMENT_VALUE_INITSIZE 64
-/// Plugin descriptor name
+/// Plugin descriptor name
#define CP_PLUGIN_DESCRIPTOR "plugin.xml"
typedef struct ploader_context_t ploader_context_t;
-/// Parser states
+/// Parser states
typedef enum parser_state_t {
PARSER_BEGIN,
PARSER_PLUGIN,
PARSER_ERROR
} parser_state_t;
-/// Plug-in loader context
+/// Plug-in loader context
struct ploader_context_t {
/// The plug-in context, or NULL if none
cp_context_t *context;
- /// The XML parser being used
+ /// The XML parser being used
XML_Parser parser;
-
- /// The file being parsed
+
+ /// The file being parsed
char *file;
-
- /// The plug-in being constructed
+
+ /// The plug-in being constructed
cp_plugin_info_t *plugin;
-
- /// The configuration element being constructed
+
+ /// The configuration element being constructed
cp_cfg_element_t *configuration;
-
- /// The current parser state
+
+ /// The current parser state
parser_state_t state;
-
- /// The saved parser state (used in PARSER_UNKNOWN)
+
+ /// The saved parser state (used in PARSER_UNKNOWN)
parser_state_t saved_state;
-
+
/**
* The current parser depth (used in PARSER_UNKNOWN and PARSER_EXTENSION)
*/
unsigned int depth;
-
- /// The number of skipped configuration elements
+
+ /// The number of skipped configuration elements
unsigned int skippedCEs;
- /// Size of allocated imports table
+ /// Size of allocated imports table
size_t imports_size;
-
- /// Size of allocated extension points table
+
+ /// Size of allocated extension points table
size_t ext_points_size;
-
- /// Size of allocated extensions table
+
+ /// Size of allocated extensions table
size_t extensions_size;
-
- /// Buffer for a value being read
+
+ /// Buffer for a value being read
char *value;
-
- /// Size of allocated value field
+
+ /// Size of allocated value field
size_t value_size;
-
- /// Current length of value string
+
+ /// Current length of value string
size_t value_length;
-
- /// The number of parsing errors that have occurred
+
+ /// The number of parsing errors that have occurred
unsigned int error_count;
-
- /// The number of resource errors that have occurred
+
+ /// The number of resource errors that have occurred
unsigned int resource_error_count;
};
/**
* Reports a descriptor error. Does not set the parser to error state but
* increments the error count, unless this is merely a warning.
- *
+ *
* @param context the parsing context
* @param warn whether this is only a warning
* @param error_msg the error message
XML_GetCurrentLineNumber(plcontext->parser),
XML_GetCurrentColumnNumber(plcontext->parser) + 1,
message);
- } else {
+ } else {
cpi_errorf(plcontext->context,
N_("Invalid plug-in descriptor content in %s, line %d, column %d (%s)."),
plcontext->file,
/**
* Reports insufficient system resources while parsing and increments the
* resource error count.
- *
+ *
* @param context the parsing context
*/
static void resource_error(ploader_context_t *plcontext) {
/**
* Returns whether the specified NULL-terminated list of strings includes
* the specified string.
- *
+ *
* @param list the NULL-terminated list of strings, or NULL if none
* @param str the string
* @param step the stepping (1 to check every string or 2 to check every
/**
* Checks that an element has non-empty values for required attributes.
* Increments the error count for each missing attribute.
- *
+ *
* @param context the parsing context
* @param elem the element being checked
* @param atts the attribute list for the element
const XML_Char * const *req_atts) {
const XML_Char * const *a;
int error = 0;
-
- // Check that required attributes have non-empty values
+
+ // Check that required attributes have non-empty values
for (a = req_atts; a != NULL && *a != NULL; a++) {
const XML_Char * const *av;
-
+
if ((av = contains_str(atts, *a, 2)) != NULL) {
if ((*(av + 1))[0] == '\0') {
descriptor_errorf(plcontext, 0,
error = 1;
}
}
-
+
return !error;
}
* Checks that an element has non-empty values for required attributes and
* warns if there are unknown attributes. Increments the error count for
* each missing required attribute.
- *
+ *
* @param context the parsing context
* @param elem the element being checked
* @param atts the attribute list for the element
const XML_Char *elem, const XML_Char * const *atts,
const XML_Char * const *req_atts, const XML_Char * const *opt_atts) {
int error = 0;
-
+
// Check required attributes
error = !check_req_attributes(plcontext, elem, atts, req_atts);
-
- // Warn if there are unknown attributes
+
+ // Warn if there are unknown attributes
for (; *atts != NULL; atts += 2) {
if (contains_str(req_atts, *atts, 1) == NULL
&& contains_str(opt_atts, *atts, 1) == NULL) {
*atts, elem);
}
}
-
+
return !error;
}
/**
* Allocates memory using malloc. Reports a resource error if there is not
* enough available memory.
- *
+ *
* @param context the parsing context
* @param size the number of bytes to allocate
* @return pointer to the allocated memory, or NULL if memory allocation failed
/**
* Makes a copy of the specified string. The memory is allocated using malloc.
* Reports a resource error if there is not enough available memory.
- *
+ *
* @param context the parsing context
* @param src the source string to be copied
* @return copy of the string, or NULL if memory allocation failed
* Concatenates the specified strings into a new string. The memory for the concatenated
* string is allocated using malloc. Reports a resource error if there is not
* enough available memory.
- *
+ *
* @param context the parsing context
* @param ... the strings to be concatenated, terminated by NULL
* @return the concatenated string, or NULL if memory allocation failed
const char *str;
char *dst;
size_t len;
-
- // Calculate the length of the concatenated string
+
+ // Calculate the length of the concatenated string
va_start(ap, plcontext);
len = 0;
while ((str = va_arg(ap, const char *)) != NULL) {
len += strlen(str);
}
va_end(ap);
-
- // Allocate space for the concatenated string
+
+ // Allocate space for the concatenated string
if ((dst = parser_malloc(plcontext, sizeof(char) * (len + 1))) == NULL) {
return NULL;
}
-
- // Copy the strings
+
+ // Copy the strings
len = 0;
va_start(ap, plcontext);
while ((str = va_arg(ap, const char *)) != NULL) {
/**
* Puts the parser to a state in which it skips an unknown element.
* Warns error handlers about the unknown element.
- *
+ *
* @param context the parsing context
* @param elem the element name
*/
/**
* Creates a copy of the specified attributes. Reports failed memory
* allocation.
- *
+ *
* @param context the parser context
* @param src the source attributes to be copied
* @param num pointer to the location where number of attributes is stored,
unsigned int i;
unsigned int num;
size_t attr_size;
-
- // Calculate the number of attributes and the amount of space required
+
+ // Calculate the number of attributes and the amount of space required
for (num = 0, attr_size = 0; src[num] != NULL; num++) {
attr_size += strlen(src[num]) + 1;
}
assert((num & 1) == 0);
-
- // Allocate necessary memory and copy attribute data
+
+ // Allocate necessary memory and copy attribute data
if (num > 0) {
if ((atts = parser_malloc(plcontext, num * sizeof(char *))) != NULL) {
if ((attr_data = parser_malloc(plcontext, attr_size * sizeof(char))) != NULL) {
size_t offset;
-
+
for (i = 0, offset = 0; i < num; i++) {
strcpy(attr_data + offset, src[i]);
atts[i] = attr_data + offset;
}
}
}
-
- // If successful then return duplicates, otherwise free any allocations
+
+ // If successful then return duplicates, otherwise free any allocations
if (num == 0 || (atts != NULL && attr_data != NULL)) {
if (num_atts != NULL) {
*num_atts = num / 2;
/**
* Initializes a configuration element. Reports an error if memory allocation fails.
- *
+ *
* @param context the parser context
* @param ce the configuration element to be initialized
* @param name the element name
*/
static void init_cfg_element(ploader_context_t *plcontext, cp_cfg_element_t *ce,
const XML_Char *name, const XML_Char * const *atts, cp_cfg_element_t *parent) {
-
- // Initialize the configuration element
+
+ // Initialize the configuration element
memset(ce, 0, sizeof(cp_cfg_element_t));
ce->name = parser_strdup(plcontext, name);
ce->atts = parser_attsdup(plcontext, atts, &(ce->num_atts));
plcontext->value_size = 0;
plcontext->value_length = 0;
ce->parent = parent;
- ce->children = NULL;
+ ce->children = NULL;
}
/**
* Processes the character data while parsing.
- *
+ *
* @param userData the parsing context
* @param str the string data
* @param len the string length
static void CP_XMLCALL character_data_handler(
void *userData, const XML_Char *str, int len) {
ploader_context_t *plcontext = userData;
-
- // Ignore leading whitespace
+
+ // Ignore leading whitespace
if (plcontext->value == NULL) {
int i;
-
+
for (i = 0; i < len; i++) {
if (str[i] != ' ' && str[i] != '\n' && str[i] != '\r' && str[i] != '\t') {
break;
return;
}
}
-
- // Allocate more memory for the character data if needed
+
+ // Allocate more memory for the character data if needed
if (plcontext->value_length + len >= plcontext->value_size) {
size_t ns;
char *nv;
ns = plcontext->value_size;
- while (plcontext->value_length + len >= ns) {
+ while (plcontext->value_length + len >= ns) {
if (ns == 0) {
ns = CP_CFG_ELEMENT_VALUE_INITSIZE;
} else {
return;
}
}
-
- // Copy character data
+
+ // Copy character data
strncpy(plcontext->value + plcontext->value_length, str, len * sizeof(char));
plcontext->value_length += len;
}
/**
* Processes the start of element events while parsing.
- *
+ *
* @param userData the parsing context
* @param name the element name
* @param atts the element attributes
ploader_context_t *plcontext = userData;
unsigned int i;
- // Process element start
+ // Process element start
switch (plcontext->state) {
case PARSER_BEGIN:
if (check_attributes(plcontext, name, atts,
req_ext_point_atts, opt_ext_point_atts)) {
cp_ext_point_t *ext_point;
-
- // Allocate space for extension points, if necessary
+
+ // Allocate space for extension points, if necessary
if (plcontext->plugin->num_ext_points == plcontext->ext_points_size) {
cp_ext_point_t *nep;
size_t ns;
-
+
if (plcontext->ext_points_size == 0) {
ns = 4;
} else {
plcontext->plugin->ext_points = nep;
plcontext->ext_points_size = ns;
}
-
- // Parse extension point specification
+
+ // Parse extension point specification
ext_point = plcontext->plugin->ext_points
+ plcontext->plugin->num_ext_points;
memset(ext_point, 0, sizeof(cp_ext_point_t));
}
}
plcontext->plugin->num_ext_points++;
-
+
}
} else if (!(strcmp(name, "extension"))) {
plcontext->state = PARSER_EXTENSION;
if (check_req_attributes(
plcontext, name, atts, req_extension_atts)) {
cp_extension_t *extension;
-
- // Allocate space for extensions, if necessary
+
+ // Allocate space for extensions, if necessary
if (plcontext->plugin->num_extensions == plcontext->extensions_size) {
cp_extension_t *ne;
size_t ns;
-
+
if (plcontext->extensions_size == 0) {
ns = 16;
} else {
plcontext->plugin->extensions = ne;
plcontext->extensions_size = ns;
}
-
- // Parse extension attributes
+
+ // Parse extension attributes
extension = plcontext->plugin->extensions
+ plcontext->plugin->num_extensions;
memset(extension, 0, sizeof(cp_extension_t));
}
}
plcontext->plugin->num_extensions++;
-
- // Initialize configuration parsing
+
+ // Initialize configuration parsing
if ((extension->configuration = plcontext->configuration
= parser_malloc(plcontext, sizeof(cp_cfg_element_t))) != NULL) {
init_cfg_element(plcontext, plcontext->configuration, name, atts, NULL);
if (check_attributes(plcontext, name, atts,
req_import_atts, opt_import_atts)) {
cp_plugin_import_t *import = NULL;
-
- // Allocate space for imports, if necessary
+
+ // Allocate space for imports, if necessary
if (plcontext->plugin->num_imports == plcontext->imports_size) {
cp_plugin_import_t *ni;
size_t ns;
-
+
if (plcontext->imports_size == 0) {
ns = 16;
} else {
plcontext->plugin->imports = ni;
plcontext->imports_size = ns;
}
-
- // Parse import specification
+
+ // Parse import specification
import = plcontext->plugin->imports
+ plcontext->plugin->num_imports;
memset(import, 0, sizeof(cp_plugin_import_t));
plcontext->depth++;
if (plcontext->configuration != NULL && plcontext->skippedCEs == 0) {
cp_cfg_element_t *ce;
-
- // Allocate more space for children, if necessary
+
+ // Allocate more space for children, if necessary
if (plcontext->configuration->num_children == plcontext->configuration->index) {
cp_cfg_element_t *nce;
size_t ns;
-
+
if (plcontext->configuration->index == 0) {
ns = 16;
} else {
plcontext->configuration->children = nce;
plcontext->configuration->index = ns;
}
-
- // Save possible value
+
+ // Save possible value
if (plcontext->value != NULL) {
plcontext->value[plcontext->value_length] = '\0';
plcontext->configuration->value = plcontext->value;
}
-
+
ce = plcontext->configuration->children + plcontext->configuration->num_children;
init_cfg_element(plcontext, ce, name, atts, plcontext->configuration);
plcontext->configuration->num_children++;
plcontext->configuration = ce;
}
break;
-
+
case PARSER_UNKNOWN:
plcontext->depth++;
break;
/**
* Processes the end of element events while parsing.
- *
+ *
* @param context the parsing context
* @param name the element name
*/
static void CP_XMLCALL end_element_handler(
void *userData, const XML_Char *name) {
ploader_context_t *plcontext = userData;
-
- // Process element end
+
+ // Process element end
switch (plcontext->state) {
case PARSER_PLUGIN:
if (!strcmp(name, "plugin")) {
-
- // Readjust memory allocated for extension points, if necessary
+
+ // Readjust memory allocated for extension points, if necessary
if (plcontext->ext_points_size != plcontext->plugin->num_ext_points) {
cp_ext_point_t *nep;
-
+
if ((nep = realloc(plcontext->plugin->ext_points,
plcontext->plugin->num_ext_points *
sizeof(cp_ext_point_t))) != NULL
plcontext->ext_points_size = plcontext->plugin->num_ext_points;
}
}
-
- // Readjust memory allocated for extensions, if necessary
+
+ // Readjust memory allocated for extensions, if necessary
if (plcontext->extensions_size != plcontext->plugin->num_extensions) {
cp_extension_t *ne;
-
+
if ((ne = realloc(plcontext->plugin->extensions,
plcontext->plugin->num_extensions *
sizeof(cp_extension_t))) != NULL
|| plcontext->plugin->num_extensions == 0) {
plcontext->plugin->extensions = ne;
plcontext->extensions_size = plcontext->plugin->num_extensions;
- }
+ }
}
-
+
plcontext->state = PARSER_END;
}
break;
case PARSER_REQUIRES:
if (!strcmp(name, "requires")) {
-
- // Readjust memory allocated for imports, if necessary
+
+ // Readjust memory allocated for imports, if necessary
if (plcontext->imports_size != plcontext->plugin->num_imports) {
cp_plugin_import_t *ni;
-
+
if ((ni = realloc(plcontext->plugin->imports,
plcontext->plugin->num_imports *
sizeof(cp_plugin_import_t))) != NULL
plcontext->imports_size = plcontext->plugin->num_imports;
}
}
-
+
plcontext->state = PARSER_PLUGIN;
}
break;
if (plcontext->skippedCEs > 0) {
plcontext->skippedCEs--;
} else if (plcontext->configuration != NULL) {
-
- // Readjust memory allocated for children, if necessary
+
+ // Readjust memory allocated for children, if necessary
if (plcontext->configuration->index != plcontext->configuration->num_children) {
cp_cfg_element_t *nce;
-
+
if ((nce = realloc(plcontext->configuration->children,
plcontext->configuration->num_children *
sizeof(cp_cfg_element_t))) != NULL
plcontext->configuration->children = nce;
}
}
-
+
if (plcontext->configuration->parent != NULL) {
plcontext->configuration->index = plcontext->configuration->parent->num_children - 1;
} else {
if (plcontext->value != NULL) {
char *v = plcontext->value;
int i;
-
- // Ignore trailing whitespace
+
+ // Ignore trailing whitespace
for (i = plcontext->value_length - 1; i >= 0; i--) {
if (v[i] != ' ' && v[i] != '\n' && v[i] != '\r' && v[i] != '\t') {
break;
}
}
if (plcontext->value != NULL) {
-
- // Readjust memory allocated for value, if necessary
+
+ // Readjust memory allocated for value, if necessary
if (plcontext->value_size > plcontext->value_length + 1) {
char *nv;
-
+
if ((nv = realloc(plcontext->value, (plcontext->value_length + 1) * sizeof(char))) != NULL) {
plcontext->value = nv;
}
}
-
+
plcontext->value[plcontext->value_length] = '\0';
plcontext->configuration->value = plcontext->value;
plcontext->value = NULL;
plcontext->value_length = 0;
}
plcontext->configuration = plcontext->configuration->parent;
-
- // Restore possible value
+
+ // Restore possible value
if (plcontext->configuration != NULL
&& plcontext->configuration->value != NULL) {
plcontext->value = plcontext->configuration->value;
plcontext->value_size *= 2;
}
}
-
- }
+
+ }
if (plcontext->depth-- == 0) {
assert(!strcmp(name, "extension"));
plcontext->state = PARSER_PLUGIN;
XML_SetCharacterDataHandler(plcontext->parser, NULL);
}
break;
-
+
default:
descriptor_errorf(plcontext, 0, _("unexpected closing tag for %s"),
name);
do {
int path_len;
- // Construct the file name for the plug-in descriptor
+ // Construct the file name for the plug-in descriptor
path_len = strlen(path);
if (path_len == 0) {
status = CP_ERR_IO;
file[path_len] = CP_FNAMESEP_CHAR;
strcpy(file + path_len + 1, CP_PLUGIN_DESCRIPTOR);
- // Open the file
+ // Open the file
if ((fh = fopen(file, "rb")) == NULL) {
status = CP_ERR_IO;
break;
}
- // Initialize the XML parsing
+ // Initialize the XML parsing
parser = XML_ParserCreate(NULL);
if (parser == NULL) {
status = CP_ERR_RESOURCE;
XML_SetElementHandler(parser,
start_element_handler,
end_element_handler);
-
- // Initialize the parsing context
+
+ // Initialize the parsing context
if ((plcontext = malloc(sizeof(ploader_context_t))) == NULL) {
status = CP_ERR_RESOURCE;
break;
plcontext->plugin->resourcetype = NULL;
XML_SetUserData(parser, plcontext);
- // Parse the plug-in descriptor
+ // Parse the plug-in descriptor
while (1) {
int bytes_read;
void *xml_buffer;
int i;
-
- // Get buffer from Expat
+
+ // Get buffer from Expat
if ((xml_buffer = XML_GetBuffer(parser, CP_XML_PARSER_BUFFER_SIZE))
== NULL) {
status = CP_ERR_RESOURCE;
break;
}
-
- // Read data into buffer
+
+ // Read data into buffer
bytes_read = fread(xml_buffer, 1, CP_XML_PARSER_BUFFER_SIZE, fh);
if (ferror(fh)) {
status = CP_ERR_IO;
break;
}
- // Parse the data
+ // Parse the data
if (!(i = XML_ParseBuffer(parser, bytes_read, bytes_read == 0))
&& context != NULL) {
cpi_lock_context(context);
status = CP_ERR_MALFORMED;
break;
}
-
+
if (bytes_read == 0) {
break;
}
break;
}
- // Initialize the plug-in path
+ // Initialize the plug-in path
*(file + path_len) = '\0';
plcontext->plugin->plugin_path = file;
file = NULL;
-
+
// Increase plug-in usage count
if ((status = cpi_register_info(context, plcontext->plugin, (void (*)(cp_context_t *, void *)) dealloc_plugin_info)) != CP_OK) {
break;
}
-
+
} while (0);
// Report possible errors
}
cpi_unlock_context(context);
- // Release persistently allocated data on failure
+ // Release persistently allocated data on failure
if (status != CP_OK) {
if (file != NULL) {
free(file);
plcontext->plugin = NULL;
}
}
-
+
// Otherwise copy the plug-in pointer
else {
plugin = plcontext->plugin;
}
- // Release data allocated for parsing
+ // Release data allocated for parsing
if (parser != NULL) {
XML_ParserFree(parser);
}
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
int pdir_path_size = 0;
int plugins_stopped = 0;
cp_status_t status = CP_OK;
-
+
CHECK_NOT_NULL(context);
-
+
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_ANY, __func__);
cpi_debug(context, N_("Plug-in scan is starting."));
lnode_t *lnode;
hscan_t hscan;
hnode_t *hnode;
-
- // Create a hash for available plug-ins
+
+ // Create a hash for available plug-ins
if ((avail_plugins = hash_create(HASHCOUNT_T_MAX, (int (*)(const void *, const void *)) strcmp, NULL)) == NULL) {
status = CP_ERR_RESOURCE;
break;
}
-
- // Scan plug-in directories for available plug-ins
+
+ // Scan plug-in directories for available plug-ins
lnode = list_first(context->env->plugin_dirs);
while (lnode != NULL) {
const char *dir_path;
DIR *dir;
-
+
dir_path = lnode_get(lnode);
dir = opendir(dir_path);
if (dir != NULL) {
int dir_path_len;
struct dirent *de;
-
+
dir_path_len = strlen(dir_path);
if (dir_path[dir_path_len - 1] == CP_FNAMESEP_CHAR) {
dir_path_len--;
cp_status_t s;
hnode_t *hnode;
- // Allocate memory for plug-in descriptor path
+ // Allocate memory for plug-in descriptor path
if (pdir_path_size <= pdir_path_len) {
char *new_pdir_path;
-
+
if (pdir_path_size == 0) {
pdir_path_size = 128;
}
if (new_pdir_path == NULL) {
cpi_errorf(context, N_("Could not check possible plug-in location %s%c%s due to insufficient system resources."), dir_path, CP_FNAMESEP_CHAR, de->d_name);
status = CP_ERR_RESOURCE;
- // continue loading plug-ins from other directories
+ // continue loading plug-ins from other directories
continue;
}
pdir_path = new_pdir_path;
}
-
- // Construct plug-in descriptor path
+
+ // Construct plug-in descriptor path
strcpy(pdir_path, dir_path);
pdir_path[dir_path_len] = CP_FNAMESEP_CHAR;
strcpy(pdir_path + dir_path_len + 1, de->d_name);
-
- // Try to load a plug-in
+
+ // Try to load a plug-in
plugin = cp_load_plugin_descriptor(context, pdir_path, &s);
if (plugin == NULL) {
status = s;
- // continue loading plug-ins from other directories
+ // continue loading plug-ins from other directories
continue;
}
-
- // Insert plug-in to the list of available plug-ins
+
+ // Insert plug-in to the list of available plug-ins
if ((hnode = hash_lookup(avail_plugins, plugin->identifier)) != NULL) {
cp_plugin_info_t *plugin2 = hnode_get(hnode);
if (cpi_vercmp(plugin->version, plugin2->version) > 0) {
cpi_errorf(context, N_("Plug-in %s version %s could not be loaded due to insufficient system resources."), plugin->identifier, plugin->version);
cp_release_info(context, plugin);
status = CP_ERR_RESOURCE;
- // continue loading plug-ins from other directories
+ // continue loading plug-ins from other directories
continue;
}
}
-
+
}
errno = 0;
}
if (errno) {
cpi_errorf(context, N_("Could not read plug-in directory %s: %s"), dir_path, strerror(errno));
status = CP_ERR_IO;
- // continue loading plug-ins from other directories
+ // continue loading plug-ins from other directories
}
closedir(dir);
} else {
cpi_errorf(context, N_("Could not open plug-in directory %s: %s"), dir_path, strerror(errno));
status = CP_ERR_IO;
- // continue loading plug-ins from other directories
+ // continue loading plug-ins from other directories
}
-
+
lnode = list_next(context->env->plugin_dirs, lnode);
}
-
- // Copy the list of started plug-ins, if necessary
+
+ // Copy the list of started plug-ins, if necessary
if ((flags & CP_SP_RESTART_ACTIVE)
&& (flags & (CP_SP_UPGRADE | CP_SP_STOP_ALL_ON_INSTALL))) {
int i;
}
for (i = 0; plugins[i] != NULL; i++) {
cp_plugin_state_t state;
-
+
state = cp_get_plugin_state(context, plugins[i]->identifier);
if (state == CP_PLUGIN_STARTING || state == CP_PLUGIN_ACTIVE) {
char *pid;
-
+
if ((pid = strdup(plugins[i]->identifier)) == NULL) {
status = CP_ERR_RESOURCE;
break;
cpi_release_info(context, plugins);
plugins = NULL;
}
-
- // Install/upgrade plug-ins
+
+ // Install/upgrade plug-ins
hash_scan_begin(&hscan, avail_plugins);
while ((hnode = hash_scan_next(&hscan)) != NULL) {
cp_plugin_info_t *plugin;
cp_plugin_t *ip = NULL;
hnode_t *hn2;
int s;
-
+
plugin = hnode_get(hnode);
hn2 = hash_lookup(context->env->plugins, plugin->identifier);
if (hn2 != NULL) {
ip = hnode_get(hn2);
}
-
- // Unload the installed plug-in if it is to be upgraded
+
+ // Unload the installed plug-in if it is to be upgraded
if (ip != NULL
&& (flags & CP_SP_UPGRADE)
&& ((ip->plugin->version == NULL && plugin->version != NULL)
assert(s == CP_OK);
ip = NULL;
}
-
- // Install the plug-in, if to be installed
+
+ // Install the plug-in, if to be installed
if (ip == NULL) {
if ((flags & CP_SP_STOP_ALL_ON_INSTALL) && !plugins_stopped) {
plugins_stopped = 1;
break;
}
}
-
+
// Remove the plug-in from the hash
hash_scan_delfree(avail_plugins, hnode);
cp_release_info(context, plugin);
}
-
- // Restart stopped plug-ins if necessary
+
+ // Restart stopped plug-ins if necessary
if (started_plugins != NULL) {
lnode = list_first(started_plugins);
while (lnode != NULL) {
char *pid;
int s;
-
+
pid = lnode_get(lnode);
s = cp_start_plugin(context, pid);
if (s != CP_OK) {
lnode = list_next(started_plugins, lnode);
}
}
-
+
} while (0);
// Report error
break;
}
cpi_unlock_context(context);
-
- // Release resources
+
+ // Release resources
if (pdir_path != NULL) {
free(pdir_path);
}
if (avail_plugins != NULL) {
hscan_t hscan;
hnode_t *hnode;
-
+
hash_scan_begin(&hscan, avail_plugins);
while ((hnode = hash_scan_next(&hscan)) != NULL) {
cp_plugin_info_t *p = hnode_get(hnode);
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
/// Information about symbol providing plug-in
typedef struct symbol_provider_info_t {
-
+
// The providing plug-in
cp_plugin_t *plugin;
-
+
// Whether there is also an import dependency for the plug-in
int imported;
-
+
// Total symbol usage count
int usage_count;
-
+
} symbol_provider_info_t;
/// Information about used symbol
// Symbol usage count
int usage_count;
-
+
// Information about providing plug-in
symbol_provider_info_t *provider_info;
-
+
} symbol_info_t;
CP_C_API cp_status_t cp_define_symbol(cp_context_t *context, const char *name, void *ptr) {
cp_status_t status = CP_OK;
-
+
CHECK_NOT_NULL(context);
CHECK_NOT_NULL(name);
// CHECK_NOT_NULL(ptr);
if (context->plugin == NULL) {
cpi_fatalf(_("Only plug-ins can define context specific symbols."));
}
-
+
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_LOGGER | CPI_CF_LISTENER, __func__);
do {
char *n;
-
+
// Create a symbol hash if necessary
if (context->plugin->defined_symbols == NULL) {
if ((context->plugin->defined_symbols = hash_create(HASHCOUNT_T_MAX, (int (*)(const void *, const void *)) strcmp, NULL)) == NULL) {
break;
}
}
-
+
// Check for a previously defined symbol
if (hash_lookup(context->plugin->defined_symbols, name) != NULL) {
status = CP_ERR_CONFLICT;
free(n);
status = CP_ERR_RESOURCE;
break;
- }
+ }
} while (0);
-
+
// Report error
if (status != CP_OK) {
switch (status) {
}
}
cpi_unlock_context(context);
-
+
return status;
}
CHECK_NOT_NULL(context);
CHECK_NOT_NULL(id);
CHECK_NOT_NULL(name);
-
+
// Resolve the symbol
cpi_lock_context(context);
cpi_check_invocation(context, CPI_CF_LOGGER | CPI_CF_LISTENER | CPI_CF_STOP, __func__);
break;
}
}
-
+
// Lookup or initialize symbol information
if ((node = hash_lookup(context->resolved_symbols, symbol)) != NULL) {
symbol_info = hnode_get(node);
break;
}
}
-
+
// Add dependencies (for plug-in)
if (provider_info != NULL
&& !provider_info->imported
}
cpi_debugf(context, "A dynamic dependency was created from plug-in %s to plug-in %s.", context->plugin->plugin->identifier, pp->plugin->identifier);
}
-
+
// Increase usage counts
symbol_info->usage_count++;
provider_info->usage_count++;
if (error != NULL) {
*error = status;
}
-
+
// Return symbol
return symbol;
}
hnode_t *node;
symbol_info_t *symbol_info;
symbol_provider_info_t *provider_info;
-
+
CHECK_NOT_NULL(context);
CHECK_NOT_NULL(ptr);
}
symbol_info = hnode_get(node);
provider_info = symbol_info->provider_info;
-
+
// Decrease usage count
assert(symbol_info->usage_count > 0);
symbol_info->usage_count--;
assert(provider_info->usage_count > 0);
provider_info->usage_count--;
-
+
// Check if the symbol is not being used anymore
if (symbol_info->usage_count == 0) {
hash_delete_free(context->resolved_symbols, node);
cpi_debugf(context, _("%s released the symbol at address %p defined by plug-in %s."), cpi_context_owner(context, owner, sizeof(owner)), ptr, provider_info->plugin->plugin->identifier);
}
}
-
+
// Check if the symbol providing plug-in is not being used anymore
if (provider_info->usage_count == 0) {
node = hash_lookup(context->symbol_providers, provider_info->plugin);
}
free(provider_info);
}
-
+
} while (0);
cpi_unlock_context(context);
}
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
/// A holder structure for a run function.
typedef struct run_func_t {
-
+
/// The run function
cp_run_func_t runfunc;
-
+
/// The registering plug-in instance
cp_plugin_t *plugin;
-
+
/// Whether currently in execution
int in_execution;
-
+
} run_func_t;
CP_C_API cp_status_t cp_run_function(cp_context_t *ctx, cp_run_func_t runfunc) {
lnode_t *node = NULL;
run_func_t *rf = NULL;
cp_status_t status = CP_OK;
-
+
CHECK_NOT_NULL(ctx);
CHECK_NOT_NULL(runfunc);
if (ctx->plugin == NULL) {
&& ctx->plugin->state != CP_PLUGIN_STARTING) {
cpi_fatalf(_("Only starting or active plug-ins can register run functions."));
}
-
+
cpi_lock_context(ctx);
cpi_check_invocation(ctx, CPI_CF_STOP | CPI_CF_LOGGER, __func__);
do {
int found = 0;
lnode_t *n;
-
+
// Check if already registered
n = list_first(ctx->env->run_funcs);
while (n != NULL && !found) {
status = CP_ERR_RESOURCE;
break;
}
-
+
// Initialize run function entry
memset(rf, 0, sizeof(run_func_t));
rf->runfunc = runfunc;
rf->plugin = ctx->plugin;
-
+
// Append the run function to queue
list_append(ctx->env->run_funcs, node);
if (ctx->env->run_wait == NULL) {
// Log error
if (status == CP_ERR_RESOURCE) {
cpi_error(ctx, N_("Could not register a run function due to insufficient memory."));
- }
+ }
cpi_unlock_context(ctx);
-
+
// Free resources on error
if (status != CP_OK) {
if (node != NULL) {
free(rf);
}
}
-
+
return status;
}
CP_C_API int cp_run_plugins_step(cp_context_t *ctx) {
int runnables;
-
+
CHECK_NOT_NULL(ctx);
cpi_lock_context(ctx);
if (ctx->env->run_wait != NULL) {
lnode_t *node = ctx->env->run_wait;
run_func_t *rf = lnode_get(node);
int rerun;
-
+
ctx->env->run_wait = list_next(ctx->env->run_funcs, node);
rf->in_execution = 1;
cpi_unlock_context(ctx);
CP_HIDDEN void cpi_stop_plugin_run(cp_plugin_t *plugin) {
int stopped = 0;
cp_context_t *ctx;
-
+
CHECK_NOT_NULL(plugin);
ctx = plugin->context;
assert(cpi_is_context_locked(ctx));
while (!stopped) {
lnode_t *node;
-
+
stopped = 1;
node = list_first(ctx->env->run_funcs);
while (node != NULL) {
run_func_t *rf = lnode_get(node);
lnode_t *next_node = list_next(ctx->env->run_funcs, node);
-
+
if (rf->plugin == plugin) {
if (rf->in_execution) {
stopped = 0;
}
node = next_node;
}
-
+
// If some run functions were in execution, wait for them to finish
if (!stopped) {
cpi_wait_context(ctx);
#ifdef __cplusplus
}
-#endif //__cplusplus
+#endif //__cplusplus
#endif //CP_THREADS
#endif //THREAD_H_
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* Data types
* ----------------------------------------------------------------------*/
-// A generic recursive mutex implementation
+// A generic recursive mutex implementation
struct cpi_mutex_t {
- /// The current lock count
+ /// The current lock count
int lock_count;
-
- /// The underlying operating system mutex
+
+ /// The underlying operating system mutex
pthread_mutex_t os_mutex;
-
- /// The condition variable for signaling availability
+
+ /// The condition variable for signaling availability
pthread_cond_t os_cond_lock;
-
+
/// The condition variable for broadcasting a wake request
pthread_cond_t os_cond_wake;
- /// The locking thread if currently locked
+ /// The locking thread if currently locked
pthread_t os_thread;
-
+
};
CP_HIDDEN cpi_mutex_t * cpi_create_mutex(void) {
cpi_mutex_t *mutex;
-
+
if ((mutex = malloc(sizeof(cpi_mutex_t))) == NULL) {
return NULL;
}
return NULL;
} else if (pthread_cond_init(&(mutex->os_cond_lock), NULL)) {
int ec;
-
+
ec = pthread_mutex_destroy(&(mutex->os_mutex));
assert(!ec);
return NULL;
} else if (pthread_cond_init(&(mutex->os_cond_wake), NULL)) {
int ec;
-
+
ec = pthread_mutex_destroy(&(mutex->os_mutex));
assert(!ec);
ec = pthread_cond_destroy(&(mutex->os_cond_wake));
CP_HIDDEN void cpi_destroy_mutex(cpi_mutex_t *mutex) {
int ec;
-
+
assert(mutex != NULL);
assert(mutex->lock_count == 0);
ec = pthread_mutex_destroy(&(mutex->os_mutex));
static void lock_mutex(pthread_mutex_t *mutex) {
int ec;
-
+
if ((ec = pthread_mutex_lock(mutex))) {
cpi_fatalf(_("Could not lock a mutex due to error %d."), ec);
}
static void unlock_mutex(pthread_mutex_t *mutex) {
int ec;
-
+
if ((ec = pthread_mutex_unlock(mutex))) {
cpi_fatalf(_("Could not unlock a mutex due to error %d."), ec);
}
static void lock_mutex_holding(cpi_mutex_t *mutex) {
pthread_t self = pthread_self();
-
+
while (mutex->lock_count != 0
&& !pthread_equal(self, mutex->os_thread)) {
int ec;
-
+
if ((ec = pthread_cond_wait(&(mutex->os_cond_lock), &(mutex->os_mutex)))) {
cpi_fatalf(_("Could not wait for a condition variable due to error %d."), ec);
}
CP_HIDDEN void cpi_unlock_mutex(cpi_mutex_t *mutex) {
pthread_t self = pthread_self();
-
+
assert(mutex != NULL);
lock_mutex(&(mutex->os_mutex));
if (mutex->lock_count > 0
&& pthread_equal(self, mutex->os_thread)) {
if (--mutex->lock_count == 0) {
int ec;
-
+
if ((ec = pthread_cond_signal(&(mutex->os_cond_lock)))) {
cpi_fatalf(_("Could not signal a condition variable due to error %d."), ec);
}
CP_HIDDEN void cpi_wait_mutex(cpi_mutex_t *mutex) {
pthread_t self = pthread_self();
-
+
assert(mutex != NULL);
lock_mutex(&(mutex->os_mutex));
if (mutex->lock_count > 0
&& pthread_equal(self, mutex->os_thread)) {
int ec;
int lc = mutex->lock_count;
-
+
// Release mutex
mutex->lock_count = 0;
if ((ec = pthread_cond_signal(&(mutex->os_cond_lock)))) {
cpi_fatalf(_("Could not signal a condition variable due to error %d."), ec);
}
-
+
// Wait for signal
if ((ec = pthread_cond_wait(&(mutex->os_cond_wake), &(mutex->os_mutex)))) {
cpi_fatalf(_("Could not wait for a condition variable due to error %d."), ec);
}
-
+
// Re-acquire mutex and restore lock count for this thread
lock_mutex_holding(mutex);
mutex->lock_count = lc;
-
+
} else {
cpi_fatalf(_("Internal C-Pluff error: Unauthorized attempt at waiting on a mutex."));
}
CP_HIDDEN void cpi_signal_mutex(cpi_mutex_t *mutex) {
pthread_t self = pthread_self();
-
+
assert(mutex != NULL);
lock_mutex(&(mutex->os_mutex));
if (mutex->lock_count > 0
&& pthread_equal(self, mutex->os_thread)) {
int ec;
-
+
// Signal the mutex
if ((ec = pthread_cond_broadcast(&(mutex->os_cond_wake)))) {
cpi_fatalf(_("Could not broadcast a condition variable due to error %d."), ec);
}
-
+
} else {
cpi_fatalf(_("Internal C-Pluff error: Unauthorized attempt at signaling a mutex."));
}
#if !defined(NDEBUG)
CP_HIDDEN int cpi_is_mutex_locked(cpi_mutex_t *mutex) {
int locked;
-
+
lock_mutex(&(mutex->os_mutex));
locked = (mutex->lock_count != 0);
unlock_mutex(&(mutex->os_mutex));
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* Data types
* ----------------------------------------------------------------------*/
-// A generic recursive mutex implementation
+// A generic recursive mutex implementation
struct cpi_mutex_t {
- /// The current lock count
+ /// The current lock count
int lock_count;
-
- /// The underlying operating system mutex
+
+ /// The underlying operating system mutex
HANDLE os_mutex;
-
- /// The condition variable for signaling availability
+
+ /// The condition variable for signaling availability
HANDLE os_cond_lock;
-
+
/// The condition variable for signaling a wake request
HANDLE os_cond_wake;
/// Number of threads currently waiting on this mutex
int num_wait_threads;
- /// The locking thread if currently locked
+ /// The locking thread if currently locked
DWORD os_thread;
-
+
};
CP_HIDDEN cpi_mutex_t * cpi_create_mutex(void) {
cpi_mutex_t *mutex;
-
+
if ((mutex = malloc(sizeof(cpi_mutex_t))) == NULL) {
return NULL;
}
return NULL;
} else if ((mutex->os_cond_lock = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
int ec;
-
+
ec = CloseHandle(mutex->os_mutex);
assert(ec);
return NULL;
} else if ((mutex->os_cond_wake = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) {
int ec;
-
+
ec = CloseHandle(mutex->os_mutex);
assert(ec);
ec = CloseHandle(mutex->os_cond_lock);
CP_HIDDEN void cpi_destroy_mutex(cpi_mutex_t *mutex) {
int ec;
-
+
assert(mutex != NULL);
assert(mutex->lock_count == 0);
ec = CloseHandle(mutex->os_mutex);
static void lock_mutex(HANDLE mutex) {
DWORD ec;
-
+
if ((ec = WaitForSingleObject(mutex, INFINITE)) != WAIT_OBJECT_0) {
char buffer[256];
ec = GetLastError();
static void lock_mutex_holding(cpi_mutex_t *mutex) {
DWORD self = GetCurrentThreadId();
-
+
while (mutex->lock_count != 0
&& self != mutex->os_thread) {
unlock_mutex(mutex->os_mutex);
CP_HIDDEN void cpi_unlock_mutex(cpi_mutex_t *mutex) {
DWORD self = GetCurrentThreadId();
-
+
assert(mutex != NULL);
lock_mutex(mutex->os_mutex);
if (mutex->lock_count > 0
CP_HIDDEN void cpi_wait_mutex(cpi_mutex_t *mutex) {
DWORD self = GetCurrentThreadId();
-
+
assert(mutex != NULL);
lock_mutex(mutex->os_mutex);
if (mutex->lock_count > 0
&& self == mutex->os_thread) {
int lc = mutex->lock_count;
-
+
// Release mutex
mutex->lock_count = 0;
mutex->num_wait_threads++;
set_event(mutex->os_cond_lock);
unlock_mutex(mutex->os_mutex);
-
+
// Wait for signal
wait_for_event(mutex->os_cond_wake);
-
+
// Reset wake signal if last one waking up
lock_mutex(mutex->os_mutex);
if (--mutex->num_wait_threads == 0) {
reset_event(mutex->os_cond_wake);
}
-
+
// Re-acquire mutex and restore lock count for this thread
lock_mutex_holding(mutex);
- mutex->lock_count = lc;
-
+ mutex->lock_count = lc;
+
} else {
cpi_fatalf(_("Internal C-Pluff error: Unauthorized attempt at waiting on a mutex."));
}
CP_HIDDEN void cpi_signal_mutex(cpi_mutex_t *mutex) {
DWORD self = GetCurrentThreadId();
-
+
assert(mutex != NULL);
lock_mutex(mutex->os_mutex);
if (mutex->lock_count > 0
} else {
cpi_fatalf(_("Internal C-Pluff error: Unauthorized attempt at signaling a mutex."));
}
- unlock_mutex(mutex->os_mutex);
+ unlock_mutex(mutex->os_mutex);
}
#if !defined(NDEBUG)
CP_HIDDEN int cpi_is_mutex_locked(cpi_mutex_t *mutex) {
int locked;
-
+
lock_mutex(mutex->os_mutex);
locked = (mutex->lock_count != 0);
unlock_mutex(mutex->os_mutex);
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
/** @file
* Internal utility functions
- */
+ */
#include <stdio.h>
#include <stdlib.h>
}
CP_HIDDEN int cpi_ptrset_add(list_t *set, void *ptr) {
-
- // Only add the pointer if it is not already included
+
+ // Only add the pointer if it is not already included
if (cpi_ptrset_contains(set, ptr)) {
return 1;
} else {
lnode_t *node;
- /* Add the pointer to the list */
+ /* Add the pointer to the list */
node = lnode_create(ptr);
if (node == NULL) {
return 0;
list_append(set, node);
return 1;
}
-
+
}
CP_HIDDEN int cpi_ptrset_remove(list_t *set, const void *ptr) {
lnode_t *node;
-
- // Find the pointer if it is in the set
+
+ // Find the pointer if it is in the set
node = list_find(set, ptr, cpi_comp_ptr);
if (node != NULL) {
list_delete(set, node);
}
static int vercmp_num_value(const char *v, const char *vn) {
-
+
// Skip leading zeros
while (v < vn && *v == '0') {
v++;
}
-
+
// Empty string equals to zero
if (v == vn) {
return 0;
}
-
+
// Otherwise return the integer value
else {
char str[16];
CP_HIDDEN int cpi_vercmp(const char *v1, const char *v2) {
const char *v1n;
const char *v2n;
-
+
// Check for NULL versions
if (v1 == NULL && v2 != NULL) {
return -1;
return 1;
}
assert(v1 != NULL && v2 != NULL);
-
+
// Component comparison loop
while (*v1 != '\0' || *v2 != '\0') {
-
+
// Determine longest non-digit prefix
v1n = vercmp_nondigit_end(v1);
v2n = vercmp_nondigit_end(v2);
-
+
// Compare the non-digit strings
while (v1 < v1n || v2 < v2n) {
char c1 = '\0';
char c2 = '\0';
-
+
if (v1 < v1n) {
c1 = *v1++;
}
assert(v1 <= v1n && v2 <= v2n);
}
assert(v1 == v1n && v2 == v2n);
-
+
// Determine the longest digit prefix
v1n = vercmp_digit_end(v1);
v2n = vercmp_digit_end(v2);
-
+
// Compare the digit strings
{
int i1 = vercmp_num_value(v1, v1n);
}
v1 = v1n;
v2 = v2n;
-
+
}
return 0;
}
#ifdef __cplusplus
}
-#endif //__cplusplus
+#endif //__cplusplus
#endif //UTIL_H_
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
-cpluff-loader$(EXEEXT): $(cpluff_loader_OBJECTS) $(cpluff_loader_DEPENDENCIES) $(EXTRA_cpluff_loader_DEPENDENCIES)
+cpluff-loader$(EXEEXT): $(cpluff_loader_OBJECTS) $(cpluff_loader_DEPENDENCIES) $(EXTRA_cpluff_loader_DEPENDENCIES)
@rm -f cpluff-loader$(EXEEXT)
$(LINK) $(cpluff_loader_OBJECTS) $(cpluff_loader_LDADD) $(LIBS)
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* Defines
* ---------------------------------------------------------------------*/
-// Gettext defines
+// Gettext defines
#ifdef HAVE_GETTEXT
#define _(String) gettext(String)
#define gettext_noop(String) String
/// A string list container
struct str_list_t {
-
+
/// The first entry or NULL if empty
str_list_entry_t *first;
-
+
/// The last entry or NULL if empty
str_list_entry_t *last;
-
+
};
/// A holder for a string list entry
struct str_list_entry_t {
-
+
/// The string
const char *str;
-
+
/// Next entry
str_list_entry_t *next;
};
/**
* Prints an error message and exits. In quiet mode the error message is
* not printed.
- *
+ *
* @param msg the error message
*/
CP_GCC_NORETURN static void error(const char *msg) {
/**
* Formats and prints an error message and exits. In quiet mode the error
* message is not printed.
- *
+ *
* @param msg the error message
*/
CP_GCC_NORETURN static void errorf(const char *msg, ...) {
/**
* Allocates memory using malloc and checks for failures.
- *
+ *
* @param size the amount of memory to allocate
* @return the allocated memory (always non-NULL)
*/
minv = 1;
break;
default:
- /* TRANSLATORS: A tag for unknown severity level. */
+ /* TRANSLATORS: A tag for unknown severity level. */
level = _("UNKNOWN");
minv = 1;
break;
}
if (verbosity >= minv) {
if (apid != NULL) {
- /* TRANSLATORS: A formatting string for log messages caused by plug-in activity. */
+ /* TRANSLATORS: A formatting string for log messages caused by plug-in activity. */
fprintf(stderr, _("C-Pluff: %s: [%s] %s\n"), level, apid, msg);
} else {
- /* TRANSLATORS: A formatting string for log messages caused by loader activity. */
+ /* TRANSLATORS: A formatting string for log messages caused by loader activity. */
fprintf(stderr, _("C-Pluff: %s: [loader] %s\n"), level, msg);
}
- }
+ }
}
/// The main function
#ifdef HAVE_GETTEXT
setlocale(LC_ALL, "");
#endif
-
+
// Initialize the framework
if (cp_init() != CP_OK) {
error(_("The C-Pluff initialization failed."));
}
-
- // Set gettext domain
+
+ // Set gettext domain
#ifdef HAVE_GETTEXT
textdomain(PACKAGE);
#endif
// Parse arguments
while ((i = getopt(argc, argv, "hc:p:s:vqV")) != -1) {
switch (i) {
-
+
// Display help and exit
case 'h':
print_help();
case 'p':
str_list_append(&lst_plugin_dirs, optarg);
break;
-
+
// Add a plug-in to be started
case 's':
str_list_append(&lst_start, optarg);
fputs(cp_get_version(), stdout);
putchar('\n');
exit(0);
-
+
// Unrecognized option
default:
error(_("Unrecognized option or argument. Try option -h for help."));
// Display startup information
if (verbosity >= 1) {
-
+
/* TRANSLATORS: This is a version string displayed on startup. */
fprintf(stderr, _("C-Pluff Loader, version %s\n"), PACKAGE_VERSION);
-
+
/* TRANSLATORS: This is a version string displayed on startup.
The first %s is version and the second %s is platform type. */
fprintf(stderr, _("C-Pluff Library, version %s for %s\n"),
cp_get_version(), cp_get_host_type());
}
-
+
// Check arguments
if (lst_plugin_dirs.first == NULL && lst_plugin_collections.first == NULL) {
error(_("No plug-ins to load. Try option -h for help."));
}
-
+
// Create the context
if ((context = cp_create_context(NULL)) == NULL) {
error(_("Plug-in context creation failed."));
}
-
+
// Register logger
if (verbosity >= 1) {
cp_log_severity_t mv = CP_LOG_DEBUG;
}
cp_register_logger(context, logger, NULL, mv);
}
-
+
// Set context arguments
ctx_argv = chk_malloc((argc - optind + 2) * sizeof(char *));
ctx_argv[0] = "";
cp_release_info(context, pi);
}
str_list_clear(&lst_plugin_dirs);
-
+
// Load plug-in collections
for (entry = lst_plugin_collections.first; entry != NULL; entry = entry->next) {
if (cp_register_pcollection(context, entry->str) != CP_OK) {
- errorf(_("Failed to register a plug-in collection at path %s."), entry->str);
+ errorf(_("Failed to register a plug-in collection at path %s."), entry->str);
}
}
if (lst_plugin_collections.first != NULL
error(_("Failed to load and install plug-ins from plug-in collections."));
}
str_list_clear(&lst_plugin_collections);
-
+
// Start plug-ins
for (entry = lst_start.first; entry != NULL; entry = entry->next) {
if (cp_start_plugin(context, entry->str) != CP_OK) {
// Destroy framework
cp_destroy();
-
+
// Release context argument data
free(ctx_argv);
top_srcdir = @top_srcdir@
# This can be defined to a debugging wrapper program such as Valgrind.
-TEST_WRAPPER =
+TEST_WRAPPER =
# This can be defined to a subset of test cases to be performed
SELECTED_TESTS = all
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
-testsuite$(EXEEXT): $(testsuite_OBJECTS) $(testsuite_DEPENDENCIES) $(EXTRA_testsuite_DEPENDENCIES)
+testsuite$(EXEEXT): $(testsuite_OBJECTS) $(testsuite_DEPENDENCIES) $(EXTRA_testsuite_DEPENDENCIES)
@rm -f testsuite$(EXEEXT)
$(testsuite_LINK) $(testsuite_OBJECTS) $(testsuite_LDADD) $(LIBS)
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
cp_status_t status;
int errors;
int i;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_scan_plugins(ctx, 0) == CP_OK);
check((plugins = cp_get_plugins_info(ctx, &status, &i)) != NULL && status == CP_OK && i == 0);
void onecollection(void) {
cp_context_t *ctx;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_register_pcollection(ctx, pcollectiondir("collection1")) == CP_OK);
check(cp_scan_plugins(ctx, 0) == CP_OK);
void twocollections(void) {
cp_context_t *ctx;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_register_pcollection(ctx, pcollectiondir("collection1")) == CP_OK);
check(cp_register_pcollection(ctx, pcollectiondir("collection2")) == CP_OK);
void unregcollection(void) {
cp_context_t *ctx;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_register_pcollection(ctx, pcollectiondir("collection1")) == CP_OK);
check(cp_register_pcollection(ctx, pcollectiondir("collection2")) == CP_OK);
void unregcollections(void) {
cp_context_t *ctx;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_register_pcollection(ctx, pcollectiondir("collection1")) == CP_OK);
check(cp_register_pcollection(ctx, pcollectiondir("collection2")) == CP_OK);
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
Installed extensions:
IDENTIFIER NAME
maximal.ext1 Extension 1
- maximal.<anonymous>
+ maximal.<anonymous>
maximal.<anonymous> Extension 3
- maximal.ext2
-C-Pluff Console >
+ maximal.ext2
+C-Pluff Console >
Installed extension points:
IDENTIFIER NAME
- maximal.extpt4
+ maximal.extpt4
maximal.extpt2 Extension Point 2
maximal.extpt1 Extension Point 1
- maximal.extpt3
-C-Pluff Console >
+ maximal.extpt3
+C-Pluff Console >
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
int errors;
cp_status_t status;
int i;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check((plugin = cp_load_plugin_descriptor(ctx, plugindir("maximal"), &status)) != NULL && status == CP_OK);
for (i = 0, ext = NULL; ext == NULL && i < plugin->num_extensions; i++) {
}
}
check(ext != NULL);
-
+
// Look up using forward path
check((ce = cp_lookup_cfg_element(ext->configuration, "structure/parameter")) != NULL && ce->value != NULL && strcmp(ce->value, "parameter") == 0);
check((ce = cebase = cp_lookup_cfg_element(ext->configuration, "structure/deeper/struct/is")) != NULL && ce->value != NULL && strcmp(ce->value, "here") == 0);
check((str = cp_lookup_cfg_value(ext->configuration, "structure/parameter")) != NULL && strcmp(str, "parameter") == 0);
check((str = cp_lookup_cfg_value(ext->configuration, "@name")) != NULL && strcmp(str, "Extension 1") == 0);
-
+
// Look up using reverse path
check((ce = cp_lookup_cfg_element(cebase, "../../../parameter/../deeper")) != NULL && strcmp(ce->name, "deeper") == 0);
check((str = cp_lookup_cfg_value(cebase, "../../../../@name")) != NULL && strcmp(str, "Extension 1") == 0);
-
+
// Look up nonexisting components
check(cp_lookup_cfg_element(ext->configuration, "non/existing") == NULL);
check(cp_lookup_cfg_element(ext->configuration, "structure/../..") == NULL);
cp_release_info(ctx, plugin);
cp_destroy_context(ctx);
- check(errors == 0);
+ check(errors == 0);
}
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
static void cause_fatal_error(void) {
cp_context_t *ctx;
-
+
cp_init();
ctx = init_context(CP_LOG_ERROR + 1, NULL);
cp_release_info(ctx, &testvar);
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
void initdestroy(void) {
int i;
-
+
for (i = 0; i < 10; i++) {
check(cp_init() == CP_OK);
cp_destroy();
void initcreatedestroy(void) {
int i;
-
+
for (i = 0; i < 3; i++) {
int errors;
-
+
init_context(CP_LOG_ERROR, &errors);
cp_destroy();
check(errors == 0);
void initloaddestroy(void) {
int i;
-
+
for (i = 0; i < 3; i++) {
cp_context_t *ctx;
cp_plugin_info_t *pi;
const char *pdir = plugindir("minimal");
int errors;
- ctx = init_context(CP_LOG_ERROR, &errors);
+ ctx = init_context(CP_LOG_ERROR, &errors);
check((pi = cp_load_plugin_descriptor(ctx, pdir, &status)) != NULL && status == CP_OK);
cp_release_info(ctx, pi);
cp_destroy();
void initinstalldestroy(void) {
int i;
-
+
for (i = 0; i < 3; i++) {
cp_context_t *ctx;
cp_plugin_info_t *pi;
const char *pdir = plugindir("minimal");
int errors;
- ctx = init_context(CP_LOG_ERROR, &errors);
+ ctx = init_context(CP_LOG_ERROR, &errors);
check((pi = cp_load_plugin_descriptor(ctx, pdir, &status)) != NULL && status == CP_OK);
check(cp_install_plugin(ctx, pi) == CP_OK);
cp_release_info(ctx, pi);
void initstartdestroy(void) {
int i;
-
+
for (i = 0; i < 3; i++) {
cp_context_t *ctx;
cp_plugin_info_t *pi;
cp_status_t status;
const char *pdir = plugindir("minimal");
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check((pi = cp_load_plugin_descriptor(ctx, pdir, &status)) != NULL && status == CP_OK);
check(cp_install_plugin(ctx, pi) == CP_OK);
void initstartdestroyboth(void) {
int i;
-
+
for (i = 0; i < 3; i++) {
cp_context_t *ctx;
cp_plugin_info_t *pi;
cp_status_t status;
const char *pdir = plugindir("minimal");
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check((pi = cp_load_plugin_descriptor(ctx, pdir, &status)) != NULL && status == CP_OK);
check(cp_install_plugin(ctx, pi) == CP_OK);
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
cp_context_t *ctx;
cp_status_t status;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR + 1, &errors);
check(cp_load_plugin_descriptor(ctx, "nonexisting", &status) == NULL && status != CP_OK);
cp_destroy();
static void counting_logger(cp_log_severity_t severity, const char *msg, const char *apid, void *user_data) {
struct log_count_t *lc = user_data;
-
+
if (severity <= lc->max_severity) {
lc->count_max++;
} else {
void warninglogger(void) {
cp_context_t *ctx;
struct log_count_t lc = { CP_LOG_WARNING, 0, 0 };
-
+
ctx = init_context(CP_LOG_ERROR, NULL);
check(cp_register_logger(ctx, counting_logger, &lc, CP_LOG_WARNING) == CP_OK);
check(cp_start_plugin(ctx, "nonexisting") == CP_ERR_UNKNOWN);
void debuglogger(void) {
cp_context_t *ctx;
struct log_count_t lc = { CP_LOG_DEBUG, 0, 0 };
-
+
ctx = init_context(CP_LOG_INFO, NULL);
check(cp_register_logger(ctx, counting_logger, &lc, CP_LOG_DEBUG) == CP_OK);
cp_destroy();
struct log_count_t lc = { CP_LOG_DEBUG, 0, 0 };
int count = 0;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_register_logger(ctx, counting_logger, &lc, CP_LOG_DEBUG) == CP_OK);
check(count == 0 && lc.count_max > 0 && lc.count_above_max == 0);
struct log_count_t lc = { CP_LOG_DEBUG, 0, 0 };
int count = 0;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_register_logger(ctx, counting_logger, &lc, CP_LOG_DEBUG) == CP_OK);
check(count == 0 && lc.count_max > 0 && lc.count_above_max == 0);
struct log_count_t lc2 = { CP_LOG_INFO, 0, 0 };
int count = 0;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_register_logger(ctx, counting_logger, &lc, CP_LOG_DEBUG) == CP_OK);
check(count == 0 && lc.count_max > 0 && lc.count_above_max == 0);
static void store_logger(cp_log_severity_t severity, const char *msg, const char *apid, void *user_data) {
struct log_info_t *li = user_data;
-
+
// Free previous data
if (li->msg != NULL) {
free(li->msg);
free(li->apid);
li->apid = NULL;
}
-
+
// Copy information
li->severity = severity;
if (msg != NULL) {
void logmsg(void) {
cp_context_t *ctx;
-
+
ctx = init_context(CP_LOG_ERROR + 1, NULL);
logmsg_sev(ctx, CP_LOG_DEBUG, "debug");
logmsg_sev(ctx, CP_LOG_INFO, "info");
static void islogged_sev(cp_context_t *ctx, cp_log_severity_t severity) {
int count = 0;
-
+
check(!cp_is_logged(ctx, severity));
check(cp_register_logger(ctx, increment_logger, &count, severity) == CP_OK);
check(cp_is_logged(ctx, CP_LOG_ERROR));
void islogged(void) {
cp_context_t *ctx;
-
+
ctx = init_context(CP_LOG_ERROR + 1, NULL);
islogged_sev(ctx, CP_LOG_DEBUG);
islogged_sev(ctx, CP_LOG_INFO);
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
cp_plugin_info_t *plugin;
int errors;
cbc_counters_t *counters;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
cp_set_context_args(ctx, argv);
check((plugin = cp_load_plugin_descriptor(ctx, "tmp/install/plugins/callbackcounter", &status)) != NULL && status == CP_OK);
check(cp_install_plugin(ctx, plugin) == CP_OK);
cp_release_info(ctx, plugin);
-
+
// Start plug-in implicitly by resolving a symbol
check((counters = cp_resolve_symbol(ctx, "callbackcounter", "cbc_counters", &status)) != NULL && status == CP_OK);
check(counters->create == 1);
check(counters->stop == 1);
// for now 1 but might be 0 in future (delay destroy)
check(counters->destroy == 0 || counters->destroy == 1);
-
+
// Uninstall plugin
check(cp_uninstall_plugin(ctx, "callbackcounter") == CP_OK);
check(counters->create == 1);
cp_destroy();
check(errors == 0);
-
+
/* Free the counter data that was intentionally leaked by the plug-in */
free(counters);
}
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
cp_status_t status;
int i;
int errors = 0;
-
+
check((pis = cp_get_plugins_info(ctx, &status, NULL)) != NULL && status == CP_OK);
for (i = 0; !errors && pis[i] != NULL; i++) {
int j;
int should_be_active = 0;
cp_plugin_state_t state;
-
+
for (j = 0; !should_be_active && plugins[j] != NULL; j++) {
if (!strcmp(pis[i]->identifier, plugins[j])) {
should_be_active = 1;
void pluginmissingdep(void) {
cp_context_t *ctx;
const char * const act_none[] = { NULL };
-
+
ctx = init_context(CP_LOG_ERROR + 1, NULL);
check((cp_register_pcollection(ctx, pcollectiondir("dependencies"))) == CP_OK);
check(cp_scan_plugins(ctx, 0) == CP_OK);
-
+
// Try starting a plugin depending on plug-in missing dependency
check(cp_start_plugin(ctx, "chainmissingdep") == CP_ERR_DEPENDENCY);
check(active(ctx, act_none));
const char * const act_chain123[] = { "chain1", "chain2", "chain3", NULL };
const char * const act_chain23[] = { "chain2", "chain3", NULL };
const char * const act_chain3[] = { "chain3", NULL };
-
+
ctx = init_context(CP_LOG_ERROR, NULL);
check((cp_register_pcollection(ctx, pcollectiondir("dependencies"))) == CP_OK);
check(cp_scan_plugins(ctx, 0) == CP_OK);
-
+
// Try starting and stopping plug-ins in dependency chain
check(cp_start_plugin(ctx, "chain1") == CP_OK);
check(active(ctx, act_chain123));
const char * const act_loop1234[] = { "loop1", "loop2", "loop3", "loop4", NULL };
const char * const act_loop4[] = { "loop4", NULL };
const char * const act_loop12345[] = { "loop1", "loop2", "loop3", "loop4", "loop5", NULL };
-
+
ctx = init_context(CP_LOG_ERROR, NULL);
check((cp_register_pcollection(ctx, pcollectiondir("dependencies"))) == CP_OK);
check(cp_scan_plugins(ctx, 0) == CP_OK);
check(cp_get_plugin_state(ctx, "loop4") == CP_PLUGIN_UNINSTALLED);
check(cp_get_plugin_state(ctx, "loop5") == CP_PLUGIN_INSTALLED);
- cp_destroy();
+ cp_destroy();
}
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
cp_plugin_info_t *plugin;
cp_status_t status;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_UNINSTALLED);
check((plugin = cp_load_plugin_descriptor(ctx, plugindir("minimal"), &status)) != NULL && status == CP_OK);
check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_UNINSTALLED);
check(cp_install_plugin(ctx, plugin) == CP_OK);
cp_release_info(ctx, plugin);
- check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_INSTALLED);
+ check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_INSTALLED);
cp_destroy();
check(errors == 0);
}
cp_plugin_info_t *plugin;
cp_status_t status;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_UNINSTALLED);
check((plugin = cp_load_plugin_descriptor(ctx, plugindir("minimal"), &status)) != NULL && status == CP_OK);
check((plugin = cp_load_plugin_descriptor(ctx, plugindir("maximal"), &status)) != NULL && status == CP_OK);
check(cp_get_plugin_state(ctx, "maximal") == CP_PLUGIN_UNINSTALLED);
check(cp_install_plugin(ctx, plugin) == CP_OK);
- cp_release_info(ctx, plugin);
+ cp_release_info(ctx, plugin);
check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_INSTALLED);
check(cp_get_plugin_state(ctx, "maximal") == CP_PLUGIN_INSTALLED);
cp_destroy();
- check(errors == 0);
+ check(errors == 0);
}
void installconflict(void) {
cp_context_t *ctx;
cp_plugin_info_t *plugin;
cp_status_t status;
-
+
ctx = init_context(CP_LOG_ERROR + 1, NULL);
check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_UNINSTALLED);
check((plugin = cp_load_plugin_descriptor(ctx, plugindir("minimal"), &status)) != NULL && status == CP_OK);
check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_UNINSTALLED);
check(cp_install_plugin(ctx, plugin) == CP_OK);
cp_release_info(ctx, plugin);
- check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_INSTALLED);
+ check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_INSTALLED);
check((plugin = cp_load_plugin_descriptor(ctx, plugindir("minimal"), &status)) != NULL && status == CP_OK);
check(cp_install_plugin(ctx, plugin) == CP_ERR_CONFLICT);
cp_release_info(ctx, plugin);
cp_plugin_info_t *plugin;
cp_status_t status;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check((plugin = cp_load_plugin_descriptor(ctx, plugindir("minimal"), &status)) != NULL && status == CP_OK);
check(cp_install_plugin(ctx, plugin) == CP_OK);
cp_release_info(ctx, plugin);
check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_INSTALLED);
check(cp_uninstall_plugin(ctx, "minimal") == CP_OK);
- check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_UNINSTALLED);
+ check(cp_get_plugin_state(ctx, "minimal") == CP_PLUGIN_UNINSTALLED);
cp_destroy();
- check(errors == 0);
+ check(errors == 0);
}
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
cp_plugin_info_t *plugin;
cp_status_t status;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check((plugin = cp_load_plugin_descriptor(ctx, plugindir("maximal"), &status)) != NULL && status == CP_OK);
cp_release_info(ctx, plugin);
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libruntime.la: $(libruntime_la_OBJECTS) $(libruntime_la_DEPENDENCIES) $(EXTRA_libruntime_la_DEPENDENCIES)
+libruntime.la: $(libruntime_la_OBJECTS) $(libruntime_la_DEPENDENCIES) $(EXTRA_libruntime_la_DEPENDENCIES)
$(libruntime_la_LINK) -rpath $(plugindir) $(libruntime_la_OBJECTS) $(libruntime_la_LIBADD) $(LIBS)
mostlyclean-compile:
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
static void *create(cp_context_t *ctx) {
struct runtime_data *data;
-
+
if ((data = malloc(sizeof(struct runtime_data))) == NULL) {
return NULL;
}
data->ctx = ctx;
-
+
/*
* Normally data->counters would be initialized in start function.
* We do it already here to be able to record count for the create
memset(data->counters, 0, sizeof(cbc_counters_t));
data->counters->context_arg_0 = NULL;
data->counters->create++;
-
+
return data;
}
static void logger(cp_log_severity_t severity, const char *msg, const char *apid, void *user_data) {
struct runtime_data *data = user_data;
-
+
data->counters->logger++;
}
static void listener(const char *plugin_id, cp_plugin_state_t old_state, cp_plugin_state_t new_state, void *user_data) {
struct runtime_data *data = user_data;
-
+
data->counters->listener++;
}
static int run(void *d) {
struct runtime_data *data = d;
-
+
data->counters->run++;
return (data->counters->run < 3);
}
static int start(void *d) {
struct runtime_data *data = d;
char **argv;
-
+
data->counters->start++;
argv = cp_get_context_args(data->ctx, NULL);
if (argv != NULL && argv[0] != NULL) {
return CP_ERR_RUNTIME;
} else {
return CP_OK;
- }
+ }
}
static void stop(void *d) {
data->counters->stop++;
- /*
+ /*
* Normally data->counters would be freed here. However, we do not free
* it so that the test program can read counters after plug-in stops.
*/
static void destroy(void *d) {
struct runtime_data *data = d;
- data->counters->destroy++;
+ data->counters->destroy++;
data->counters = NULL;
free(data);
}
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libruntime.la: $(libruntime_la_OBJECTS) $(libruntime_la_DEPENDENCIES) $(EXTRA_libruntime_la_DEPENDENCIES)
+libruntime.la: $(libruntime_la_OBJECTS) $(libruntime_la_DEPENDENCIES) $(EXTRA_libruntime_la_DEPENDENCIES)
$(libruntime_la_LINK) -rpath $(plugindir) $(libruntime_la_OBJECTS) $(libruntime_la_LIBADD) $(LIBS)
mostlyclean-compile:
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
static int start(void *d) {
plugin_data_t *data = d;
-
+
if ((data->str = malloc(sizeof(char) * 16)) == NULL) {
return CP_ERR_RESOURCE;
}
static void destroy(void *d) {
plugin_data_t *data = d;
-
+
if (data->str != NULL) {
strcpy(data->str, "Cleared string");
free(data->str);
}
- free(d);
+ free(d);
}
CP_EXPORT cp_plugin_runtime_t sp_runtime = {
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libruntime.la: $(libruntime_la_OBJECTS) $(libruntime_la_DEPENDENCIES) $(EXTRA_libruntime_la_DEPENDENCIES)
+libruntime.la: $(libruntime_la_OBJECTS) $(libruntime_la_DEPENDENCIES) $(EXTRA_libruntime_la_DEPENDENCIES)
$(libruntime_la_LINK) -rpath $(plugindir) $(libruntime_la_OBJECTS) $(libruntime_la_LIBADD) $(LIBS)
mostlyclean-compile:
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
static void *create(cp_context_t *ctx) {
plugin_data_t *data;
-
+
if ((data = malloc(sizeof(plugin_data_t))) != NULL) {
data->ctx = ctx;
data->str = NULL;
static int start(void *d) {
plugin_data_t *data = d;
cp_extension_t **exts;
-
+
exts = cp_get_extensions_info(data->ctx, "symuser.strings", NULL, NULL);
if (exts != NULL && exts[0] != NULL) {
const char *symname;
-
+
symname = cp_lookup_cfg_value(exts[0]->configuration, "@string-symbol");
if (symname != NULL) {
data->str = cp_resolve_symbol(data->ctx, exts[0]->plugin->identifier, symname, NULL);
}
} else {
cp_log(data->ctx, CP_LOG_ERROR, "No string-symbol attribute present in extension.");
- }
+ }
} else {
cp_log(data->ctx, CP_LOG_ERROR, "No extensions available.");
}
static void stop(void *d) {
plugin_data_t *data = d;
-
+
// Check that the provided string is still available
if (data->str != NULL) {
if (strcmp(data->str, "Provided string")) {
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
static void scanupgrade_checkpver(cp_context_t *ctx, const char *plugin, const char *ver) {
cp_plugin_info_t *pi;
cp_status_t status;
-
+
check((pi = cp_get_plugin_info(ctx, plugin, &status)) != NULL && status == CP_OK);
check(ver == NULL ? pi->version == NULL : (pi->version != NULL && strcmp(pi->version, ver) == 0));
- cp_release_info(ctx, pi);
+ cp_release_info(ctx, pi);
}
void scanupgrade(void) {
cp_context_t *ctx;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_register_pcollection(ctx, pcollectiondir("collection1")) == CP_OK);
check(cp_register_pcollection(ctx, pcollectiondir("collection2")) == CP_OK);
check(cp_get_plugin_state(ctx, "plugin2a") == CP_PLUGIN_INSTALLED);
check(cp_get_plugin_state(ctx, "plugin2b") == CP_PLUGIN_INSTALLED);
scanupgrade_checkpver(ctx, "plugin1", NULL);
-
+
// Register newer version of plugin1 but do not allow upgrades
check(cp_start_plugin(ctx, "plugin1") == CP_OK);
check(cp_get_plugin_state(ctx, "plugin1") == CP_PLUGIN_ACTIVE);
// Now allow upgrade of plugin1
check(cp_scan_plugins(ctx, CP_SP_UPGRADE) == CP_OK);
scanupgrade_checkpver(ctx, "plugin1", "2");
-
+
// Register even new version and upgrade while running
check(cp_register_pcollection(ctx, pcollectiondir("collection1v3")) == CP_OK);
check(cp_start_plugin(ctx, "plugin1") == CP_OK);
check(cp_scan_plugins(ctx, CP_SP_UPGRADE) == CP_OK);
check(cp_get_plugin_state(ctx, "plugin1") == CP_PLUGIN_INSTALLED);
scanupgrade_checkpver(ctx, "plugin1", "3");
-
+
// Check that plug-in is not downgraded when newer versions are unregistered
cp_unregister_pcollection(ctx, pcollectiondir("collection1v3"));
check(cp_scan_plugins(ctx, CP_SP_UPGRADE) == CP_OK);
void scanstoponupgrade(void) {
cp_context_t *ctx;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_register_pcollection(ctx, pcollectiondir("collection1")) == CP_OK);
check(cp_register_pcollection(ctx, pcollectiondir("collection2")) == CP_OK);
check(cp_scan_plugins(ctx, 0) == CP_OK);
-
+
// First check upgrade without stopping other plug-ins
check(cp_start_plugin(ctx, "plugin1") == CP_OK);
check(cp_get_plugin_state(ctx, "plugin1") == CP_PLUGIN_ACTIVE);
check(cp_scan_plugins(ctx, CP_SP_UPGRADE) == CP_OK);
check(cp_get_plugin_state(ctx, "plugin1") == CP_PLUGIN_INSTALLED);
check(cp_get_plugin_state(ctx, "plugin2a") == CP_PLUGIN_ACTIVE);
-
+
// Then check upgrade with stop flag
check(cp_start_plugin(ctx, "plugin1") == CP_OK);
check(cp_get_plugin_state(ctx, "plugin1") == CP_PLUGIN_ACTIVE);
void scanstoponinstall(void) {
cp_context_t *ctx;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_register_pcollection(ctx, pcollectiondir("collection1")) == CP_OK);
check(cp_scan_plugins(ctx, 0) == CP_OK);
-
+
// First check install without stopping other plug-ins
check(cp_start_plugin(ctx, "plugin1") == CP_OK);
check(cp_get_plugin_state(ctx, "plugin1") == CP_PLUGIN_ACTIVE);
check(cp_scan_plugins(ctx, 0) == CP_OK);
check(cp_get_plugin_state(ctx, "plugin1") == CP_PLUGIN_ACTIVE);
check(cp_get_plugin_state(ctx, "plugin2a") == CP_PLUGIN_INSTALLED);
-
+
// Then check install and stopping of other plug-ins
check(cp_uninstall_plugin(ctx, "plugin2a") == CP_OK);
check(cp_get_plugin_state(ctx, "plugin1") == CP_PLUGIN_ACTIVE);
check(cp_scan_plugins(ctx, CP_SP_STOP_ALL_ON_INSTALL) == CP_OK);
check(cp_get_plugin_state(ctx, "plugin1") == CP_PLUGIN_RESOLVED);
check(cp_get_plugin_state(ctx, "plugin2a") == CP_PLUGIN_INSTALLED);
-
+
// Then check upgrade and stopping of other plug-ins
check(cp_start_plugin(ctx, "plugin2a") == CP_OK);
check(cp_get_plugin_state(ctx, "plugin2a") == CP_PLUGIN_ACTIVE);
void scanrestart(void) {
cp_context_t *ctx;
int errors;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_register_pcollection(ctx, pcollectiondir("collection1")) == CP_OK);
check(cp_register_pcollection(ctx, pcollectiondir("collection2")) == CP_OK);
check(cp_get_plugin_state(ctx, "plugin1") == CP_PLUGIN_ACTIVE);
check(cp_get_plugin_state(ctx, "plugin2a") == CP_PLUGIN_INSTALLED);
check(cp_get_plugin_state(ctx, "plugin2b") == CP_PLUGIN_ACTIVE);
-
+
cp_destroy();
check(errors == 0);
}
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
cp_status_t status;
int errors;
const char *str;
-
+
ctx = init_context(CP_LOG_ERROR, &errors);
check(cp_register_pcollection(ctx, "tmp/install/plugins") == CP_OK);
check(cp_scan_plugins(ctx, 0) == CP_OK);
-
+
// Start plug-in implicitly by resolving a symbol
check((str = cp_resolve_symbol(ctx, "symuser", "used_string", &status)) != NULL && status == CP_OK);
-
+
// Compare used string to the provided string
check(strcmp(str, "Provided string") == 0);
-
+
// Release string
cp_release_symbol(ctx, str);
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
fprintf(stderr, "testsuite: %s: [testsuite] %s\n", sevstr, msg);
}
if (severity >= CP_LOG_ERROR && user_data != NULL) {
- (*((int *) user_data))++;
+ (*((int *) user_data))++;
}
}
CP_HIDDEN cp_context_t *init_context(cp_log_severity_t min_disp_sev, int *error_counter) {
cp_context_t *ctx;
cp_status_t status;
-
+
check(cp_init() == CP_OK);
check((ctx = cp_create_context(&status)) != NULL && status == CP_OK);
if (error_counter != NULL) {
CP_HIDDEN const char *plugindir(const char *plugin) {
const char *srcdir;
-
+
if (plugindir_buffer != NULL) {
free(plugindir_buffer);
plugindir_buffer = NULL;
CP_HIDDEN const char *pcollectiondir(const char *collection) {
const char *srcdir;
-
+
if (pcollectiondir_buffer != NULL) {
free(pcollectiondir_buffer);
pcollectiondir_buffer = NULL;
fprintf(stderr, "testsuite: ERROR: Could not resolve symbol %s.\n", argv[1]);
exit(2);
}
-
+
// Execute the test
// (NOTE: This conversion is not ANSI C compatible)
((void (*)(void)) ptr)();
-
+
// Free test resources
free_test_resources();
-
+
// Successfully completed
exit(0);
}
plugin_manager_env.InstallTarget([ppm, pmimpl], 'libppm')
plugin_manager_env.UserInstallTargetLib([ppm, pmimpl], 'libppm')
+plugin_manager_env.UserInstallTargetHeader('src/PluginManager.h', 'service/protocol-plugin', 'PluginManager.h')
# Build JNI library for android
if env.get('TARGET_OS') == 'android':
int mosquitto_reconnect_delay_set(struct mosquitto *mosq, unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff)
{
if(!mosq) return MOSQ_ERR_INVAL;
-
+
mosq->reconnect_delay = reconnect_delay;
mosq->reconnect_delay_max = reconnect_delay_max;
mosq->reconnect_exponential_backoff = reconnect_exponential_backoff;
-
+
return MOSQ_ERR_SUCCESS;
-
+
}
void _mosquitto_destroy(struct mosquitto *mosq)
mosq->ping_t = 0;
_mosquitto_packet_cleanup(&mosq->in_packet);
-
+
pthread_mutex_lock(&mosq->current_out_packet_mutex);
pthread_mutex_lock(&mosq->out_packet_mutex);
}else{
reconnects++;
}
-
+
#ifdef WIN32
Sleep(reconnect_delay*1000);
#else
for(rp = ainfo; rp != NULL; rp = rp->ai_next){
*sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if(*sock == INVALID_SOCKET) continue;
-
+
if(rp->ai_family == PF_INET){
((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port);
}else if(rp->ai_family == PF_INET6){
}
pthread_mutex_unlock(&mosq->callback_mutex);
}else if(((packet->command)&0xF0) == DISCONNECT){
- /* FIXME what cleanup needs doing here?
+ /* FIXME what cleanup needs doing here?
* incoming/outgoing messages? */
_mosquitto_socket_close(mosq);
# Copyright (c) 2010,2011 Roger Light <roger@atchoo.org>
# All rights reserved.
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
-#
+#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# 3. Neither the name of mosquitto nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
-#
+#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
if(mosq->bridge && mosq->bridge->topics && mosq->bridge->topic_remapping){
for(i=0; i<mosq->bridge->topic_count; i++){
cur_topic = &mosq->bridge->topics[i];
- if((cur_topic->direction == bd_both || cur_topic->direction == bd_out)
+ if((cur_topic->direction == bd_both || cur_topic->direction == bd_out)
&& (cur_topic->remote_prefix || cur_topic->local_prefix)){
/* Topic mapping required on this topic if the message matches */
#ifdef WITH_SRV
static void srv_callback(void *arg, int status, int timeouts, unsigned char *abuf, int alen)
-{
+{
struct mosquitto *mosq = arg;
struct ares_srv_reply *reply = NULL;
if(status == ARES_SUCCESS){
send(mosq->sockpairW, &sockpair_data, 1, 0);
#endif
}
-
+
if(force){
pthread_cancel(mosq->thread_id);
}
mosq->last_mid++;
if(mosq->last_mid == 0) mosq->last_mid++;
-
+
return mosq->last_mid;
}
}
if(tpos == tlen-1){
/* Check for e.g. foo matching foo/# */
- if(spos == slen-3
+ if(spos == slen-3
&& sub[spos+1] == '/'
&& sub[spos+2] == '#'){
*result = true;
+++ /dev/null
-/usr/lib/i386-linux-gnu/mesa-egl:
- libOpenVG.so.1 -> libOpenVG.so.1.0.0
- libwayland-egl.so.1 -> libwayland-egl.so.1.0.0
- libEGL.so.1 -> libEGL.so.1.0.0
-/usr/lib/i386-linux-gnu/mesa:
- libGL.so.1 -> libGL.so.1.2.0
-/lib/i386-linux-gnu:
- libblkid.so.1 -> libblkid.so.1.1.0
- libnss_dns.so.2 -> libnss_dns-2.15.so
- libnss_compat.so.2 -> libnss_compat-2.15.so
- libwrap.so.0 -> libwrap.so.0.7.6
- libpcsclite.so.1 -> libpcsclite.so.1.0.0
- libkeyutils.so.1 -> libkeyutils.so.1.4
- libntfs-3g.so.831 -> libntfs-3g.so.831.0.0
- libpcprofile.so -> libpcprofile.so
- libext2fs.so.2 -> libext2fs.so.2.4
- libslang.so.2 -> libslang.so.2.2.4
- libpci.so.3 -> libpci.so.3.1.8
- libparted.so.0 -> libparted.so.0.0.1
- libdl.so.2 -> libdl-2.15.so
- libutil.so.1 -> libutil-2.15.so
- libgcc_s.so.1 -> libgcc_s.so.1
- libnss_nisplus.so.2 -> libnss_nisplus-2.15.so
- libbsd.so.0 -> libbsd.so.0.3.0
- libpng12.so.0 -> libpng12.so.0.46.0
- librt.so.1 -> librt-2.15.so
- ld-linux.so.2 -> ld-2.15.so
- libncurses.so.5 -> libncurses.so.5.9
- libcrypto.so.1.0.0 -> libcrypto.so.1.0.0
- libacl.so.1 -> libacl.so.1.1.0
- libgcrypt.so.11 -> libgcrypt.so.11.7.0
- libnsl.so.1 -> libnsl-2.15.so
- libpam.so.0 -> libpam.so.0.83.0
- libmount.so.1 -> libmount.so.1.1.0
- libselinux.so.1 -> libselinux.so.1
- libpcre.so.3 -> libpcre.so.3.12.1
- libdbus-1.so.3 -> libdbus-1.so.3.5.8
- libuuid.so.1 -> libuuid.so.1.3.0
- libexpat.so.1 -> libexpat.so.1.5.2
- libnss_files.so.2 -> libnss_files-2.15.so
- libcom_err.so.2 -> libcom_err.so.2.1
- libnss_nis.so.2 -> libnss_nis-2.15.so
- libatasmart.so.4 -> libatasmart.so.4.0.4
- libssl.so.1.0.0 -> libssl.so.1.0.0
- libthread_db.so.1 -> libthread_db-1.0.so
- libncursesw.so.5 -> libncursesw.so.5.9
- libgpg-error.so.0 -> libgpg-error.so.0.8.0
- libe2p.so.2 -> libe2p.so.2.3
- libss.so.2 -> libss.so.2.0
- libBrokenLocale.so.1 -> libBrokenLocale-2.15.so
- libcidn.so.1 -> libcidn-2.15.so
- libpamc.so.0 -> libpamc.so.0.82.1
- libmemusage.so -> libmemusage.so
- libglib-2.0.so.0 -> libglib-2.0.so.0.3200.4
- libnss_hesiod.so.2 -> libnss_hesiod-2.15.so
- libanl.so.1 -> libanl-2.15.so
- libcap.so.2 -> libcap.so.2.22
- libresolv.so.2 -> libresolv-2.15.so
- libattr.so.1 -> libattr.so.1.1.0
- libpthread.so.0 -> libpthread-2.15.so
- libm.so.6 -> libm-2.15.so
- libz.so.1 -> libz.so.1.2.3.4
- libhistory.so.6 -> libhistory.so.6.2
- libnih-dbus.so.1 -> libnih-dbus.so.1.0.0
- libSegFault.so -> libSegFault.so
- libudev.so.0 -> libudev.so.0.13.0
- libreadline.so.6 -> libreadline.so.6.2
- libusb-1.0.so.0 -> libusb-1.0.so.0.1.0
- libcrypt.so.1 -> libcrypt-2.15.so
- libpam_misc.so.0 -> libpam_misc.so.0.82.0
- libnih.so.1 -> libnih.so.1.0.0
- libtinfo.so.5 -> libtinfo.so.5.9
- libpopt.so.0 -> libpopt.so.0.0.0
- libbz2.so.1.0 -> libbz2.so.1.0.4
- libc.so.6 -> libc-2.15.so
- libusb-0.1.so.4 -> libusb-0.1.so.4.4.4
-/usr/lib/i386-linux-gnu:
- libnss3.so -> libnss3.so
- libsmbclient.so.0 -> libsmbclient.so.0
- libgobject-2.0.so.0 -> libgobject-2.0.so.0.3200.4
- libpoppler-glib.so.8 -> libpoppler-glib.so.8.2.0
- libavcodec.so.53 -> libavcodec.so.53.35.0
- libwbclient.so.0 -> libwbclient.so.0
- libbonoboui-2.so.0 -> libbonoboui-2.so.0.0.0
- libjasper.so.1 -> libjasper.so.1.0.0
- libsqlite3.so.0 -> libsqlite3.so.0.8.6
- libgstbasevideo-1.0.so.0 -> libgstbasevideo-1.0.so.0.5.0
- librtmp.so.0 -> librtmp.so.0
- libframe.so.6 -> libframe.so.6.0.0
- libnspr4.so -> libnspr4.so
- libportaudio.so.2 -> libportaudio.so.2.0.0
- libXdmcp.so.6 -> libXdmcp.so.6.0.0
- libcanberra-gtk3.so.0 -> libcanberra-gtk3.so.0.1.8
- libnettle.so.4 -> libnettle.so.4.3
- libcups.so.2 -> libcups.so.2
- libxcb-shape.so.0 -> libxcb-shape.so.0.0.0
- libunistring.so.0 -> libunistring.so.0.1.2
- libQtDeclarative.so.4 -> libQtDeclarative.so.4.8.1
- libdbusmenu-gtk3.so.4 -> libdbusmenu-gtk3.so.4.0.13
- libgsttag-0.10.so.0 -> libgsttag-0.10.so.0.25.0
- libwmflite-0.2.so.7 -> libwmflite-0.2.so.7.0.1
- libapt-pkg.so.4.12 -> libapt-pkg.so.4.12.0
- libQtNetwork.so.4 -> libQtNetwork.so.4.8.1
- libgnomecanvas-2.so.0 -> libgnomecanvas-2.so.0.3000.3
- libtheoradec.so.1 -> libtheoradec.so.1.1.4
- libcanberra.so.0 -> libcanberra.so.0.2.5
- libgnutls-extra.so.26 -> libgnutls-extra.so.26.21.8
- libxcb-render.so.0 -> libxcb-render.so.0.0.0
- libgpm.so.2 -> libgpm.so.2
- libxcb-util.so.0 -> libxcb-util.so.0.0.0
- libraw1394.so.11 -> libraw1394.so.11.0.1
- libpangocairo-1.0.so.0 -> libpangocairo-1.0.so.0.3000.0
- libssl3.so -> libssl3.so
- libgstcontroller-0.10.so.0 -> libgstcontroller-0.10.so.0.30.0
- libcupsimage.so.2 -> libcupsimage.so.2
- liblcms2.so.2 -> liblcms2.so.2.0.2
- libgio-2.0.so.0 -> libgio-2.0.so.0.3200.4
- libtxc_dxtn_s2tc.so.0 -> libtxc_dxtn_s2tc.so.0.0.0
- libdbus-glib-1.so.2 -> libdbus-glib-1.so.2.2.2
- libgstallocators-1.0.so.0 -> libgstallocators-1.0.so.0.201.0
- libXi.so.6 -> libXi.so.6.1.0
- libsvn_ra_svn-1.so.1 -> libsvn_ra_svn-1.so.1.0.0
- liblber-2.4.so.2 -> liblber.so
- libgstsignalprocessor-1.0.so.0 -> libgstsignalprocessor-1.0.so.0.5.0
- libhcrypto.so.4 -> libhcrypto.so.4.1.0
- libcanberra-gtk.so.0 -> libcanberra-gtk.so.0.1.8
- libavahi-glib.so.1 -> libavahi-glib.so.1.0.2
- libedit.so.2 -> libedit.so.2.11
- libavahi-ui-gtk3.so.0 -> libavahi-ui-gtk3.so.0.1.4
- libx264.so.120 -> libx264.so.120
- libgstsdp-1.0.so.0 -> libgstsdp-1.0.so.0.201.0
- libgstnet-0.10.so.0 -> libgstnet-0.10.so.0.30.0
- libfarstream-0.1.so.0 -> libfarstream-0.1.so.0.0.1
- libgstfft-0.10.so.0 -> libgstfft-0.10.so.0.25.0
- libgstcdda-0.10.so.0 -> libgstcdda-0.10.so.0.25.0
- libbamf3.so.0 -> libbamf3.so.0.0.0
- libgstbasecamerabinsrc-1.0.so.0 -> libgstbasecamerabinsrc-1.0.so.0.7.0
- libexempi.so.3 -> libexempi.so.3.2.2
- libXss.so.1 -> libXss.so.1.0.0
- libffi.so.6 -> libffi.so.6.0.0
- libavformat.so.53 -> libavformat.so.53.21.1
- libgstpbutils-0.10.so.0 -> libgstpbutils-0.10.so.0.25.0
- libcdda_paranoia.so.0 -> libcdda_paranoia.so.0.10.2
- libavahi-gobject.so.0 -> libavahi-gobject.so.0.0.4
- libpolkit-gobject-1.so.0 -> libpolkit-gobject-1.so.0.0.0
- libXfixes.so.3 -> libXfixes.so.3.1.0
- libp11-kit.so.0 -> libp11-kit.so.0.0.0
- libpng12.so.0 -> libpng.so
- libswscale.so.2 -> libswscale.so.2.1.0
- libxkbfile.so.1 -> libxkbfile.so.1.0.2
- libcupscgi.so.1 -> libcupscgi.so.1
- libtic.so.5 -> libtic.so.5.9
- libSDL-1.2.so.0 -> libSDL-1.2.so.0.11.3
- libgettextpo.so.0 -> libgettextpo.so.0.5.1
- libgoa-1.0.so.0 -> libgoa-1.0.so.0.0.0
- libvisual-0.4.so.0 -> libvisual-0.4.so.0.0.0
- libQtXml.so.4 -> libQtXml.so.4.8.1
- libdrm_intel.so.1 -> libdrm_intel.so.1.0.0
- libltdl.so.7 -> libltdl.so.7.3.0
- libgomp.so.1 -> libgomp.so.1.0.0
- libXtst.so.6 -> libXtst.so.6.1.0
- libgtk-3.so.0 -> libgtk-3.so.0.400.2
- libogg.so.0 -> libogg.so.0.7.1
- libXaw.so.7 -> libXaw7.so.7.0.0
- libssh.so.4 -> libssh.so.4.2.2
- libtdb.so.1 -> libtdb.so.1.2.9
- libsvn_ra-1.so.1 -> libsvn_ra-1.so.1.0.0
- libiec61883.so.0 -> libiec61883.so.0.1.1
- libk5crypto.so.3 -> libk5crypto.so.3.1
- libXinerama.so.1 -> libXinerama.so.1.0.0
- libcupsfilters.so.1 -> libcupsfilters.so.1
- libfontconfig.so.1 -> libfontconfig.so.1.4.4
- libXrandr_ltss.so.2 -> libXrandr_ltss.so.2.2.0
- libcupsdriver.so.1 -> libcupsdriver.so.1
- libgstcontroller-1.0.so.0 -> libgstcontroller-1.0.so.0.201.0
- libgnutlsxx.so.27 -> libgnutlsxx.so.27.0.0
- libICE.so.6 -> libICE.so.6.3.0
- libQtGui.so.4 -> libQtGui.so.4.8.1
- libgssrpc.so.4 -> libgssrpc.so.4.1
- librsvg-2.so.2 -> librsvg-2.so.2.36.1
- libgdk-x11-2.0.so.0 -> libgdk-x11-2.0.so.0.2400.10
- libsvn_subr-1.so.1 -> libsvn_subr-1.so.1.0.0
- libgphoto2.so.2 -> libgphoto2.so.2.4.0
- libtiff.so.4 -> libtiff.so.4.3.4
- libv4l1.so.0 -> libv4l1.so.0
- libgstsdp-0.10.so.0 -> libgstsdp-0.10.so.0.25.0
- libORBitCosNaming-2.so.0 -> libORBitCosNaming-2.so.0.1.0
- libdatrie.so.1 -> libdatrie.so.1.1.0
- libplc4.so -> libplc4.so
- libwacom.so.2 -> libwacom.so.2.0.0
- libsoup-gnome-2.4.so.1 -> libsoup-gnome-2.4.so.1.5.0
- libwayland_ltss-server.so.0 -> libwayland_ltss-server.so.0.0.0
- libgstpbutils-1.0.so.0 -> libgstpbutils-1.0.so.0.201.0
- libpangoxft-1.0.so.0 -> libpangoxft-1.0.so.0.3000.0
- libglibmm-2.4.so.1 -> libglibmm-2.4.so.1.3.0
- libpulse.so.0 -> libpulse.so.0.13.5
- libbonobo-activation.so.4 -> libbonobo-activation.so.4.0.0
- libpolkit-agent-1.so.0 -> libpolkit-agent-1.so.0.0.0
- libtag.so.1 -> libtag.so.1.7.0
- libGLEWmx.so.1.6 -> libGLEWmx.so.1.6.0
- libatspi.so.0 -> libatspi.so.0.0.1
- libgphoto2_port.so.0 -> libgphoto2_port.so.0.8.0
- libcurl-gnutls.so.4 -> libcurl.so
- libgbm.so.1 -> libgbm.so.1.0.0
- libgstapp-0.10.so.0 -> libgstapp-0.10.so.0.25.0
- libsndfile.so.1 -> libsndfile.so.1.0.25
- libgmodule-2.0.so.0 -> libgmodule-2.0.so.0.3200.4
- libXmu.so.6 -> libXmu.so.6.2.0
- libaudiofile.so.1 -> libaudiofile.so.1.0.0
- libexif.so.12 -> libexif.so.12.3.2
- libXau.so.6 -> libXau.so.6.0.0
- libglapi.so.0 -> libglapi.so.0.0.0
- libgtksourceview-3.0.so.0 -> libgtksourceview-3.0.so.0.0.0
- liborc-0.4.so.0 -> liborc-0.4.so.0.18.0
- libnotify.so.4 -> libnotify.so.4.0.0
- libwind.so.0 -> libwind.so.0.0.0
- libldap_r-2.4.so.2 -> libldap_r.so
- libpcrecpp.so.0 -> libpcrecpp.so.0.0.0
- libgstinterfaces-0.10.so.0 -> libgstinterfaces-0.10.so.0.25.0
- libelf.so.1 -> libelf-0.152.so
- libdrm_nouveau.so.1 -> libdrm_nouveau1.so
- libthai.so.0 -> libthai.so.0.1.6
- libgstnet-1.0.so.0 -> libgstnet-1.0.so.0.201.0
- libcares.so.2 -> libcares.so.2.0.0
- liborc-test-0.4.so.0 -> liborc-test-0.4.so.0.18.0
- libaa.so.1 -> libaa.so.1.0.4
- libsvn_ra_local-1.so.1 -> libsvn_ra_local-1.so.1.0.0
- libdrm.so.2 -> libdrm.so.2.4.0
- libLLVM-3.3.so.1 -> libLLVM-3.3.so.1
- libpcap.so.0.8 -> libpcap.so.1.1.1
- libcupsmime.so.1 -> libcupsmime.so.1
- libxcb.so.1 -> libxcb.so.1.1.0
- libSM.so.6 -> libSM.so.6.0.1
- libkms.so.1 -> libkms.so.1.0.0
- libdbusmenu-gtk.so.4 -> libdbusmenu-gtk.so.4.0.13
- libFLAC.so.8 -> libFLAC.so.8.2.0
- libxcb-xfixes.so.0 -> libxcb-xfixes.so.0.0.0
- libgstriff-1.0.so.0 -> libgstriff-1.0.so.0.201.0
- libidn.so.11 -> libidn.so.11.6.6
- libIDL-2.so.0 -> libIDL-2.so.0.0.0
- libdbusmenu-qt.so.2 -> libdbusmenu-qt.so.2.6.0
- libQtScript.so.4 -> libQtScript.so.4.8.1
- libcairo-gobject.so.2 -> libcairo-gobject.so.2.11000.2
- libluajit-5.1.so.2 -> libluajit-5.1.so.2.0.0
- libpangomm-1.4.so.1 -> libpangomm-1.4.so.1.0.30
- libXpm.so.4 -> libXpm.so.4.11.0
- libsvn_diff-1.so.1 -> libsvn_diff-1.so.1.0.0
- libdbusmenu-glib.so.4 -> libdbusmenu-glib.so.4.0.13
- liblua5.1.so.0 -> liblua5.1.so.0.0.0
- libbonobo-2.so.0 -> libbonobo-2.so.0.0.0
- libpulse-mainloop-glib.so.0 -> libpulse-mainloop-glib.so.0.0.4
- libexslt.so.0 -> libexslt.so.0.8.15
- libmp3lame.so.0 -> libmp3lame.so.0.0.0
- libpcreposix.so.3 -> libpcreposix.so.3.12.1
- libquvi.so.7 -> libquvi.so.7.0.0
- libaudio.so.2 -> libaudio.so.2.4
- libpulse-simple.so.0 -> libpulse-simple.so.0.0.3
- liboauth.so.0 -> liboauth.so.0.8.1
- libQtCore.so.4 -> libQtCore.so.4.8.1
- libwayland_ltss-client.so.0 -> libwayland_ltss-client.so.0.1.0
- libQtDBus.so.4 -> libQtDBus.so.4.8.1
- libtheoraenc.so.1 -> libtheoraenc.so.1.1.2
- libatkmm-1.6.so.1 -> libatkmm-1.6.so.1.1.0
- libgailutil-3.so.0 -> libgailutil-3.so.0.0.0
- libgsttag-1.0.so.0 -> libgsttag-1.0.so.0.201.0
- libgdk_pixbuf_xlib-2.0.so.0 -> libgdk_pixbuf_xlib-2.0.so.0.2600.1
- libkrb5.so.3 -> libkrb5.so.3.3
- libgnome-2.so.0 -> libgnome-2.so.0.3200.1
- libgallium.so.0 -> libgallium.so.0.0.0
- libXcomposite.so.1 -> libXcomposite.so.1.0.0
- libsvn_fs-1.so.1 -> libsvn_fs-1.so.1.0.0
- libgstreamer-0.10.so.0 -> libgstreamer-0.10.so.0.30.0
- libXrender.so.1 -> libXrender.so.1.3.0
- libmng.so.1 -> libmng.so.1.1.0.10
- libgdu.so.0 -> libgdu.so.0.0.0
- libxatracker.so.1 -> libxatracker.so.1.0.0
- librom1394.so.0 -> librom1394.so.0.3.0
- liblua5.1-c++.so.0 -> liblua5.1-c++.so.0.0.0
- libplds4.so -> libplds4.so
- libbamf.so.0 -> libbamf.so.0.0.0
- libheimntlm.so.0 -> libheimntlm.so.0.1.0
- libarchive.so.12 -> libarchive.so.12.0.3
- libmad.so.0 -> libmad.so.0.2.1
- libgthread-2.0.so.0 -> libgthread-2.0.so.0.3200.4
- libgstaudio-1.0.so.0 -> libgstaudio-1.0.so.0.201.0
- libgudev-1.0.so.0 -> libgudev-1.0.so.0.1.1
- libvpx.so.1 -> libvpx.so.1.2.0
- libgailutil.so.18 -> libgailutil.so.18.0.1
- libsvn_client-1.so.1 -> libsvn_client-1.so.1.0.0
- libdricore9.2.1.so.1 -> libdricore9.2.1.so.1.0.0
- libQtOpenGL.so.4 -> libQtOpenGL.so.4.8.1
- libhunspell-1.3.so.0 -> libhunspell-1.3.so.0.0.0
- libcupsppdc.so.1 -> libcupsppdc.so.1
- libkdb5.so.6 -> libkdb5.so.6.0
- libpixman-1.so.0 -> libpixman-1.so.0.30.2
- libpolkit-backend-1.so.0 -> libpolkit-backend-1.so.0.0.0
- libibus-1.0.so.0 -> libibus-1.0.so.0.401.0
- libxcb-dri2.so.0 -> libxcb-dri2.so.0.0.0
- libgstcheck-0.10.so.0 -> libgstcheck-0.10.so.0.30.0
- libXp.so.6 -> libXp.so.6.2.0
- libart_lgpl_2.so.2 -> libart_lgpl_2.so.2.3.21
- libhx509.so.5 -> libhx509.so.5.0.0
- libform.so.5 -> libform.so.5.9
- libgstbase-1.0.so.0 -> libgstbase-1.0.so.0.201.0
- libX11-xcb.so.1 -> libX11-xcb.so.1.0.0
- libgstaudio-0.10.so.0 -> libgstaudio-0.10.so.0.25.0
- libjson-glib-1.0.so.0 -> libjson-glib-1.0.so.0.1400.2
- libspeex.so.1 -> libspeex.so.1.5.0
- libsvn_fs_util-1.so.1 -> libsvn_fs_util-1.so.1.0.0
- libpoppler.so.19 -> libpoppler.so.19.0.0
- libdconf.so.0 -> libdconf.so.0.0.0
- libavahi-common.so.3 -> libavahi-common.so.3.5.3
- libyajl.so.1 -> libyajl.so.1.0.12
- libvorbis.so.0 -> libvorbis.so.0.4.5
- libavc1394.so.0 -> libavc1394.so.0.3.0
- libv4l2.so.0 -> libv4l2.so.0
- libcolord.so.1 -> libcolord.so.1.0.8
- libcairo.so.2 -> libcairo.so.2.11000.2
- libGLEW.so.1.6 -> libGLEW.so.1.6.0
- libgdbm_compat.so.3 -> libgdbm_compat.so.3.0.0
- libdb-5.1.so -> libdb-5.1.so
- libXt.so.6 -> libXt.so.6.0.0
- libwavpack.so.1 -> libwavpack.so.1.1.4
- libmpfr.so.4 -> libmpfr.so.4.1.0
- libpangoft2-1.0.so.0 -> libpangoft2-1.0.so.0.3000.0
- libieee1284.so.3 -> libieee1284.so.3.2.2
- libfreetype.so.6 -> libfreetype.so.6.8.0
- libdrm_nouveau.so.2 -> libdrm_nouveau.so.2.0.0
- libgssapi.so.3 -> libgssapi.so.3.0.0
- libspeexdsp.so.1 -> libspeexdsp.so.1.5.0
- libdconf-dbus-1.so.0 -> libdconf-dbus-1.so.0.0.0
- libgmp.so.10 -> libgmp.so.10.0.2
- libcaca.so.0 -> libcucul.so.0.99.17
- libcairomm-1.0.so.1 -> libcairomm-1.0.so.1.4.0
- libsvn_repos-1.so.1 -> libsvn_repos-1.so.1.0.0
- libgupnp-igd-1.0.so.4 -> libgupnp-igd-1.0.so.4.1.0
- libgstvideo-1.0.so.0 -> libgstvideo-1.0.so.0.201.0
- libXdamage.so.1 -> libXdamage.so.1.1.0
- libasn1.so.8 -> libasn1.so.8.0.0
- libsvn_fs_base-1.so.1 -> libsvn_fs_base-1.so.1.0.0
- libvorbisenc.so.2 -> libvorbisenc.so.2.0.8
- libgstapp-1.0.so.0 -> libgstapp-1.0.so.0.201.0
- libvo-amrwbenc.so.0 -> libvo-amrwbenc.so.0.0.2
- libtalloc.so.2 -> libtalloc.so.2.0.7
- libshout.so.3 -> libshout.so.3.2.0
- libnice.so.10 -> libnice.so.10.0.1
- libbluetooth.so.3 -> libbluetooth.so.3.11.5
- libgrail.so.5 -> libgrail.so.5.0.0
- libgutenprint.so.3 -> libgutenprint.so.3.0.0
- libmenuw.so.5 -> libmenuw.so.5.9
- libpanelw.so.5 -> libpanelw.so.5.9
- libkrb5.so.26 -> libkrb5.so.26.0.0
- libgdu-gtk.so.0 -> libgdu-gtk.so.0.0.0
- libgdbm.so.3 -> libgdbm.so.3.0.0
- libgnutls-openssl.so.27 -> libgnutls-openssl.so.27.0.0
- libmenu.so.5 -> libmenu.so.5.9
- libpangox-1.0.so.0 -> libpangox-1.0.so.0.3000.0
- libXft.so.2 -> libXft.so.2.2.0
- libsensors.so.4 -> libsensors.so.4.3.1
- libgstphotography-0.10.so.0 -> libgstphotography-0.10.so.0.0.0
- libstartup-notification-1.so.0 -> libstartup-notification-1.so.0.0.0
- libatk-1.0.so.0 -> libatk-1.0.so.0.20409.1
- libsvn_auth_gnome_keyring-1.so.1 -> libsvn_auth_gnome_keyring-1.so.1.0.0
- libquadmath.so.0 -> libquadmath.so.0.0.0
- libgif.so.4 -> libungif.so.4.1.6
- libstdc++.so.6 -> libstdc++.so.6.0.16
- liblzma.so.5 -> liblzma.so.5.0.0
- libass.so.4 -> libass.so.4.1.0
- libproxy.so.1 -> libproxy.so.1.0.0
- libcaca++.so.0 -> libcucul++.so.0.99.17
- libglade-2.0.so.0 -> libglade-2.0.so.0.0.7
- libavutil.so.51 -> libavutil.so.51.22.2
- libxslt.so.1 -> libxslt.so.1.1.26
- libva.so.1 -> libva.so.1.3200.0
- libsmime3.so -> libsmime3.so
- libdv.so.4 -> libdv.so.4.0.3
- libavahi-client.so.3 -> libavahi-client.so.3.2.9
- libsvn_fs_fs-1.so.1 -> libsvn_fs_fs-1.so.1.0.0
- libgiomm-2.4.so.1 -> libgiomm-2.4.so.1.3.0
- libgstrtp-1.0.so.0 -> libgstrtp-1.0.so.0.201.0
- libgnutls.so.26 -> libgnutls.so.26.21.8
- libQtXmlPatterns.so.4 -> libQtXmlPatterns.so.4.8.1
- libao.so.4 -> libao.so.4.0.0
- libpulsecommon-1.1.so -> libpulsecommon-1.1.so
- libQtCLucene.so.4 -> libQtCLucene.so.4.8.1
- libgstbase-0.10.so.0 -> libgstbase-0.10.so.0.30.0
- libsvn_auth_kwallet-1.so.1 -> libsvn_auth_kwallet-1.so.1.0.0
- libjpeg.so.8 -> libjpeg.so.8.0.2
- libsamplerate.so.0 -> libsamplerate.so.0.1.8
- libcurl.so.4 -> libcurl.so.4.2.0
- libpipeline.so.1 -> libpipeline.so.1.2.1
- libglamor_ltss.so.0 -> libglamor_ltss.so.0.0.0
- libpciaccess.so.0 -> libpciaccess.so.0.11.0
- libnssutil3.so -> libnssutil3.so
- libgstriff-0.10.so.0 -> libgstriff-0.10.so.0.25.0
- libXcursor.so.1 -> libXcursor.so.1.0.2
- libformw.so.5 -> libformw.so.5.9
- libjson.so.0 -> libjson.so.0.0.1
- libgconf-2.so.4 -> libgconf-2.so.4.1.5
- libkrb5support.so.0 -> libkrb5support.so.0.1
- libwmf-0.2.so.7 -> libwmf-0.2.so.7.1.0
- libdiscid.so.0 -> libdiscid.so.0.2.1
- libjacknet.so.0 -> libjacknet.so.0.1.0
- libgstbasecamerabinsrc-0.10.so.0 -> libgstbasecamerabinsrc-0.10.so.0.0.0
- libgee.so.2 -> libgee.so.2.0.0
- libavahi-core.so.7 -> libavahi-core.so.7.0.2
- liblcms.so.1 -> liblcms.so.1.0.19
- liblockfile.so.1 -> liblockfile.so.1.0
- libdb-4.8.so -> libdb-4.8.so
- libxcb-glx.so.0 -> libxcb-glx.so.0.0.0
- libtiffxx.so.0 -> libtiffxx.so.0.0.8
- libasyncns.so.0 -> libasyncns.so.0.3.1
- libcdda_interface.so.0 -> libcdda_interface.so.0.10.2
- libgstrtsp-0.10.so.0 -> libgstrtsp-0.10.so.0.25.0
- libtheora.so.0 -> libtheora.so.0.3.10
- libvo-aacenc.so.0 -> libvo-aacenc.so.0.0.2
- libORBit-2.so.0 -> libORBit-2.so.0.1.0
- libv4lconvert.so.0 -> libv4lconvert.so.0
- libXv.so.1 -> libXv.so.1.0.0
- libgnomeui-2.so.0 -> libgnomeui-2.so.0.2400.5
- libsvn_wc-1.so.1 -> libsvn_wc-1.so.1.0.0
- libgstphotography-1.0.so.0 -> libgstphotography-1.0.so.0.7.0
- libasound.so.2 -> libasound.so.2.0.0
- libsvn_ra_neon-1.so.1 -> libsvn_ra_neon-1.so.1.0.0
- libcroco-0.6.so.3 -> libcroco-0.6.so.3.0.1
- libopus.so.0 -> libopus.so.0.5.0
- libXext.so.6 -> libXext.so.6.4.0
- libXrandr.so.2 -> libXrandr.so.2.2.0
- libQtSql.so.4 -> libQtSql.so.4.8.1
- libsonic.so.0 -> libsonic.so.0.1.17
- libapt-inst.so.1.4 -> libapt-inst.so.1.4.0
- libgstvideo-0.10.so.0 -> libgstvideo-0.10.so.0.25.0
- libpanel.so.5 -> libpanel.so.5.9
- libSoundTouch.so.0 -> libSoundTouch.so.0.0.0
- libgd.so.2 -> libgd.so.2.0.0
- libXxf86vm.so.1 -> libXxf86vm.so.1.0.0
- libpulsedsp.so -> libpulsedsp.so
- libGLU.so.1 -> libGLU.so.1.3.08004
- libmpc.so.2 -> libmpc.so.2.0.0
- libgdk_pixbuf-2.0.so.0 -> libgdk_pixbuf-2.0.so.0.2600.1
- libroken.so.18 -> libroken.so.18.1.0
- libtasn1.so.3 -> libtasn1.so.3.1.12
- libsvn_delta-1.so.1 -> libsvn_delta-1.so.1.0.0
- libgstrtp-0.10.so.0 -> libgstrtp-0.10.so.0.25.0
- libgstnetbuffer-0.10.so.0 -> libgstnetbuffer-0.10.so.0.25.0
- libgstfft-1.0.so.0 -> libgstfft-1.0.so.0.201.0
- libORBit-imodule-2.so.0 -> libORBit-imodule-2.so.0.0.0
- libkadm5srv_mit.so.8 -> libkadm5srv_mit.so.8.0
- libgssapi_krb5.so.2 -> libgssapi_krb5.so.2.2
- libdrm_radeon.so.1 -> libdrm_radeon.so.1.0.1
- libgoa-backend-1.0.so.0 -> libgoa-backend-1.0.so.0.0.0
- libXmuu.so.1 -> libXmuu.so.1.0.0
- libpango-1.0.so.0 -> libpango-1.0.so.0.3000.0
- libsigc-2.0.so.0 -> libsigc-2.0.so.0.0.0
- libsoup-2.4.so.1 -> libsoup-2.4.so.1.5.0
- libssh_threads.so.4 -> libssh_threads.so.4.2.2
- libkadm5clnt_mit.so.8 -> libkadm5clnt_mit.so.8.0
- libgstcodecparsers-1.0.so.0 -> libgstcodecparsers-1.0.so.0.5.0
- libgstrtsp-1.0.so.0 -> libgstrtsp-1.0.so.0.201.0
- libgtk-x11-2.0.so.0 -> libgtk-x11-2.0.so.0.2400.10
- libespeak.so.1 -> libespeak.so.1.1.46
- libjack.so.0 -> libjack.so.0.1.0
- libxcb-shm.so.0 -> libxcb-shm.so.0.0.0
- libQtSvg.so.4 -> libQtSvg.so.4.8.1
- libglibmm_generate_extra_defs-2.4.so.1 -> libglibmm_generate_extra_defs-2.4.so.1.3.0
- libcurl-nss.so.4 -> libcurl-nss.so.4.2.0
- libtelepathy-logger.so.2 -> libtelepathy-logger.so.2.2.1
- libX11.so.6 -> libX11.so.6.3.0
- libexpatw.so.1 -> libexpatw.so.1.5.2
- libxml2.so.2 -> libxml2.so.2.7.8
- libsane.so.1 -> libsane.so.1.0.22
- libgeis.so.1 -> libgeis.so.1.3.0
- libgnome-keyring.so.0 -> libgnome-keyring.so.0.2.0
- libgdk-3.so.0 -> libgdk-3.so.0.400.2
- libgstreamer-1.0.so.0 -> libgstreamer-1.0.so.0.201.0
- libgstcheck-1.0.so.0 -> libgstcheck-1.0.so.0.201.0
- libheimbase.so.1 -> libheimbase.so.1.0.0
- libsasl2.so.2 -> libsasl2.so.2.0.25
- liblouis.so.2 -> liblouis.so.2.2.3
- libgnomevfs-2.so.0 -> libgnomevfs-2.so.0.2400.4
- libgstdataprotocol-0.10.so.0 -> libgstdataprotocol-0.10.so.0.30.0
- libvorbisfile.so.3 -> libvorbisfile.so.3.3.4
-/usr/local/lib:
- libefreet.so.1 -> libefreet.so.1.9.3
- libecore_ipc.so.1 -> libecore_ipc.so.1.9.3
- libefreet_trash.so.1 -> libefreet_trash.so.1.9.3
- libecore_evas.so.1 -> libecore_evas.so.1.9.3
- libecore.so.1 -> libecore.so.1.9.3
- libmosquittopp.so.1 -> libmosquittopp.so.1
- libeina.so.1 -> libeina.so.1.9.3
- libeet.so.1 -> libeet.so.1.9.3
- libecore_imf_evas.so.1 -> libecore_imf_evas.so.1.9.3
- libembryo.so.1 -> libembryo.so.1.9.3
- libecore_avahi.so.1 -> libecore_avahi.so.1.9.3
- libeldbus.so.1 -> libeldbus.so.1.9.3
- libethumb.so.1 -> libethumb.so.1.9.3
- libemotion.so.1 -> libemotion.so.1.9.3
- libecore_con.so.1 -> libecore_con.so.1.9.3
- libecore_imf.so.1 -> libecore_imf.so.1.9.3
- libeeze.so.1 -> libeeze.so.1.9.3
- libecore_input.so.1 -> libecore_input.so.1.9.3
- libedje.so.1 -> libedje.so.1.9.3
- libeo.so.1 -> libeo.so.1.9.3
- libethumb_client.so.1 -> libethumb_client.so.1.9.3
- libecore_file.so.1 -> libecore_file.so.1.9.3
- libeio.so.1 -> libeio.so.1.9.3
- libmosquitto.so.1 -> libmosquitto.so.1
- libelementary.so.1 -> libelementary.so.1.9.3
- libecore_audio.so.1 -> libecore_audio.so.1.9.3
- libevas.so.1 -> libevas.so.1.9.3
- libecore_input_evas.so.1 -> libecore_input_evas.so.1.9.3
- libefreet_mime.so.1 -> libefreet_mime.so.1.9.3
- libecore_x.so.1 -> libecore_x.so.1.9.3
-/lib:
- libnl-genl-3.so.200 -> libnl-genl-3.so.200.3.0
- libnss_mdns6_minimal.so.2 -> libnss_mdns6_minimal.so.2
- libip6tc.so.0 -> libip6tc.so.0.0.0
- libply.so.2 -> libply.so.2.0.0
- libnss_mdns6.so.2 -> libnss_mdns6.so.2
- libipq_pic.so.0 -> libipq_pic.so.0.0.0
- liblvm2app.so.2.2 -> liblvm2app.so.2.2
- libdevmapper.so.1.02.1 -> libdevmapper.so.1.02.1
- libcryptsetup.so.4 -> libcryptsetup.so.4.0.0
- libnss_mdns.so.2 -> libnss_mdns.so.2
- libnss_mdns_minimal.so.2 -> libnss_mdns_minimal.so.2
- libfuse.so.2 -> libfuse.so.2.8.6
- libiw.so.30 -> libiw.so.30
- libdevmapper-event.so.1.02.1 -> libdevmapper-event.so.1.02.1
- libply-splash-graphics.so.2 -> libply-splash-graphics.so.2.0.0
- libply-splash-core.so.2 -> libply-splash-core.so.2.0.0
- libsysfs.so.2 -> libsysfs.so.2.0.1
- libply-boot-client.so.2 -> libply-boot-client.so.2.0.0
- libnss_mdns4.so.2 -> libnss_mdns4.so.2
- libnss_mdns4_minimal.so.2 -> libnss_mdns4_minimal.so.2
- libproc-3.2.8.so -> libproc-3.2.8.so
- libbrlapi.so.0.5 -> libbrlapi.so.0.5.6
- libnewt.so.0.52 -> libnewt.so.0.52.11
- libipq.so.0 -> libipq.so.0.0.0
- libiptc.so.0 -> libiptc.so.0.0.0
- libulockmgr.so.1 -> libulockmgr.so.1.0.1
- libnl-3.so.200 -> libnl-3.so.200.3.0
- libxtables.so.7 -> libxtables.so.7.0.0
- libip4tc.so.0 -> libip4tc.so.0.0.0
- libx86.so.1 -> libx86.so.1
-/usr/lib:
- liba52-0.7.4.so -> liba52-0.7.4.so
- libvncserver.so.0 -> libvncserver.so.0.0.0
- libspandsp.so.2 -> libspandsp.so.2.0.0
- libflite_usenglish.so.1 -> libflite_usenglish.so.1.4
- libido3-0.1.so.0 -> libido3-0.1.so.0.0.0
- libicui18n.so.48 -> libicui18n.so.48.1.1
- libXvMC.so.1 -> libXvMC.so.1.0.0
- libdmapsharing-3.0.so.2 -> libdmapsharing-3.0.so.2.9.14
- libgmime-2.6.so.0 -> libgmime-2.6.so.0.600.7
- libefreet_trash.so.1 -> libefreet_trash.so.1.0.0
- libQtGConf.so.1 -> libQtGConf.so.1.0.0
- libbfd-2.22-system.so -> libbfd-2.22-system.so
- libgs.so.9 -> libgs.so.9.05
- libedbus.so.1 -> libedbus.so.1.0.0
- libperl.so.5.14 -> libperl.so.5.14.2
- libgdkmm-3.0.so.1 -> libgdkmm-3.0.so.1.1.0
- libeconnman.so.1 -> libeconnman.so.1.0.0
- libxklavier.so.16 -> libxklavier.so.16.2.0
- libnux-2.0.so.0 -> libnux-2.0.so.0.1401.0
- libvlccore.so.5 -> libvlccore.so.5.1.1
- libopcodes-2.22-system.so -> libopcodes-2.22-system.so
- libaccountsservice.so.0 -> libaccountsservice.so.0.0.0
- libnm-util.so.2 -> libnm-util.so.2.3.0
- libjavascriptcoregtk-1.0.so.0 -> libjavascriptcoregtk-1.0.so.0.13.4
- libpulsecore-1.1.so -> libpulsecore-1.1.so
- libflite_cmu_us_slt.so.1 -> libflite_cmu_us_slt.so.1.4
- libkeybinder.so.0 -> libkeybinder.so.0.0.1
- libguile-srfi-srfi-1-v-3.so.3 -> libguile-srfi-srfi-1-v-3.so.3.0.2
- libindicator-messages-status-provider.so.1 -> libindicator-messages-status-provider.so.1.0.0
- libopencore-amrwb.so.0 -> libopencore-amrwb.so.0.0.2
- libfolks.so.25 -> libfolks.so.25.7.0
- libisccc.so.80 -> libisccc.so.80.0.0
- libutempter.so.0 -> libutempter.so.1.1.5
- libijs-0.35.so -> libijs-0.35.so
- libefreet.so.1 -> libefreet.so.1.0.0
- libflite_cmu_us_awb.so.1 -> libflite_cmu_us_awb.so.1.4
- libwpg-0.2.so.2 -> libwpg-0.2.so.2.0.1
- libvte2_90.so.9 -> libvte2_90.so.9.3200.1
- libvncclient.so.0 -> libvncclient.so.0.0.0
- libtcl8.5.so.0 -> libtcl8.5.so.0
- libgnome-control-center.so.1 -> libgnome-control-center.so.1.0.0
- libpyglib-gi-2.0-python2.7.so.0 -> libpyglib-gi-2.0-python2.7.so.0.0.0
- libisc.so.83 -> libisc.so.83.0.1
- libenotify.so.1 -> libenotify.so.1.0.0
- libwps-0.2.so.2 -> libwps-0.2.so.2.0.4
- libschroedinger-1.0.so.0 -> libschroedinger-1.0.so.0.11.0
- libgtkmm-3.0.so.1 -> libgtkmm-3.0.so.1.1.0
- librest-0.7.so.0 -> librest-0.7.so.0.0.0
- libicalss.so.0 -> libicalss.so.0.48.0
- libgrip.so.0 -> libgrip.so.0.305.0
- libtimezonemap.so.1 -> libtimezonemap.so.1.0.0
- libecore_evas.so.1 -> libecore_evas.so.1.0.0
- libvte.so.9 -> libvte.so.9.2800.2
- libmetacity-private.so.0 -> libmetacity-private.so.0.0.0
- libXxf86dga.so.1 -> libXxf86dga.so.1.0.0
- libgck-1.so.0 -> libgck-1.so.0.0.0
- libicutu.so.48 -> libicutu.so.48.1.1
- libedje.so.1 -> libedje.so.1.0.0
- libgwibber-gtk.so.2 -> libgwibber-gtk.so.2.0.0
- libpurple-client.so.0 -> libpurple-client.so.0.10.3
- libhpip.so.0 -> libhpip.so.0.0.1
- libwnck-1.so.22 -> libwnck-1.so.22.3.31
- libfreerdp-core.so.1.0 -> libfreerdp-core.so.1.0.1
- libmhash.so.2 -> libmhash.so.2.0.1
- libindicator3.so.7 -> libindicator3.so.7.0.0
- libfreerdp-codec.so.1.0 -> libfreerdp-codec.so.1.0.1
- libflite.so.1 -> libflite.so.1.4
- libgweather-3.so.0 -> libgweather-3.so.0.0.6
- libpeas-1.0.so.0 -> libpeas-1.0.so.0.200.0
- libbind9.so.80 -> libbind9.so.80.0.3
- libgnomekbd.so.7 -> libgnomekbd.so.7.0.0
- libcrypto.so.1.0.0 -> libcrypto.so.1.0.0
- libwnck-3.so.0 -> libwnck-3.so.0.2.0
- libeina.so.1 -> libeina.so.1.0.0
- libebook-1.2.so.12 -> libebook-1.2.so.12.3.1
- libFS.so.6 -> libFS.so.6.0.0
- libnetsnmpagent.so.15 -> libnetsnmpagent.so.15.1.2
- libdaemon.so.0 -> libdaemon.so.0.5.0
- libfribidi.so.0 -> libfribidi.so.0.3.1
- libeet.so.1 -> libeet.so.1.4.0
- libunity-misc.so.4 -> libunity-misc.so.4.1.0
- libbulletml.so.0d2 -> libbulletml.so.0d2.0
- libebluez.so.1 -> libebluez.so.1.0.0
- libindicate.so.5 -> libindicate.so.5.0.7
- libicule.so.48 -> libicule.so.48.1.1
- libmtdev.so.1 -> libmtdev.so.1.0.0
- libgnome-media-profiles-3.0.so.0 -> libgnome-media-profiles-3.0.so.0.0.0
- libnetsnmpmibs.so.15 -> libnetsnmpmibs.so.15.1.2
- liboverlay-scrollbar-0.2.so.0 -> liboverlay-scrollbar-0.2.so.0.0.16
- libecore_imf_evas.so.1 -> libecore_imf_evas.so.1.0.0
- libpaper.so.1 -> libpaper.so.1.1.2
- libjte.so.1 -> libjte.so.1.0.0
- libdotconf-1.0.so.0 -> libdotconf-1.0.so.0.10.4
- libicutest.so.48 -> libicutest.so.48.1.1
- libmimic.so.0 -> libmimic.so.0.0.1
- libeukit.so.1 -> libeukit.so.1.0.0
- libtotem-plparser.so.17 -> libtotem-plparser.so.17.0.3
- libfolks-telepathy.so.25 -> libfolks-telepathy.so.25.7.0
- libgtop-2.0.so.7 -> libgtop-2.0.so.7.2.0
- libtwolame.so.0 -> libtwolame.so.0.0.0
- libgwibber.so.2 -> libgwibber.so.2.0.0
- libfreerdp-utils.so.1.0 -> libfreerdp-utils.so.1.0.1
- libgnome-menu.so.2 -> libgnome-menu.so.2.4.13
- libecore_file.so.1 -> libecore_file.so.1.0.0
- libedataserver-1.2.so.15 -> libedataserver-1.2.so.15.0.0
- librasqal.so.3 -> librasqal.so.3.0.0
- libgexiv2.so.1 -> libgexiv2.so.1.0.0
- libgettextlib-0.18.1.so -> libgettextlib.so
- libmythes-1.2.so.0 -> libmythes-1.2.so.0.0.0
- libprotoc.so.7 -> libprotoc.so.7.0.0
- libfreerdp-rail.so.1.0 -> libfreerdp-rail.so.1.0.1
- libsgutils2.so.2 -> libsgutils2.so.2.0.0
- libaprutil-1.so.0 -> libaprutil-1.so.0.3.12
- libraptor2.so.0 -> libraptor2.so.0.0.0
- libgirepository-1.0.so.1 -> libgirepository-1.0.so.1.0.0
- libunity-core-5.0.so.5 -> libunity-core-5.0.so.5.0.0
- libflite_cmu_us_kal16.so.1 -> libflite_cmu_us_kal16.so.1.4
- libecore_con.so.1 -> libecore_con.so.1.0.0
- libecore_input_evas.so.1 -> libecore_input_evas.so.1.0.0
- libjbig2dec.so.0 -> libjbig2dec.so.0.0.0
- libnetsnmp.so.15 -> libnetsnmp.so.15.1.2
- libzbar.so.0 -> libzbar.so.0.2.0
- libXRes.so.1 -> libXRes.so.1.0.0
- libcdio_paranoia.so.1 -> libcdio_paranoia.so.1.0.0
- libedata-book-1.2.so.11 -> libedata-book-1.2.so.11.0.0
- libnetsnmphelpers.so.15 -> libnetsnmphelpers.so.15.1.2
- libgksu2.so.0 -> libgksu2.so.0.0.2
- libQtBamf.so.1 -> libQtBamf.so.1.0.0
- libnautilus-extension.so.1 -> libnautilus-extension.so.1.4.0
- libebackend-1.2.so.1 -> libebackend-1.2.so.1.0.0
- libI810XvMC.so.1 -> libI810XvMC.so.1.0.0
- libembryo.so.1 -> libembryo.so.1.0.0
- libmission-control-plugins.so.0 -> libmission-control-plugins.so.0.3.1
- libguilereadline-v-17.so.17 -> libguilereadline-v-17.so.17.0.3
- libsox.so.1 -> libsox.so.1.0.0
- libcdio.so.13 -> libcdio.so.13.0.0
- libsqlite.so.0 -> libsqlite.so.0.8.6
- libecore_imf.so.1 -> libecore_imf.so.1.0.0
- libevdocument3.so.4 -> libevdocument3.so.4.0.0
- libehal.so.1 -> libehal.so.1.0.0
- libt1.so.5 -> libt1.so.5.1.2
- libdconf-qt.so.0 -> libdconf-qt.so.0.0.0
- libboost_wserialization.so.1.46.1 -> libboost_wserialization.so.1.46.1
- libaspell.so.15 -> libaspell.so.15.2.0
- libusbmuxd.so.1 -> libusbmuxd.so.1.0.7
- libevent-2.0.so.5 -> libevent-2.0.so.5.1.4
- libdee-1.0.so.4 -> libdee-1.0.so.4.1.1
- libimobiledevice.so.2 -> libimobiledevice.so.2.0.1
- libtotem.so.0 -> libtotem.so.0.0.0
- libopencore-amrnb.so.0 -> libopencore-amrnb.so.0.0.2
- libgtkspell-3.so.0 -> libgtkspell-3.so.0.0.0
- libsyncdaemon-1.0.so.1 -> libsyncdaemon-1.0.so.1.0.0
- libid3tag.so.0 -> libid3tag.so.0.3.0
- libxcb-keysyms.so.1 -> libxcb-keysyms.so.1.0.0
- liblwres.so.80 -> liblwres.so.80.0.1
- libgnome-menu-3.so.0 -> libgnome-menu-3.so.0.0.1
- libgpgme-pthread.so.11 -> libgpgme-pthread.so.11.7.0
- libXvMCW.so.1 -> libXvMCW.so.1.0.0
- libenchant.so.1 -> libenchant.so.1.6.0
- libgupnp-1.0.so.4 -> libgupnp-1.0.so.4.0.0
- liblightdm-gobject-1.so.0 -> liblightdm-gobject-1.so.0.0.0
- libasprintf.so.0 -> libasprintf.so.0.0.0
- libprotobuf.so.7 -> libprotobuf.so.7.0.0
- libwebkitgtk-1.0.so.0 -> libwebkitgtk-1.0.so.0.13.4
- libmpeg2.so.0 -> libmpeg2.so.0.0.0
- libssl.so.1.0.0 -> libssl.so.1.0.0
- libfreerdp-gdi.so.1.0 -> libfreerdp-gdi.so.1.0.1
- libgpgme.so.11 -> libgpgme.so.11.7.0
- libplist.so.1 -> libplist.so.1.1.8
- libmtp.so.9 -> libmtp.so.9.0.3
- libecore_x.so.1 -> libecore_x.so.1.0.0
- libcap-ng.so.0 -> libcap-ng.so.0.0.0
- libnux-core-2.0.so.0 -> libnux-core-2.0.so.0.1401.0
- libpyglib-2.0-python2.7.so.0 -> libpyglib-2.0-python2.7.so.0.0.0
- libsidplay.so.1 -> libsidplay.so.1.0.3
- libXfont.so.1 -> libXfont.so.1.4.1
- libical.so.0 -> libical.so.0.48.0
- libdvdnav.so.4 -> libdvdnav.so.4.2.0
- libfreerdp-cache.so.1.0 -> libfreerdp-cache.so.1.0.1
- libexttextcat.so.0 -> libexttextcat.so.0.0.0
- libboost_serialization.so.1.46.1 -> libboost_serialization.so.1.46.1
- libmagic.so.1 -> libmagic.so.1.0.0
- libcamel-provider-1.2.so.29 -> libcamel-provider-1.2.so.29.0.0
- libedata-cal-1.2.so.13 -> libedata-cal-1.2.so.13.0.0
- libxcb-image.so.0 -> libxcb-image.so.0.0.0
- librpmbuild.so.2 -> librpmbuild.so.2.0.1
- libzeitgeist-1.0.so.1 -> libzeitgeist-1.0.so.1.1.4
- libmpeg2convert.so.0 -> libmpeg2convert.so.0.0.0
- libecore.so.1 -> libecore.so.1.0.0
- libwpd-0.9.so.9 -> libwpd-0.9.so.9.0.4
- libmms.so.0 -> libmms.so.0.0.2
- libstlport_gcc.so.4.6 -> libstlport_gcc.so.4.6
- libopencc.so.1 -> libopencc.so.1.0.0
- libck-connector.so.0 -> libck-connector.so.0.0.0
- libcdio_cdda.so.1 -> libcdio_cdda.so.1.0.0
- librdf.so.0 -> librdf.so.0.0.0
- libtelepathy-glib.so.0 -> libtelepathy-glib.so.0.70.2
- libGeoIPUpdate.so.0 -> libGeoIPUpdate.so.0.0.0
- libraw_r.so.5 -> libraw_r.so.5.0.0
- libwebkitgtk-3.0.so.0 -> libwebkitgtk-3.0.so.0.13.4
- libbrasero-utils3.so.1 -> libbrasero-utils3.so.1.2.3
- libgcr-3.so.1 -> libgcr-3.so.1.0.0
- libdca.so.0 -> libdca.so.0.0.0
- libcompizconfig.so.0 -> libcompizconfig.so.0.0.0
- librpmsign.so.0 -> librpmsign.so.0.0.1
- libburn.so.4 -> libburn.so.4.71.0
- libzephyr.so.4 -> libzephyr.so.4.0.0
- libcamel-1.2.so.29 -> libcamel-1.2.so.29.0.0
- libmodplug.so.1 -> libmodplug.so.1.0.0
- liblrdf.so.0 -> liblrdf.so.0.0.0
- libflite_cmu_us_kal.so.1 -> libflite_cmu_us_kal.so.1.4
- libjavascriptcoregtk-3.0.so.0 -> libjavascriptcoregtk-3.0.so.0.13.4
- libiculx.so.48 -> libiculx.so.48.1.1
- libgdata.so.13 -> libgdata.so.13.2.0
- libedataserverui-3.0.so.1 -> libedataserverui-3.0.so.1.0.0
- libecore_ipc.so.1 -> libecore_ipc.so.1.0.0
- libindicate-gtk.so.3 -> libindicate-gtk.so.3.0.3
- libexiv2.so.11 -> libexiv2.so.11.0.0
- libyelp.so.0 -> libyelp.so.0.0.0
- libxapian.so.22 -> libxapian.so.22.4.2
- libnm-glib.so.4 -> libnm-glib.so.4.3.0
- libflite_cmu_time_awb.so.1 -> libflite_cmu_time_awb.so.1.4
- libhpmud.so.0 -> libhpmud.so.0.0.6
- librarian.so.0 -> librarian.so.0.0.0
- libnetsnmptrapd.so.15 -> libnetsnmptrapd.so.15.1.2
- libGeoIP.so.1 -> libGeoIP.so.1.4.8
- libgettextsrc-0.18.1.so -> libgettextsrc.so
- libpackagekit-glib2.so.14 -> libpackagekit-glib2.so.14.0.11
- libecore_fb.so.1 -> libecore_fb.so.1.0.0
- libgnome-bluetooth.so.8 -> libgnome-bluetooth.so.8.0.0
- libminiupnpc.so.8 -> libminiupnpc.so.8
- libguile-srfi-srfi-13-14-v-3.so.3 -> libguile-srfi-srfi-13-14-v-3.so.3.0.1
- libraw.so.5 -> libraw.so.5.0.0
- librhythmbox-core.so.5 -> librhythmbox-core.so.5.0.0
- libxdelta.so.2 -> libxdelta.so.2.0.0
- libgeoclue.so.0 -> libgeoclue.so.0.0.0
- libfreerdp-channels.so.1.0 -> libfreerdp-channels.so.1.0.1
- libgsm.so.1 -> libgsm.so.1.0.12
- libgme.so.0 -> libgme.so.0.5.3
- librpmio.so.2 -> librpmio.so.2.0.1
- libnetfilter_conntrack.so.3 -> libnetfilter_conntrack.so.3.1.3
- libappindicator3.so.1 -> libappindicator3.so.1.0.0
- libicudata.so.48 -> libicudata.so.48.1.1
- libnl-route-3.so.200 -> libnl-route-3.so.200.3.0
- libicuuc.so.48 -> libicuuc.so.48.1.1
- libIntelXvMC.so.1 -> libIntelXvMC.so.1.0.0
- libraptor.so.1 -> libraptor.so.1.2.0
- libgedit-private.so.0 -> libgedit-private.so.0.0.0
- libindicator.so.7 -> libindicator.so.7.0.0
- libsnmp.so.15 -> libsnmp.so.15.1.2
- libguile.so.17 -> libguile.so.17.4.0
- libcompiz_core.so.ABI-20120305 -> libcompiz_core.so.0.9.7.12
- libunique-3.0.so.0 -> libunique-3.0.so.0.0.2
- libfaad.so.2 -> libfaad.so.2.0.0
- libneon-gnutls.so.27 -> libneon-gnutls.so.27.2.6
- libpython2.7.so.1.0 -> libpython2.7.so.1.0
- libspeechd.so.2 -> libspeechd.so.2.3.0
- libecal-1.2.so.10 -> libecal-1.2.so.10.2.2
- libwpd-stream-0.9.so.9 -> libwpd-stream-0.9.so.9.0.4
- liboverlay-scrollbar3-0.2.so.0 -> liboverlay-scrollbar3-0.2.so.0.0.16
- libunity.so.9 -> libunity.so.9.0.2
- libhyphen.so.0 -> libhyphen.so.0.2.1
- libbrasero-media3.so.1 -> libbrasero-media3.so.1.2.3
- libelementary-ver-pre-svn-09.so.0 -> libelementary.so
- libkpathsea.so.5 -> libkpathsea.so.5.0.0
- libvlc.so.5 -> libvlc.so.5.3.2
- libflite_cmulex.so.1 -> libflite_cmulex.so.1.4
- libopenobex.so.1 -> libopenobex.so.1.5.0
- libdns.so.81 -> libdns.so.81.3.1
- libfreerdp-kbd.so.1.0 -> libfreerdp-kbd.so.1.0.1
- libpspell.so.15 -> libpspell.so.15.2.0
- libfolks-eds.so.25 -> libfolks-eds.so.25.7.0
- libisofs.so.6 -> libisofs.so.6.54.0
- libecore_input.so.1 -> libecore_input.so.1.0.0
- libpurple.so.0 -> libpurple.so.0.10.3
- librsync.so.1 -> librsync.so.1.0.2
- librpm.so.2 -> librpm.so.2.0.1
- libmeanwhile.so.1 -> libmeanwhile.so.1.0.2
- libevas.so.1 -> libevas.so.1.0.0
- libapr-1.so.0 -> libapr-1.so.0.4.6
- liblirc_client.so.0 -> liblirc_client.so.0.2.1
- libexpect.so.5.45 -> libexpect.so.5.45
- libgucharmap_2_90.so.7 -> libgucharmap_2_90.so.7.0.0
- libicuio.so.48 -> libicuio.so.48.1.1
- libgpod.so.4 -> libgpod.so.4.3.2
- libfontenc.so.1 -> libfontenc.so.1.0.0
- libchromeXvMC.so.1 -> libchromeXvMC.so.1.0.0
- libgssdp-1.0.so.3 -> libgssdp-1.0.so.3.0.0
- libguile-srfi-srfi-4-v-3.so.3 -> libguile-srfi-srfi-4-v-3.so.3.0.1
- libflite_cmu_us_rms.so.1 -> libflite_cmu_us_rms.so.1.4
- liblaunchpad-integration-3.0.so.1 -> liblaunchpad-integration-3.0.so.1.0.0
- libdjvulibre.so.21 -> libdjvulibre.so.21.3.0
- libdecoration.so.0 -> libdecoration.so.0.0.0
- libnm-gtk.so.0 -> libnm-gtk.so.0.0.0
- libcmis-0.2.so.0 -> libcmis-0.2.so.0.0.0
- libgpgme-pth.so.11 -> libgpgme-pth.so.11.7.0
- libguile-srfi-srfi-60-v-2.so.2 -> libguile-srfi-srfi-60-v-2.so.2.0.2
- libgnome-desktop-3.so.2 -> libgnome-desktop-3.so.2.1.4
- libnfnetlink.so.0 -> libnfnetlink.so.0.2.0
- libpeas-gtk-1.0.so.0 -> libpeas-gtk-1.0.so.0.200.0
- libevview3.so.3 -> libevview3.so.3.0.0
- libappindicator.so.1 -> libappindicator.so.1.0.0
- libisccfg.so.82 -> libisccfg.so.82.0.0
- libt1x.so.5 -> libt1x.so.5.1.2
- libtotem-plparser-mini.so.17 -> libtotem-plparser-mini.so.17.0.3
- libgnomekbdui.so.7 -> libgnomekbdui.so.7.0.0
- libspectre.so.1 -> libspectre.so.1.1.6
- libnm-glib-vpn.so.1 -> libnm-glib-vpn.so.1.1.0
- libdvdread.so.4 -> libdvdread.so.4.2.0
- libQtDee.so.2 -> libQtDee.so.2.0.0
- libnux-graphics-2.0.so.0 -> libnux-graphics-2.0.so.0.1401.0
- libslp.so.1 -> libslp.so.1.0.1
- libdvdnavmini.so.4 -> libdvdnavmini.so.4.2.0
- libnux-image-2.0.so.0 -> libnux-image-2.0.so.0.1401.0
- libunity-2d-private.so.0 -> libunity-2d-private.so.0.0.0
- libtelepathy-farstream.so.2 -> libtelepathy-farstream.so.2.0.1
- libedsio.so.0 -> libedsio.so.0.0.0
- libmusicbrainz3.so.6 -> libmusicbrainz3.so.6.2.0
- libefreet_mime.so.1 -> libefreet_mime.so.1.0.0
- libenca.so.0 -> libenca.so.0.5.1
- libpth.so.20 -> libpth.so.20.0.27
- libchromeXvMCPro.so.1 -> libchromeXvMCPro.so.1.0.0
- libicalvcal.so.0 -> libicalvcal.so.0.48.0
- libbrasero-burn3.so.1 -> libbrasero-burn3.so.1.2.3
- libupower-glib.so.1 -> libupower-glib.so.1.0.1
-/usr/lib/i386-linux-gnu/sse2: (hwcap: 0x0000000004000000)
- libspeex.so.1 -> libspeex.so.1.5.0
- libspeexdsp.so.1 -> libspeexdsp.so.1.5.0
-/usr/lib/i386-linux-gnu/i686: (hwcap: 0x0008000000000000)
-/usr/lib/sse2: (hwcap: 0x0000000004000000)
- libxapian.so.22 -> libxapian.so.22.4.2
-/usr/lib/i386-linux-gnu/i686/sse2: (hwcap: 0x0008000004000000)
- libx264.so.120 -> libx264.so.120
-/usr/lib/i386-linux-gnu/i686/cmov: (hwcap: 0x0008000000008000)
- libavcodec.so.53 -> libavcodec.so.53.35.0
- libavformat.so.53 -> libavformat.so.53.21.1
- libswscale.so.2 -> libswscale.so.2.1.0
- libavutil.so.51 -> libavutil.so.51.22.2
int mosquitto_reconnect_delay_set(struct mosquitto *mosq, unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff)
{
if(!mosq) return MOSQ_ERR_INVAL;
-
+
mosq->reconnect_delay = reconnect_delay;
mosq->reconnect_delay_max = reconnect_delay_max;
mosq->reconnect_exponential_backoff = reconnect_exponential_backoff;
-
+
return MOSQ_ERR_SUCCESS;
-
+
}
void _mosquitto_destroy(struct mosquitto *mosq)
mosq->ping_t = 0;
_mosquitto_packet_cleanup(&mosq->in_packet);
-
+
pthread_mutex_lock(&mosq->current_out_packet_mutex);
pthread_mutex_lock(&mosq->out_packet_mutex);
}else{
reconnects++;
}
-
+
#ifdef WIN32
Sleep(reconnect_delay*1000);
#else
for(rp = ainfo; rp != NULL; rp = rp->ai_next){
*sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if(*sock == INVALID_SOCKET) continue;
-
+
if(rp->ai_family == PF_INET){
((struct sockaddr_in *)rp->ai_addr)->sin_port = htons(port);
}else if(rp->ai_family == PF_INET6){
}
pthread_mutex_unlock(&mosq->callback_mutex);
}else if(((packet->command)&0xF0) == DISCONNECT){
- /* FIXME what cleanup needs doing here?
+ /* FIXME what cleanup needs doing here?
* incoming/outgoing messages? */
_mosquitto_socket_close(mosq);
# Copyright (c) 2010,2011 Roger Light <roger@atchoo.org>
# All rights reserved.
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
-#
+#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# 3. Neither the name of mosquitto nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
-#
+#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
if(mosq->bridge && mosq->bridge->topics && mosq->bridge->topic_remapping){
for(i=0; i<mosq->bridge->topic_count; i++){
cur_topic = &mosq->bridge->topics[i];
- if((cur_topic->direction == bd_both || cur_topic->direction == bd_out)
+ if((cur_topic->direction == bd_both || cur_topic->direction == bd_out)
&& (cur_topic->remote_prefix || cur_topic->local_prefix)){
/* Topic mapping required on this topic if the message matches */
#ifdef WITH_SRV
static void srv_callback(void *arg, int status, int timeouts, unsigned char *abuf, int alen)
-{
+{
struct mosquitto *mosq = arg;
struct ares_srv_reply *reply = NULL;
if(status == ARES_SUCCESS){
send(mosq->sockpairW, &sockpair_data, 1, 0);
#endif
}
-
+
if(force){
pthread_cancel(mosq->thread_id);
}
mosq->last_mid++;
if(mosq->last_mid == 0) mosq->last_mid++;
-
+
return mosq->last_mid;
}
}
if(tpos == tlen-1){
/* Check for e.g. foo matching foo/# */
- if(spos == slen-3
+ if(spos == slen-3
&& sub[spos+1] == '/'
&& sub[spos+2] == '#'){
*result = true;
'src/resourceCache/include'
])
-resourceClient_env.PrependUnique(LIBS = ['oc', 'rcs_common', 'octbstack', 'gnustl_shared','oc_logger', 'compatibility', 'log'])
+resourceClient_env.PrependUnique(LIBS = ['oc', 'rcs_common', 'octbstack','oc_logger'])
if target_os not in ['windows', 'winrt']:
resourceClient_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-fmessage-length=0', '-std=c++0x'])
if target_os == 'linux':
resourceClient_env.AppendUnique(LIBS = ['pthread'])
-
+
if target_os == 'android':
resourceClient_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
- resourceClient_env.PrependUnique(LIBS = ['gnustl_shared', 'compatibility', 'log'])
+ resourceClient_env.PrependUnique(LIBS = ['gnustl_shared', 'log'])
resourceClient_env.AppendUnique(LIBS = ['dl'])
RESOURCECLIENT_DIR + 'RCSDiscoveryManager.cpp',
RESOURCECLIENT_DIR + 'RCSRemoteResourceObject.cpp'
]
-ResourceClientsdk = resourceClient_env.StaticLibrary('rcs_client', client_src)
-resourceClient_env.InstallTarget(ResourceClientsdk , 'librcs_client')
+ResourceClientsdk_static = resourceClient_env.StaticLibrary('rcs_client', client_src)
+ResourceClientsdk_shared = resourceClient_env.SharedLibrary('rcs_client', client_src)
+
+resourceClient_env.InstallTarget([ResourceClientsdk_static,ResourceClientsdk_shared], 'librcs_client')
+resourceClient_env.UserInstallTargetLib([ResourceClientsdk_static,ResourceClientsdk_shared], 'librcs_client')
+resourceClient_env.UserInstallTargetHeader('include/RCSAddress.h', 'service/resource-encapsulation', 'RCSAddress.h')
+resourceClient_env.UserInstallTargetHeader('include/RCSDiscoveryManager.h', 'service/resource-encapsulation', 'RCSDiscoveryManager.h')
+resourceClient_env.UserInstallTargetHeader('include/RCSRemoteResourceObject.h', 'service/resource-encapsulation', 'RCSRemoteResourceObject.h')
+resourceClient_env.UserInstallTargetHeader('include/RCSResourceAttributes.h', 'service/resource-encapsulation', 'RCSResourceAttributes.h')
+resourceClient_env.UserInstallTargetHeader('include/RCSResourceObject.h', 'service/resource-encapsulation', 'RCSResourceObject.h')
+resourceClient_env.UserInstallTargetHeader('include/RCSBundleInfo.h', 'service/resource-encapsulation', 'RCSBundleInfo.h')
+resourceClient_env.UserInstallTargetHeader('include/RCSException.h', 'service/resource-encapsulation', 'RCSException.h')
+resourceClient_env.UserInstallTargetHeader('include/RCSRequest.h', 'service/resource-encapsulation', 'RCSRequest.h')
+resourceClient_env.UserInstallTargetHeader('include/RCSResourceContainer.h', 'service/resource-encapsulation', 'RCSResourceContainer.h')
+resourceClient_env.UserInstallTargetHeader('include/RCSResponse.h', 'service/resource-encapsulation', 'RCSResponse.h')
######################################################################
# Build Sample App: SampleResourceClient & SampleResourceServer
######################################################################
# Build UnitTests Resource Client , resourceCache and resourceBroker
################################################ ######################
-SConscript('unittests/SConscript')
-SConscript('src/resourceCache/unittests/SConscript')
-SConscript('src/resourceBroker/unittest/SConscript')
+if target_os == 'linux':
+ SConscript('unittests/SConscript')
+ SConscript('src/resourceCache/unittests/SConscript')
+ SConscript('src/resourceBroker/unittest/SConscript')
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+ <classpathentry combineaccessrules="false" exported="true" kind="src" path="/java"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>REClient</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.re.sampleclient"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="8"
+ android:targetSdkVersion="21" />
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/iot"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.re.sampleclient.MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name="com.re.sampleclient.ResourceClientActivity"
+ android:label="@string/app_name" >
+ </activity>
+ <activity
+ android:name="com.re.sampleclient.ContainerClientActivity"
+ android:label="@string/app_name" >
+ </activity>
+ </application>
+
+</manifest>
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-21
+android.library.reference.1=../../../sdk/java
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ListView
+ android:id="@+id/list"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent">
+ </ListView>
+</RelativeLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <Button
+ android:id="@+id/discoverResource"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:text="Discover Resource" />
+
+ <EditText
+ android:id="@+id/log"
+ android:layout_width="fill_parent"
+ android:layout_height="250dp"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/discoverResource"
+ android:editable="false"
+ android:ems="10" />
+
+</RelativeLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:text="Discover Resource" />
+
+ <ListView
+ android:id="@+id/groupaApiList"
+ android:layout_width="match_parent"
+ android:layout_height="300dp"
+ android:layout_below="@id/button1">
+ </ListView>
+
+ <EditText
+ android:id="@+id/EditText"
+ android:layout_width="fill_parent"
+ android:layout_height="250dp"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/groupaApiList"
+ android:layout_marginTop="15dp"
+ android:ems="10"
+ android:editable="false" >
+
+ <requestFocus />
+ </EditText>
+
+</RelativeLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <EditText
+ android:id="@+id/attributeValue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="28dp"
+ android:ems="10"
+ android:hint="Enter the Temperature" />
+
+ <Button
+ android:id="@+id/ok"
+ android:layout_width="150dp"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/region"
+ android:layout_marginTop="101dp"
+ android:text="OK" />
+
+ <Button
+ android:id="@+id/cancel"
+ android:layout_width="150dp"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/ok"
+ android:layout_alignBottom="@+id/ok"
+ android:layout_alignParentRight="true"
+ android:text="Cancel" />
+
+</RelativeLayout>
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/action_settings"/>
+
+</menu>
--- /dev/null
+<resources>
+
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ </style>
+
+</resources>
--- /dev/null
+ <resources>
+
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ </style>
+
+ <style name="AppTheme" parent="AppBaseTheme">
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+ -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">REClient</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+
+ </style>
+
+</resources>
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+package com.re.sampleclient;
+
+import java.util.Vector;
+
+import org.iotivity.ResourceEncapsulation.client.RCSAddress;
+import org.iotivity.ResourceEncapsulation.client.RCSDiscoveryManager;
+import org.iotivity.ResourceEncapsulation.client.RCSDiscoveryManager.IDiscoverResourceListener;
+import org.iotivity.ResourceEncapsulation.client.RCSRemoteResourceObject;
+import org.iotivity.ResourceEncapsulation.common.RCSException;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+
+/**
+ * It contains the discover resource API for Discovering Container Resource
+ */
+public class ContainerClientActivity extends Activity {
+
+ private final RCSDiscoveryManager discoveyManagerObj = RCSDiscoveryManager
+ .getInstance();
+ private final String LOG_TAG = "[ReSample] "
+ + this.getClass()
+ .getSimpleName();
+ private Button discoverResourceButton;
+ private EditText logs;
+ public static String logMessage;
+ private DiscoverResourceListener discoverResourceListener;
+ public static ContainerClientActivity containerClientActivityObj;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.resource_container);
+
+ containerClientActivityObj = this;
+ discoverResourceButton = (Button) findViewById(R.id.discoverResource);
+ logs = (EditText) findViewById(R.id.log);
+
+ discoverResourceListener = new DiscoverResourceListener();
+ discoveyManagerObj
+ .setDiscoverResourceListener(discoverResourceListener);
+
+ discoverResourceButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ RCSAddress address = RCSAddress.multicast();
+ try {
+ discoveyManagerObj.discoverResourceByType(address,
+ "oic.softsensor");
+ logMessage = "";
+ logs.setText(logMessage);
+ } catch (RCSException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+ /**
+ * Listener for receiving Resource discovered in the network.
+ */
+ private class DiscoverResourceListener implements IDiscoverResourceListener {
+
+ @Override
+ public void onResourceDiscovered(RCSRemoteResourceObject foundResource) {
+ Log.i(LOG_TAG, "onResourceDiscovered invoked");
+
+ String resourceURI = foundResource.getUri();
+ String hostAddress = foundResource.getAddress();
+ boolean isObservableflag = foundResource.isObservable();
+
+ Vector<String> resourceTypes = foundResource.getTypes();
+ Vector<String> resourceInterfaces = foundResource.getInterFaces();
+
+ logMessage = "URI : " + resourceURI + "\n";
+ logMessage += "Host : " + hostAddress + "\n";
+ for (int i = 0; i < resourceTypes.size(); i++) {
+ logMessage += "resourceType : " + resourceTypes.get(i) + "\n";
+ }
+
+ for (int i = 0; i < resourceInterfaces.size(); i++) {
+ logMessage += "resourceInterfaces : "
+ + resourceInterfaces.get(i) + "\n";
+ }
+ logMessage += "isObservable : " + isObservableflag + "\n";
+
+ ContainerClientActivity.this.runOnUiThread(new Runnable() {
+ public void run() {
+ logs.setText(logMessage);
+ }
+ });
+ }
+ };
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+package com.re.sampleclient;
+
+import java.util.ArrayList;
+
+import org.iotivity.base.ModeType;
+import org.iotivity.base.OcPlatform;
+import org.iotivity.base.PlatformConfig;
+import org.iotivity.base.QualityOfService;
+import org.iotivity.base.ServiceType;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * Starting Activity of the application responsible for configuring the
+ * OcPlatform and redirecting to ResourceClient activity or Container Activity
+ * as per user's selection.
+ */
+public class MainActivity extends Activity {
+
+ private static MainActivity activityObj;
+ private ArrayAdapter<String> apis;
+ private ArrayList<String> apisList;
+ private ListView list;
+ private final String LOG_TAG = "[ReSample] "
+ + this.getClass()
+ .getSimpleName();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ activityObj = this;
+
+ list = (ListView) findViewById(R.id.list);
+ apisList = new ArrayList<String>();
+
+ // adding the item to list that will be displayed on the UI.
+ apisList.add("Resource Client");
+ apisList.add("Discover Container Resource");
+ apis = new ArrayAdapter<String>(activityObj,
+ android.R.layout.simple_list_item_1, apisList);
+ list.setAdapter(apis);
+
+ // handling user's selection on the UI
+ list.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view,
+ int position, long id) {
+
+ if (position == 0) {
+ Intent intent = new Intent(activityObj,
+ ResourceClientActivity.class);
+ startActivity(intent);
+ }
+ if (position == 1) {
+
+ Intent intent = new Intent(activityObj,
+ ContainerClientActivity.class);
+ startActivity(intent);
+ }
+ }
+ });
+
+ // calling the method to check the Wi-fi connectivity and configuring
+ // the OcPlatform
+ configurePlatform();
+ }
+
+ @Override
+ public void onBackPressed() {
+ apisList.clear();
+ super.onBackPressed();
+ }
+
+ private void configurePlatform() {
+ // local Variables
+ ConnectivityManager connManager;
+ NetworkInfo wifi;
+ AlertDialog dialog;
+ PlatformConfig platformConfigObj;
+
+ // Check the wifi connectivity
+ connManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
+ wifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+ if (false == wifi.isConnected()) {
+ // WiFi is not connected close the application
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
+ dialogBuilder.setTitle("Error");
+ dialogBuilder
+ .setMessage("WiFi is not enabled/connected! Please connect the WiFi and start application again...");
+ dialogBuilder.setCancelable(false);
+ dialogBuilder.setPositiveButton("OK", new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // Closing the application
+ activityObj.finish();
+ }
+ });
+
+ dialog = dialogBuilder.create();
+ dialog.show();
+ Log.i(LOG_TAG,
+ "WiFi is not enabled/connected! Please connect the WiFi and start application again...");
+ return;
+ }
+ // If wifi is connected calling the configure method for configuring the
+ // OcPlatform
+ platformConfigObj = new PlatformConfig(getApplicationContext(),
+ ServiceType.IN_PROC, ModeType.CLIENT_SERVER, "0.0.0.0", 0,
+ QualityOfService.LOW);
+
+ OcPlatform.Configure(platformConfigObj);
+ Log.i(LOG_TAG, "Configuration done Successfully");
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+package com.re.sampleclient;
+
+import java.util.Vector;
+
+import org.iotivity.ResourceEncapsulation.client.RCSAddress;
+import org.iotivity.ResourceEncapsulation.client.RCSDiscoveryManager;
+import org.iotivity.ResourceEncapsulation.client.RCSDiscoveryManager.IDiscoverResourceListener;
+import org.iotivity.ResourceEncapsulation.client.RCSRemoteResourceObject.IGetRemoteAttributeListener;
+import org.iotivity.ResourceEncapsulation.client.RCSRemoteResourceObject.ISetRemoteAttributeListener;
+import org.iotivity.ResourceEncapsulation.client.RCSRemoteResourceObject.IStateChangedCallbackListener;
+import org.iotivity.ResourceEncapsulation.client.RCSRemoteResourceObject.ICacheUpdateListener;
+import org.iotivity.ResourceEncapsulation.client.RCSRemoteResourceObject.CacheState;
+import org.iotivity.ResourceEncapsulation.client.RCSRemoteResourceObject.ResourceState;
+import org.iotivity.ResourceEncapsulation.client.RCSRemoteResourceObject;
+import org.iotivity.ResourceEncapsulation.common.RCSException;
+import org.iotivity.ResourceEncapsulation.common.RCSResourceAttributes;
+
+import android.os.Message;
+import android.util.Log;
+
+/**
+ * For calling the Resource Client APIs as per user selection on UI and for
+ * updating the UI
+ *
+ * It contains all the Resource Client APIs.
+ */
+public class ResourceClient {
+
+ private static final String LOG_TAG = "[RESample] Client";
+ private static Message msg;
+ public String logMessage;
+
+ private final RCSDiscoveryManager discoveyManagerObj;
+ public RCSRemoteResourceObject remoteResourceObj;
+
+ private static ResourceClientActivity resourcClientActivityObj = null;
+ private final DiscoverResourceListener discoverResourceListener;
+ private final StateChangedListener stateChangedListener;
+ private final CacheUpdateListener cacheUpdateListener;
+ private final RemoteAttributeGetListener remoteAttributeGetListener;
+ private final RemoteAttributeSetListener remoteAttributeSetListener;
+ static boolean monitoringState = false;
+ static boolean cachingState = false;
+
+ // constructor
+ public ResourceClient() {
+ discoveyManagerObj = RCSDiscoveryManager.getInstance();
+ discoverResourceListener = new DiscoverResourceListener();
+ stateChangedListener = new StateChangedListener();
+ cacheUpdateListener = new CacheUpdateListener();
+ remoteAttributeGetListener = new RemoteAttributeGetListener();
+ remoteAttributeSetListener = new RemoteAttributeSetListener();
+
+ discoveyManagerObj
+ .setDiscoverResourceListener(discoverResourceListener);
+
+ resourcClientActivityObj = ResourceClientActivity
+ .getResourceClientActivityObj();
+ }
+
+ /**
+ * Listener for receiving Resource discovered in network.
+ */
+ private class DiscoverResourceListener implements IDiscoverResourceListener {
+
+ @Override
+ public void onResourceDiscovered(RCSRemoteResourceObject foundResource) {
+ Log.i(LOG_TAG, "onResourceDiscovered invoked");
+
+ String resourceURI = foundResource.getUri();
+ String hostAddress = foundResource.getAddress();
+ boolean isObservableflag = foundResource.isObservable();
+
+ Vector<String> resourceTypes = foundResource.getTypes();
+ Vector<String> resourceInterfaces = foundResource.getInterFaces();
+ remoteResourceObj = foundResource;
+ cachingState = false;
+ monitoringState = false;
+
+ msg = Message.obtain();
+ msg.what = 0;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+
+ logMessage = "URI : " + resourceURI + "\n";
+ logMessage += "Host : " + hostAddress + "\n";
+ for (int i = 0; i < resourceTypes.size(); i++) {
+ logMessage += "resourceType : " + resourceTypes.get(i) + "\n";
+ }
+
+ for (int i = 0; i < resourceInterfaces.size(); i++) {
+ logMessage += "resourceInterfaces : "
+ + resourceInterfaces.get(i) + "\n";
+ }
+ logMessage += "isObservable : " + isObservableflag + "\n";
+
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+ }
+ };
+
+ /**
+ * Listener for receiving Changed resource state as a result of
+ * startMonitoring API
+ */
+ private class StateChangedListener implements IStateChangedCallbackListener {
+
+ @Override
+ public void onStateChanged(ResourceState resourceState) {
+ Log.i(LOG_TAG, "onStateChangedCallback invoked");
+
+ switch (resourceState) {
+ case NONE:
+ Log.i(LOG_TAG, "Current Resource State : NOT_MONITORING");
+ logMessage = "Current Resource State : NOT_MONITORING\n";
+ break;
+
+ case ALIVE:
+ Log.i(LOG_TAG, "Current Resource State : ALIVE");
+ logMessage = "Current Resource State : ALIVE\n";
+ break;
+
+ case REQUESTED:
+ Log.i(LOG_TAG, "Current Resource State : REQUESTED");
+ logMessage = "Current Resource State : REQUESTED\n";
+ break;
+
+ case LOST_SIGNAL:
+ Log.i(LOG_TAG, "Current Resource State : LOST_SIGNAL");
+ logMessage = "Current Resource State : LOST_SIGNAL\n";
+ logMessage += "Start the server and press discover resource button"
+ + "\n";
+ break;
+
+ case DESTROYED:
+ Log.i(LOG_TAG, "Current Resource State : DESTROYED");
+ logMessage = "Current Resource State : DESTROYED\n";
+ break;
+ }
+
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+ }
+ }
+
+ /**
+ * Listener for receiving updated resource attributes as a result of
+ * startCaching() API with callback
+ */
+ private class CacheUpdateListener implements ICacheUpdateListener {
+ @Override
+ public void onCacheUpdatedCallback(RCSResourceAttributes attributes) {
+ Log.i(LOG_TAG, "onCacheUpdatedCallback invoked");
+
+ printAttributes(attributes);
+ }
+ };
+
+ /**
+ * Listener for receiving the resource attributes as a result of
+ * getRemoteAttributes() API
+ */
+ private class RemoteAttributeGetListener implements
+ IGetRemoteAttributeListener {
+ @Override
+ public void onRemoteAttributesGetCallback(
+ RCSResourceAttributes attributes) {
+
+ Log.i(LOG_TAG, "onRemoteAttributesGetCallback invoked");
+ printAttributes(attributes);
+ }
+ };
+
+ /**
+ * Listener for receiving the resource attributes as a result of
+ * setRemoteAttributes() API
+ */
+ private class RemoteAttributeSetListener implements
+ ISetRemoteAttributeListener {
+ @Override
+ public void onRemoteAttributesSetCallback(
+ RCSResourceAttributes attributes) {
+
+ Log.i(LOG_TAG, "onRemoteAttributesSetCallback invoked");
+ printAttributes(attributes);
+ }
+ };
+
+ // Discover Resource
+ public void disocverResources() {
+ Log.d(LOG_TAG, "discover resources entry");
+ RCSAddress address = RCSAddress.multicast();
+ try {
+ discoveyManagerObj.discoverResource(address);
+ } catch (RCSException e) {
+ e.printStackTrace();
+ }
+ Log.d(LOG_TAG, "discover resources exit");
+ }
+
+ // Start Monitoring
+ public void startMonitoring() {
+ Log.d(LOG_TAG, "startMonitoring entry");
+
+ if (null == remoteResourceObj) {
+ Log.e(LOG_TAG, "Remote Resource object NULL");
+ return;
+ }
+
+ if (true == monitoringState) {
+ logMessage = "Monitoring already started\n";
+ Log.e(LOG_TAG, "Monitoring already started");
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+ return;
+ }
+
+ remoteResourceObj.setStateChangedListener(stateChangedListener);
+
+ if (null != stateChangedListener) {
+ try {
+ remoteResourceObj.startMonitoring();
+ monitoringState = true;
+ } catch (RCSException e) {
+ e.printStackTrace();
+ return;
+ }
+ }
+ Log.d(LOG_TAG, "startMonitoring exit");
+ }
+
+ // Stop Monitoring
+ public void stopMonitoring() {
+ Log.d(LOG_TAG, "stopMonitoring entry");
+
+ if (monitoringState) {
+ if (null == remoteResourceObj) {
+ Log.e(LOG_TAG, "Remote Resource object NULL");
+ return;
+ }
+
+ remoteResourceObj.stopMonitoring();
+ monitoringState = false;
+ logMessage = "Stopped Resource Monitoring\n";
+ } else {
+ Log.i(LOG_TAG, "Monitoring not started");
+ logMessage = "Monitoring not started\n";
+ }
+
+ Log.d(LOG_TAG, "stopMonitoring exit");
+
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+ }
+
+ // Get Attributes
+ public void getRemoteAttributes() {
+ Log.d(LOG_TAG, "getRemoteAttributes entry");
+
+ if (null == remoteResourceObj) {
+ Log.e(LOG_TAG, "Remote Resource object NULL");
+ return;
+ }
+
+ try {
+ remoteResourceObj
+ .setGetRemoteAttributesListener(remoteAttributeGetListener);
+
+ if (null != remoteAttributeGetListener) {
+ remoteResourceObj.getRemoteAttributes();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return;
+ }
+
+ Log.d(LOG_TAG, "getRemoteAttributes exit");
+ }
+
+ // Set Attributes
+ public void setRemoteAttributes(int value) {
+ Log.d(LOG_TAG, "setRemoteAttributes entry");
+
+ if (null == remoteResourceObj) {
+ Log.e(LOG_TAG, "Remote Resource object NULL");
+ return;
+ }
+
+ try {
+ remoteResourceObj
+ .setSetRemoteAttributesListener(remoteAttributeSetListener);
+
+ if (null != remoteAttributeSetListener) {
+ RCSResourceAttributes attr = new RCSResourceAttributes();
+ attr.setValueInt("Temperature", value);
+ remoteResourceObj.setRemoteAttributes(attr);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return;
+ }
+
+ Log.d(LOG_TAG, "setRemoteAttributes exit");
+ }
+
+ // Start Caching
+ public void startCaching(int cachingType) {
+ Log.d(LOG_TAG, "startCaching entry");
+
+ if (null == remoteResourceObj) {
+ Log.e(LOG_TAG, "Remote Resource object NULL");
+ return;
+ }
+
+ if (true == cachingState) {
+ Log.d(LOG_TAG, "Caching already started");
+ logMessage = "Caching already started\n";
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+ return;
+ }
+
+ if (0 == cachingType) {
+ Log.d(LOG_TAG, "startCaching without callback");
+ remoteResourceObj.setCacheUpdateListener(null);
+ logMessage = "Caching started without callback\n";
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+ } else {
+ Log.d(LOG_TAG, "startCaching with callback");
+ remoteResourceObj.setCacheUpdateListener(cacheUpdateListener);
+ logMessage = "Caching started\n";
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+ }
+
+ try {
+ remoteResourceObj.startCaching();
+ cachingState = true;
+ } catch (RCSException e) {
+ e.printStackTrace();
+ return;
+ }
+
+ Log.d(LOG_TAG, "startCaching exit");
+ }
+
+ // Get Cache State
+ public void getCacheState() {
+ Log.d(LOG_TAG, "getCacheState entry");
+
+ if (null == remoteResourceObj) {
+ Log.e(LOG_TAG, "Remote Resource object NULL");
+ return;
+ }
+
+ CacheState cState = remoteResourceObj.getCacheState();
+ Log.i(LOG_TAG, "Cache State : " + cState.name());
+
+ logMessage = "Cache State : " + cState.toString() + "\n";
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+
+ Log.d(LOG_TAG, "getCacheState exit");
+ }
+
+ // Get Cached Attributes
+ public void getCachedAttributes() {
+ Log.d(LOG_TAG, "getCachedAttributes entry");
+
+ if (null == remoteResourceObj) {
+ Log.e(LOG_TAG, "Remote Resource object NULL");
+ return;
+ }
+ if (true == cachingState) {
+ RCSResourceAttributes attributes = null;
+ try {
+ attributes = remoteResourceObj.getCachedAttributes();
+ } catch (RCSException e) {
+ e.printStackTrace();
+ return;
+ }
+ printAttributes(attributes);
+ } else {
+ logMessage = "Caching not started" + "\n";
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+ }
+ Log.d(LOG_TAG, "getCachedAttributes exit");
+ }
+
+ // Get Cached Attribute
+ public void getCachedAttribute() {
+ Log.d(LOG_TAG, "getCachedAttribute entry");
+
+ if (null == remoteResourceObj) {
+ Log.e(LOG_TAG, "Remote Resource object NULL");
+ return;
+ }
+
+ if (true == cachingState) {
+ String key = "Temperature";
+ String attribute;
+ try {
+ attribute = remoteResourceObj.getCachedAttribute(key);
+ } catch (RCSException e) {
+ e.printStackTrace();
+ return;
+ }
+ logMessage = "Key : " + key + "\n";
+ logMessage += "Value : " + attribute + "\n";
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+ } else {
+ logMessage = "Caching not started" + "\n";
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+ }
+ Log.d(LOG_TAG, "getCachedAttribute exit");
+ }
+
+ // Stop Caching
+ public void stopCaching() {
+ Log.d(LOG_TAG, "stopCaching entry");
+
+ if (null == remoteResourceObj) {
+ Log.e(LOG_TAG, "Remote Resource object NULL");
+ return;
+ }
+
+ if (false == cachingState) {
+ Log.e(LOG_TAG, "Caching not started");
+ logMessage = "Caching not started\n";
+ } else {
+ remoteResourceObj.stopCaching();
+ cachingState = false;
+ logMessage = "Stopped Caching\n";
+ }
+
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+ Log.d(LOG_TAG, "stopCaching exit");
+ }
+
+ // For Printing the Attributes on the UI
+ private void printAttributes(RCSResourceAttributes attributes) {
+ Log.d(LOG_TAG, "Printing Attributes");
+
+ try {
+ int temperature = attributes.getValueInt("Temperature");
+ Log.i(LOG_TAG, "Temperature : " + temperature);
+ logMessage = "Attributes : \n\nTemperature : " + temperature + "\n";
+ } catch (Exception e) {
+ Log.i(LOG_TAG, "Temperature attribute not found");
+ logMessage = "Attributes Temperature not found \n";
+ e.printStackTrace();
+ return;
+ }
+ ResourceClientActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+ }
+}
\ No newline at end of file
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+package com.re.sampleclient;
+
+import java.util.ArrayList;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.Toast;
+
+/*
+ * Activity for handling user's selection on UI for Resource Client APIs.
+ * & for updating UI.
+ */
+public class ResourceClientActivity extends Activity {
+
+ private ListView list;
+ private Button discoverResourceButton;
+ private ArrayAdapter<String> groupApis;
+ private ArrayList<String> clientApisList;
+ private static ResourceClientActivity clientApiActivityObj;
+ private static Handler mHandler;
+ private ResourceClient resourceClientObj;
+ public static Context mcontext;
+
+ private static EditText logs;
+ private static String logMessage;
+
+ private final String LOG_TAG = "[ReSample] "
+ + this.getClass()
+ .getSimpleName();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.resourceclientapis);
+
+ clientApiActivityObj = this;
+ mcontext = this;
+
+ resourceClientObj = new ResourceClient();
+ clientApisList = new ArrayList<String>();
+ list = (ListView) findViewById(R.id.groupaApiList);
+ discoverResourceButton = (Button) findViewById(R.id.button1);
+ logs = (EditText) findViewById(R.id.EditText);
+
+ // adding the item to list that will be displayed on the UI.
+ clientApisList.add("1. Start Monitoring");
+ clientApisList.add("2. Stop Monitoring");
+
+ clientApisList.add("3. Get Remote Attributes");
+ clientApisList.add("4. Set Remote Attributes");
+
+ clientApisList.add("5. Start Caching without callback");
+ clientApisList.add("6. Start Caching with callback");
+
+ clientApisList.add("7. Get Cache State");
+ clientApisList.add("8. Get All Cached Attributes");
+ clientApisList.add("9. Get Cached Attribute");
+
+ clientApisList.add("10. Stop Caching");
+
+ // handler for updating the UI i.e. MessageLog (TextBox) & ListView
+ mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case 0:
+ groupApis = new ArrayAdapter<String>(
+ clientApiActivityObj,
+ android.R.layout.simple_list_item_1,
+ clientApisList);
+ list.setAdapter(groupApis);
+ list.bringToFront();
+ break;
+ case 1:
+ logs.setText("");
+ logs.setText(logMessage);
+ Log.i(LOG_TAG, logMessage);
+ }
+ }
+ };
+ setHandler(mHandler);
+
+ // Discover ResourceButton Listener
+ discoverResourceButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ resourceClientObj.disocverResources();
+ }
+ });
+
+ // Listener for item clicked by the user on the UI
+ list.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view,
+ int position, long id) {
+ if (position == 0) {
+ resourceClientObj.startMonitoring();
+ } else if (position == 1) {
+ resourceClientObj.stopMonitoring();
+ } else if (position == 2) {
+ resourceClientObj.getRemoteAttributes();
+ } else if (position == 3) {
+ userInputDialog();
+ } else if (position == 4) {
+ resourceClientObj.startCaching(0);
+ } else if (position == 5) {
+ resourceClientObj.startCaching(1);
+ } else if (position == 6) {
+ resourceClientObj.getCacheState();
+ } else if (position == 7) {
+ resourceClientObj.getCachedAttributes();
+ } else if (position == 8) {
+ resourceClientObj.getCachedAttribute();
+ } else if (position == 9) {
+ resourceClientObj.stopCaching();
+ }
+ }
+ });
+ }
+
+ // Dialog for taking user input for setting the attribute [Temperature]
+ // value
+ private void userInputDialog() {
+
+ if (null == resourceClientObj) {
+ displayToastMessage("Resource Object is NULL");
+ } else {
+ final Dialog dialog = new Dialog(mcontext);
+ dialog.setContentView(R.layout.userinputforattributevalue);
+ dialog.setTitle("Enter the Temperature Value");
+
+ dialog.setCancelable(false);
+ dialog.show();
+ Button ok = (Button) dialog.findViewById(R.id.ok);
+ Button cancel = (Button) dialog.findViewById(R.id.cancel);
+
+ ok.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ EditText temperatureValue = (EditText) dialog
+ .findViewById(R.id.attributeValue);
+ String value = temperatureValue.getText().toString();
+
+ try {
+ int intValue = Integer.parseInt(value);
+ resourceClientObj.setRemoteAttributes(intValue);
+ dialog.dismiss();
+
+ } catch (NumberFormatException e) {
+ String toastmessage = "Please enter the Integer Value";
+ displayToastMessage(toastmessage);
+ }
+ }
+ });
+ cancel.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ dialog.dismiss();
+ }
+ });
+ }
+ }
+
+ public static void setMessageLog(String message) {
+ logMessage = message;
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ }
+
+ public static ResourceClientActivity getResourceClientActivityObj() {
+ return clientApiActivityObj;
+ }
+
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ public void setHandler(Handler mHandler) {
+ ResourceClientActivity.mHandler = mHandler;
+ }
+
+ public void displayToastMessage(String message) {
+ Toast toast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
+ toast.show();
+ Log.i(LOG_TAG, message);
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>REServer</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.sampleresourceserver"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="8"
+ android:targetSdkVersion="21" />
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/iot"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.example.sampleserver.MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name="com.example.sampleserver.ServerBuilderActivity"
+ android:label="@string/app_name" >
+ </activity>
+ <activity
+ android:name="com.example.sampleserver.ResourceContainerActivity"
+ android:label="@string/app_name" >
+ </activity>
+ <activity
+ android:name="com.example.sampleserver.ServerBuilderAutoActivity"
+ android:label="@string/app_name" >
+ </activity>
+ <activity
+ android:name="com.example.sampleserver.ServerBuilderDevActivity"
+ android:label="@string/app_name" >
+ </activity>
+ </application>
+
+</manifest>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<container>
+ <bundle>
+ <id>oic.bundle.discomfortIndexSensor</id>
+ <path>data/data/com.example.sampleresourceserver/files/libSoftSensorBundle.so</path>
+ <version>1.0.0</version>
+ <resources>
+ <resourceInfo>
+ <name>DiscomfortIndexSensor1</name>
+ <resourceType>oic.softsensor</resourceType>
+ <outputs>
+ <output>
+ <name>discomfortIndex</name>
+ <type>int</type>
+ </output>
+ </outputs>
+ <inputs>
+ <input>
+ <name>humidity</name>
+ <type>double</type>
+ </input>
+ <input>
+ <name>temperature</name>
+ <type>double</type>
+ </input>
+ </inputs>
+ </resourceInfo>
+ </resources>
+ </bundle>
+</container>
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-21
+android.library.reference.1=../../../sdk/java
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ListView
+ android:id="@+id/list"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent">
+ </ListView>
+
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <Button
+ android:id="@+id/startContainer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:text="Start Container" />
+
+ <ListView
+ android:id="@+id/containerApiList"
+ android:layout_width="match_parent"
+ android:layout_height="300dp"
+ android:layout_below="@id/startContainer">
+ </ListView>
+
+ <EditText
+ android:id="@+id/log"
+ android:layout_width="fill_parent"
+ android:layout_height="250dp"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/containerApiList"
+ android:layout_marginTop="15dp"
+ android:ems="10"
+ android:editable="false" >
+
+ <requestFocus />
+ </EditText>
+
+ <Button
+ android:id="@+id/stopContainer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:text="Stop Container" />
+
+</RelativeLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ListView
+ android:id="@+id/buildeList"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent">
+ </ListView>
+
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <ListView
+ android:id="@+id/serverBuilderAutoList"
+ android:layout_width="match_parent"
+ android:layout_height="300dp" >
+ </ListView>
+
+ <EditText
+ android:id="@+id/Autolog"
+ android:layout_width="fill_parent"
+ android:layout_height="250dp"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/serverBuilderAutoList"
+ android:layout_marginTop="15dp"
+ android:editable="false"
+ android:ems="10" >
+
+ <requestFocus />
+ </EditText>
+
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <ListView
+ android:id="@+id/serverBuilderDevList"
+ android:layout_width="match_parent"
+ android:layout_height="300dp" >
+ </ListView>
+
+ <EditText
+ android:id="@+id/devLog"
+ android:layout_width="fill_parent"
+ android:layout_height="250dp"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/serverBuilderDevList"
+ android:layout_marginTop="15dp"
+ android:editable="false"
+ android:ems="10" >
+
+ <requestFocus />
+ </EditText>
+
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <EditText
+ android:id="@+id/attributeValue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="28dp"
+ android:ems="10"
+ android:hint="Enter the Temperature" />
+
+ <Button
+ android:id="@+id/ok"
+ android:layout_width="150dp"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/region"
+ android:layout_marginTop="101dp"
+ android:text="OK" />
+
+ <Button
+ android:id="@+id/cancel"
+ android:layout_width="150dp"
+ android:layout_height="wrap_content"
+ android:layout_alignBaseline="@+id/ok"
+ android:layout_alignBottom="@+id/ok"
+ android:layout_alignParentRight="true"
+ android:text="Cancel" />
+
+</RelativeLayout>
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/action_settings"/>
+
+</menu>
\ No newline at end of file
--- /dev/null
+<resources>
+
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ </style>
+
+</resources>
--- /dev/null
+ <resources>
+
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ </style>
+
+ <style name="AppTheme" parent="AppBaseTheme">
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+ -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">REServer</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+
+ </style>
+
+</resources>
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+package com.example.sampleserver;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+
+import org.iotivity.base.ModeType;
+import org.iotivity.base.OcPlatform;
+import org.iotivity.base.PlatformConfig;
+import org.iotivity.base.QualityOfService;
+import org.iotivity.base.ServiceType;
+
+import com.example.sampleresourceserver.R;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.DialogInterface.OnClickListener;
+import android.content.res.AssetManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.AdapterView.OnItemClickListener;
+
+/**
+ * Starting Activity of the application responsible for configuring the
+ * OcPlatform and redirecting to ServerBuilder or ResourceContainer activity as
+ * per user's selection
+ */
+public class MainActivity extends Activity {
+
+ private static MainActivity activityObj;
+ private ArrayAdapter<String> apis;
+ private ArrayList<String> apisList;
+ private ListView list;
+ private final String LOG_TAG = "[ReSampleServer]"
+ + this.getClass()
+ .getSimpleName();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ activityObj = this;
+
+ list = (ListView) findViewById(R.id.list);
+ apisList = new ArrayList<String>();
+
+ // adding the item to list that will be displayed on the UI.
+ apisList.add("Server Builder");
+ apisList.add("Resource Container");
+ apis = new ArrayAdapter<String>(activityObj,
+ android.R.layout.simple_list_item_1, apisList);
+ list.setAdapter(apis);
+
+ // handling user's selection on the UI
+ list.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view,
+ int position, long id) {
+
+ if (position == 0) {
+
+ ServerBuilder builderObject = new ServerBuilder();
+ builderObject.createResource();
+
+ Intent intent = new Intent(activityObj,
+ ServerBuilderActivity.class);
+ startActivity(intent);
+ }
+ if (position == 1) {
+ Intent intent = new Intent(activityObj,
+ ResourceContainerActivity.class);
+ startActivity(intent);
+ }
+ }
+ });
+
+ // calling the method to check the Wi-fi connectivity and configuring
+ // the OcPlatform
+ configurePlatform();
+
+ // copy assets folder file to SDcard
+ copyFiles("lib");
+ }
+
+ private void copyFiles(String path) {
+ AssetManager assetManager = getAssets();
+ String assets[] = null;
+
+ try {
+ assets = assetManager.list(path);
+
+ if (assets.length == 0) {
+ copyFile(path);
+ } else {
+ String fullPath = "/data/data/"
+ + this.getClass().getPackage().toString() + "/" + path;
+ File dir = new File(fullPath);
+
+ if (!dir.exists())
+ dir.mkdir();
+ for (int i = 0; i < assets.length; ++i) {
+ copyFiles(path + "/" + assets[i]);
+ }
+ }
+ } catch (IOException ex) {
+ Log.e("tag", "I/O Exception", ex);
+ }
+ }
+
+ private void copyFile(String filename) {
+ AssetManager assetManager = getAssets();
+ InputStream in = null;
+ OutputStream out = null;
+
+ try {
+ in = assetManager.open(filename);
+ out = openFileOutput(filename.split("/")[1], Context.MODE_PRIVATE);
+
+ byte[] buffer = new byte[1024];
+ int read;
+
+ while ((read = in.read(buffer)) != -1) {
+ out.write(buffer, 0, read);
+ }
+
+ in.close();
+ in = null;
+ out.flush();
+ out.close();
+ out = null;
+ } catch (Exception e) {
+ Log.e("tag", e.getMessage());
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ apisList.clear();
+ super.onBackPressed();
+ }
+
+ private void configurePlatform() {
+ // local Variables
+ ConnectivityManager connManager;
+ NetworkInfo wifi;
+ AlertDialog dialog;
+ PlatformConfig platformConfigObj;
+
+ // Check the wifi connectivity
+ connManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
+ wifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+ if (false == wifi.isConnected()) {
+ // WiFi is not connected close the application
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
+ dialogBuilder.setTitle("Error");
+ dialogBuilder
+ .setMessage("WiFi is not enabled/connected! Please connect the WiFi and start application again...");
+ dialogBuilder.setCancelable(false);
+ dialogBuilder.setPositiveButton("OK", new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // Closing the application
+ activityObj.finish();
+ }
+ });
+
+ dialog = dialogBuilder.create();
+ dialog.show();
+ Log.i(LOG_TAG,
+ "WiFi is not enabled/connected! Please connect the WiFi and start application again...");
+ return;
+ }
+ // If wifi is connected calling the configure method for configuring the
+ // OcPlatform
+ platformConfigObj = new PlatformConfig(getApplicationContext(),
+ ServiceType.IN_PROC, ModeType.CLIENT_SERVER, "0.0.0.0", 0,
+ QualityOfService.LOW);
+
+ OcPlatform.Configure(platformConfigObj);
+ Log.i(LOG_TAG, "Configuration done Successfully");
+ }
+}
\ No newline at end of file
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+package com.example.sampleserver;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.iotivity.ResourceEncapsulation.server.RCSBundleInfo;
+import org.iotivity.ResourceEncapsulation.server.RCSResourceContainer;
+
+import android.content.Context;
+import android.os.Message;
+
+/**
+ * For calling the Resource Container APIs as per user selection on UI and for
+ * updating the UI
+ *
+ * It contains all the Resource Container APIs.
+ */
+public class ResourceContainer {
+
+ private RCSResourceContainer containerInstance;
+ public static String logMessage;
+ private static ResourceContainerActivity resourceContainerActivityInstance;
+ private static Message msg;
+ private static boolean startBundleFlag;
+ private static boolean isStarted = false;
+
+ // constructor
+ public ResourceContainer() {
+ resourceContainerActivityInstance = ResourceContainerActivity
+ .getResourceContainerActivityObj();
+ containerInstance = RCSResourceContainer.getInstance();
+ }
+
+ // Start Container
+ public void startContainer(String sdCardPath) {
+
+ startBundleFlag = true;
+ String configFile = sdCardPath + "/ResourceContainerConfig.xml";
+
+ if (!isStarted) {
+ for (int i = 0; i < 2; i++) {
+ containerInstance.startContainer(configFile);
+ isStarted = true;
+ }
+ } else {
+ containerInstance.startContainer(configFile);
+ }
+ logMessage = "Container Started";
+ ResourceContainerActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+
+ msg = Message.obtain();
+ msg.what = 0;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // Stop Container
+ public void stopContainer() {
+
+ containerInstance.stopContainer();
+ logMessage = "Container stopped";
+ ResourceContainerActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // List Bundle Resources
+ public void listBundleResources() {
+
+ List<String> bundleResources = containerInstance
+ .listBundleResources("oic.bundle.discomfortIndexSensor");
+ Iterator<String> it = bundleResources.iterator();
+ logMessage = "";
+
+ if (0 == bundleResources.size()) {
+ logMessage = logMessage + "No resource found in the bundle" + "\n";
+ } else {
+ while (it.hasNext()) {
+ String element = (String) it.next();
+ logMessage = logMessage + element + "\n";
+ }
+ }
+ ResourceContainerActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // List Bundles
+ public void listBundles() {
+
+ List<RCSBundleInfo> bundleList = containerInstance.listBundles();
+ Iterator<RCSBundleInfo> it = bundleList.iterator();
+ logMessage = "";
+ logMessage = logMessage + "size of bundleList : " + bundleList.size()
+ + "\n";
+
+ while (it.hasNext()) {
+
+ RCSBundleInfo object = (RCSBundleInfo) it.next();
+ logMessage = logMessage + "ID :" + object.getID() + "\n";
+ logMessage = logMessage + "Path: " + object.getPath() + "\n";
+ logMessage = logMessage + "version : " + object.getVersion() + "\n";
+ }
+ ResourceContainerActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // Add Bundles
+ public void addBundle() {
+
+ Map<String, String> bundleParams = null;
+ List<RCSBundleInfo> bundleList = containerInstance.listBundles();
+ if (0 < bundleList.size()) {
+ logMessage = "Bundle already added" + "\n";
+
+ } else {
+ for (int i = 0; i < 2; i++) {
+ containerInstance
+ .addBundle(
+ "oic.bundle.discomfortIndexSensor",
+ "xyz",
+ "data/data/com.example.sampleresourceserver/files/libSoftSensorBundle.so",
+ bundleParams);
+ }
+
+ logMessage = "bundle to add : " + "\n";
+ logMessage = logMessage + "ID :"
+ + "oic.bundle.discomfortIndexSensor" + "\n";
+ logMessage = logMessage + "Uri: " + "xyz" + "\n";
+ logMessage = logMessage
+ + "Path : "
+ + "data/data/com.re.sampleclient/files/libSoftSensorBundle.so"
+ + "\n";
+ logMessage = logMessage + "bundle added successfully" + "\n";
+ }
+
+ ResourceContainerActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // Remove Bundle
+ public void removeBundle() {
+
+ List<RCSBundleInfo> bundleList = containerInstance.listBundles();
+ if (0 == bundleList.size()) {
+ logMessage = "No bundle to remove" + "\n";
+
+ } else {
+
+ for (int i = 0; i < 2; i++) {
+ containerInstance
+ .removeBundle("oic.bundle.discomfortIndexSensor");
+ }
+ startBundleFlag = false;
+ logMessage = "bundle to remove : " + "\n";
+ logMessage = logMessage + "ID :"
+ + "oic.bundle.discomfortIndexSensor" + "\n";
+ logMessage = logMessage + " bundle removed successfully" + "\n";
+ }
+ ResourceContainerActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // Start Bundle
+ public void startBundle() {
+
+ List<RCSBundleInfo> bundleList = containerInstance.listBundles();
+ if (0 == bundleList.size()) {
+ logMessage = "No bundle to Start" + "\n";
+ } else if (true == startBundleFlag) {
+ logMessage = "Bundle already started" + "\n";
+ } else {
+ startBundleFlag = true;
+ containerInstance.startBundle("oic.bundle.discomfortIndexSensor");
+
+ logMessage = " bundle to start" + "\n";
+ logMessage = logMessage + " ID : oic.bundle.discomfortIndexSensor"
+ + "\n";
+ logMessage = logMessage + " bundle started successfully" + "\n";
+ }
+ ResourceContainerActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // Stop Bundle
+ public void stopBundle() {
+
+ if (false == startBundleFlag) {
+ logMessage = "Bundle already stopped" + "\n";
+ } else {
+
+ List<RCSBundleInfo> bundleList = containerInstance.listBundles();
+ if (0 == bundleList.size()) {
+ logMessage = "No bundle to Stop" + "\n";
+
+ } else {
+ containerInstance
+ .stopBundle("oic.bundle.discomfortIndexSensor");
+ startBundleFlag = false;
+ logMessage = " bundle to stop" + "\n";
+ logMessage = logMessage
+ + " ID : oic.bundle.discomfortIndexSensor" + "\n";
+ logMessage = logMessage + " bundle stopped successfully" + "\n";
+ }
+ }
+
+ ResourceContainerActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // Add Resource Configuration
+ public void addResourceConfig() {
+
+ if (false == startBundleFlag) {
+ logMessage = "Bundle is not started" + "\n";
+
+ } else {
+
+ List<RCSBundleInfo> bundleList = containerInstance.listBundles();
+ List<String> bundleResources = containerInstance
+ .listBundleResources("oic.bundle.discomfortIndexSensor");
+
+ if (0 == bundleList.size()) {
+
+ logMessage = "No bundle found" + "\n";
+
+ } else if ((0 == bundleList.size())
+ && (0 == bundleResources.size())) {
+
+ logMessage = "No bundle found" + "\n";
+ } else {
+
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("resourceType", "oic.softsensor");
+ params.put("address",
+ "http://192.168.0.2/api/newdeveloper/sensor/22");
+ containerInstance.addResourceConfig(
+ "oic.bundle.discomfortIndexSensor", "", params);
+ logMessage = "resource added successfully" + "\n";
+ }
+ }
+ ResourceContainerActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // Remove Resource Configuration
+ public void removeResourceConfig() {
+
+ List<String> bundleResources = containerInstance
+ .listBundleResources("oic.bundle.discomfortIndexSensor");
+ if (bundleResources.size() >= 1) {
+ String element = bundleResources.get(0);
+ containerInstance.removeResourceConfig(
+ "oic.bundle.discomfortIndexSensor", element);
+ Message msg;
+ logMessage = "resource removed successfully: \n" + element + "\n";
+ ResourceContainerActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+ } else {
+ logMessage = "No resource to remove" + "\n";
+ ResourceContainerActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 1;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+ }
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+package com.example.sampleserver;
+
+import java.util.ArrayList;
+
+import com.example.sampleresourceserver.*;
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.Toast;
+
+/**
+ * Activity for handling user's selection on UI for Resource container APIs. &
+ * for updating UI.
+ */
+public class ResourceContainerActivity extends Activity {
+
+ private final String LOG_TAG = "[ReSample] "
+ + this.getClass()
+ .getSimpleName();
+ private static ResourceContainerActivity resourceContainerActivityInstance;
+ private ResourceContainer resourceContainerInstance;
+ private static String logMessage;
+
+ private ArrayAdapter<String> containerApis;
+ private ArrayList<String> containerApiList;
+ private static Handler mHandler;
+ private ListView list;
+ private Button startContainer;
+ private Button stopContainer;
+ private static EditText logs;
+ private static String sdCardPath;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.resource_container);
+
+ resourceContainerActivityInstance = this;
+ resourceContainerInstance = new ResourceContainer();
+
+ containerApiList = new ArrayList<String>();
+
+ list = (ListView) findViewById(R.id.containerApiList);
+ startContainer = (Button) findViewById(R.id.startContainer);
+ stopContainer = (Button) findViewById(R.id.stopContainer);
+ stopContainer.setEnabled(false);
+ logs = (EditText) findViewById(R.id.log);
+
+ sdCardPath = this.getFilesDir().getPath();
+ // adding the item to list that will be displayed on the UI.
+ containerApiList.add("1. List Bundles");
+ containerApiList.add("2. List bundle resources");
+ containerApiList.add("3. Add Resource Config");
+ containerApiList.add("4. Remove Resource Config");
+ containerApiList.add("5. Remove Bundle");
+ containerApiList.add("6. Add Bundle");
+ containerApiList.add("7. Start Bundle");
+ containerApiList.add("8. Stop Bundle");
+
+ // handler for updating the UI i.e. MessageLog (TextBox) & ListView
+ mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case 0:
+ containerApis = new ArrayAdapter<String>(
+ resourceContainerActivityInstance,
+ android.R.layout.simple_list_item_1,
+ containerApiList);
+ list.setAdapter(containerApis);
+ list.bringToFront();
+ break;
+ case 1:
+ logs.setText("");
+ logs.setText(logMessage);
+ Log.i(LOG_TAG, logMessage);
+ break;
+ case 2:
+ list.setAdapter(null);
+ break;
+ }
+ }
+ };
+ setHandler(mHandler);
+
+ // StartContainer Button Listener
+ startContainer.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ resourceContainerInstance.startContainer(sdCardPath);
+ startContainer.setEnabled(false);
+ stopContainer.setEnabled(true);
+
+ }
+ });
+
+ // StopContainer Button Listener
+ stopContainer.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ resourceContainerInstance.stopContainer();
+ startContainer.setEnabled(true);
+ stopContainer.setEnabled(false);
+ Message msg;
+ msg = Message.obtain();
+ msg.what = 2;
+ resourceContainerActivityInstance.getHandler().sendMessage(msg);
+ }
+ });
+
+ // Listener for item clicked by the user on the UI
+ list.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view,
+ int position, long id) {
+ if (position == 0) {
+ resourceContainerInstance.listBundles();
+ } else if (position == 1) {
+ resourceContainerInstance.listBundleResources();
+ } else if (position == 2) {
+ resourceContainerInstance.addResourceConfig();
+ } else if (position == 3) {
+ resourceContainerInstance.removeResourceConfig();
+ } else if (position == 4) {
+ resourceContainerInstance.removeBundle();
+ } else if (position == 5) {
+ resourceContainerInstance.addBundle();
+ } else if (position == 6) {
+ resourceContainerInstance.startBundle();
+ } else if (position == 7) {
+ resourceContainerInstance.stopBundle();
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ }
+
+ // ****Utility Functions*****//
+
+ public static void setMessageLog(String message) {
+ logMessage = message;
+ }
+
+ public static ResourceContainerActivity getResourceContainerActivityObj() {
+ return resourceContainerActivityInstance;
+ }
+
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ public void setHandler(Handler mHandler) {
+ ResourceContainerActivity.mHandler = mHandler;
+ }
+
+ public void displayToastMessage(String message) {
+ Toast toast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
+ toast.show();
+ Log.i(LOG_TAG, message);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+package com.example.sampleserver;
+
+import org.iotivity.ResourceEncapsulation.common.RCSException;
+import org.iotivity.ResourceEncapsulation.common.RCSResourceAttributes;
+import org.iotivity.ResourceEncapsulation.server.Builder;
+import org.iotivity.ResourceEncapsulation.server.RCSResourceObject.*;
+import org.iotivity.ResourceEncapsulation.server.RCSGetResponse;
+import org.iotivity.ResourceEncapsulation.server.RCSRequest;
+import org.iotivity.ResourceEncapsulation.server.RCSResourceObject;
+import org.iotivity.ResourceEncapsulation.server.RCSSetResponse;
+
+import android.os.Message;
+
+public class ServerBuilder {
+
+ public static RCSResourceObject rcsResourceObject;
+ private static ServerBuilderDevActivity serverBuilderDevActivityInstance;
+ private static String logMessage;
+ private static Message msg;
+
+ private final GetRequestHandler getRequestListener;
+ private final SetRequestHandler setRequestListener;
+ private final AddAttributeUpdatedListener attributeUpdatedListener;
+
+ // constructor
+ public ServerBuilder() {
+ serverBuilderDevActivityInstance = ServerBuilderDevActivity
+ .getServerBuilderDevActivity();
+ getRequestListener = new GetRequestHandler();
+ setRequestListener = new SetRequestHandler();
+ attributeUpdatedListener = new AddAttributeUpdatedListener();
+ }
+
+ // Create Resource
+ public void createResource() {
+
+ Builder builderObject = new Builder("/a/TempSensor",
+ "core.TemperatureSensor", "oic.if.");
+ builderObject.setDiscoverable(true);
+ builderObject.setObservable(true);
+
+ RCSResourceAttributes attr = new RCSResourceAttributes();
+ try {
+ attr.setValueInt("Temperature", 10);
+ } catch (RCSException e) {
+ e.printStackTrace();
+ }
+ builderObject.setAttributes(attr);
+
+ try {
+ rcsResourceObject = builderObject.build();
+ rcsResourceObject
+ .setSetRequestHandlerPolicy(SetRequestHandlerPolicy.ACCEPTANCE);
+ } catch (RCSException e) {
+ e.printStackTrace();
+ }
+ }
+
+ // Set Attribute
+ public void setAttribute(int value) {
+
+ rcsResourceObject.setAttribute("Temperature", value);
+ logMessage = "Attribute set successfully" + "\n";
+ logMessage = logMessage + "Temperature : " + value;
+
+ serverBuilderDevActivityInstance.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 0;
+ serverBuilderDevActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // Set Get Request Listener
+ public void setGetRequestListener() {
+ rcsResourceObject.setGetRequestListener(getRequestListener);
+ rcsResourceObject.setGetRequestHandler();
+ logMessage = "Get Handler set successfully." + "\n";
+
+ serverBuilderDevActivityInstance.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 0;
+ serverBuilderDevActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // Set Set Request Listener
+ public void setSetRequestListener() {
+ rcsResourceObject.setSetRequestListener(setRequestListener);
+ rcsResourceObject.setSetRequestHandler();
+ logMessage = "Set Handler set successfully." + "\n";
+
+ serverBuilderDevActivityInstance.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 0;
+ serverBuilderDevActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // Set Attribute Updated Listener
+ public void setAttributeUpdatedListener() {
+
+ rcsResourceObject.setAttributeUpdatedListener(attributeUpdatedListener);
+ rcsResourceObject.addAttributeUpdatedListener("Temperature");
+ logMessage = "Attribte updated listener set successfully." + "\n";
+
+ serverBuilderDevActivityInstance.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 0;
+ serverBuilderDevActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ // Remove Attribute Updated Listener
+ public void removeAttributeUpdatedListener() {
+
+ rcsResourceObject.removeAttributeUpdatedListener("Temperature");
+ logMessage = "Attribte updated listener removed successfully." + "\n";
+
+ serverBuilderDevActivityInstance.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 0;
+ serverBuilderDevActivityInstance.getHandler().sendMessage(msg);
+ }
+
+ /**
+ * Listener for receiving Get Request and for Sending Response
+ */
+ private class GetRequestHandler implements IGetRequestHandler {
+
+ @Override
+ public RCSGetResponse onGetRequest(RCSRequest request,
+ RCSResourceAttributes attributes) {
+
+ logMessage = "Got a Get request from client sending dafault response \n"
+ + "URI : " + request.getResourceUri() + "\n";
+ serverBuilderDevActivityInstance.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 0;
+ serverBuilderDevActivityInstance.getHandler().sendMessage(msg);
+
+ RCSGetResponse object = RCSGetResponse.defaultAction();
+
+ return object;
+ }
+ };
+
+ /**
+ * Listener for receiving Set Request and for Sending Response
+ */
+ private class SetRequestHandler implements ISetRequestHandler {
+
+ @Override
+ public RCSSetResponse onSetRequest(RCSRequest request,
+ RCSResourceAttributes attributes) {
+
+ logMessage = "Got a Set request from client sending dafault response"
+ + "\n" + "URI : " + request.getResourceUri() + "\n";
+ serverBuilderDevActivityInstance.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 0;
+ serverBuilderDevActivityInstance.getHandler().sendMessage(msg);
+ RCSSetResponse object = RCSSetResponse.defaultAction();
+ return object;
+ }
+ };
+
+ /**
+ * Listener for receiving Updated Attribute
+ */
+ private class AddAttributeUpdatedListener implements
+ IAttributeUpdatedListener {
+ @Override
+ public void onAttributeUpdate(String oldValue, String newValue) {
+
+ logMessage = "attributed updated" + "\n";
+ logMessage = logMessage + "oldValue : " + oldValue + "\n";
+ logMessage = logMessage + "newValue : " + newValue + "\n";
+ serverBuilderDevActivityInstance.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 0;
+ serverBuilderDevActivityInstance.getHandler().sendMessage(msg);
+ }
+ };
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+package com.example.sampleserver;
+
+import java.util.ArrayList;
+
+import com.example.sampleresourceserver.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.AdapterView.OnItemClickListener;
+
+/**
+ * Starting Activity for ServerBuilder and redirect to ServerBuilderAutoActivity
+ * or ServerBuilderDevActivity as per user's selection
+ */
+public class ServerBuilderActivity extends Activity {
+
+ private static ServerBuilderActivity activityObj;
+ private ArrayAdapter<String> apis;
+ private ArrayList<String> apisList;
+ private ListView list;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.server_builder);
+ activityObj = this;
+ list = (ListView) findViewById(R.id.buildeList);
+ apisList = new ArrayList<String>();
+
+ // adding the item to list that will be displayed on the UI.
+ apisList.add("Auto Control for created Resource");
+ apisList.add("Developer Control for created Resource");
+ apis = new ArrayAdapter<String>(activityObj,
+ android.R.layout.simple_list_item_1, apisList);
+ list.setAdapter(apis);
+
+ // handling user's selection on the UI
+ list.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view,
+ int position, long id) {
+
+ if (position == 0) {
+
+ Intent intent = new Intent(activityObj,
+ ServerBuilderAutoActivity.class);
+ startActivity(intent);
+ }
+ if (position == 1) {
+
+ Intent intent = new Intent(activityObj,
+ ServerBuilderDevActivity.class);
+ startActivity(intent);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+package com.example.sampleserver;
+
+import java.util.ArrayList;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.Toast;
+import android.widget.AdapterView.OnItemClickListener;
+import com.example.sampleresourceserver.R;
+
+/**
+ * Activity for handling user's selection on UI for changing temperature. & for
+ * updating UI.
+ */
+public class ServerBuilderAutoActivity extends Activity {
+
+ private static ServerBuilderAutoActivity activityObj;
+ private ArrayAdapter<String> apis;
+ private ArrayList<String> apisList;
+ private final String LOG_TAG = "[ReSample] "
+ + this.getClass()
+ .getSimpleName();
+ private ListView list;
+ private EditText logs;
+ private static Handler mHandler;
+ public static Context mcontext;
+ private static String logMessage;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.server_builder_auto);
+
+ logs = (EditText) findViewById(R.id.Autolog);
+ activityObj = this;
+ mcontext = this;
+
+ list = (ListView) findViewById(R.id.serverBuilderAutoList);
+ apisList = new ArrayList<String>();
+
+ // adding the item to list that will be displayed on the UI.
+ apisList.add("Set Temperature");
+
+ apis = new ArrayAdapter<String>(activityObj,
+ android.R.layout.simple_list_item_1, apisList);
+ list.setAdapter(apis);
+
+ // handling user's selection on the UI
+ list.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view,
+ int position, long id) {
+
+ if (position == 0) {
+ userInputDialog();
+ }
+ }
+ });
+
+ // handler for updating the UI i.e. MessageLog (TextBox) & ListView
+ mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case 0:
+ logs.setText("");
+ logs.setText(logMessage);
+ Log.i(LOG_TAG, logMessage);
+ break;
+ }
+ }
+ };
+ setHandler(mHandler);
+ }
+
+ // Dialog for taking user input for setting the attribute [Temperature]
+ // value
+ private void userInputDialog() {
+
+ if (null == ServerBuilder.rcsResourceObject) {
+ displayToastMessage("Resource Object is NULL");
+ } else {
+ final Dialog dialog = new Dialog(mcontext);
+ dialog.setContentView(R.layout.userinputfortemperaturevalue);
+ dialog.setTitle("Enter the Temperature Value");
+
+ dialog.setCancelable(false);
+ dialog.show();
+ Button ok = (Button) dialog.findViewById(R.id.ok);
+ Button cancel = (Button) dialog.findViewById(R.id.cancel);
+
+ ok.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ EditText temperatureValue = (EditText) dialog
+ .findViewById(R.id.attributeValue);
+ String value = temperatureValue.getText().toString();
+ if (value.equalsIgnoreCase("")) {
+ String toastmessage = "Please enter the Temperature Value";
+ displayToastMessage(toastmessage);
+ } else {
+ dialog.dismiss();
+ int val = Integer.parseInt(value);
+
+ setAttribute(val);
+ }
+ }
+ });
+ cancel.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ dialog.dismiss();
+ }
+ });
+ }
+ }
+
+ // Set the attribute value as per user's selection on the UI
+ public void setAttribute(int value) {
+
+ ServerBuilder.rcsResourceObject.setAttribute("Temperature", value);
+ logMessage = "Attribute set successfully" + "\n";
+ logMessage = logMessage + "Temperature : " + value;
+ Message msg;
+ ServerBuilderAutoActivity.setMessageLog(logMessage);
+ msg = Message.obtain();
+ msg.what = 0;
+ this.getHandler().sendMessage(msg);
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ }
+
+ // ****Utility Functions*****//
+
+ public static ServerBuilderAutoActivity getServerBuilderAutoActivity() {
+ return activityObj;
+ }
+
+ public static void setMessageLog(String message) {
+ logMessage = message;
+ }
+
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ public void setHandler(Handler mHandler) {
+ ServerBuilderAutoActivity.mHandler = mHandler;
+ }
+
+ public void displayToastMessage(String message) {
+ Toast toast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
+ toast.show();
+ Log.i(LOG_TAG, message);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+package com.example.sampleserver;
+
+import java.util.ArrayList;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.Toast;
+import android.widget.AdapterView.OnItemClickListener;
+
+import com.example.sampleresourceserver.R;
+
+/**
+ * Activity for handling user's selection on UI & for updating UI.
+ */
+public class ServerBuilderDevActivity extends Activity {
+
+ private static ServerBuilderDevActivity activityObj;
+ private ArrayAdapter<String> apis;
+ private ArrayList<String> apisList;
+ private final String LOG_TAG = "[ReSample] "
+ + this.getClass()
+ .getSimpleName();
+ private ListView list;
+ private EditText logs;
+ private static Handler mHandler;
+ public static Context mcontext;
+ private static String logMessage;
+ private ServerBuilder builderObj;
+
+ public static boolean getHandlerFlag = false;
+ public static boolean setHandlerFlag = false;
+ public static boolean setAttributeUpdatedListenerFlag = false;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.server_builder_dev);
+
+ logs = (EditText) findViewById(R.id.devLog);
+ logs.setText("Resource Created Successfully");
+
+ activityObj = this;
+ mcontext = this;
+ builderObj = new ServerBuilder();
+
+ list = (ListView) findViewById(R.id.serverBuilderDevList);
+ apisList = new ArrayList<String>();
+
+ // adding the item to list that will be displayed on the UI.
+ apisList.add("Set Temperature");
+ apisList.add("Set Get Request Handler");
+ apisList.add("Set Set Request Handler");
+ apisList.add("Set Attribute Updated Listener");
+ apisList.add("Remove Attribute Updated Listener");
+
+ apis = new ArrayAdapter<String>(activityObj,
+ android.R.layout.simple_list_item_1, apisList);
+ list.setAdapter(apis);
+
+ // handling user's selection on the UI
+ list.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view,
+ int position, long id) {
+
+ if (position == 0) {
+ userInputDialog();
+ }
+ if (position == 1) {
+ if (getHandlerFlag == true) {
+ displayToastMessage("GetRequest Handle already set");
+ } else {
+ builderObj.setGetRequestListener();
+ getHandlerFlag = true;
+ }
+ }
+ if (position == 2) {
+ if (setHandlerFlag == true) {
+ displayToastMessage("GetRequest Handle already set");
+ } else {
+ builderObj.setSetRequestListener();
+ setHandlerFlag = true;
+ }
+ }
+ if (position == 3) {
+ if (setAttributeUpdatedListenerFlag == true) {
+ displayToastMessage("Attribute Updated Listener already set");
+ } else {
+ builderObj.setAttributeUpdatedListener();
+ setAttributeUpdatedListenerFlag = true;
+ }
+ }
+ if (position == 4) {
+ if (setAttributeUpdatedListenerFlag == false) {
+ displayToastMessage("Attribute Updated Listener is not set");
+ } else {
+ builderObj.removeAttributeUpdatedListener();
+ setAttributeUpdatedListenerFlag = false;
+ }
+ }
+ }
+ });
+
+ // handler for updating the UI i.e. MessageLog (TextBox) & ListView
+ mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case 0:
+ logs.setText("");
+ logs.setText(logMessage);
+ Log.i(LOG_TAG, logMessage);
+ break;
+ }
+ }
+ };
+ setHandler(mHandler);
+ }
+
+ // Dialog for taking user input for setting the attribute [Temperature]
+ // value
+ private void userInputDialog() {
+
+ if (null == builderObj) {
+ displayToastMessage("Resource Object is NULL");
+ } else {
+ final Dialog dialog = new Dialog(mcontext);
+ dialog.setContentView(R.layout.userinputfortemperaturevalue);
+ dialog.setTitle("Enter the Temperature Value");
+
+ dialog.setCancelable(false);
+ dialog.show();
+ Button ok = (Button) dialog.findViewById(R.id.ok);
+ Button cancel = (Button) dialog.findViewById(R.id.cancel);
+
+ ok.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ EditText temperatureValue = (EditText) dialog
+ .findViewById(R.id.attributeValue);
+ String value = temperatureValue.getText().toString();
+ if (value.equalsIgnoreCase("")) {
+ String toastmessage = "Please enter the Temperature Value";
+ displayToastMessage(toastmessage);
+ } else {
+ dialog.dismiss();
+ int val = Integer.parseInt(value);
+
+ builderObj.setAttribute(val);
+ }
+ }
+ });
+ cancel.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ dialog.dismiss();
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ }
+
+ // ****Utility Functions*****//
+
+ public void setMessageLog(String message) {
+ logMessage = message;
+ }
+
+ public static ServerBuilderDevActivity getServerBuilderDevActivity() {
+ return activityObj;
+ }
+
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ public void setHandler(Handler mHandler) {
+ ServerBuilderDevActivity.mHandler = mHandler;
+ }
+
+ public void displayToastMessage(String message) {
+ Toast toast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
+ toast.show();
+ Log.i(LOG_TAG, message);
+ }
+}
if env.get('SECURED') == '1':
ResourceClient_env.AppendUnique(LIBS = ['tinydtls'])
ResourceServer_env.AppendUnique(LIBS = ['tinydtls'])
-
+
if 'rt' in ResourceClient_env.get('LIBS'):
ResourceClient_env.Append(LIBS = ['rt'])
if 'rt' in ResourceServer_env.get('LIBS'):
std::shared_ptr<RCSRemoteResourceObject> resource;
const std::string defaultKey = "Temperature";
-const std::string resourceType = "?rt=core.TemperatureSensor";
-const std::string targetUri = OC_RSRVD_WELL_KNOWN_URI + resourceType;
+const std::string resourceType = "core.TemperatureSensor";
+const std::string relativetUri = OC_RSRVD_WELL_KNOWN_URI;
std::mutex mtx;
std::condition_variable cond;
{
std::cout << "Wait 2 seconds until discovered." << std::endl;
- RCSDiscoveryManager::getInstance()->discoverResource(RCSAddress::multicast(), targetUri,
- &onResourceDiscovered);
+ RCSDiscoveryManager::getInstance()->discoverResourceByType(RCSAddress::multicast(),
+ relativetUri, resourceType, &onResourceDiscovered);
std::unique_lock<std::mutex> lck(mtx);
cond.wait_for(lck,std::chrono::seconds(2));
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="org.tizen.nativecore.config.sbi.gcc45.app.debug.109194109">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="org.tizen.nativecore.config.sbi.gcc45.app.debug.109194109" moduleId="org.eclipse.cdt.core.settings" name="Debug">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="resampleclient" buildArtefactType="org.tizen.nativecore.buildArtefactType.app" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.tizen.nativecore.buildArtefactType.app,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" description="" errorParsers="org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;" id="org.tizen.nativecore.config.sbi.gcc45.app.debug.109194109" name="Debug" parent="org.tizen.nativecore.config.sbi.gcc45.app.debug">
+ <folderInfo id="org.tizen.nativecore.config.sbi.gcc45.app.debug.109194109." name="/" resourcePath="">
+ <toolChain id="org.tizen.nativecore.toolchain.sbi.gcc45.app.debug.266200202" name="Tizen Native Toolchain" superClass="org.tizen.nativecore.toolchain.sbi.gcc45.app.debug">
+ <targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="org.tizen.nativeide.target.sbi.gnu.platform.base.1788661429" osList="linux,win32" superClass="org.tizen.nativeide.target.sbi.gnu.platform.base"/>
+ <builder arguments="--eval="SHELL=cmd" -r" autoBuildTarget="all" buildPath="${workspace_loc:/TMSampleApp}/Debug" enableAutoBuild="true" id="org.tizen.nativecore.target.sbi.gnu.builder.1749302123" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Tizen Application Builder" superClass="org.tizen.nativecore.target.sbi.gnu.builder"/>
+ <tool id="org.tizen.nativecore.tool.sbi.gnu.archiver.345678603" name="Archiver" superClass="org.tizen.nativecore.tool.sbi.gnu.archiver"/>
+ <tool command="arm-linux-gnueabi-g++.exe" id="org.tizen.nativecore.tool.sbi.gnu.cpp.compiler.1794187316" name="C++ Compiler" superClass="org.tizen.nativecore.tool.sbi.gnu.cpp.compiler">
+ <option id="gnu.cpp.compiler.option.optimization.level.719656926" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
+ <option id="sbi.gnu.cpp.compiler.option.debugging.level.core.378028433" name="Debug level" superClass="sbi.gnu.cpp.compiler.option.debugging.level.core" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
+ <option id="sbi.gnu.cpp.compiler.option.831567474" name="Tizen-Target" superClass="sbi.gnu.cpp.compiler.option" useByScannerDiscovery="false" valueType="userObjs">
+ <listOptionValue builtIn="false" value="mobile-2.3-device.core_gcc46.armel.core.app"/>
+ </option>
+ <option id="sbi.gnu.cpp.compiler.option.frameworks_inc.core.1543030783" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.cpp.compiler.option.frameworks_inc.core" useByScannerDiscovery="false" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libxml2""/>
+ <listOptionValue builtIn="false" value=""${SDK_PATH}/library""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/AL""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appcore-agent""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appfw""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/base""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/cairo""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/calendar-service2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ckm""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/contacts-svc""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/curl""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dbus-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/dbus-1.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dlog""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ecore-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/e_dbus-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/edje-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efreet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1/eina""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/elementary-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ethumb-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/evas-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/fontconfig""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/freetype2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/gio-unix-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/glib-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/glib-2.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0/json-glib""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libexif""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media-content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/minizip""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/network""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/notification""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/shortcut""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/storage""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/system""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ui""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/vconf""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/web""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/badge""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eio-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/email-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/embryo-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/messaging""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/msg-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ug-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/context-manager""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony-client""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ewebkit2-0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/location""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/sensor""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efl-extension""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/wifi-direct""/>
+ </option>
+ <option id="sbi.gnu.cpp.compiler.option.frameworks_cflags.core.1612037830" name="Tizen-Frameworks-Other-Cflags" superClass="sbi.gnu.cpp.compiler.option.frameworks_cflags.core" useByScannerDiscovery="false" valueType="stringList">
+ <listOptionValue builtIn="false" value="${TC_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value=" -fPIE"/>
+ <listOptionValue builtIn="false" value="--sysroot="${SBI_SYSROOT}""/>
+ <listOptionValue builtIn="false" value="-mthumb"/>
+ </option>
+ <option id="gnu.cpp.compiler.option.include.paths.1501991974" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc}""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\src\resourceBroker\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\src\resourceCache\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\src\common\utils\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\src\common\expiryTimer\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\src\common\expiryTimer\src""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\src\common\primitiveResource\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\c_common""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\stack\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\logger\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\occoap\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\ocrandom\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\ocsocket\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\oc_logger\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\extlibs\timer""/>
+ </option>
+ <option id="sbi.gnu.cpp.compiler.option.frameworks.core.1095600730" name="Tizen-Frameworks" superClass="sbi.gnu.cpp.compiler.option.frameworks.core" useByScannerDiscovery="false" valueType="userObjs">
+ <listOptionValue builtIn="false" value="Native_API"/>
+ </option>
+ <option id="gnu.cpp.compiler.option.preprocessor.def.371963530" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="_DEBUG"/>
+ </option>
+ <option id="gnu.cpp.compiler.option.dialect.std.1929207991" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/>
+ <option id="sbi.gnu.cpp.compiler.option.misc.pic.core.755649926" name="-fPIC option" superClass="sbi.gnu.cpp.compiler.option.misc.pic.core" value="true" valueType="boolean"/>
+ <option id="gnu.cpp.compiler.option.other.other.1760093561" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" value="-c -fmessage-length=0 -std=c++0x" valueType="string"/>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1956958926" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+ </tool>
+ <tool command="arm-linux-gnueabi-gcc.exe" id="org.tizen.nativecore.tool.sbi.gnu.c.compiler.2072036030" name="C Compiler" superClass="org.tizen.nativecore.tool.sbi.gnu.c.compiler">
+ <option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.1042898971" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
+ <option id="sbi.gnu.c.compiler.option.debugging.level.core.135607770" name="Debug level" superClass="sbi.gnu.c.compiler.option.debugging.level.core" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/>
+ <option id="sbi.gnu.c.compiler.option.571493571" name="Tizen-Target" superClass="sbi.gnu.c.compiler.option" useByScannerDiscovery="false" valueType="userObjs">
+ <listOptionValue builtIn="false" value="mobile-2.3-device.core_gcc46.armel.core.app"/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.frameworks_inc.core.107632308" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.c.compiler.option.frameworks_inc.core" useByScannerDiscovery="false" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libxml2""/>
+ <listOptionValue builtIn="false" value=""${SDK_PATH}/library""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/AL""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appcore-agent""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appfw""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/base""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/cairo""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/calendar-service2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ckm""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/contacts-svc""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/curl""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dbus-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/dbus-1.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dlog""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ecore-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/e_dbus-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/edje-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efreet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1/eina""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/elementary-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ethumb-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/evas-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/fontconfig""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/freetype2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/gio-unix-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/glib-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/glib-2.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0/json-glib""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libexif""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media-content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/minizip""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/network""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/notification""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/shortcut""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/storage""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/system""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ui""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/vconf""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/web""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/badge""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eio-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/email-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/embryo-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/messaging""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/msg-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ug-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/context-manager""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony-client""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ewebkit2-0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/location""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/sensor""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efl-extension""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/wifi-direct""/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.frameworks_cflags.core.1275911900" name="Tizen-Frameworks-Other-Cflags" superClass="sbi.gnu.c.compiler.option.frameworks_cflags.core" useByScannerDiscovery="false" valueType="stringList">
+ <listOptionValue builtIn="false" value="${TC_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value=" -fPIE"/>
+ <listOptionValue builtIn="false" value="--sysroot="${SBI_SYSROOT}""/>
+ <listOptionValue builtIn="false" value="-mthumb"/>
+ </option>
+ <option id="gnu.c.compiler.option.include.paths.109116980" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc}""/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.frameworks.core.1552601669" name="Tizen-Frameworks" superClass="sbi.gnu.c.compiler.option.frameworks.core" useByScannerDiscovery="false" valueType="userObjs">
+ <listOptionValue builtIn="false" value="Native_API"/>
+ </option>
+ <option id="gnu.c.compiler.option.preprocessor.def.symbols.2021130927" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="_DEBUG"/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.misc.pic.core.1304419386" name="-fPIC option" superClass="sbi.gnu.c.compiler.option.misc.pic.core" value="false" valueType="boolean"/>
+ <option id="gnu.c.compiler.option.misc.other.2029079564" name="Other flags" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -std=c++0x" valueType="string"/>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1859092644" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+ <tool id="org.tizen.nativeide.tool.sbi.gnu.c.linker.base.944066372" name="C Linker" superClass="org.tizen.nativeide.tool.sbi.gnu.c.linker.base"/>
+ <tool command="arm-linux-gnueabi-g++.exe" id="org.tizen.nativecore.tool.sbi.gnu.cpp.linker.1667264058" name="C++ Linker" superClass="org.tizen.nativecore.tool.sbi.gnu.cpp.linker">
+ <option id="sbi.gnu.cpp.linker.option.frameworks_lflags.core.1178784315" name="Tizen-Frameworks-Other-Lflags" superClass="sbi.gnu.cpp.linker.option.frameworks_lflags.core" valueType="stringList">
+ <listOptionValue builtIn="false" value="${TC_LINKER_MISC}"/>
+ <listOptionValue builtIn="false" value="${RS_LINKER_MISC}"/>
+ <listOptionValue builtIn="false" value="-pie -lpthread "/>
+ <listOptionValue builtIn="false" value="-Xlinker -rpath="/home/developer/sdk_tools/lib""/>
+ <listOptionValue builtIn="false" value="--sysroot="${SBI_SYSROOT}""/>
+ <listOptionValue builtIn="false" value="-Xlinker --version-script=${PROJ_PATH}/.exportMap"/>
+ <listOptionValue builtIn="false" value="-L"${SBI_SYSROOT}/usr/lib""/>
+ <listOptionValue builtIn="false" value="$(RS_LIBRARIES)"/>
+ </option>
+ <option id="gnu.cpp.link.option.paths.1087248355" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" valueType="libPaths">
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/lib}""/>
+ </option>
+ <option id="gnu.cpp.link.option.libs.2039500142" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs">
+ <listOptionValue builtIn="false" value="oc"/>
+ <listOptionValue builtIn="false" value="octbstack"/>
+ <listOptionValue builtIn="false" value="oc_logger"/>
+ <listOptionValue builtIn="false" value="oc_logger_core"/>
+ <listOptionValue builtIn="false" value="connectivity_abstraction"/>
+ <listOptionValue builtIn="false" value="uuid"/>
+ <listOptionValue builtIn="false" value="rcs_client"/>
+ <listOptionValue builtIn="false" value="rcs_common"/>
+ <listOptionValue builtIn="false" value="rcs_container"/>
+ <listOptionValue builtIn="false" value="rcs_server"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.618645708" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+ </inputType>
+ </tool>
+ <tool command="arm-linux-gnueabi-as.exe" id="org.tizen.nativeapp.tool.sbi.gnu.assembler.base.1585687908" name="Assembler" superClass="org.tizen.nativeapp.tool.sbi.gnu.assembler.base">
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.89256350" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+ </tool>
+ <tool id="org.tizen.nativecore.tool.fnmapgen.353447784" name="C FN-Map Generator" superClass="org.tizen.nativecore.tool.fnmapgen"/>
+ <tool id="org.tizen.nativecore.tool.fnmapgen.cpp.734608698" name="C++ FN-Map Generator" superClass="org.tizen.nativecore.tool.fnmapgen.cpp"/>
+ <tool id="org.tizen.nativecore.tool.ast.125567506" name="C Static Analyzer" superClass="org.tizen.nativecore.tool.ast"/>
+ <tool id="org.tizen.nativecore.tool.ast.cpp.2107204356" name="C++ Static Analyzer" superClass="org.tizen.nativecore.tool.ast.cpp"/>
+ <tool id="org.tizen.nativecore.tool.sbi.po.compiler.1190161351" name="PO Resource Compiler" superClass="org.tizen.nativecore.tool.sbi.po.compiler"/>
+ <tool id="org.tizen.nativecore.tool.sbi.edc.compiler.1621384631" name="EDC Resource Compiler" superClass="org.tizen.nativecore.tool.sbi.edc.compiler"/>
+ </toolChain>
+ </folderInfo>
+ <sourceEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="inc"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="res"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
+ </sourceEntries>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ <cconfiguration id="org.tizen.nativecore.config.sbi.gcc45.app.release.1584352396">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="org.tizen.nativecore.config.sbi.gcc45.app.release.1584352396" moduleId="org.eclipse.cdt.core.settings" name="Release">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="tmsampleapp" buildArtefactType="org.tizen.nativecore.buildArtefactType.app" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.tizen.nativecore.buildArtefactType.app,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" description="" errorParsers="org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;" id="org.tizen.nativecore.config.sbi.gcc45.app.release.1584352396" name="Release" parent="org.tizen.nativecore.config.sbi.gcc45.app.release">
+ <folderInfo id="org.tizen.nativecore.config.sbi.gcc45.app.release.1584352396." name="/" resourcePath="">
+ <toolChain id="org.tizen.nativecore.toolchain.sbi.gcc45.app.release.32000863" name="Tizen Native Toolchain" superClass="org.tizen.nativecore.toolchain.sbi.gcc45.app.release">
+ <targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="org.tizen.nativeide.target.sbi.gnu.platform.base.1750758769" osList="linux,win32" superClass="org.tizen.nativeide.target.sbi.gnu.platform.base"/>
+ <builder buildPath="${workspace_loc:/TMSampleApp}/Release" id="org.tizen.nativecore.target.sbi.gnu.builder.2029564551" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Tizen Application Builder" superClass="org.tizen.nativecore.target.sbi.gnu.builder"/>
+ <tool id="org.tizen.nativecore.tool.sbi.gnu.archiver.224082468" name="Archiver" superClass="org.tizen.nativecore.tool.sbi.gnu.archiver"/>
+ <tool command="clang++.exe" id="org.tizen.nativecore.tool.sbi.gnu.cpp.compiler.1434486618" name="C++ Compiler" superClass="org.tizen.nativecore.tool.sbi.gnu.cpp.compiler">
+ <option id="gnu.cpp.compiler.option.optimization.level.1709393206" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
+ <option id="sbi.gnu.cpp.compiler.option.debugging.level.core.221700213" name="Debug level" superClass="sbi.gnu.cpp.compiler.option.debugging.level.core"/>
+ <option id="sbi.gnu.cpp.compiler.option.710876023" name="Tizen-Target" superClass="sbi.gnu.cpp.compiler.option" valueType="userObjs">
+ <listOptionValue builtIn="false" value="mobile-2.3-emulator.core_llvm34.i386.core.app"/>
+ </option>
+ <option id="sbi.gnu.cpp.compiler.option.frameworks_inc.core.1622581330" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.cpp.compiler.option.frameworks_inc.core" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libxml2""/>
+ <listOptionValue builtIn="false" value=""${SDK_PATH}/library""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/AL""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appcore-agent""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appfw""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/base""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/cairo""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/calendar-service2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ckm""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/contacts-svc""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/curl""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dbus-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/dbus-1.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dlog""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ecore-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/e_dbus-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/edje-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efreet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1/eina""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/elementary-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ethumb-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/evas-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/fontconfig""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/freetype2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/gio-unix-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/glib-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/glib-2.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0/json-glib""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libexif""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media-content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/minizip""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/network""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/notification""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/shortcut""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/storage""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/system""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ui""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/vconf""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/web""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/badge""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eio-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/email-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/embryo-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/messaging""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/msg-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ug-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/context-manager""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony-client""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ewebkit2-0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/location""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/sensor""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efl-extension""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/wifi-direct""/>
+ </option>
+ <option id="sbi.gnu.cpp.compiler.option.frameworks_cflags.core.1695583788" name="Tizen-Frameworks-Other-Cflags" superClass="sbi.gnu.cpp.compiler.option.frameworks_cflags.core" valueType="stringList">
+ <listOptionValue builtIn="false" value="${TC_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value=" -fPIE"/>
+ <listOptionValue builtIn="false" value="--sysroot="${SBI_SYSROOT}""/>
+ </option>
+ <option id="gnu.cpp.compiler.option.include.paths.585301879" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc}""/>
+ </option>
+ <option id="sbi.gnu.cpp.compiler.option.frameworks.core.708669314" name="Tizen-Frameworks" superClass="sbi.gnu.cpp.compiler.option.frameworks.core" valueType="userObjs">
+ <listOptionValue builtIn="false" value="Native_API"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.2006056090" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+ </tool>
+ <tool command="clang.exe" id="org.tizen.nativecore.tool.sbi.gnu.c.compiler.601285388" name="C Compiler" superClass="org.tizen.nativecore.tool.sbi.gnu.c.compiler">
+ <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.option.optimization.level.1778561828" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" valueType="enumerated"/>
+ <option id="sbi.gnu.c.compiler.option.debugging.level.core.1695949408" name="Debug level" superClass="sbi.gnu.c.compiler.option.debugging.level.core"/>
+ <option id="sbi.gnu.c.compiler.option.1422818783" name="Tizen-Target" superClass="sbi.gnu.c.compiler.option" valueType="userObjs">
+ <listOptionValue builtIn="false" value="mobile-2.3-emulator.core_llvm34.i386.core.app"/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.frameworks_inc.core.1871683675" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.c.compiler.option.frameworks_inc.core" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libxml2""/>
+ <listOptionValue builtIn="false" value=""${SDK_PATH}/library""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/AL""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appcore-agent""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appfw""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/base""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/cairo""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/calendar-service2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ckm""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/contacts-svc""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/curl""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dbus-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/dbus-1.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dlog""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ecore-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/e_dbus-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/edje-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efreet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1/eina""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/elementary-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ethumb-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/evas-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/fontconfig""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/freetype2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/gio-unix-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/glib-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/glib-2.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0/json-glib""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libexif""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media-content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/minizip""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/network""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/notification""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/shortcut""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/storage""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/system""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ui""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/vconf""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/web""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/badge""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eio-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/email-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/embryo-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/messaging""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/msg-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ug-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/context-manager""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony-client""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ewebkit2-0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/location""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/sensor""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efl-extension""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/wifi-direct""/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.frameworks_cflags.core.371848582" name="Tizen-Frameworks-Other-Cflags" superClass="sbi.gnu.c.compiler.option.frameworks_cflags.core" valueType="stringList">
+ <listOptionValue builtIn="false" value="${TC_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value=" -fPIE"/>
+ <listOptionValue builtIn="false" value="--sysroot="${SBI_SYSROOT}""/>
+ </option>
+ <option id="gnu.c.compiler.option.include.paths.1254567673" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc}""/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.frameworks.core.627340354" name="Tizen-Frameworks" superClass="sbi.gnu.c.compiler.option.frameworks.core" valueType="userObjs">
+ <listOptionValue builtIn="false" value="Native_API"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.749706957" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+ <tool id="org.tizen.nativeide.tool.sbi.gnu.c.linker.base.1794486202" name="C Linker" superClass="org.tizen.nativeide.tool.sbi.gnu.c.linker.base"/>
+ <tool command="clang++.exe" id="org.tizen.nativecore.tool.sbi.gnu.cpp.linker.2579106" name="C++ Linker" superClass="org.tizen.nativecore.tool.sbi.gnu.cpp.linker">
+ <option id="sbi.gnu.cpp.linker.option.frameworks_lflags.core.1582557344" name="Tizen-Frameworks-Other-Lflags" superClass="sbi.gnu.cpp.linker.option.frameworks_lflags.core" valueType="stringList">
+ <listOptionValue builtIn="false" value="${TC_LINKER_MISC}"/>
+ <listOptionValue builtIn="false" value="${RS_LINKER_MISC}"/>
+ <listOptionValue builtIn="false" value="-pie -lpthread "/>
+ <listOptionValue builtIn="false" value="-Xlinker -rpath="/home/developer/sdk_tools/lib""/>
+ <listOptionValue builtIn="false" value="--sysroot="${SBI_SYSROOT}""/>
+ <listOptionValue builtIn="false" value="-Xlinker --version-script=${PROJ_PATH}/.exportMap"/>
+ <listOptionValue builtIn="false" value="-L"${SBI_SYSROOT}/usr/lib""/>
+ <listOptionValue builtIn="false" value="$(RS_LIBRARIES)"/>
+ </option>
+ <option id="gnu.cpp.link.option.paths.1396123174" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" valueType="libPaths">
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/lib}""/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.768667264" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+ </inputType>
+ </tool>
+ <tool command="i386-linux-gnueabi-as.exe" id="org.tizen.nativeapp.tool.sbi.gnu.assembler.base.380499784" name="Assembler" superClass="org.tizen.nativeapp.tool.sbi.gnu.assembler.base">
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1638213209" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+ </tool>
+ <tool id="org.tizen.nativecore.tool.fnmapgen.1617359663" name="C FN-Map Generator" superClass="org.tizen.nativecore.tool.fnmapgen"/>
+ <tool id="org.tizen.nativecore.tool.fnmapgen.cpp.759297757" name="C++ FN-Map Generator" superClass="org.tizen.nativecore.tool.fnmapgen.cpp"/>
+ <tool id="org.tizen.nativecore.tool.ast.495578509" name="C Static Analyzer" superClass="org.tizen.nativecore.tool.ast"/>
+ <tool id="org.tizen.nativecore.tool.ast.cpp.91235808" name="C++ Static Analyzer" superClass="org.tizen.nativecore.tool.ast.cpp"/>
+ <tool id="org.tizen.nativecore.tool.sbi.po.compiler.619869321" name="PO Resource Compiler" superClass="org.tizen.nativecore.tool.sbi.po.compiler"/>
+ <tool id="org.tizen.nativecore.tool.sbi.edc.compiler.1045552473" name="EDC Resource Compiler" superClass="org.tizen.nativecore.tool.sbi.edc.compiler"/>
+ </toolChain>
+ </folderInfo>
+ <sourceEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="inc"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="res"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
+ </sourceEntries>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="TMSampleApp.org.tizen.nativecore.target.sbi.gcc45.app.278712545" name="Tizen Native Application" projectType="org.tizen.nativecore.target.sbi.gcc45.app"/>
+ </storageModule>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ <scannerConfigBuildInfo instanceId="org.tizen.nativecore.config.sbi.gcc45.app.release.1584352396">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="org.tizen.nativecore.config.sbi.gcc45.app.debug.109194109">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ </scannerConfigBuildInfo>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+ <storageModule moduleId="refreshScope" versionNumber="2">
+ <configuration configurationName="Debug">
+ <resource resourceType="PROJECT" workspacePath="/TMSampleApp"/>
+ </configuration>
+ <configuration configurationName="Release">
+ <resource resourceType="PROJECT" workspacePath="/TMSampleApp"/>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="com.samsung.tizen.nativeapp.projectInfo" version="1.0.0"/>
+</cproject>
--- /dev/null
+{
+ global: main;
+ local: *;
+};
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>RESampleClient</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+ <triggers>full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.tizen.nativecore.apichecker.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>org.eclipse.cdt.core.ccnature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ <nature>org.tizen.nativecore.apichecker.core.tizenCppNature</nature>
+ </natures>
+ <filteredResources>
+ <filter>
+ <id>0</id>
+ <name></name>
+ <type>26</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-projectRelativePath-matches-false-false-*/.tpk</arguments>
+ </matcher>
+ </filter>
+ </filteredResources>
+</projectDescription>
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+#define POPUP_CONTENT_DEFAULT_PADDING_LEFT_MIN_INC 15
+#define POPUP_EDITFIELD_LAYOUT_MINMAX_HEIGHT_INC 96
+
+group
+{
+ name: "group_layout";
+ parts
+ {
+ part
+ {
+ name: "find_button";
+ type: SWALLOW;
+ scale: 1;
+ description
+ {
+ rel1.relative: 0.01 0.01;
+ rel2.relative: 0.5 0.09;
+ }
+ }
+ part
+ {
+ name: "list";
+ type: SWALLOW;
+ scale: 1;
+ description
+ {
+ rel1.relative: 0.01 0.1;
+ rel2.relative: 0.99 0.7;
+ }
+ }
+ part
+ {
+ name: "log_bg";
+ type: RECT;
+ scale: 1;
+ description
+ {
+ state: "default" 0.0;
+ rel1.relative: 0.01 0.71;
+ rel2.relative: 0.98 1.0;
+ color: 220 220 220 255;
+ }
+ }
+ part
+ {
+ name: "log";
+ type: SWALLOW;
+ scale: 1;
+ description
+ {
+ rel1.to: "log_bg";
+ rel2.to: "log_bg";
+ }
+ }
+ }
+}
+
+group
+{
+ name: "popup_datetime_text";
+ parts
+ {
+ part
+ {
+ name: "pad_l";
+ type: SPACER;
+ scale: 1;
+ description
+ {
+ state: "default" 0.0;
+ min: POPUP_CONTENT_DEFAULT_PADDING_LEFT_MIN_INC 0;
+ fixed: 1 0;
+ rel1.relative: 0.0 0.0;
+ rel2.relative: 0.0 1.0;
+ align: 0.0 0.0;
+ }
+ }
+ part
+ {
+ name: "pad_r";
+ type: SPACER;
+ scale: 1;
+ description
+ {
+ state: "default" 0.0;
+ min: POPUP_CONTENT_DEFAULT_PADDING_LEFT_MIN_INC 0;
+ fixed: 1 0;
+ rel1.relative: 1.0 0.0;
+ rel2.relative: 1.0 1.0;
+ align: 1.0 0.0;
+ }
+ }
+ part
+ {
+ name: "elm.swallow.content";
+ type: SWALLOW;
+ scale: 1;
+ description
+ {
+ state: "default" 0.0;
+ min: 0 POPUP_EDITFIELD_LAYOUT_MINMAX_HEIGHT_INC;
+ max: -1 POPUP_EDITFIELD_LAYOUT_MINMAX_HEIGHT_INC;
+ align: 0.5 0.5;
+ rel1
+ {
+ relative: 1.0 0.0;
+ to_x: "pad_l";
+ }
+ rel2
+ {
+ relative: 0.0 1.0;
+ to_x: "pad_r";
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 __RECLIENT_H__
+#define __RECLIENT_H__
+
+typedef void(*ClientMenuHandler)();
+typedef int ReturnValue;
+
+void *showGroupAPIs(void *data);
+
+#endif // __RECLIENT_H__
--- /dev/null
+/******************************************************************
+ *
+ * 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 __RECLIENTMAIN_H__
+#define __RECLIENTMAIN_H__
+
+#include <app.h>
+#include <Elementary.h>
+#include <system_settings.h>
+#include <efl_extension.h>
+#include <dlog.h>
+
+#include "OCPlatform.h"
+#include "OCApi.h"
+
+using namespace OC;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "reclientmain"
+
+#if !defined(PACKAGE)
+#define PACKAGE "org.tizen.resampleclient"
+#endif
+
+#define ELM_DEMO_EDJ "opt/usr/apps/org.tizen.resampleclient/res/ui_controls.edj"
+
+void group_cb(void *data, Evas_Object *obj, void *event_info);
+
+#endif // __RECLIENTMAIN_H__
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+collections
+{
+ base_scale: 1.8;
+ #include "../edc_resource/re_client_control.edc"
+}
\ No newline at end of file
--- /dev/null
+/******************************************************************
+ *
+ * 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 "reclient.h"
+
+#include<iostream>
+#include "mutex"
+#include "condition_variable"
+
+#include "reclientmain.h"
+
+#include "RCSDiscoveryManager.h"
+#include "RCSRemoteResourceObject.h"
+#include "RCSResourceAttributes.h"
+#include "RCSAddress.h"
+
+#include "OCPlatform.h"
+
+# define checkResource nullptr == resource?false:true
+
+using namespace std;
+using namespace OC;
+using namespace OIC::Service;
+
+constexpr int CORRECT_INPUT = 1;
+constexpr int INCORRECT_INPUT = 2;
+constexpr int QUIT_INPUT = 3;
+
+std::shared_ptr<RCSRemoteResourceObject> resource;
+
+const std::string defaultKey = "Temperature";
+const std::string resourceType = "?rt=core.TemperatureSensor";
+const std::string targetUri = OC_RSRVD_WELL_KNOWN_URI + resourceType;
+
+std::mutex mtx;
+std::condition_variable cond;
+
+static Evas_Object *log_entry = NULL;
+static Evas_Object *list = NULL;
+static Evas_Object *naviframe = NULL;
+
+typedef struct temperature_popup
+{
+ Evas_Object *popup;
+ Evas_Object *entry;
+} temperature_popup_fields;
+
+// Function to update the log in UI
+void *updateGroupLog(void *data)
+{
+ string *log = (string *)data;
+ // Show the log
+ elm_entry_entry_append(log_entry, (*log).c_str());
+ elm_entry_cursor_end_set(log_entry);
+ return NULL;
+}
+
+static void onDestroy()
+{
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Destroy sequence called");
+ resource = nullptr;
+}
+
+void onResourceDiscovered(std::shared_ptr<RCSRemoteResourceObject> foundResource)
+{
+ dlog_print(DLOG_INFO, LOG_TAG, "#### onResourceDiscovered callback");
+
+ std::string resourceURI = foundResource->getUri();
+ std::string hostAddress = foundResource->getAddress();
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Resource URI : %s", resourceURI.c_str());
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Resource Host : %S", hostAddress.c_str());
+
+ string logMessage = "Resource Found <br>";
+ logMessage = logMessage + "URI: " + resourceURI + "<br>";
+ logMessage = logMessage + "Host:" + hostAddress + "<br>";
+ logMessage += "----------------------<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, " %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+
+ resource = foundResource;
+
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))showGroupAPIs, NULL);
+ cond.notify_all();
+}
+
+void onResourceStateChanged(const ResourceState &resourceState)
+{
+ dlog_print(DLOG_INFO, LOG_TAG, "#### onResourceStateChanged");
+
+ std::string logMessage = "State changed to : ";
+
+ switch (resourceState)
+ {
+ case ResourceState::NONE:
+ logMessage = logMessage + "NOT_MONITORING <br>";
+ break;
+
+ case ResourceState::ALIVE:
+ logMessage = logMessage + "ALIVE <br>";
+ break;
+
+ case ResourceState::REQUESTED:
+ logMessage = logMessage + "REQUESTED <br>";
+ break;
+
+ case ResourceState::LOST_SIGNAL:
+ logMessage = logMessage + "LOST_SIGNAL <br>";
+ resource = nullptr;
+ break;
+
+ case ResourceState::DESTROYED:
+ logMessage = logMessage + "DESTROYED <br>";
+ break;
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+void onCacheUpdated(const RCSResourceAttributes &attributes)
+{
+ dlog_print(DLOG_INFO, LOG_TAG, "#### onCacheUpdated callback");
+
+ string logMessage = "Cache Updated : <br> ";
+
+ if (attributes.empty())
+ {
+ logMessage + logMessage + "Attribute is Empty <br>";
+ return;
+ }
+
+ for (const auto & attr : attributes)
+ {
+ logMessage = logMessage + "KEY:" + attr.key().c_str() + "<br>";
+ logMessage = logMessage + "VALUE:" + attr.value().toString().c_str() + "<br>";
+ }
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+void onRemoteAttributesReceivedCallback(const RCSResourceAttributes &attributes)
+{
+ dlog_print(DLOG_INFO, LOG_TAG, "#### onRemoteAttributesReceivedCallback callback");
+
+ string logMessage = "Remote Attribute Updated : <br> ";
+
+ if (attributes.empty())
+ {
+ logMessage + logMessage + "Attribute is Empty <br>";
+ return;
+ }
+
+ for (const auto & attr : attributes)
+ {
+ logMessage = logMessage + "KEY:" + attr.key().c_str() + "<br>";
+ logMessage = logMessage + "VALUE:" + attr.value().toString().c_str() + "<br>";
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+static void startMonitoring(void *data, Evas_Object *obj, void *event_info)
+{
+ string logMessage = "";
+
+ if (checkResource)
+ {
+ if (!resource->isMonitoring())
+ {
+ try
+ {
+ logMessage = logMessage + "Started Monitoring <br>";
+ resource->startMonitoring(&onResourceStateChanged);
+ }
+ catch (const BadRequestException &e)
+ {
+ logMessage = logMessage + "Exception BadRequest<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in isMonitoring : %s", e.what());
+ }
+ catch (const InvalidParameterException &e)
+ {
+ logMessage = logMessage + "Exception Invalid Param<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in isMonitoring : %s", e.what());
+ }
+ }
+ else
+ {
+ logMessage = logMessage + "Already Monitoring <br>";
+ }
+ }
+ else
+ {
+ logMessage = logMessage + "No Resource to monitor <br>";
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+static void stopMonitoring(void *data, Evas_Object *obj, void *event_info)
+{
+ string logMessage = "";
+
+ if (checkResource)
+ {
+ if (resource->isMonitoring())
+ {
+ resource->stopMonitoring();
+ logMessage = logMessage + "Stopped Monitoring <br>";
+ }
+ else
+ {
+ logMessage = logMessage + "Monitoring not started <br>";
+ }
+ }
+ else
+ {
+ logMessage = logMessage + "NO Resource to stop monitor <br>";
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, " %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+static void list_selected_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ Elm_Object_Item *it = (Elm_Object_Item *)event_info;
+ elm_list_item_selected_set(it, EINA_FALSE);
+}
+
+static void getAttributeFromRemoteServer(void *data, Evas_Object *obj, void *event_info)
+{
+ if (checkResource)
+ {
+ resource->getRemoteAttributes(&onRemoteAttributesReceivedCallback);
+ }
+ else
+ {
+ dlog_print(DLOG_INFO, LOG_TAG, "#### No Resource to getAttributeFromRemoteServer...");
+ }
+}
+
+static void setAttributeToRemoteServer(int setTemperature)
+{
+ string key = "Temperature";
+ string logMessage = "";
+
+ RCSResourceAttributes setAttribute;
+ setAttribute[key] = setTemperature;
+
+ if (checkResource)
+ {
+ resource->setRemoteAttributes(setAttribute,
+ &onRemoteAttributesReceivedCallback);
+ }
+ else
+ {
+ logMessage = "No Resource to setAttributeToRemoteServer";
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+static void startCaching(std::function <void (const RCSResourceAttributes &)>cb)
+{
+ string logMessage = "";
+
+ if (checkResource)
+ {
+ if (!resource->isCaching())
+ {
+ if (cb)
+ {
+ try
+ {
+ logMessage = logMessage + "Caching with callback <br>";
+ resource->startCaching(&onCacheUpdated);
+ }
+ catch (const BadRequestException &e)
+ {
+ logMessage = logMessage + "Exception BadRequest<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in startCaching : %s", e.what());
+ }
+
+ }
+ else
+ {
+ try
+ {
+ logMessage = logMessage + "Caching without callback <br>";
+ resource->startCaching();
+ }
+ catch (const BadRequestException &e)
+ {
+ logMessage = logMessage + "Exception BadRequest<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in startCaching : %s", e.what());
+ }
+ }
+ }
+ else
+ {
+ logMessage = logMessage + "Caching Already Started <br>";
+ }
+ }
+ else
+ {
+ logMessage = logMessage + "No resource to start Caching <br>";
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+static void startCachingWithoutCallback(void *data, Evas_Object *obj, void *event_info)
+{
+ startCaching(nullptr);
+}
+
+static void startCachingWithCallback(void *data, Evas_Object *obj, void *event_info)
+{
+ startCaching(onCacheUpdated);
+}
+
+static void getResourceCacheState(void *data, Evas_Object *obj, void *event_info)
+{
+ string logMessage = "CACHE STATE : ";
+ switch (resource->getCacheState())
+ {
+ case CacheState::READY:
+ logMessage = logMessage + "READY <br>";
+ break;
+
+ case CacheState::UNREADY:
+ logMessage = logMessage + "UNREADY <br>";
+ break;
+
+ case CacheState::LOST_SIGNAL:
+ logMessage = logMessage + "LOST_SIGNAL <br>";
+ break;
+
+ case CacheState::NONE:
+ logMessage = logMessage + "NONE <br>";
+ break;
+
+ default:
+ break;
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+static void getCachedAttributes(void *data, Evas_Object *obj, void *event_info)
+{
+ string logMessage = "";
+
+ if (checkResource)
+ {
+ try
+ {
+ if (resource->getCachedAttributes().empty())
+ {
+ logMessage = "Cached attribute empty<br>";
+ }
+ else
+ {
+ for (const auto & attr : resource->getCachedAttributes())
+ {
+ logMessage = logMessage + "KEY:" + attr.key().c_str() + "<br>";
+ logMessage = logMessage + "VALUE:" + attr.value().toString().c_str() + "<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Cached attributes received ");
+ }
+ }
+ }
+ catch (const BadRequestException &e)
+ {
+ logMessage = "Exception Received<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in getCachedAttributes : %s", e.what());
+ }
+ }
+ else
+ {
+ logMessage = logMessage + "No Resource<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### No Resource to getCachedAttributes...");
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+static void getCachedAttribute(void *data, Evas_Object *obj, void *event_info)
+{
+ string logMessage = "";
+
+ if (checkResource)
+ {
+ try
+ {
+ logMessage = logMessage + "KEY:" + defaultKey.c_str() + "<br>";
+ int attrValue = resource->getCachedAttribute(defaultKey).get< int >();
+ logMessage = logMessage + "VALUE:" + to_string(attrValue) + "<br>";
+ }
+ catch (const BadRequestException &e)
+ {
+ logMessage = logMessage + "Exception BadRequest<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in getCachedAttribute : %s", e.what());
+ }
+ catch (const BadGetException &e)
+ {
+ logMessage = logMessage + "Exception BadGet<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in getCachedAttribute : %s", e.what());
+ }
+ }
+ else
+ {
+ logMessage = logMessage + "No resource<br>";
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+static void stopCaching(void *data, Evas_Object *obj, void *event_info)
+{
+ string logMessage = "";
+
+ if (checkResource)
+ {
+ if (resource->isCaching())
+ {
+ resource->stopCaching();
+ logMessage = logMessage + "Caching stopped <br>";
+ }
+ else
+ {
+ logMessage = logMessage + "Caching not started <br>";
+ }
+ }
+ else
+ {
+ logMessage = logMessage + "No resource found<br>";
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, " %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+void discoverResource()
+{
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Wait 2 seconds until discovered");
+
+ RCSDiscoveryManager::getInstance()->discoverResource(RCSAddress::multicast(), targetUri,
+ &onResourceDiscovered);
+
+ std::unique_lock<std::mutex> lck(mtx);
+ cond.wait_for(lck, std::chrono::seconds(2));
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Discovery over");
+}
+
+static void
+popup_cancel_clicked_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ temperature_popup_fields *popup_fields = (temperature_popup_fields *)data;
+ evas_object_del(popup_fields->popup);
+ free(popup_fields);
+}
+
+static void
+popup_set_clicked_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ temperature_popup_fields *popup_fields = (temperature_popup_fields *)data;
+ Evas_Object *entry = popup_fields->entry;
+ const char *temperatureString = elm_entry_entry_get(entry);
+ // Remove white spaces(if any) at the beginning
+ int beginning = 0;
+ while (temperatureString[beginning] == ' ')
+ {
+ (beginning)++;
+ }
+
+ int len = strlen(temperatureString);
+ if (NULL == temperatureString || 1 > len)
+ {
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Read NULL Temperature Value");
+ string logMessage = "Temperature Cannot be NULL<br>";
+ logMessage += "----------------------<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, " %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog, &logMessage);
+ }
+ else
+ {
+ int temperate = atoi(temperatureString);
+ string tempString(temperatureString);
+ setAttributeToRemoteServer(temperate);
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Temperature to set : %d", temperate);
+
+ string logMessage = "Temperature to set : " + tempString + "<br>";
+ logMessage += "----------------------<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, " %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+ }
+ evas_object_del(popup_fields->popup);
+ free(popup_fields);
+}
+
+static void
+list_scheduled_actionset_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ Evas_Object *popup, *btn;
+ Evas_Object *nf = naviframe;
+ Evas_Object *entry;
+ Evas_Object *layout;
+
+ /* popup */
+ popup = elm_popup_add(nf);
+ elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0);
+ eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, eext_popup_back_cb, NULL);
+ evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_object_part_text_set(popup, "title,text", "Enter the temperature");
+
+ layout = elm_layout_add(popup);
+ elm_layout_file_set(layout, ELM_DEMO_EDJ, "popup_datetime_text");
+ evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_object_content_set(popup, layout);
+
+ entry = elm_entry_add(layout);
+ elm_entry_single_line_set(entry, EINA_TRUE);
+ elm_entry_scrollable_set(entry, EINA_TRUE);
+ evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ eext_entry_selection_back_event_allow_set(entry, EINA_TRUE);
+ elm_object_part_text_set(entry, "elm.guide", "in degree celsius");
+ elm_entry_input_panel_layout_set(entry, ELM_INPUT_PANEL_LAYOUT_NUMBER);
+ elm_object_part_content_set(layout, "elm.swallow.content", entry);
+
+ temperature_popup_fields *popup_fields;
+ popup_fields = (temperature_popup_fields *)malloc(sizeof(temperature_popup_fields));
+ if (NULL == popup_fields)
+ {
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Memory allocation failed");
+ }
+ else
+ {
+ popup_fields->popup = popup;
+ popup_fields->entry = entry;
+ }
+
+ /* Cancel button */
+ btn = elm_button_add(popup);
+ elm_object_style_set(btn, "popup");
+ elm_object_text_set(btn, "Cancel");
+ elm_object_part_content_set(popup, "button1", btn);
+ evas_object_smart_callback_add(btn, "clicked", popup_cancel_clicked_cb, popup_fields);
+
+ /* Set button */
+ btn = elm_button_add(popup);
+ elm_object_style_set(btn, "popup");
+ elm_object_text_set(btn, "Set");
+ elm_object_part_content_set(popup, "button2", btn);
+ evas_object_smart_callback_add(btn, "clicked", popup_set_clicked_cb, popup_fields);
+
+ evas_object_show(popup);
+}
+
+void *showGroupAPIs(void *data)
+{
+ // Add items to the list only if the list is empty
+ const Eina_List *eina_list = elm_list_items_get(list);
+ int count = eina_list_count(eina_list);
+ if (!count)
+ {
+ elm_list_item_append(list, "1. Start Monitoring", NULL, NULL,
+ startMonitoring, NULL);
+
+ elm_list_item_append(list, "2. Stop Monitoring", NULL, NULL,
+ stopMonitoring, NULL);
+
+ elm_list_item_append(list, "3. Get Attribute", NULL, NULL,
+ getAttributeFromRemoteServer, NULL);
+
+ elm_list_item_append(list, "4. Set Attribute", NULL, NULL,
+ list_scheduled_actionset_cb, NULL);
+
+ elm_list_item_append(list, "5. Start Caching - No update", NULL, NULL,
+ startCachingWithoutCallback, NULL);
+
+ elm_list_item_append(list, "6. Start Caching - With update", NULL, NULL,
+ startCachingWithCallback, NULL);
+
+ elm_list_item_append(list, "7. Get Cache State", NULL, NULL,
+ getResourceCacheState, NULL);
+
+ elm_list_item_append(list, "8. Get cached attributes", NULL, NULL,
+ getCachedAttributes, NULL);
+
+ elm_list_item_append(list, "9. Stop Caching", NULL, NULL,
+ stopCaching, NULL);
+
+ elm_list_go(list);
+ }
+ return NULL;
+}
+
+static Eina_Bool
+naviframe_pop_cb(void *data, Elm_Object_Item *it)
+{
+ onDestroy();
+
+ if (NULL != log_entry)
+ {
+ evas_object_del(log_entry);
+ log_entry = NULL;
+ }
+ if (NULL != list)
+ {
+ evas_object_del(list);
+ list = NULL;
+ }
+ return EINA_TRUE;
+}
+
+// Method to be called when the Group APIs UI Button is selected
+void group_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ Evas_Object *layout;
+ Evas_Object *scroller;
+ Evas_Object *nf = (Evas_Object *)data;
+ Elm_Object_Item *nf_it;
+
+ naviframe = nf;
+
+ // Scroller
+ scroller = elm_scroller_add(nf);
+ elm_scroller_bounce_set(scroller, EINA_FALSE, EINA_TRUE);
+ elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
+
+ // Layout
+ layout = elm_layout_add(nf);
+ elm_layout_file_set(layout, ELM_DEMO_EDJ, "group_layout");
+ evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+ elm_object_content_set(scroller, layout);
+
+ // List
+ list = elm_list_add(layout);
+ elm_list_mode_set(list, ELM_LIST_COMPRESS);
+ evas_object_smart_callback_add(list, "selected", list_selected_cb, NULL);
+ elm_object_part_content_set(layout, "list", list);
+ elm_list_go(list);
+
+ // log_entry - textarea for log
+ log_entry = elm_entry_add(layout);
+ elm_entry_scrollable_set(log_entry, EINA_TRUE);
+ elm_entry_editable_set(log_entry, EINA_FALSE);
+ elm_object_part_text_set(log_entry, "elm.guide", "Logs will be updated here!!!");
+ evas_object_size_hint_weight_set(log_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(log_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_object_part_content_set(layout, "log", log_entry);
+
+ nf_it = elm_naviframe_item_push(nf, "Resource Encapsulation", NULL, NULL, scroller, NULL);
+ elm_naviframe_item_pop_cb_set(nf_it, naviframe_pop_cb, NULL);
+
+ discoverResource();
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "reclientmain.h"
+#include <tizen.h>
+
+#include "OCPlatform.h"
+#include "OCApi.h"
+
+typedef struct appdata
+{
+ Evas_Object *win;
+ Evas_Object *conform;
+ Evas_Object *layout;
+ Evas_Object *nf;
+ Evas_Object *findButton;
+ Evas_Object *logtext;
+ Evas_Object *listview;
+} appdata_s;
+
+static void
+win_delete_request_cb(void *data , Evas_Object *obj , void *event_info)
+{
+ ui_app_exit();
+}
+
+static void
+list_selected_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ Elm_Object_Item *it = (Elm_Object_Item *)event_info;
+ elm_list_item_selected_set(it, EINA_FALSE);
+}
+
+static Eina_Bool
+naviframe_pop_cb(void *data, Elm_Object_Item *it)
+{
+ ui_app_exit();
+ return EINA_FALSE;
+}
+
+static void
+create_list_view(appdata_s *ad)
+{
+ Evas_Object *list;
+ Evas_Object *btn;
+ Evas_Object *nf = ad->nf;
+ Elm_Object_Item *nf_it;
+
+ // List
+ list = elm_list_add(nf);
+ elm_list_mode_set(list, ELM_LIST_COMPRESS);
+ evas_object_smart_callback_add(list, "selected", list_selected_cb, NULL);
+
+ // Main Menu Items Here
+ elm_list_item_append(list, "Discover Resource", NULL, NULL, group_cb, nf);
+
+ elm_list_go(list);
+
+ // This button is set for devices which doesn't have H/W back key.
+ btn = elm_button_add(nf);
+ elm_object_style_set(btn, "naviframe/end_btn/default");
+ nf_it = elm_naviframe_item_push(nf, "Resource Encapsulation", btn, NULL, list, NULL);
+ elm_naviframe_item_pop_cb_set(nf_it, naviframe_pop_cb, ad->win);
+}
+
+
+static void
+create_base_gui(appdata_s *ad)
+{
+ // Window
+ ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE);
+ elm_win_conformant_set(ad->win, EINA_TRUE);
+ elm_win_autodel_set(ad->win, EINA_TRUE);
+
+ if (elm_win_wm_rotation_supported_get(ad->win))
+ {
+ int rots[4] = { 0, 90, 180, 270 };
+ elm_win_wm_rotation_available_rotations_set(ad->win, (const int *)(&rots), 4);
+ }
+
+ evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, NULL);
+
+ // Conformant
+ ad->conform = elm_conformant_add(ad->win);
+ evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(ad->win, ad->conform);
+ evas_object_show(ad->conform);
+
+ // Base Layout
+ ad->layout = elm_layout_add(ad->conform);
+ evas_object_size_hint_weight_set(ad->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_layout_theme_set(ad->layout, "layout", "application", "default");
+ evas_object_show(ad->layout);
+
+ elm_object_content_set(ad->conform, ad->layout);
+
+ // Naviframe
+ ad->nf = elm_naviframe_add(ad->layout);
+ create_list_view(ad);
+ elm_object_part_content_set(ad->layout, "elm.swallow.content", ad->nf);
+ eext_object_event_callback_add(ad->nf, EEXT_CALLBACK_BACK, eext_naviframe_back_cb, NULL);
+ eext_object_event_callback_add(ad->nf, EEXT_CALLBACK_MORE, eext_naviframe_more_cb, NULL);
+
+ // Show window after base gui is set up
+ evas_object_show(ad->win);
+}
+
+// Configures the OCPlatform
+static void
+configure_platform()
+{
+ try
+ {
+ PlatformConfig config
+ { OC::ServiceType::InProc, ModeType::Client, "0.0.0.0", 0, OC::QualityOfService::LowQos };
+
+ OCPlatform::Configure(config);
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Platform configuration done!!!!");
+ }
+ catch (OCException &e)
+ {
+ dlog_print(DLOG_ERROR, LOG_TAG, "Exception occured! (%s)", e.what());
+ }
+}
+
+static bool
+app_create(void *data)
+{
+ /* Hook to take necessary actions before main event loop starts
+ Initialize UI resources and application's data
+ If this function returns true, the main loop of application starts
+ If this function returns false, the application is terminated */
+ appdata_s *ad = (appdata_s *)data;
+
+ elm_app_base_scale_set(1.8);
+
+ create_base_gui(ad);
+
+ configure_platform();
+
+ return true;
+}
+
+static void
+app_control(app_control_h app_control, void *data)
+{
+ // Handle the launch request.
+}
+
+static void
+app_pause(void *data)
+{
+ // Take necessary actions when application becomes invisible.
+}
+
+static void
+app_resume(void *data)
+{
+ // Take necessary actions when application becomes visible.
+}
+
+static void
+app_terminate(void *data)
+{
+ // Release all resources.
+}
+
+static void
+ui_app_lang_changed(app_event_info_h event_info, void *user_data)
+{
+ // APP_EVENT_LANGUAGE_CHANGED
+ char *locale = NULL;
+ system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &locale);
+ elm_language_set(locale);
+ free(locale);
+ return;
+}
+
+static void
+ui_app_orient_changed(app_event_info_h event_info, void *user_data)
+{
+ // APP_EVENT_DEVICE_ORIENTATION_CHANGED
+ return;
+}
+
+static void
+ui_app_region_changed(app_event_info_h event_info, void *user_data)
+{
+ // APP_EVENT_REGION_FORMAT_CHANGED
+}
+
+static void
+ui_app_low_battery(app_event_info_h event_info, void *user_data)
+{
+ // APP_EVENT_LOW_BATTERY
+}
+
+static void
+ui_app_low_memory(app_event_info_h event_info, void *user_data)
+{
+ // APP_EVENT_LOW_MEMORY
+}
+
+int
+main(int argc, char *argv[])
+{
+ appdata_s ad = {0,};
+ int ret = 0;
+
+ ui_app_lifecycle_callback_s event_callback = {0,};
+ app_event_handler_h handlers[5] = {NULL, };
+
+ event_callback.create = app_create;
+ event_callback.terminate = app_terminate;
+ event_callback.pause = app_pause;
+ event_callback.resume = app_resume;
+ event_callback.app_control = app_control;
+
+ ui_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY,
+ ui_app_low_battery, &ad);
+ ui_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY,
+ ui_app_low_memory, &ad);
+ ui_app_add_event_handler(&handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED],
+ APP_EVENT_DEVICE_ORIENTATION_CHANGED,
+ ui_app_orient_changed, &ad);
+ ui_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED],
+ APP_EVENT_LANGUAGE_CHANGED,
+ ui_app_lang_changed, &ad);
+ ui_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED],
+ APP_EVENT_REGION_FORMAT_CHANGED,
+ ui_app_region_changed, &ad);
+ ui_app_remove_event_handler(handlers[APP_EVENT_LOW_MEMORY]);
+
+ ret = ui_app_main(argc, argv, &event_callback, &ad);
+ if (APP_ERROR_NONE != ret)
+ {
+ dlog_print(DLOG_ERROR, LOG_TAG, "app_main() is failed. err = %d", ret);
+ }
+ return ret;
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.resampleclient" version="1.0.0">
+ <profile name="mobile"/>
+ <ui-application appid="org.tizen.resampleclient" exec="resampleclient" multiple="false" nodisplay="false" taskmanage="true" type="capp">
+ <label>resampleclient</label>
+ <icon>resampleapp.png</icon>
+ </ui-application>
+ <privileges>
+ <privilege>http://tizen.org/privilege/network.get</privilege>
+ <privilege>http://tizen.org/privilege/internet</privilege>
+ </privileges>
+ <feature name="http://tizen.org/feature/network.wifi">true</feature>
+</manifest>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="org.tizen.nativecore.config.sbi.gcc45.app.debug.109194109">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="org.tizen.nativecore.config.sbi.gcc45.app.debug.109194109" moduleId="org.eclipse.cdt.core.settings" name="Debug">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="resampleserver" buildArtefactType="org.tizen.nativecore.buildArtefactType.app" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.tizen.nativecore.buildArtefactType.app,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" description="" errorParsers="org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;" id="org.tizen.nativecore.config.sbi.gcc45.app.debug.109194109" name="Debug" parent="org.tizen.nativecore.config.sbi.gcc45.app.debug">
+ <folderInfo id="org.tizen.nativecore.config.sbi.gcc45.app.debug.109194109." name="/" resourcePath="">
+ <toolChain id="org.tizen.nativecore.toolchain.sbi.gcc45.app.debug.266200202" name="Tizen Native Toolchain" superClass="org.tizen.nativecore.toolchain.sbi.gcc45.app.debug">
+ <targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="org.tizen.nativeide.target.sbi.gnu.platform.base.1788661429" osList="linux,win32" superClass="org.tizen.nativeide.target.sbi.gnu.platform.base"/>
+ <builder arguments="--eval="SHELL=cmd" -r" autoBuildTarget="all" buildPath="${workspace_loc:/TMSampleApp}/Debug" enableAutoBuild="true" id="org.tizen.nativecore.target.sbi.gnu.builder.1749302123" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Tizen Application Builder" superClass="org.tizen.nativecore.target.sbi.gnu.builder"/>
+ <tool id="org.tizen.nativecore.tool.sbi.gnu.archiver.345678603" name="Archiver" superClass="org.tizen.nativecore.tool.sbi.gnu.archiver"/>
+ <tool command="arm-linux-gnueabi-g++.exe" id="org.tizen.nativecore.tool.sbi.gnu.cpp.compiler.1794187316" name="C++ Compiler" superClass="org.tizen.nativecore.tool.sbi.gnu.cpp.compiler">
+ <option id="gnu.cpp.compiler.option.optimization.level.719656926" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
+ <option id="sbi.gnu.cpp.compiler.option.debugging.level.core.378028433" name="Debug level" superClass="sbi.gnu.cpp.compiler.option.debugging.level.core" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
+ <option id="sbi.gnu.cpp.compiler.option.831567474" name="Tizen-Target" superClass="sbi.gnu.cpp.compiler.option" useByScannerDiscovery="false" valueType="userObjs">
+ <listOptionValue builtIn="false" value="mobile-2.3-device.core_gcc46.armel.core.app"/>
+ </option>
+ <option id="sbi.gnu.cpp.compiler.option.frameworks_inc.core.1543030783" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.cpp.compiler.option.frameworks_inc.core" useByScannerDiscovery="false" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libxml2""/>
+ <listOptionValue builtIn="false" value=""${SDK_PATH}/library""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/AL""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appcore-agent""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appfw""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/base""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/cairo""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/calendar-service2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ckm""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/contacts-svc""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/curl""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dbus-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/dbus-1.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dlog""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ecore-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/e_dbus-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/edje-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efreet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1/eina""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/elementary-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ethumb-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/evas-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/fontconfig""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/freetype2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/gio-unix-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/glib-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/glib-2.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0/json-glib""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libexif""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media-content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/minizip""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/network""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/notification""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/shortcut""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/storage""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/system""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ui""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/vconf""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/web""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/badge""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eio-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/email-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/embryo-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/messaging""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/msg-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ug-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/context-manager""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony-client""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ewebkit2-0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/location""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/sensor""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efl-extension""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/wifi-direct""/>
+ </option>
+ <option id="sbi.gnu.cpp.compiler.option.frameworks_cflags.core.1612037830" name="Tizen-Frameworks-Other-Cflags" superClass="sbi.gnu.cpp.compiler.option.frameworks_cflags.core" useByScannerDiscovery="false" valueType="stringList">
+ <listOptionValue builtIn="false" value="${TC_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value=" -fPIE"/>
+ <listOptionValue builtIn="false" value="--sysroot="${SBI_SYSROOT}""/>
+ <listOptionValue builtIn="false" value="-mthumb"/>
+ </option>
+ <option id="gnu.cpp.compiler.option.include.paths.1501991974" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc}""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\src\resourceBroker\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\src\resourceCache\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\src\common\utils\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\src\common\expiryTimer\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\src\common\expiryTimer\src""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\src\common\primitiveResource\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\c_common""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\stack\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\logger\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\occoap\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\ocrandom\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\ocsocket\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\oc_logger\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\extlibs\timer""/>
+ </option>
+ <option id="sbi.gnu.cpp.compiler.option.frameworks.core.1095600730" name="Tizen-Frameworks" superClass="sbi.gnu.cpp.compiler.option.frameworks.core" useByScannerDiscovery="false" valueType="userObjs">
+ <listOptionValue builtIn="false" value="Native_API"/>
+ </option>
+ <option id="gnu.cpp.compiler.option.preprocessor.def.371963530" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="_DEBUG"/>
+ </option>
+ <option id="gnu.cpp.compiler.option.dialect.std.1929207991" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/>
+ <option id="sbi.gnu.cpp.compiler.option.misc.pic.core.755649926" name="-fPIC option" superClass="sbi.gnu.cpp.compiler.option.misc.pic.core" value="true" valueType="boolean"/>
+ <option id="gnu.cpp.compiler.option.other.other.1760093561" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" value="-c -fmessage-length=0 -std=c++0x" valueType="string"/>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1956958926" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+ </tool>
+ <tool command="arm-linux-gnueabi-gcc.exe" id="org.tizen.nativecore.tool.sbi.gnu.c.compiler.2072036030" name="C Compiler" superClass="org.tizen.nativecore.tool.sbi.gnu.c.compiler">
+ <option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.1042898971" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
+ <option id="sbi.gnu.c.compiler.option.debugging.level.core.135607770" name="Debug level" superClass="sbi.gnu.c.compiler.option.debugging.level.core" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/>
+ <option id="sbi.gnu.c.compiler.option.571493571" name="Tizen-Target" superClass="sbi.gnu.c.compiler.option" useByScannerDiscovery="false" valueType="userObjs">
+ <listOptionValue builtIn="false" value="mobile-2.3-device.core_gcc46.armel.core.app"/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.frameworks_inc.core.107632308" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.c.compiler.option.frameworks_inc.core" useByScannerDiscovery="false" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libxml2""/>
+ <listOptionValue builtIn="false" value=""${SDK_PATH}/library""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/AL""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appcore-agent""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appfw""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/base""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/cairo""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/calendar-service2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ckm""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/contacts-svc""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/curl""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dbus-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/dbus-1.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dlog""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ecore-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/e_dbus-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/edje-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efreet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1/eina""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/elementary-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ethumb-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/evas-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/fontconfig""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/freetype2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/gio-unix-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/glib-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/glib-2.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0/json-glib""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libexif""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media-content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/minizip""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/network""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/notification""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/shortcut""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/storage""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/system""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ui""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/vconf""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/web""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/badge""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eio-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/email-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/embryo-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/messaging""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/msg-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ug-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/context-manager""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony-client""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ewebkit2-0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/location""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/sensor""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efl-extension""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/wifi-direct""/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.frameworks_cflags.core.1275911900" name="Tizen-Frameworks-Other-Cflags" superClass="sbi.gnu.c.compiler.option.frameworks_cflags.core" useByScannerDiscovery="false" valueType="stringList">
+ <listOptionValue builtIn="false" value="${TC_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value=" -fPIE"/>
+ <listOptionValue builtIn="false" value="--sysroot="${SBI_SYSROOT}""/>
+ <listOptionValue builtIn="false" value="-mthumb"/>
+ </option>
+ <option id="gnu.c.compiler.option.include.paths.109116980" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc}""/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.frameworks.core.1552601669" name="Tizen-Frameworks" superClass="sbi.gnu.c.compiler.option.frameworks.core" useByScannerDiscovery="false" valueType="userObjs">
+ <listOptionValue builtIn="false" value="Native_API"/>
+ </option>
+ <option id="gnu.c.compiler.option.preprocessor.def.symbols.2021130927" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="_DEBUG"/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.misc.pic.core.1304419386" name="-fPIC option" superClass="sbi.gnu.c.compiler.option.misc.pic.core" value="false" valueType="boolean"/>
+ <option id="gnu.c.compiler.option.misc.other.2029079564" name="Other flags" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -std=c++0x" valueType="string"/>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1859092644" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+ <tool id="org.tizen.nativeide.tool.sbi.gnu.c.linker.base.944066372" name="C Linker" superClass="org.tizen.nativeide.tool.sbi.gnu.c.linker.base"/>
+ <tool command="arm-linux-gnueabi-g++.exe" id="org.tizen.nativecore.tool.sbi.gnu.cpp.linker.1667264058" name="C++ Linker" superClass="org.tizen.nativecore.tool.sbi.gnu.cpp.linker">
+ <option id="sbi.gnu.cpp.linker.option.frameworks_lflags.core.1178784315" name="Tizen-Frameworks-Other-Lflags" superClass="sbi.gnu.cpp.linker.option.frameworks_lflags.core" valueType="stringList">
+ <listOptionValue builtIn="false" value="${TC_LINKER_MISC}"/>
+ <listOptionValue builtIn="false" value="${RS_LINKER_MISC}"/>
+ <listOptionValue builtIn="false" value="-pie -lpthread "/>
+ <listOptionValue builtIn="false" value="-Xlinker -rpath="/home/developer/sdk_tools/lib""/>
+ <listOptionValue builtIn="false" value="--sysroot="${SBI_SYSROOT}""/>
+ <listOptionValue builtIn="false" value="-Xlinker --version-script=${PROJ_PATH}/.exportMap"/>
+ <listOptionValue builtIn="false" value="-L"${SBI_SYSROOT}/usr/lib""/>
+ <listOptionValue builtIn="false" value="$(RS_LIBRARIES)"/>
+ </option>
+ <option id="gnu.cpp.link.option.paths.1087248355" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" valueType="libPaths">
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/lib}""/>
+ </option>
+ <option id="gnu.cpp.link.option.libs.2039500142" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs">
+ <listOptionValue builtIn="false" value="oc"/>
+ <listOptionValue builtIn="false" value="octbstack"/>
+ <listOptionValue builtIn="false" value="oc_logger"/>
+ <listOptionValue builtIn="false" value="oc_logger_core"/>
+ <listOptionValue builtIn="false" value="connectivity_abstraction"/>
+ <listOptionValue builtIn="false" value="uuid"/>
+ <listOptionValue builtIn="false" value="rcs_client"/>
+ <listOptionValue builtIn="false" value="rcs_common"/>
+ <listOptionValue builtIn="false" value="rcs_container"/>
+ <listOptionValue builtIn="false" value="rcs_server"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.618645708" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+ </inputType>
+ </tool>
+ <tool command="arm-linux-gnueabi-as.exe" id="org.tizen.nativeapp.tool.sbi.gnu.assembler.base.1585687908" name="Assembler" superClass="org.tizen.nativeapp.tool.sbi.gnu.assembler.base">
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.89256350" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+ </tool>
+ <tool id="org.tizen.nativecore.tool.fnmapgen.353447784" name="C FN-Map Generator" superClass="org.tizen.nativecore.tool.fnmapgen"/>
+ <tool id="org.tizen.nativecore.tool.fnmapgen.cpp.734608698" name="C++ FN-Map Generator" superClass="org.tizen.nativecore.tool.fnmapgen.cpp"/>
+ <tool id="org.tizen.nativecore.tool.ast.125567506" name="C Static Analyzer" superClass="org.tizen.nativecore.tool.ast"/>
+ <tool id="org.tizen.nativecore.tool.ast.cpp.2107204356" name="C++ Static Analyzer" superClass="org.tizen.nativecore.tool.ast.cpp"/>
+ <tool id="org.tizen.nativecore.tool.sbi.po.compiler.1190161351" name="PO Resource Compiler" superClass="org.tizen.nativecore.tool.sbi.po.compiler"/>
+ <tool id="org.tizen.nativecore.tool.sbi.edc.compiler.1621384631" name="EDC Resource Compiler" superClass="org.tizen.nativecore.tool.sbi.edc.compiler"/>
+ </toolChain>
+ </folderInfo>
+ <sourceEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="inc"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="res"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
+ </sourceEntries>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ <cconfiguration id="org.tizen.nativecore.config.sbi.gcc45.app.release.1584352396">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="org.tizen.nativecore.config.sbi.gcc45.app.release.1584352396" moduleId="org.eclipse.cdt.core.settings" name="Release">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="tmsampleapp" buildArtefactType="org.tizen.nativecore.buildArtefactType.app" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.tizen.nativecore.buildArtefactType.app,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" description="" errorParsers="org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;" id="org.tizen.nativecore.config.sbi.gcc45.app.release.1584352396" name="Release" parent="org.tizen.nativecore.config.sbi.gcc45.app.release">
+ <folderInfo id="org.tizen.nativecore.config.sbi.gcc45.app.release.1584352396." name="/" resourcePath="">
+ <toolChain id="org.tizen.nativecore.toolchain.sbi.gcc45.app.release.32000863" name="Tizen Native Toolchain" superClass="org.tizen.nativecore.toolchain.sbi.gcc45.app.release">
+ <targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="org.tizen.nativeide.target.sbi.gnu.platform.base.1750758769" osList="linux,win32" superClass="org.tizen.nativeide.target.sbi.gnu.platform.base"/>
+ <builder buildPath="${workspace_loc:/TMSampleApp}/Release" id="org.tizen.nativecore.target.sbi.gnu.builder.2029564551" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Tizen Application Builder" superClass="org.tizen.nativecore.target.sbi.gnu.builder"/>
+ <tool id="org.tizen.nativecore.tool.sbi.gnu.archiver.224082468" name="Archiver" superClass="org.tizen.nativecore.tool.sbi.gnu.archiver"/>
+ <tool command="clang++.exe" id="org.tizen.nativecore.tool.sbi.gnu.cpp.compiler.1434486618" name="C++ Compiler" superClass="org.tizen.nativecore.tool.sbi.gnu.cpp.compiler">
+ <option id="gnu.cpp.compiler.option.optimization.level.1709393206" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
+ <option id="sbi.gnu.cpp.compiler.option.debugging.level.core.221700213" name="Debug level" superClass="sbi.gnu.cpp.compiler.option.debugging.level.core"/>
+ <option id="sbi.gnu.cpp.compiler.option.710876023" name="Tizen-Target" superClass="sbi.gnu.cpp.compiler.option" valueType="userObjs">
+ <listOptionValue builtIn="false" value="mobile-2.3-emulator.core_llvm34.i386.core.app"/>
+ </option>
+ <option id="sbi.gnu.cpp.compiler.option.frameworks_inc.core.1622581330" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.cpp.compiler.option.frameworks_inc.core" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libxml2""/>
+ <listOptionValue builtIn="false" value=""${SDK_PATH}/library""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/AL""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appcore-agent""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appfw""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/base""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/cairo""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/calendar-service2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ckm""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/contacts-svc""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/curl""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dbus-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/dbus-1.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dlog""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ecore-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/e_dbus-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/edje-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efreet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1/eina""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/elementary-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ethumb-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/evas-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/fontconfig""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/freetype2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/gio-unix-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/glib-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/glib-2.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0/json-glib""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libexif""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media-content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/minizip""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/network""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/notification""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/shortcut""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/storage""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/system""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ui""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/vconf""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/web""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/badge""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eio-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/email-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/embryo-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/messaging""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/msg-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ug-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/context-manager""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony-client""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ewebkit2-0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/location""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/sensor""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efl-extension""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/wifi-direct""/>
+ </option>
+ <option id="sbi.gnu.cpp.compiler.option.frameworks_cflags.core.1695583788" name="Tizen-Frameworks-Other-Cflags" superClass="sbi.gnu.cpp.compiler.option.frameworks_cflags.core" valueType="stringList">
+ <listOptionValue builtIn="false" value="${TC_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value=" -fPIE"/>
+ <listOptionValue builtIn="false" value="--sysroot="${SBI_SYSROOT}""/>
+ </option>
+ <option id="gnu.cpp.compiler.option.include.paths.585301879" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc}""/>
+ </option>
+ <option id="sbi.gnu.cpp.compiler.option.frameworks.core.708669314" name="Tizen-Frameworks" superClass="sbi.gnu.cpp.compiler.option.frameworks.core" valueType="userObjs">
+ <listOptionValue builtIn="false" value="Native_API"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.2006056090" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+ </tool>
+ <tool command="clang.exe" id="org.tizen.nativecore.tool.sbi.gnu.c.compiler.601285388" name="C Compiler" superClass="org.tizen.nativecore.tool.sbi.gnu.c.compiler">
+ <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.option.optimization.level.1778561828" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" valueType="enumerated"/>
+ <option id="sbi.gnu.c.compiler.option.debugging.level.core.1695949408" name="Debug level" superClass="sbi.gnu.c.compiler.option.debugging.level.core"/>
+ <option id="sbi.gnu.c.compiler.option.1422818783" name="Tizen-Target" superClass="sbi.gnu.c.compiler.option" valueType="userObjs">
+ <listOptionValue builtIn="false" value="mobile-2.3-emulator.core_llvm34.i386.core.app"/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.frameworks_inc.core.1871683675" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.c.compiler.option.frameworks_inc.core" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libxml2""/>
+ <listOptionValue builtIn="false" value=""${SDK_PATH}/library""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/AL""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appcore-agent""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/appfw""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/base""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/cairo""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/calendar-service2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ckm""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/contacts-svc""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/curl""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dbus-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/dbus-1.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/dlog""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ecore-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/e_dbus-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/edje-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efreet-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1/eina""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eina-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/elementary-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ethumb-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/evas-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/fontconfig""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/freetype2""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/gio-unix-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/glib-2.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/lib/glib-2.0/include""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/json-glib-1.0/json-glib""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/libexif""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media-content""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/media""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/minizip""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/network""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/notification""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/shortcut""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/storage""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/system""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ui""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/vconf""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/web""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/badge""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/eio-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/email-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/embryo-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/messaging""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/msg-service""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ug-1""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/context-manager""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/telephony-client""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/ewebkit2-0""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/location""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/sensor""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/efl-extension""/>
+ <listOptionValue builtIn="false" value=""${SBI_SYSROOT}/usr/include/wifi-direct""/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.frameworks_cflags.core.371848582" name="Tizen-Frameworks-Other-Cflags" superClass="sbi.gnu.c.compiler.option.frameworks_cflags.core" valueType="stringList">
+ <listOptionValue builtIn="false" value="${TC_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
+ <listOptionValue builtIn="false" value=" -fPIE"/>
+ <listOptionValue builtIn="false" value="--sysroot="${SBI_SYSROOT}""/>
+ </option>
+ <option id="gnu.c.compiler.option.include.paths.1254567673" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc}""/>
+ </option>
+ <option id="sbi.gnu.c.compiler.option.frameworks.core.627340354" name="Tizen-Frameworks" superClass="sbi.gnu.c.compiler.option.frameworks.core" valueType="userObjs">
+ <listOptionValue builtIn="false" value="Native_API"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.749706957" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+ <tool id="org.tizen.nativeide.tool.sbi.gnu.c.linker.base.1794486202" name="C Linker" superClass="org.tizen.nativeide.tool.sbi.gnu.c.linker.base"/>
+ <tool command="clang++.exe" id="org.tizen.nativecore.tool.sbi.gnu.cpp.linker.2579106" name="C++ Linker" superClass="org.tizen.nativecore.tool.sbi.gnu.cpp.linker">
+ <option id="sbi.gnu.cpp.linker.option.frameworks_lflags.core.1582557344" name="Tizen-Frameworks-Other-Lflags" superClass="sbi.gnu.cpp.linker.option.frameworks_lflags.core" valueType="stringList">
+ <listOptionValue builtIn="false" value="${TC_LINKER_MISC}"/>
+ <listOptionValue builtIn="false" value="${RS_LINKER_MISC}"/>
+ <listOptionValue builtIn="false" value="-pie -lpthread "/>
+ <listOptionValue builtIn="false" value="-Xlinker -rpath="/home/developer/sdk_tools/lib""/>
+ <listOptionValue builtIn="false" value="--sysroot="${SBI_SYSROOT}""/>
+ <listOptionValue builtIn="false" value="-Xlinker --version-script=${PROJ_PATH}/.exportMap"/>
+ <listOptionValue builtIn="false" value="-L"${SBI_SYSROOT}/usr/lib""/>
+ <listOptionValue builtIn="false" value="$(RS_LIBRARIES)"/>
+ </option>
+ <option id="gnu.cpp.link.option.paths.1396123174" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" valueType="libPaths">
+ <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/lib}""/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.768667264" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+ </inputType>
+ </tool>
+ <tool command="i386-linux-gnueabi-as.exe" id="org.tizen.nativeapp.tool.sbi.gnu.assembler.base.380499784" name="Assembler" superClass="org.tizen.nativeapp.tool.sbi.gnu.assembler.base">
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1638213209" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+ </tool>
+ <tool id="org.tizen.nativecore.tool.fnmapgen.1617359663" name="C FN-Map Generator" superClass="org.tizen.nativecore.tool.fnmapgen"/>
+ <tool id="org.tizen.nativecore.tool.fnmapgen.cpp.759297757" name="C++ FN-Map Generator" superClass="org.tizen.nativecore.tool.fnmapgen.cpp"/>
+ <tool id="org.tizen.nativecore.tool.ast.495578509" name="C Static Analyzer" superClass="org.tizen.nativecore.tool.ast"/>
+ <tool id="org.tizen.nativecore.tool.ast.cpp.91235808" name="C++ Static Analyzer" superClass="org.tizen.nativecore.tool.ast.cpp"/>
+ <tool id="org.tizen.nativecore.tool.sbi.po.compiler.619869321" name="PO Resource Compiler" superClass="org.tizen.nativecore.tool.sbi.po.compiler"/>
+ <tool id="org.tizen.nativecore.tool.sbi.edc.compiler.1045552473" name="EDC Resource Compiler" superClass="org.tizen.nativecore.tool.sbi.edc.compiler"/>
+ </toolChain>
+ </folderInfo>
+ <sourceEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="inc"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="res"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
+ </sourceEntries>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="TMSampleApp.org.tizen.nativecore.target.sbi.gcc45.app.278712545" name="Tizen Native Application" projectType="org.tizen.nativecore.target.sbi.gcc45.app"/>
+ </storageModule>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ <scannerConfigBuildInfo instanceId="org.tizen.nativecore.config.sbi.gcc45.app.release.1584352396">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ </scannerConfigBuildInfo>
+ <scannerConfigBuildInfo instanceId="org.tizen.nativecore.config.sbi.gcc45.app.debug.109194109">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ </scannerConfigBuildInfo>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+ <storageModule moduleId="refreshScope" versionNumber="2">
+ <configuration configurationName="Debug">
+ <resource resourceType="PROJECT" workspacePath="/TMSampleApp"/>
+ </configuration>
+ <configuration configurationName="Release">
+ <resource resourceType="PROJECT" workspacePath="/TMSampleApp"/>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="com.samsung.tizen.nativeapp.projectInfo" version="1.0.0"/>
+</cproject>
--- /dev/null
+{
+ global: main;
+ local: *;
+};
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>RESampleServer</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+ <triggers>full,incremental,</triggers>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.tizen.nativecore.apichecker.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.cdt.core.cnature</nature>
+ <nature>org.eclipse.cdt.core.ccnature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+ <nature>org.tizen.nativecore.apichecker.core.tizenCppNature</nature>
+ </natures>
+ <filteredResources>
+ <filter>
+ <id>0</id>
+ <name></name>
+ <type>26</type>
+ <matcher>
+ <id>org.eclipse.ui.ide.multiFilter</id>
+ <arguments>1.0-projectRelativePath-matches-false-false-*/.tpk</arguments>
+ </matcher>
+ </filter>
+ </filteredResources>
+</projectDescription>
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+#define POPUP_CONTENT_DEFAULT_PADDING_LEFT_MIN_INC 15
+#define POPUP_EDITFIELD_LAYOUT_MINMAX_HEIGHT_INC 96
+
+group
+{
+ name: "group_layout";
+ parts
+ {
+ part
+ {
+ name: "find_button";
+ type: SWALLOW;
+ scale: 1;
+ description
+ {
+ rel1.relative: 0.01 0.01;
+ rel2.relative: 0.5 0.09;
+ }
+ }
+ part
+ {
+ name: "list";
+ type: SWALLOW;
+ scale: 1;
+ description
+ {
+ rel1.relative: 0.01 0.1;
+ rel2.relative: 0.99 0.7;
+ }
+ }
+ part
+ {
+ name: "log_bg";
+ type: RECT;
+ scale: 1;
+ description
+ {
+ state: "default" 0.0;
+ rel1.relative: 0.01 0.71;
+ rel2.relative: 0.98 1.0;
+ color: 220 220 220 255;
+ }
+ }
+ part
+ {
+ name: "log";
+ type: SWALLOW;
+ scale: 1;
+ description
+ {
+ rel1.to: "log_bg";
+ rel2.to: "log_bg";
+ }
+ }
+ }
+}
+
+group
+{
+ name: "popup_datetime_text";
+ parts
+ {
+ part
+ {
+ name: "pad_l";
+ type: SPACER;
+ scale: 1;
+ description
+ {
+ state: "default" 0.0;
+ min: POPUP_CONTENT_DEFAULT_PADDING_LEFT_MIN_INC 0;
+ fixed: 1 0;
+ rel1.relative: 0.0 0.0;
+ rel2.relative: 0.0 1.0;
+ align: 0.0 0.0;
+ }
+ }
+ part
+ {
+ name: "pad_r";
+ type: SPACER;
+ scale: 1;
+ description
+ {
+ state: "default" 0.0;
+ min: POPUP_CONTENT_DEFAULT_PADDING_LEFT_MIN_INC 0;
+ fixed: 1 0;
+ rel1.relative: 1.0 0.0;
+ rel2.relative: 1.0 1.0;
+ align: 1.0 0.0;
+ }
+ }
+ part
+ {
+ name: "elm.swallow.content";
+ type: SWALLOW;
+ scale: 1;
+ description
+ {
+ state: "default" 0.0;
+ min: 0 POPUP_EDITFIELD_LAYOUT_MINMAX_HEIGHT_INC;
+ max: -1 POPUP_EDITFIELD_LAYOUT_MINMAX_HEIGHT_INC;
+ align: 0.5 0.5;
+ rel1
+ {
+ relative: 1.0 0.0;
+ to_x: "pad_l";
+ }
+ rel2
+ {
+ relative: 0.0 1.0;
+ to_x: "pad_r";
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "reservermain.h"
+
+#include "RCSResourceObject.h"
+
+#ifndef __RESERVER_H__
+#define __RESERVER_H__
+
+using namespace std;
+using namespace OIC::Service;
+
+typedef void(*ClientMenuHandler)();
+typedef int ReturnValue;
+
+constexpr int DEFALUT_VALUE = 0;
+
+std::string resourceUri = "/a/TempSensor";
+std::string resourceType = "core.TemperatureSensor";
+std::string resourceInterface = "oic.if.";
+std::string attributeKey = "Temperature";
+
+enum class Control
+{
+ INCREASE,
+ DECREASE
+};
+
+void printAttribute(const RCSResourceAttributes &attrs);
+
+void *showGroupAPIs(void *data);
+
+void serverCreateUI(void *data);
+
+#endif // __RESERVER_H__
--- /dev/null
+/******************************************************************
+ *
+ * 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 __RESERVERMAIN_H__
+#define __RESERVERMAIN_H__
+
+#include <app.h>
+#include <Elementary.h>
+#include <system_settings.h>
+#include <efl_extension.h>
+#include <dlog.h>
+
+#include "OCPlatform.h"
+#include "OCApi.h"
+
+using namespace OC;
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "reservermain"
+
+#if !defined(PACKAGE)
+#define PACKAGE "org.tizen.resampleserver"
+#endif
+
+#define ELM_DEMO_EDJ "opt/usr/apps/org.tizen.resampleserver/res/ui_controls.edj"
+
+void start_server(void *data, Evas_Object *obj, void *event_info);
+
+void start_server_cb(void *data, Evas_Object *obj, void *event_info);
+
+#endif // __RESERVERMAIN_H__
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+collections
+{
+ base_scale: 1.8;
+ #include "../edc_resource/re_server_control.edc"
+}
\ No newline at end of file
--- /dev/null
+/******************************************************************
+ *
+ * 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 "reserver.h"
+
+#include "reservermain.h"
+#include "PrimitiveResource.h"
+#include "RCSResourceObject.h"
+
+#include <string>
+
+using namespace std;
+using namespace OC;
+using namespace OIC::Service;
+
+RCSResourceObject::Ptr server;
+static bool serverCallback = false;
+
+# define checkServer NULL!=server?true:false
+
+static Evas_Object *log_entry = NULL;
+static Evas_Object *list = NULL;
+static Evas_Object *naviframe = NULL;
+
+typedef struct datetime_popup
+{
+ Evas_Object *popup;
+ Evas_Object *entry;
+} datetime_popup_fields;
+
+// Function to update the log in UI
+void *updateGroupLog(void *data)
+{
+ string *log = (string *)data;
+ // Show the log
+ elm_entry_entry_append(log_entry, (*log).c_str());
+ elm_entry_cursor_end_set(log_entry);
+ return NULL;
+}
+
+void printAttribute(const RCSResourceAttributes &attrs)
+{
+ string logMessage = "";
+ for (const auto & attr : attrs)
+ {
+ logMessage = logMessage + "KEY:" + attr.key().c_str() + "<br>";
+ logMessage = logMessage + "VALUE:" + attr.value().toString().c_str() + "<br>";
+ }
+ dlog_print(DLOG_INFO, LOG_TAG, " %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+static void onDestroy()
+{
+ server = NULL;
+ string logMessage = "SERVER DESTROYED";
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+//hander for get request (if developer choose second option for resource Creation)
+RCSGetResponse requestHandlerForGet(const RCSRequest &request,
+ RCSResourceAttributes &attrs)
+{
+ string logMessage = "GET REQUEST RECEIVED<br>";
+
+ RCSResourceObject::LockGuard lock(*server);
+ RCSResourceAttributes attributes = server->getAttributes();
+ printAttribute(attributes);
+ logMessage += "RESPONSE SENT<br>";
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+ return RCSGetResponse::defaultAction();
+}
+
+//hander for set request (if developer choose second option for resource Creation)
+RCSSetResponse requestHandlerForSet(const RCSRequest &request,
+ RCSResourceAttributes &attrs)
+{
+ string logMessage = "SET REQUEST RECEIVED<br>";
+
+ RCSResourceObject::LockGuard lock(*server);
+ for (const auto & attr : attrs)
+ {
+ logMessage = logMessage + "KEY:" + attr.key().c_str() + "<br>";
+ logMessage = logMessage + "VALUE:" + attr.value().toString().c_str() + "<br>";
+ server->setAttribute(attr.key(), attr.value());
+ }
+
+ printAttribute(attrs);
+ logMessage += "RESPONSE SENT<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+
+ return RCSSetResponse::defaultAction();
+}
+
+static void list_selected_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ Elm_Object_Item *it = (Elm_Object_Item *)event_info;
+ elm_list_item_selected_set(it, EINA_FALSE);
+}
+
+static void increaseTemp(void *data, Evas_Object *obj, void *event_info)
+{
+ string logMessage = "";
+
+ if (checkServer)
+ {
+ RCSResourceObject::LockGuard lock(server);
+ server->getAttributes()[attributeKey] = server->getAttribute<int>(attributeKey) + 10;
+ string tempString = std::to_string(server->getAttribute<int>(attributeKey));
+ logMessage = "TEMPERATURE CHANGED : " + tempString + "<br>";
+
+ }
+ else
+ {
+ logMessage = "NO SERRVER <br>";
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ logMessage += "----------------------<br>";
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+static void decreaseTemp(void *data, Evas_Object *obj, void *event_info)
+{
+ string logMessage = "";
+
+ if (checkServer)
+ {
+ RCSResourceObject::LockGuard lock(server);
+ server->getAttributes()[attributeKey] = server->getAttribute<int>(attributeKey) - 10;
+ string tempString = std::to_string(server->getAttribute<int>(attributeKey));
+ logMessage = "TEMPERATURE CHANGED : " + tempString + "<br>";
+ }
+ else
+ {
+ logMessage = "NO SERRVER <br>";
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ logMessage += "----------------------<br>";
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+static void initServer()
+{
+ OCPlatform::startPresence(3);
+
+ try
+ {
+ server = RCSResourceObject::Builder(resourceUri, resourceType,
+ resourceInterface).setDiscoverable(true).setObservable(true).build();
+ }
+ catch (const PlatformException &e)
+ {
+ dlog_print(DLOG_ERROR, LOG_TAG, "#### Create resource exception! (%s)", e.what());
+ }
+
+ server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
+ server->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::NEVER);
+ server->setAttribute(attributeKey, DEFALUT_VALUE);
+
+ string logMessage = "SERVER CREATED<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))showGroupAPIs, NULL);
+}
+
+static void
+popup_cancel_clicked_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ datetime_popup_fields *popup_fields = (datetime_popup_fields *)data;
+ evas_object_del(popup_fields->popup);
+ free(popup_fields);
+}
+
+static void
+popup_set_clicked_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ datetime_popup_fields *popup_fields = (datetime_popup_fields *)data;
+ Evas_Object *entry = popup_fields->entry;
+ const char *temperatureString = elm_entry_entry_get(entry);
+ // Remove white spaces(if any) at the beginning
+ string logMessage = "";
+ int beginning = 0;
+ while (temperatureString[beginning] == ' ')
+ {
+ (beginning)++;
+ }
+
+ int len = strlen(temperatureString);
+ if (NULL == temperatureString || 1 > len)
+ {
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Read NULL Temperature Value");
+ logMessage = "Temperature Cannot be NULL<br>";
+ }
+ else
+ {
+ if (checkServer)
+ {
+ RCSResourceObject::LockGuard lock(server);
+ int temperate = atoi(temperatureString);
+ server->getAttributes()[attributeKey] = temperate;
+ logMessage = "TEMPERATURE CHANGED : " + to_string(server->getAttribute<int>
+ (attributeKey)) + "<br>";
+ }
+ else
+ {
+ logMessage += "NO SERVER<br>";
+ }
+ }
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ logMessage += "----------------------<br>";
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+
+ evas_object_del(popup_fields->popup);
+ free(popup_fields);
+}
+
+static void
+list_get_temperaure_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ Evas_Object *popup, *btn;
+ Evas_Object *nf = naviframe;
+ Evas_Object *entry;
+ Evas_Object *layout;
+
+ /* pop up */
+ popup = elm_popup_add(nf);
+ elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0);
+ eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, eext_popup_back_cb, NULL);
+ evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_object_part_text_set(popup, "title,text", "Enter the temperature");
+
+ layout = elm_layout_add(popup);
+ elm_layout_file_set(layout, ELM_DEMO_EDJ, "popup_datetime_text");
+ evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_object_content_set(popup, layout);
+
+ entry = elm_entry_add(layout);
+ elm_entry_single_line_set(entry, EINA_TRUE);
+ elm_entry_scrollable_set(entry, EINA_TRUE);
+ evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ eext_entry_selection_back_event_allow_set(entry, EINA_TRUE);
+ elm_object_part_text_set(entry, "elm.guide", "in degree celsius");
+ elm_entry_input_panel_layout_set(entry, ELM_INPUT_PANEL_LAYOUT_NUMBER);
+ elm_object_part_content_set(layout, "elm.swallow.content", entry);
+
+ datetime_popup_fields *popup_fields;
+ popup_fields = (datetime_popup_fields *)malloc(sizeof(datetime_popup_fields));
+ if (NULL == popup_fields)
+ {
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Memory allocation failed");
+ }
+ else
+ {
+ popup_fields->popup = popup;
+ popup_fields->entry = entry;
+ }
+
+ /* Cancel button */
+ btn = elm_button_add(popup);
+ elm_object_style_set(btn, "popup");
+ elm_object_text_set(btn, "Cancel");
+ elm_object_part_content_set(popup, "button1", btn);
+ evas_object_smart_callback_add(btn, "clicked", popup_cancel_clicked_cb, popup_fields);
+
+ /* Set button */
+ btn = elm_button_add(popup);
+ elm_object_style_set(btn, "popup");
+ elm_object_text_set(btn, "Set");
+ elm_object_part_content_set(popup, "button2", btn);
+ evas_object_smart_callback_add(btn, "clicked", popup_set_clicked_cb, popup_fields);
+
+ evas_object_show(popup);
+}
+
+void *showGroupAPIs(void *data)
+{
+ // Add items to the list only if the list is empty
+ const Eina_List *eina_list = elm_list_items_get(list);
+ int count = eina_list_count(eina_list);
+ if (!count)
+ {
+ elm_list_item_append(list, "1. Increase Temperature", NULL, NULL,
+ increaseTemp, NULL);
+
+ elm_list_item_append(list, "2. Decrease Temperature", NULL, NULL,
+ decreaseTemp, NULL);
+
+ elm_list_item_append(list, "3. Set Temperature", NULL, NULL,
+ list_get_temperaure_cb, NULL);
+
+ elm_list_go(list);
+ }
+ return NULL;
+}
+
+static Eina_Bool
+naviframe_pop_cb(void *data, Elm_Object_Item *it)
+{
+ onDestroy();
+
+ if (NULL != log_entry)
+ {
+ evas_object_del(log_entry);
+ log_entry = NULL;
+ }
+ if (NULL != list)
+ {
+ evas_object_del(list);
+ list = NULL;
+ }
+ return EINA_TRUE;
+}
+
+// Method to set up server screens
+void serverCreateUI(void *data)
+{
+ Evas_Object *layout;
+ Evas_Object *scroller;
+ Evas_Object *nf = (Evas_Object *)data;
+ Elm_Object_Item *nf_it;
+ naviframe = nf;
+
+ // Scroller
+ scroller = elm_scroller_add(nf);
+ elm_scroller_bounce_set(scroller, EINA_FALSE, EINA_TRUE);
+ elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
+
+ // Layout
+ layout = elm_layout_add(nf);
+ elm_layout_file_set(layout, ELM_DEMO_EDJ, "group_layout");
+ evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+ elm_object_content_set(scroller, layout);
+
+ // List
+ list = elm_list_add(layout);
+ elm_list_mode_set(list, ELM_LIST_COMPRESS);
+ evas_object_smart_callback_add(list, "selected", list_selected_cb, NULL);
+ elm_object_part_content_set(layout, "list", list);
+ elm_list_go(list);
+
+ // log_entry - text area for log
+ log_entry = elm_entry_add(layout);
+ elm_entry_scrollable_set(log_entry, EINA_TRUE);
+ elm_entry_editable_set(log_entry, EINA_FALSE);
+ elm_object_part_text_set(log_entry, "elm.guide", "Logs will be updated here!!!");
+ evas_object_size_hint_weight_set(log_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(log_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_object_part_content_set(layout, "log", log_entry);
+
+ nf_it = elm_naviframe_item_push(nf, "Resource Encapsulation", NULL, NULL, scroller, NULL);
+ elm_naviframe_item_pop_cb_set(nf_it, naviframe_pop_cb, NULL);
+}
+
+void start_server(void *data, Evas_Object *obj, void *event_info)
+{
+ string logMessage = "SERVER WITHOUT CALLBACK<br>";
+
+ serverCallback = false;
+ serverCreateUI(data);
+ initServer();
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+}
+
+void start_server_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ string logMessage = "SERVER WITH CALLBACK<br>";
+
+ serverCallback = true;
+ serverCreateUI(data);
+ initServer();
+
+ if (checkServer)
+ {
+ server->setGetRequestHandler(requestHandlerForGet);
+ server->setSetRequestHandler(requestHandlerForSet);
+ logMessage = "HANDLERS SET<br>";
+ }
+ else
+ {
+ logMessage = "NO SERRVER FOUND<br>";
+ }
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
+ ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
+ &logMessage);
+
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "reservermain.h"
+#include <tizen.h>
+
+typedef struct appdata
+{
+ Evas_Object *win;
+ Evas_Object *conform;
+ Evas_Object *layout;
+ Evas_Object *nf;
+ Evas_Object *findButton;
+ Evas_Object *logtext;
+ Evas_Object *listview;
+} appdata_s;
+
+static void
+win_delete_request_cb(void *data , Evas_Object *obj , void *event_info)
+{
+ ui_app_exit();
+}
+
+static void
+list_selected_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ Elm_Object_Item *it = (Elm_Object_Item *)event_info;
+ elm_list_item_selected_set(it, EINA_FALSE);
+}
+
+static Eina_Bool
+naviframe_pop_cb(void *data, Elm_Object_Item *it)
+{
+ ui_app_exit();
+ return EINA_FALSE;
+}
+
+static void
+create_list_view(appdata_s *ad)
+{
+ Evas_Object *list;
+ Evas_Object *btn;
+ Evas_Object *nf = ad->nf;
+ Elm_Object_Item *nf_it;
+
+ // List
+ list = elm_list_add(nf);
+ elm_list_mode_set(list, ELM_LIST_COMPRESS);
+ evas_object_smart_callback_add(list, "selected", list_selected_cb, NULL);
+
+ // Main Menu Items Here
+ elm_list_item_append(list, "Create Resource [Auto control]", NULL, NULL, start_server, nf);
+
+ elm_list_item_append(list, "Create Resource [Developer control]", NULL, NULL, start_server_cb, nf);
+
+ elm_list_go(list);
+
+ // This button is set for devices which doesn't have H/W back key.
+ btn = elm_button_add(nf);
+ elm_object_style_set(btn, "naviframe/end_btn/default");
+ nf_it = elm_naviframe_item_push(nf, "Resource Encapsulation", btn, NULL, list, NULL);
+ elm_naviframe_item_pop_cb_set(nf_it, naviframe_pop_cb, ad->win);
+}
+
+
+static void
+create_base_gui(appdata_s *ad)
+{
+ // Window
+ ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE);
+ elm_win_conformant_set(ad->win, EINA_TRUE);
+ elm_win_autodel_set(ad->win, EINA_TRUE);
+
+ if (elm_win_wm_rotation_supported_get(ad->win))
+ {
+ int rots[4] = { 0, 90, 180, 270 };
+ elm_win_wm_rotation_available_rotations_set(ad->win, (const int *)(&rots), 4);
+ }
+
+ evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, NULL);
+
+ // Conformant
+ ad->conform = elm_conformant_add(ad->win);
+ evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(ad->win, ad->conform);
+ evas_object_show(ad->conform);
+
+ // Base Layout
+ ad->layout = elm_layout_add(ad->conform);
+ evas_object_size_hint_weight_set(ad->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_layout_theme_set(ad->layout, "layout", "application", "default");
+ evas_object_show(ad->layout);
+
+ elm_object_content_set(ad->conform, ad->layout);
+
+ // Naviframe
+ ad->nf = elm_naviframe_add(ad->layout);
+ create_list_view(ad);
+ elm_object_part_content_set(ad->layout, "elm.swallow.content", ad->nf);
+ eext_object_event_callback_add(ad->nf, EEXT_CALLBACK_BACK, eext_naviframe_back_cb, NULL);
+ eext_object_event_callback_add(ad->nf, EEXT_CALLBACK_MORE, eext_naviframe_more_cb, NULL);
+
+ // Show window after base gui is set up
+ evas_object_show(ad->win);
+}
+
+// Configures the OCPlatform
+static void
+configure_platform()
+{
+ try
+ {
+ PlatformConfig config
+ { OC::ServiceType::InProc, ModeType::Server, "0.0.0.0", 0, OC::QualityOfService::LowQos };
+
+ OCPlatform::Configure(config);
+
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Platform configuration done!!!!");
+ }
+ catch (OCException &e)
+ {
+ dlog_print(DLOG_ERROR, LOG_TAG, "Exception occured! (%s)", e.what());
+ }
+}
+
+static bool
+app_create(void *data)
+{
+ /* Hook to take necessary actions before main event loop starts
+ Initialize UI resources and application's data
+ If this function returns true, the main loop of application starts
+ If this function returns false, the application is terminated */
+ appdata_s *ad = (appdata_s *)data;
+
+ elm_app_base_scale_set(1.8);
+
+ create_base_gui(ad);
+
+ configure_platform();
+
+ return true;
+}
+
+static void
+app_control(app_control_h app_control, void *data)
+{
+ // Handle the launch request.
+}
+
+static void
+app_pause(void *data)
+{
+ // Take necessary actions when application becomes invisible.
+}
+
+static void
+app_resume(void *data)
+{
+ // Take necessary actions when application becomes visible.
+}
+
+static void
+app_terminate(void *data)
+{
+ // Release all resources.
+}
+
+static void
+ui_app_lang_changed(app_event_info_h event_info, void *user_data)
+{
+ // APP_EVENT_LANGUAGE_CHANGED
+ char *locale = NULL;
+ system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &locale);
+ elm_language_set(locale);
+ free(locale);
+ return;
+}
+
+static void
+ui_app_orient_changed(app_event_info_h event_info, void *user_data)
+{
+ // APP_EVENT_DEVICE_ORIENTATION_CHANGED
+ return;
+}
+
+static void
+ui_app_region_changed(app_event_info_h event_info, void *user_data)
+{
+ // APP_EVENT_REGION_FORMAT_CHANGED
+}
+
+static void
+ui_app_low_battery(app_event_info_h event_info, void *user_data)
+{
+ // APP_EVENT_LOW_BATTERY
+}
+
+static void
+ui_app_low_memory(app_event_info_h event_info, void *user_data)
+{
+ // APP_EVENT_LOW_MEMORY
+}
+
+int
+main(int argc, char *argv[])
+{
+ appdata_s ad = {0,};
+ int ret = 0;
+
+ ui_app_lifecycle_callback_s event_callback = {0,};
+ app_event_handler_h handlers[5] = {NULL, };
+
+ event_callback.create = app_create;
+ event_callback.terminate = app_terminate;
+ event_callback.pause = app_pause;
+ event_callback.resume = app_resume;
+ event_callback.app_control = app_control;
+
+ ui_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY,
+ ui_app_low_battery, &ad);
+ ui_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY,
+ ui_app_low_memory, &ad);
+ ui_app_add_event_handler(&handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED],
+ APP_EVENT_DEVICE_ORIENTATION_CHANGED,
+ ui_app_orient_changed, &ad);
+ ui_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED],
+ APP_EVENT_LANGUAGE_CHANGED,
+ ui_app_lang_changed, &ad);
+ ui_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED],
+ APP_EVENT_REGION_FORMAT_CHANGED,
+ ui_app_region_changed, &ad);
+ ui_app_remove_event_handler(handlers[APP_EVENT_LOW_MEMORY]);
+
+ ret = ui_app_main(argc, argv, &event_callback, &ad);
+ if (APP_ERROR_NONE != ret)
+ {
+ dlog_print(DLOG_ERROR, LOG_TAG, "app_main() is failed. err = %d", ret);
+ }
+ return ret;
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.tizen.resampleserver" version="1.0.0">
+ <profile name="mobile"/>
+ <ui-application appid="org.tizen.resampleserver" exec="resampleserver" multiple="false" nodisplay="false" taskmanage="true" type="capp">
+ <label>resampleserver</label>
+ <icon>resampleapp.png</icon>
+ </ui-application>
+ <privileges>
+ <privilege>http://tizen.org/privilege/network.get</privilege>
+ <privilege>http://tizen.org/privilege/internet</privilege>
+ </privileges>
+ <feature name="http://tizen.org/feature/network.wifi">true</feature>
+</manifest>
/**
* API for setting the Id of the bundle
*
- * @param name - Id of the bundle in string form
+ * @param name Id of the bundle in string form
*
*/
virtual void setID(const std::string &name) = 0;
/**
* API for getting the Id of the bundle
*
- * @return string - Id of the bundle
+ * @return Id of the bundle
*
*/
virtual const std::string &getID() = 0;
/**
* API for setting the path of the bundle
*
- * @param path - path of the bundle in string form
+ * @param path path of the bundle in string form
*
*/
virtual void setPath(const std::string &path) = 0;
/**
* API for getting the path of the bundle
*
- * @return path - path of the bundle
+ * @return path of the bundle
*
*/
virtual const std::string &getPath() = 0;
/**
* API for setting the Activator name for the bundle
*
- * @param activator - Activator name in string form
+ * @param activator Activator name in string form
*
*/
virtual void setActivatorName(const std::string &activator) = 0;
/**
* API for setting the Activator name for the bundle
*
- * @return string - Name of the activator
+ * @return Name of the activator
*
*/
virtual const std::string &getActivatorName() = 0;
/**
* API for setting the library path for the bundle
*
- * @param libpath - Library path in string form
+ * @param libpath Library path in string form
*
*/
virtual void setLibraryPath(const std::string &libpath) = 0;
/**
* API for getting the library path for the bundle
*
- * @return string - Library path in string form
+ * @return Library path in string form
*
*/
virtual const std::string& getLibraryPath() = 0;
/**
* API for setting the version of the bundle
*
- * @param version - version of the bundle in string form
+ * @param version version of the bundle in string form
*
*/
virtual void setVersion(const std::string &version) = 0;
/**
* API for getting the version of the bundle
*
- * @return string - version of the bundle
+ * @return version of the bundle
*
*/
virtual const std::string &getVersion() = 0;
/**
* API for creating new bundle information
*
- * @return RCSBundleInfo - RCSBundleInfo pointer.
+ * @return RCSBundleInfo pointer.
*
*/
static RCSBundleInfo *build();
/**
* @file
*
- * This file contains the RCSDiscoveryManager class which provide API to discover the Resource in the network
+ * This file contains the RCSDiscoveryManager class which provide APIs to discover the Resource in the network
*
*/
{
namespace Service
{
-
class RCSRemoteResourceObject;
class RCSAddress;
/**
- * This class contains the resource discovery method.
+ * This class contains the resource discovery methods.
*
* @see RCSRemoteResourceObject
*/
class RCSDiscoveryManager
{
- public:
+ public:
+
+ /**
+ * Typedef for callback of discoverResource APIs
+ *
+ * @see discoverResource
+ */
+ typedef std::function< void(std::shared_ptr< RCSRemoteResourceObject >) >
+ ResourceDiscoveredCallback;
+
+ /**
+ * @return Returns RCSDiscoveryManager instance.
+ *
+ */
+ static RCSDiscoveryManager* getInstance();
+
+ /**
+ * API for discovering the resource of Interest, regardless of URI and resource type
+ *
+ * @param address A RCSAddress object
+ * @param cb A callback to obtain discovered resource
+ *
+ * @throws InvalidParameterException If cb is empty.
+ *
+ * @note The callback will be invoked in an internal thread.
+ *
+ * @see RCSAddress
+ *
+ */
+ void discoverResource(const RCSAddress& address, ResourceDiscoveredCallback cb);
- /**
- * Typedef for callback of discoverResource API
- *
- * @see discoverResource
- */
- typedef std::function< void(std::shared_ptr< RCSRemoteResourceObject >) >
- ResourceDiscoveredCallback;
+ /**
+ * API for discovering the resource of Interest, regardless of resource type
+ *
+ * @param address A RCSAddress object
+ * @param relativeURI The relative uri of resource to be searched
+ * @param cb A callback to obtain discovered resource
+ *
+ * @throws InvalidParameterException If cb is empty.
+ *
+ * @note The callback will be invoked in an internal thread.
+ *
+ * @see RCSAddress
+ *
+ */
+ void discoverResource(const RCSAddress& address, const std::string& relativeURI,
+ ResourceDiscoveredCallback cb);
- /**
- * Returns RCSDiscoveryManager instance.
- *
- */
- static RCSDiscoveryManager* getInstance();
+ /**
+ * API for discovering the resource of Interest by Resource type.
+ *
+ * @param address A RCSAddress object
+ * @param resourceType Ressource Type
+ * @param cb A callback to obtain discovered resource
+ *
+ * @throws InvalidParameterException If cb is empty.
+ *
+ * @note The callback will be invoked in an internal thread.
+ *
+ * @see RCSAddress
+ *
+ */
+ void discoverResourceByType(const RCSAddress& address, const std::string& resourceType,
+ ResourceDiscoveredCallback cb);
- /**
- * API for discovering the resource of Interest.
- *
- * @param address A RCSAddress object
- * @param resourceURI The uri of resource to be searched
- * @param cb A callback to obtain discovered resource
- *
- * @throws InvalidParameterException If cb is empty.
- *
- * @note The callback will be invoked in an internal thread.
- *
- * @see RCSAddress
- *
- */
- void discoverResource(const RCSAddress& address, const std::string& resourceURI,
- ResourceDiscoveredCallback cb);
+ /**
+ * API for discovering the resource of Interest by Resource type with provided relativeURI
+ *
+ * @param address A RCSAddress object
+ * @param relativeURI The relative uri of resource to be searched
+ * @param resourceType Ressource Type
+ * @param cb A callback to obtain discovered resource
+ *
+ * @throws InvalidParameterException If cb is empty.
+ *
+ * @note The callback will be invoked in an internal thread.
+ *
+ * @see RCSAddress
+ *
+ */
+ void discoverResourceByType(const RCSAddress& address, const std::string& relativeURI,
+ const std::string& resourceType,
+ ResourceDiscoveredCallback cb);
- private:
- RCSDiscoveryManager() = default;
- ~RCSDiscoveryManager() = default;
+ private:
+ RCSDiscoveryManager() = default;
+ ~RCSDiscoveryManager() = default;
};
}
}
~RCSRemoteResourceObject();
/**
- * Returns whether monitoring is enabled.
+ * @return Returns whether monitoring is enabled.
*
* @see startMonitoring()
*/
bool isMonitoring() const;
/**
- * Returns whether caching is enabled.
+ * @return Returns whether caching is enabled.
*
* @see startCaching()
*/
bool isCaching() const;
/**
- * Returns whether the resource is observable.
+ * @return Returns whether the resource is observable.
*
*/
bool isObservable() const;
void stopMonitoring();
/**
- * Returns the current state of the resource.
+ * @return Returns the current state of the resource.
*
* @see startMonitoring
*/
void stopCaching();
/**
- * Returns the current cache state.
+ * @return Returns the current cache state.
*
*/
CacheState getCacheState() const;
/**
- * Returns whether cached data is available.
+ * @return Returns whether cached data is available.
*
* Cache will be available always after CacheState::READY even if current state is
* CacheState::LOST_SIGNAL.
RemoteAttributesSetCallback cb);
/**
- * Returns the uri of the resource.
+ * @return Returns the uri of the resource.
*
*/
std::string getUri() const;
/**
- * Returns the address of the resource .
+ * @return Returns the address of the resource .
*
*/
std::string getAddress() const;
/**
- * Returns the resource types of the resource.
+ * @return Returns the resource types of the resource.
*
*/
std::vector< std::string > getTypes() const;
/**
- * Returns the resource interfaces of the resource.
+ * @return Returns the resource interfaces of the resource.
*
*/
std::vector< std::string > getInterfaces() const;
/**
* Constructor to set resource URI.
*
- * @param resourceUri - URI of the resource for which the request is generated.
+ * @param resourceUri URI of the resource for which the request is generated.
*/
explicit RCSRequest(const std::string &resourceUri);
RCSRequest &operator=(RCSRequest &) = delete;
/**
- * Returns the URI of the request.
+ * @return Returns the URI of the request.
*
*/
std::string getResourceUri() const;
#include <functional>
#include <unordered_map>
+#include <vector>
#include <boost/variant.hpp>
#include <boost/mpl/contains.hpp>
double,
bool,
std::string,
- RCSResourceAttributes
+ RCSResourceAttributes,
+
+ std::vector< int >,
+ std::vector< double >,
+ std::vector< bool >,
+ std::vector< std::string >,
+ std::vector< RCSResourceAttributes >,
+
+ std::vector< std::vector< int > >,
+ std::vector< std::vector< std::vector< int > > >,
+
+ std::vector< std::vector< double > >,
+ std::vector< std::vector< std::vector< double > > >,
+
+ std::vector< std::vector< bool > >,
+ std::vector< std::vector< std::vector< bool > > >,
+
+ std::vector< std::vector< std::string > >,
+ std::vector< std::vector< std::vector< std::string > > >,
+
+ std::vector< std::vector< RCSResourceAttributes > >,
+ std::vector< std::vector< std::vector< RCSResourceAttributes > > >
> ValueVariant;
template< typename T, typename V = void,
class KeyValueVisitorHelper: public boost::static_visitor< >
{
public:
- KeyValueVisitorHelper(VISITOR& visitor) :
+ KeyValueVisitorHelper(VISITOR& visitor) noexcept :
m_visitor( visitor )
{
}
* Returns type identifier.
*
* @return Identifier of type.
+ *
+ * @see getBaseTypeId
+ */
+ TypeId getId() const noexcept;
+
+ /**
+ * Returns the type identifier of a base type of sequence.
+ *
+ * For non sequence types, it is equivalent to calling getId.
+ *
+ * @return Identifier of type.
+ *
+ * @see getDepth
+ * @see getId
+ */
+ static TypeId getBaseTypeId(const Type& t) noexcept;
+
+ /**
+ * Returns the depth of a type.
+ *
+ * The return will be zero for non sequence types.
+ *
+ * @see getBaseTypeId
*/
- TypeId getId() const;
+ static size_t getDepth(const Type& t) noexcept;
/**
* Factory method to create Type instance from T.
*
* @return An instance that has TypeId for T.
*
- * @note T must be supported by Value. Otherwise, it won't be compiled.
+ * @note T must be supported by Value. Otherwise, it won't compile.
*
* @see is_supported_type
*/
template < typename T >
- static Type typeOf(const T& value)
+ constexpr static Type typeOf(const T&) noexcept
{
- return Type(value);
+ return Type{ IndexOfType< T >::value };
+ }
+
+ /**
+ * Factory method to create Type instance from T.
+ *
+ * @return An instance that has TypeId for T.
+ *
+ * @note T must be supported by Value. Otherwise, it won't compile.
+ *
+ * @see is_supported_type
+ */
+ template < typename T >
+ constexpr static Type typeOf() noexcept
+ {
+ return Type{ IndexOfType< T >::value };
}
//! @cond
- friend bool operator==(const Type&, const Type&);
+ friend bool operator==(const Type&, const Type&) noexcept;
//! @endcond
private:
- template < typename T >
- explicit Type(const T&) :
- m_which{ IndexOfType< T >::value }
+ constexpr explicit Type(int which) noexcept :
+ m_which{ which }
{
}
Value();
Value(const Value&);
- Value(Value&&);
+ Value(Value&&) noexcept;
/**
* Constructs a Value if T is a supported type.<br/>
- * Otherwise it won't be compiled.
+ * Otherwise it won't compile.
*/
template< typename T, typename = typename enable_if_supported< T >::type >
Value(T&& value) :
/**
* Exchanges the content of the object by the content of the parameter.
*/
- void swap(Value&);
+ void swap(Value&) noexcept;
//! @cond
friend class RCSResourceAttributes;
/**
* Returns an {@link iterator} referring to the first element.
*/
- iterator begin();
+ iterator begin() noexcept;
/**
* Returns an {@link iterator} referring to the <i>past-the-end element</i>.
*/
- iterator end();
+ iterator end() noexcept;
/**
* @copydoc cbegin()
*/
- const_iterator begin() const;
+ const_iterator begin() const noexcept;
/**
* @copydoc cend()
*/
- const_iterator end() const;
+ const_iterator end() const noexcept;
/**
* Returns a const_iterator referring to the first element.
*/
- const_iterator cbegin() const;
+ const_iterator cbegin() const noexcept;
/**
* Returns a const_iterator referring to the <i>past-the-end element</i>.
*/
- const_iterator cend() const;
+ const_iterator cend() const noexcept;
/**
* Accesses a value.
/**
* Removes all elements.
*/
- void clear();
+ void clear() noexcept;
/**
* Removes a single element.
*
* @see size
*/
- bool empty() const;
+ bool empty() const noexcept;
/**
* Returns the number of elements.
*
* @see empty
*/
- size_t size() const;
+ size_t size() const noexcept;
private:
template< typename VISITOR >
template< typename T >
struct RCSResourceAttributes::IsSupportedTypeHelper
{
- typedef boost::mpl::contains<ValueVariant::types, typename std::decay< T >::type> type;
+ typedef boost::mpl::contains< ValueVariant::types, typename std::decay< T >::type > type;
};
- template <typename T>
+ template < typename T >
struct RCSResourceAttributes::IndexOfType
{
+ static_assert(RCSResourceAttributes::is_supported_type< T >::value,
+ "The type is not supported!");
+
typedef typename boost::mpl::find< ValueVariant::types, T >::type iter;
typedef typename boost::mpl::begin< ValueVariant::types >::type mpl_begin;
static constexpr int value = boost::mpl::distance< mpl_begin, iter >::value;
};
+ template < typename T > constexpr int RCSResourceAttributes::IndexOfType< T >::value;
+
/**
* @relates RCSResourceAttributes::Type
*
*
* @return true if the objects are equal, false otherwise.
*/
- bool operator==(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&);
+ bool operator==(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&)
+ noexcept;
/**
* @relates RCSResourceAttributes::Type
*
* @return true if the objects are not equal, false otherwise.
*/
- bool operator!=(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&);
+ bool operator!=(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&)
+ noexcept;
/**
* @relates RCSResourceAttributes::Value
class KeyVisitor: public boost::static_visitor< const std::string& >
{
public:
- result_type operator()(iterator*) const;
- result_type operator()(const_iterator*) const;
+ result_type operator()(iterator*) const noexcept;
+ result_type operator()(const_iterator*) const noexcept;
};
class ValueVisitor: public boost::static_visitor< Value& >
{
public:
- result_type operator()(iterator*);
+ result_type operator()(iterator*) noexcept;
result_type operator()(const_iterator*);
};
class ConstValueVisitor: public boost::static_visitor< const Value& >
{
public:
- result_type operator()(iterator*) const;
- result_type operator()(const_iterator*) const;
+ result_type operator()(iterator*) const noexcept;
+ result_type operator()(const_iterator*) const noexcept;
};
public:
- const std::string& key() const;
- const RCSResourceAttributes::Value& value() const;
+ const std::string& key() const noexcept;
+ const RCSResourceAttributes::Value& value() const noexcept;
RCSResourceAttributes::Value& value();
private:
KeyValuePair(const KeyValuePair&) = default;
- KeyValuePair(boost::variant< iterator*, const_iterator* >&&);
+ KeyValuePair(boost::variant< iterator*, const_iterator* >&&) noexcept;
KeyValuePair& operator=(const KeyValuePair&) = default;
*
* @details This API start the container with the provided Configuration file.
*
- * @param configFile - configuration File that contains the Bundle/Bundles information.
+ * @param configFile configuration File that contains the Bundle/Bundles information.
*
*/
virtual void startContainer(const std::string &configFile) = 0;
/**
* API for getting the list of all bundles in the container
*
- * @return list<BundleInfo*> -List of BundleInfo pointer each associated with a bundle
+ * @return List of BundleInfo pointer each associated with a bundle
*
*/
virtual std::list<RCSBundleInfo *> listBundles() = 0;
/**
* API for starting the bundle.
*
- * @param bundleId - Id of the Bundle
+ * @param bundleId Id of the Bundle
*
*/
virtual void startBundle(const std::string &bundleId) = 0;
/**
* API for Stopping the bundle
*
- * @param bundleId - Id of the Bundle
+ * @param bundleId Id of the Bundle
*
*/
virtual void stopBundle(const std::string &bundleId) = 0;
/**
* API for adding the bundle to the Container
*
- * @param bundleId - Id of the Bundle
- * @param bundleUri - Uri of the bundle
- * @param bundlePath - Path of the bundle
- * @param params - key-value pairs in string form for other Bundle parameters
+ * @param bundleId Id of the Bundle
+ * @param bundleUri Uri of the bundle
+ * @param bundlePath Path of the bundle
+ * @param params key-value pairs in string form for other Bundle parameters
*
*/
virtual void addBundle(const std::string &bundleId, const std::string &bundleUri, const std::string &bundlePath,
/**
* API for removing the bundle from the container
*
- * @param bundleId - Id of the Bundle
+ * @param bundleId Id of the Bundle
*
*/
virtual void removeBundle(const std::string &bundleId) = 0;
/**
* API for adding the Resource configuration information to the bundle
*
- * @param bundleId - Id of the Bundle
- * @param resourceUri - URI of the resource
- * @param params - key-value pairs in string form for other Bundle parameters
+ * @param bundleId Id of the Bundle
+ * @param resourceUri URI of the resource
+ * @param params key-value pairs in string form for other Bundle parameters
*
*/
virtual void addResourceConfig(const std::string &bundleId, const std::string &esourceUri,
/**
* API for removing the Resource configuration information from the bundle
*
- * @param bundleId - Id of the Bundle
- * @param resourceUri - URI of the resource
+ * @param bundleId Id of the Bundle
+ * @param resourceUri URI of the resource
*
*/
virtual void removeResourceConfig(const std::string &bundleId, const std::string &resourceUri) = 0;
/**
* API for getting the list of Bundle Resources
*
- * @param bundleId - Id of the Bundle
+ * @param bundleId Id of the Bundle
*
*/
virtual std::list<std::string> listBundleResources(const std::string &bundleId) = 0;
/**
* API for getting the Instance of ResourceContainer class
*
- * @return RCSResourceContainer - Instance of the "RCSResourceContainer" class
+ * @return Instance of the "RCSResourceContainer" class
*
*/
static RCSResourceContainer *getInstance();
#include <mutex>
#include <thread>
-#include <boost/atomic.hpp>
-
#include <RCSResourceAttributes.h>
#include <RCSResponse.h>
#include <RCSRequest.h>
NoLockException(std::string &&what) : RCSException { std::move(what) } {}
};
+ //! @cond
+ template < typename T >
+ class AtomicWrapper;
+ //! @endcond
+
/**
* @brief RCSResourceObject represents a resource. It handles any requests from
* clients automatically with attributes.
private:
class WeakGuard;
+ typedef AtomicWrapper< std::thread::id > AtomicThreadId;
+
public:
/**
* @brief represents the policy of AutoNotify function.
* It provides the build() API
* which builds a resource and return pointer to RCSResourceObject class.
*
- *@see build()
+ * @see build()
*/
class Builder
{
const std::string &interface);
/**
- * Sets the discoverable(OC_DISCOVERABLE) property for the resource.
- *
- * @param discoverable Whether to be discovered.
- *
- * @return reference of this Builder
- *
- *@see OC_DISCOVERABLE
- */
+ * Sets the discoverable(OC_DISCOVERABLE) property for the resource.
+ *
+ * @param discoverable Whether to be discovered.
+ *
+ * @return reference of this Builder
+ *
+ * @see OC_DISCOVERABLE
+ */
Builder &setDiscoverable(bool discoverable);
/**
- * Sets the observable(OC_OBSERVABLE) property of the resource.
- *
- * @param observable Whether to be observed.
- *
- * @return reference of this Builder
- *
- *@see OC_OBSERVABLE
- */
+ * Sets the observable(OC_OBSERVABLE) property of the resource.
+ *
+ * @param observable Whether to be observed.
+ *
+ * @return reference of this Builder
+ *
+ * @see OC_OBSERVABLE
+ */
Builder &setObservable(bool observable);
/**
- * Sets attribute of the resource.
- *
- * @param attributes Resource attributes to set
- *
- * @return reference of this Builder
- */
+ * Sets attribute of the resource.
+ *
+ * @param attributes Resource attributes to set
+ *
+ * @return reference of this Builder
+ */
Builder &setAttributes(const RCSResourceAttributes &attributes);
/**
- * API for setting attributes of the resource.
- *
- * @param attributes Resource Attributes to set
- *
- * @return reference of this Builder
- */
+ * API for setting attributes of the resource.
+ *
+ * @param attributes Resource Attributes to set
+ *
+ * @return reference of this Builder
+ */
Builder &setAttributes(RCSResourceAttributes &&attributes);
/**
typedef std::function < RCSSetResponse(const RCSRequest&,
RCSResourceAttributes&) > SetRequestHandler;
+ /**
+ * typedef for characterizing AttributeUpdatedListener with 2 parameters.
+ *
+ * The first Value represents the old Value before being changed.
+ * The second Value means the new Value right after when it is used
+ *
+ * @see addAttributeUpdatedListener
+ */
typedef std::function < void(const RCSResourceAttributes::Value&,
const RCSResourceAttributes::Value &) > AttributeUpdatedListener;
* @note It is guaranteed thread-safety about attributes.
*
* @throw InvalidKeyException
- * Throw exception when empty string is provided as Attribute key.
+ * Throw an exception when key is empty.
*/
RCSResourceAttributes::Value getAttributeValue(const std::string& key) const;
*
* @param key Name of the attribute
*
- * @return resource attributes value.
+ * @return resource attributes value which can support various types.
+ *
+ * @see ValueVariant
*
* It is guaranteed thread-safety about attributes.
*/
*
* @param key Name of the attribute.
*
- * @return If the key exist and matched attribute is deleted, return true.
+ * @return If the key exists and matched attribute is deleted, return true.
*
* It is guaranteed thread-safety about attributes.
*/
*
* @param key Name of the attribute.
*
- * @return If the key exist, return true.
+ * @return If the key exists, return true.
*
* It is guaranteed thread-safety about attributes.
*/
* API for getting all the attributes of the RCSResourceObject.
* It invokes the expectOwnLock() API to check the owner of the lock using the
* thread id.
- * If it is not the owner then it throws exception.
+ * If it is not the owner then it throws an exception.
*
* @return reference of the attributes of this RCSResourceObject.
*
const RCSResourceAttributes& getAttributes() const;
/**
- * API for checking whether the particular resource is observable or not
- */
+ * API for checking whether the particular resource is observable or not
+ */
virtual bool isObservable() const;
/**
- * API for checking whether the particular resource is discoverable or not
- */
+ * API for checking whether the particular resource is discoverable or not
+ */
virtual bool isDiscoverable() const;
/**
* @param key The interested attribute's key
* @param listener Listener for updation of the interested attribute
*
+ * @see AttributeUpdatedListener
*/
virtual void addAttributeUpdatedListener(const std::string& key,
AttributeUpdatedListener listener);
* @param key The interested attribute's key
* @param listener Listener for updation of the interested attribute
*
+ * @see AttributeUpdatedListener
*/
virtual void addAttributeUpdatedListener(std::string&& key,
AttributeUpdatedListener listener);
/**
- * API for removing the handler for a particular attribute update.
- *
- * @param key The interested attribute's key
- *
- */
+ * API for removing the Listener for a particular attribute update.
+ *
+ * @param key The name of interested attribute's key
+ *
+ */
virtual bool removeAttributeUpdatedListener(const std::string& key);
/**
virtual void notify() const;
/**
- * API for setting Auto notify policy
- *
- * @param policy policy to be set
- *
- * @see AutoNotifyPolicy
- *
- */
+ * API for setting Auto notify policy
+ *
+ * @param policy policy to be set
+ *
+ * @see AutoNotifyPolicy
+ *
+ */
void setAutoNotifyPolicy(AutoNotifyPolicy policy);
/**
- * API for getting auto notify policy
- *
- * @returns AntoNotify policy
- *
- * @see AutoNotifyPolicy
- *
- */
+ * API for getting auto notify policy
+ *
+ * @returns AntoNotify policy
+ *
+ * @see AutoNotifyPolicy
+ *
+ */
AutoNotifyPolicy getAutoNotifyPolicy() const;
/**
- * API for setting the policy for a setRequestHandler.
- *
- * @param policy policy to be set
- *
- * @see SetRequestHandlerPolicy
- *
- */
+ * API for setting the policy for a setRequestHandler.
+ *
+ * @param policy policy to be set
+ *
+ * @see SetRequestHandlerPolicy
+ *
+ */
void setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy);
/**
- * API for getting the SetRequestHandler Policy.
- *
- * @returns Property of setRequesthandler
- *
- * @see SetRequestHandlerPolicy
- *
- */
+ * API for getting the SetRequestHandler Policy.
+ *
+ * @returns Property of setRequesthandler
+ *
+ * @see SetRequestHandlerPolicy
+ *
+ */
SetRequestHandlerPolicy getSetRequestHandlerPolicy() const;
private:
void expectOwnLock() const;
+ std::thread::id getLockOwner() const noexcept;
+
+ void setLockOwner(std::thread::id&&) const noexcept;
+
void autoNotify(bool, AutoNotifyPolicy) const;
void autoNotify(bool) const;
std::unordered_map< std::string, AttributeUpdatedListener >
m_keyAttributesUpdatedListeners;
- mutable boost::atomic< std::thread::id > m_lockOwner;
+ mutable std::unique_ptr< AtomicThreadId > m_lockOwner;
mutable std::mutex m_mutex;
std::mutex m_mutexKeyAttributeUpdate;
};
+ /**
+ * @class LockGuard
+ *
+ * The class LockGuard owns a mutex for the duration of a scoped block.
+ * When a LockGuard is created, it attempts to take ownership of the mutex it is given.
+ * When control leaves the scope in which the LockGuard object was created,
+ * the LockGuard is destructed and the mutex is released.
+ *
+ */
class RCSResourceObject::LockGuard
{
public:
+ /**
+ * The function locks the objects and ensures that all arguments are locked on return.
+ * Working of AutoNotifyPolicy follows the current AutoNotifyPolicy status
+ *
+ * @param Object to be locked
+ *
+ */
LockGuard(const RCSResourceObject&);
+
+ /**
+ * @overload
+ */
LockGuard(const RCSResourceObject::Ptr);
+
+ /**
+ * The function locks the objects and ensures that all arguments are locked on return.
+ *
+ * @param Object to be locked
+ * @param AutoNotifyPolicy is set for sepcifying AutoNotifyPolicy status
+ *
+ * @see AutoNotifyPolicy
+ */
LockGuard(const RCSResourceObject&, AutoNotifyPolicy);
+
+ /**
+ * @overload
+ */
LockGuard(const RCSResourceObject::Ptr, AutoNotifyPolicy);
~LockGuard();
/**
* Sets the acceptance method for the RCSSetResponse.
*
- * @param method - AcceptanceMethod value to set
+ * @param method AcceptanceMethod value to set
*
* @return The reference to this RCSSetResponse
*
--- /dev/null
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.resdk"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="8"
+ android:targetSdkVersion="21" />
+
+</manifest>
--- /dev/null
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../../out/android/$(TARGET_ARCH_ABI)/release
+LOCAL_MODULE := android-oc_logger
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/liboc_logger.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../../out/android/$(TARGET_ARCH_ABI)/release
+LOCAL_MODULE := android-oc_loggercore
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/liboc_logger_core.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../../out/android/$(TARGET_ARCH_ABI)/release
+LOCAL_MODULE := android-octbstack
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/liboctbstack.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../../out/android/$(TARGET_ARCH_ABI)/release
+LOCAL_MODULE := android-oc
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/liboc.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../../out/android/$(TARGET_ARCH_ABI)/release
+LOCAL_MODULE := android-connectivity_abstraction
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/libconnectivity_abstraction.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../../android/android_api/base/libs/$(TARGET_ARCH_ABI)
+LOCAL_MODULE := android-ocstack-jni
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/libocstack-jni.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../../android/android_api/base/libs/$(TARGET_ARCH_ABI)
+LOCAL_MODULE := android-ca-interface
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/libca-interface.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../../out/android/$(TARGET_ARCH_ABI)/release
+LOCAL_MODULE := android-resourcecommon
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/librcs_common.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../../out/android/$(TARGET_ARCH_ABI)/release
+LOCAL_MODULE := android-resourceclient
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/librcs_client.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../../out/android/$(TARGET_ARCH_ABI)/release
+LOCAL_MODULE := android-resourceserver
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/librcs_server.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+OIC_LIB_PATH := ../../../../../out/android/$(TARGET_ARCH_ABI)/release
+LOCAL_MODULE := android-resourcecontainer
+LOCAL_SRC_FILES := $(OIC_LIB_PATH)/librcs_container.so
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+OIC_SRC_DIR := ../../../..
+LOCAL_MODULE := re-jni
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/jniutil/inc \
+ $(OIC_SRC_DIR)/android/android_api/base/jni \
+ $(OIC_SRC_DIR)/resource/include \
+ $(OIC_SRC_DIR)/resource/c_common \
+ $(OIC_SRC_DIR)/resource/csdk/stack/include \
+ $(OIC_SRC_DIR)/resource/oc_logger/include \
+ $(OIC_SRC_DIR)/extlibs/boost/boost_1_58_0 \
+ $(OIC_SRC_DIR)/extlibs/timer \
+ $(OIC_SRC_DIR)/service/resource-encapsulation/include \
+ $(LOCAL_PATH)/re/include
+
+LOCAL_SRC_FILES += $(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(LOCAL_PATH)/jniutil/src/*.cpp))
+LOCAL_SRC_FILES += $(patsubst $(LOCAL_PATH)/%, %, $(wildcard $(LOCAL_PATH)/re/src/*.cpp))
+
+LOCAL_CPPFLAGS := -std=c++0x -frtti -fexceptions
+
+LOCAL_LDLIBS := -llog
+LOCAL_SHARED_LIBRARIES := android-ocstack-jni
+LOCAL_SHARED_LIBRARIES += android-resourcecommon
+LOCAL_SHARED_LIBRARIES += android-resourceclient
+LOCAL_SHARED_LIBRARIES += android-resourceserver
+LOCAL_SHARED_LIBRARIES += android-resourcecontainer
+LOCAL_SHARED_LIBRARIES += android-oc
+LOCAL_SHARED_LIBRARIES += android-octbstack
+
+include $(BUILD_SHARED_LIBRARY)
--- /dev/null
+NDK_TOOLCHAIN_VERSION := 4.9
+APP_STL := gnustl_shared
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file jni_re_jvm.h
+ *
+ * @brief This file contains the essential declarations and functions required
+ * for JNI implementation
+ */
+
+#ifndef __JNI_RE_JVM_H
+#define __JNI_RE_JVM_H
+
+#include <jni.h>
+#include <android/log.h>
+#include<string>
+
+#define RETAG "RE-JNI"
+#define JNI_CURRENT_VERSION JNI_VERSION_1_6
+
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, RETAG, __VA_ARGS__)
+#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, RETAG, __VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, RETAG, __VA_ARGS__)
+
+extern JavaVM *g_jvm;
+
+extern jclass g_cls_Integer;
+extern jclass g_cls_Double;
+extern jclass g_cls_Boolean;
+extern jclass g_cls_String;
+extern jclass g_cls_LinkedList;
+extern jclass g_cls_Iterator;
+extern jclass g_cls_Vector;
+extern jclass g_cls_Map;
+extern jclass g_cls_Set;
+extern jclass g_cls_MapEntry;
+extern jclass g_cls_RCSRemoteResourceObject;
+extern jclass g_cls_RCSRemoteResourceAttributesObject;
+extern jclass g_cls_RCSException;
+
+extern jclass g_cls_RCSResourceObject;
+extern jclass g_cls_RCSRequest;
+extern jclass g_cls_RCSBundleInfo;
+
+extern jmethodID g_mid_Integer_ctor;
+extern jmethodID g_mid_Double_ctor;
+extern jmethodID g_mid_Boolean_ctor;
+extern jmethodID g_mid_LinkedList_ctor;
+extern jmethodID g_mid_LinkedList_add_object;
+extern jmethodID g_mid_Map_entrySet;
+extern jmethodID g_mid_MapEntry_getKey;
+extern jmethodID g_mid_MapEntry_getValue;
+extern jmethodID g_mid_Set_iterator;
+extern jmethodID g_mid_Iterator_hasNext;
+extern jmethodID g_mid_Iterator_next;
+extern jmethodID g_mid_HashMap_ctor;
+extern jmethodID g_mid_HashMap_put;
+extern jmethodID g_mid_RCSRemoteResourceObject_ctor;
+extern jmethodID g_mid_RCSRemoteResourceAttributesObject_ctor;
+extern jmethodID g_mid_RCSException_ctor;
+
+extern jmethodID g_mid_RCSResourceObject_ctor;
+extern jmethodID g_mid_RCSRequest_ctor;
+extern jmethodID g_mid_RCSBundleInfo_ctor;
+
+typedef void(*RemoveListenerCallback)(JNIEnv *env, jobject jListener);
+
+/**
+ * @brief Get the native handle field
+ */
+static jfieldID REGetHandleField(JNIEnv *env, jobject jobj)
+{
+ jclass cls = env->GetObjectClass(jobj);
+ return env->GetFieldID(cls, "m_nativeHandle", "J");
+}
+
+/**
+ * @brief Get the native handle
+ */
+template <typename T>
+static T *REGetHandle(JNIEnv *env, jobject jobj)
+{
+ jlong handle = env->GetLongField(jobj, REGetHandleField(env, jobj));
+ return reinterpret_cast<T *>(handle);
+}
+
+/**
+ * @brief Set the native handle
+ */
+template <typename T>
+static void RESetHandle(JNIEnv *env, jobject jobj, T *type)
+{
+ jlong handle = reinterpret_cast<jlong>(type);
+
+ env->SetLongField(jobj, REGetHandleField(env, jobj), handle);
+}
+
+/**
+ * @brief Get the JNI Environment
+ */
+static JNIEnv *GetREJNIEnv(jint &ret)
+{
+ JNIEnv *env = NULL;
+
+ ret = g_jvm->GetEnv((void **)&env, JNI_CURRENT_VERSION);
+ switch (ret)
+ {
+ case JNI_OK:
+ return env;
+ case JNI_EDETACHED:
+ if (g_jvm->AttachCurrentThread(&env, NULL) < 0)
+ {
+ LOGE("Failed to get the environment");
+ return nullptr;
+ }
+ else
+ {
+ return env;
+ }
+
+ case JNI_EVERSION:
+ LOGE("JNI version not supported");
+ default:
+ LOGE("Failed to get the environment");
+ return nullptr;
+ }
+}
+#endif // __JNI_RE_JVM_H
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file jni_re_utils.h
+ *
+ * @brief This file contains the utility functions for JNI
+ */
+
+#ifndef __JNI_RE_UTILS_H_
+#define __JNI_RE_UTILS_H_
+
+#include "jni_re_jvm.h"
+#include "RCSRemoteResourceObject.h"
+#include "RCSResourceObject.h"
+
+#include <map>
+#include <list>
+#include <jni.h>
+
+using namespace OIC::Service;
+
+/**
+ * @brief Convert Native ResourceState to Integer
+ */
+int covertResourceStateToInt(ResourceState state);
+
+/**
+ * @brief Convert Native CacheState to Integer
+ */
+int convertCacheStateToInt(CacheState state);
+
+/**
+ * @brief Native Vector to Java list
+ */
+jobject convertStrVectorToJavaStrList(JNIEnv *env, std::vector<std::string> vector);
+
+/**
+ * @brief Convert Native ResourceState to Java ResourceState
+ */
+jobject convertNativeResourceStateToJavaResourceState(ResourceState nativeResourceState,
+ JNIEnv *env);
+
+
+/**
+ * @brief Convert Java AutoNotifyPolicy to Native AutoNotifyPolicy
+ */
+RCSResourceObject::AutoNotifyPolicy convertJavaNotifyPolicyToNativePolicy( int policy);
+
+/**
+ * @brief Convert AutoNotifyPolicy to integer
+ */
+int convertAutoNotifyPolicyToInt(RCSResourceObject::AutoNotifyPolicy policy);
+
+/**
+ *@brief Convert Java setRequestHandlerPolicy to Native setRequestHandlerPolicy
+ */
+RCSResourceObject::SetRequestHandlerPolicy convertJavasetRequestHandlerPolicyToNativePolicy(
+ int policy);
+
+/**
+ *@brief Convert setRequestHandlerPolicy to int
+ */
+int convertSetRequestHandlerPolicyToInt( RCSResourceObject::SetRequestHandlerPolicy policy);
+
+/**
+ *@brief Convert int to OCEntityHandlerResult
+ */
+OCEntityHandlerResult convertIntToOCEntityHandlerResult(int result);
+
+/**
+ *@brief Convert java map to native map
+ */
+void convertJavaMapToParamsMap(JNIEnv *env, jobject hashMap,
+ std::map<std::string, std::string> ¶ms);
+
+/**
+ *@brief Convert native string list to java list
+ */
+jobject convertStrListToJavaStrList(JNIEnv *env, std::list<std::string> &list);
+
+/**
+ * @brief Throw the RCS exception to the upper layer
+ */
+void throwRCSException(JNIEnv *env, std::string reason);
+
+/**
+ * @class ResourceStateWrapper
+ * @brief This class is JNI wrapper for Java ResourceState.
+ *
+ */
+class ResourceStateWrapper
+{
+ ResourceStateWrapper() {}
+ public :
+
+ //Field IDs
+ static jfieldID ALIVE_ID;
+ static jfieldID REQUESTED_ID;
+ static jfieldID LOST_SIGNAL_ID;
+ static jfieldID DESTROYED_ID;
+ static jfieldID NONE_ID;
+
+ //Method IDs
+ static jmethodID ordinal_ID;
+ static jmethodID toString_ID;
+ static jmethodID valueOf_ID;
+
+ static jclass clazz;
+
+ /**
+ * @brief Get jobject for ALIVE ResourceState
+ */
+ static jobject getALIVE(JNIEnv *env);
+
+ /**
+ * @brief Get jobject for REQUESTED ResourceState
+ */
+ static jobject getREQUESTED(JNIEnv *env);
+
+ /**
+ * @brief Get jobject for SIGNAL ResourceState
+ */
+ static jobject getLOST_SIGNAL(JNIEnv *env);
+
+ /**
+ * @brief Get jobject for DESTROYED ResourceState
+ */
+ static jobject getDESTROYED(JNIEnv *env);
+
+ /**
+ * @brief Get jobject for NONE ResourceState
+ */
+ static jobject getNONE(JNIEnv *env);
+
+ /**
+ * @brief Returns the ordinal value of Enum Object
+ */
+ static jint ordinal(JNIEnv *env, jobject enumObj);
+
+ /**
+ * @brief Returns the name of Enum Object
+ */
+ static jstring toString(JNIEnv *env, jobject enumObj);
+
+ /**
+ * @brief Returns Enum Object by name
+ */
+ static jobject valueOf(JNIEnv *env, jstring enumName);
+
+ /**
+ * @brief virtual destructor
+ */
+ virtual ~ResourceStateWrapper() {};
+};
+#endif //__JNI_RE_UTILS_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_jvm.h"
+#include "jni_re_utils.h"
+
+JavaVM *g_jvm = NULL;
+
+jclass g_cls_Integer = NULL;
+jclass g_cls_Double = NULL;
+jclass g_cls_Boolean = NULL;
+jclass g_cls_String = NULL;
+jclass g_cls_LinkedList = NULL;
+jclass g_cls_Iterator = NULL;
+jclass g_cls_Vector = NULL;
+jclass g_cls_Map = NULL;
+jclass g_cls_Set = NULL;
+jclass g_cls_MapEntry = NULL;
+jclass g_cls_RCSRemoteResourceObject = NULL;
+jclass g_cls_RCSRemoteResourceAttributesObject = NULL;
+jclass g_cls_RCSException = NULL;
+
+jclass g_cls_RCSResourceObject = NULL;
+jclass g_cls_RCSRequest = NULL;
+jclass g_cls_RCSBundleInfo = NULL;
+
+jmethodID g_mid_Integer_ctor = NULL;
+jmethodID g_mid_Double_ctor = NULL;
+jmethodID g_mid_Boolean_ctor = NULL;
+jmethodID g_mid_LinkedList_ctor = NULL;
+jmethodID g_mid_Set_iterator = NULL;
+jmethodID g_mid_LinkedList_add_object = NULL;
+jmethodID g_mid_Map_entrySet = NULL;
+jmethodID g_mid_MapEntry_getKey = NULL;
+jmethodID g_mid_MapEntry_getValue = NULL;
+jmethodID g_mid_Iterator_hasNext = NULL;
+jmethodID g_mid_Iterator_next = NULL;
+jmethodID g_mid_RCSRemoteResourceObject_ctor = NULL;
+jmethodID g_mid_RCSRemoteResourceAttributesObject_ctor = NULL;
+jmethodID g_mid_RCSException_ctor = NULL;
+
+jmethodID g_mid_RCSResourceObject_ctor = NULL;
+jmethodID g_mid_RCSRequest_ctor = NULL;
+jmethodID g_mid_RCSBundleInfo_ctor = NULL;
+
+// JNI OnLoad
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+ LOGI("JNI_OnLoad");
+ JNIEnv *env;
+ g_jvm = vm;
+
+ if (g_jvm->GetEnv((void **)&env, JNI_CURRENT_VERSION) != JNI_OK)
+ {
+ LOGE("Failed to get the environment using GetEnv()");
+ return JNI_ERR;
+ }
+
+ jclass clazz = nullptr;
+
+ //Integer
+ clazz = env->FindClass("java/lang/Integer");
+ if (!clazz) return JNI_ERR;
+ g_cls_Integer = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_Integer_ctor = env->GetMethodID(g_cls_Integer, "<init>", "(I)V");
+ if (!g_mid_Integer_ctor) return JNI_ERR;
+
+ //Double
+ clazz = env->FindClass("java/lang/Double");
+ if (!clazz) return JNI_ERR;
+ g_cls_Double = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_Double_ctor = env->GetMethodID(g_cls_Double, "<init>", "(D)V");
+ if (!g_mid_Double_ctor) return JNI_ERR;
+
+ //Boolean
+ clazz = env->FindClass("java/lang/Boolean");
+ if (!clazz) return JNI_ERR;
+ g_cls_Boolean = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_Boolean_ctor = env->GetMethodID(g_cls_Boolean, "<init>", "(Z)V");
+ if (!g_mid_Boolean_ctor) return JNI_ERR;
+
+ //String
+ clazz = env->FindClass("java/lang/String");
+ if (!clazz) return JNI_ERR;
+ g_cls_String = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ //LinkedList
+ clazz = env->FindClass("java/util/LinkedList");
+ if (!clazz) return JNI_ERR;
+ g_cls_LinkedList = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_LinkedList_ctor = env->GetMethodID(g_cls_LinkedList, "<init>", "()V");
+ if (!g_mid_LinkedList_ctor) return JNI_ERR;
+
+ g_mid_LinkedList_add_object = env->GetMethodID(g_cls_LinkedList, "add", "(Ljava/lang/Object;)Z");
+ if (!g_mid_LinkedList_add_object) return JNI_ERR;
+
+ //Map
+ clazz = env->FindClass("java/util/Map");
+ if (!clazz) return JNI_ERR;
+ g_cls_Map = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_Map_entrySet = env->GetMethodID(g_cls_Map, "entrySet", "()Ljava/util/Set;");
+ if (!g_mid_Map_entrySet) return JNI_ERR;
+
+ //MapEntry
+ clazz = env->FindClass("java/util/Map$Entry");
+ if (!clazz) return JNI_ERR;
+ g_cls_MapEntry = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_MapEntry_getKey = env->GetMethodID(g_cls_MapEntry, "getKey", "()Ljava/lang/Object;");
+ if (!g_mid_MapEntry_getKey) return JNI_ERR;
+ g_mid_MapEntry_getValue = env->GetMethodID(g_cls_MapEntry, "getValue", "()Ljava/lang/Object;");
+ if (!g_mid_MapEntry_getValue) return JNI_ERR;
+
+ //Set
+ clazz = env->FindClass("java/util/Set");
+ if (!clazz) return JNI_ERR;
+ g_cls_Set = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_Set_iterator = env->GetMethodID(g_cls_Set, "iterator", "()Ljava/util/Iterator;");
+ if (!g_mid_Set_iterator) return JNI_ERR;
+
+ //Iterator
+ clazz = env->FindClass("java/util/Iterator");
+ if (!clazz) return JNI_ERR;
+ g_cls_Iterator = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_Iterator_hasNext = env->GetMethodID(g_cls_Iterator, "hasNext", "()Z");
+ if (!g_mid_Iterator_hasNext) return JNI_ERR;
+
+ g_mid_Iterator_next = env->GetMethodID(g_cls_Iterator, "next", "()Ljava/lang/Object;");
+ if (!g_mid_Iterator_next) return JNI_ERR;
+
+ //Vector
+ clazz = env->FindClass("java/util/Vector");
+ if (!clazz) return JNI_ERR;
+ g_cls_Vector = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ //RCSRemoteResourceObject
+ clazz = env->FindClass("org/iotivity/ResourceEncapsulation/client/RCSRemoteResourceObject");
+ if (!clazz) return JNI_ERR;
+ g_cls_RCSRemoteResourceObject = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_RCSRemoteResourceObject_ctor = env->GetMethodID(g_cls_RCSRemoteResourceObject, "<init>",
+ "(J)V");
+ if (!g_mid_RCSRemoteResourceObject_ctor) return JNI_ERR;
+
+ //ResourceState enum
+ jclass tmpclazz = reinterpret_cast<jclass>
+ (env->FindClass("org/iotivity/ResourceEncapsulation/client/RCSRemoteResourceObject$ResourceState"));
+ if (!tmpclazz)
+ {
+ LOGE("Failed to get the class ResourceState");
+ return JNI_ERR;
+ }
+ ResourceStateWrapper::clazz = reinterpret_cast<jclass> (env->NewGlobalRef(tmpclazz));
+ env->DeleteLocalRef(tmpclazz);
+
+ //RCS Remote Resource Attributes
+ clazz = env->FindClass("org/iotivity/ResourceEncapsulation/common/RCSResourceAttributes");
+ if (!clazz) return JNI_ERR;
+ g_cls_RCSRemoteResourceAttributesObject = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_RCSRemoteResourceAttributesObject_ctor = env->GetMethodID(
+ g_cls_RCSRemoteResourceAttributesObject, "<init>", "(J)V");
+ if (!g_mid_RCSRemoteResourceAttributesObject_ctor) return JNI_ERR;
+
+ //RCSException
+ clazz = env->FindClass("org/iotivity/ResourceEncapsulation/common/RCSException");
+ if (!clazz) return JNI_ERR;
+ g_cls_RCSException = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_RCSException_ctor = env->GetMethodID(g_cls_RCSException, "<init>", "(Ljava/lang/String;)V");
+ if (!g_mid_RCSException_ctor) return JNI_ERR;
+
+ //RCSResourceObject
+ clazz = env->FindClass("org/iotivity/ResourceEncapsulation/server/RCSResourceObject");
+ if (!clazz) return JNI_ERR;
+ g_cls_RCSResourceObject = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_RCSResourceObject_ctor = env->GetMethodID(g_cls_RCSResourceObject, "<init>",
+ "(J)V");
+ if (!g_mid_RCSResourceObject_ctor) return JNI_ERR;
+
+ //RCSRequest
+ clazz = env->FindClass("org/iotivity/ResourceEncapsulation/server/RCSRequest");
+ if (!clazz) return JNI_ERR;
+ g_cls_RCSRequest = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ //RCSBundleInfo
+ clazz = env->FindClass("org/iotivity/ResourceEncapsulation/server/RCSBundleInfo");
+ if (!clazz) return JNI_ERR;
+ g_cls_RCSBundleInfo = (jclass)env->NewGlobalRef(clazz);
+ env->DeleteLocalRef(clazz);
+
+ g_mid_RCSBundleInfo_ctor = env->GetMethodID(g_cls_RCSBundleInfo, "<init>",
+ "(J)V");
+ if (!g_mid_RCSBundleInfo_ctor) return JNI_ERR;
+
+ return JNI_CURRENT_VERSION;
+}
+
+JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
+{
+ LOGI("JNI_OnUnload");
+ JNIEnv *env;
+
+ if (g_jvm->GetEnv((void **)&env, JNI_CURRENT_VERSION) != JNI_OK)
+ {
+ LOGE("Failed to get the environment using GetEnv()");
+ return;
+ }
+
+ env->DeleteGlobalRef(g_cls_Integer);
+ env->DeleteGlobalRef(g_cls_Double);
+ env->DeleteGlobalRef(g_cls_Boolean);
+ env->DeleteGlobalRef(g_cls_String);
+ env->DeleteGlobalRef(g_cls_LinkedList);
+ env->DeleteGlobalRef(g_cls_Iterator);
+ env->DeleteGlobalRef(g_cls_RCSRemoteResourceObject);
+ env->DeleteGlobalRef(g_cls_RCSRemoteResourceAttributesObject);
+ env->DeleteGlobalRef(g_cls_RCSException);
+ env->DeleteGlobalRef(g_cls_RCSResourceObject);
+ env->DeleteGlobalRef(g_cls_RCSRequest);
+ env->DeleteGlobalRef(g_cls_Map);
+ env->DeleteGlobalRef(g_cls_Set);
+ env->DeleteGlobalRef(g_cls_MapEntry);
+ env->DeleteGlobalRef(g_cls_RCSBundleInfo);
+
+ if (env)
+ {
+ if (ResourceStateWrapper::clazz != 0)
+ env->DeleteGlobalRef(ResourceStateWrapper::clazz);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_utils.h"
+
+int covertResourceStateToInt(ResourceState state)
+{
+ switch (state)
+ {
+ case ResourceState::NONE:
+ return 0;
+
+ case ResourceState::REQUESTED:
+ return 1;
+
+ case ResourceState::ALIVE:
+ return 2;
+
+ case ResourceState::LOST_SIGNAL:
+ return 3;
+
+ case ResourceState::DESTROYED:
+ return 4;
+ }
+ return 0;
+}
+
+int convertCacheStateToInt(CacheState state)
+{
+ switch (state)
+ {
+ case CacheState::NONE:
+ return 0;
+
+ case CacheState::UNREADY:
+ return 1;
+
+ case CacheState::READY:
+ return 2;
+
+ case CacheState::LOST_SIGNAL:
+ return 3;
+ }
+ return 0;
+}
+
+jobject convertStrVectorToJavaStrList(JNIEnv *env, std::vector<std::string> vector)
+{
+ jobject jList = env->NewObject(g_cls_LinkedList, g_mid_LinkedList_ctor);
+ if (!jList) return nullptr;
+ for (size_t i = 0; i < vector.size(); ++i)
+ {
+ jstring jStr = env->NewStringUTF(vector[i].c_str());
+ if (!jStr) return nullptr;
+ env->CallBooleanMethod(jList, g_mid_LinkedList_add_object, jStr);
+ if (env->ExceptionCheck()) return nullptr;
+ env->DeleteLocalRef(jStr);
+ }
+ return jList;
+}
+
+OCEntityHandlerResult convertIntToOCEntityHandlerResult(int result)
+{
+ switch (result)
+ {
+ case 0:
+ return OCEntityHandlerResult::OC_EH_OK;
+ case 1:
+ return OCEntityHandlerResult::OC_EH_ERROR;
+ case 2:
+ return OCEntityHandlerResult::OC_EH_RESOURCE_CREATED;
+ case 3:
+ return OCEntityHandlerResult::OC_EH_RESOURCE_DELETED;
+ case 4:
+ return OCEntityHandlerResult::OC_EH_SLOW;
+ case 5:
+ return OCEntityHandlerResult::OC_EH_FORBIDDEN;
+ case 6:
+ return OCEntityHandlerResult::OC_EH_RESOURCE_NOT_FOUND;
+ }
+ return OCEntityHandlerResult::OC_EH_ERROR;
+}
+
+void throwRCSException(JNIEnv *env, std::string reason)
+{
+ jobject ex = env->NewObject(g_cls_RCSException, g_mid_RCSException_ctor,
+ env->NewStringUTF(reason.c_str()));
+ if (!ex)
+ {
+ LOGI("throwRCSException jobject == NULL");
+ }
+ env->Throw((jthrowable)ex);
+}
+
+jfieldID ResourceStateWrapper::ALIVE_ID = 0;
+jfieldID ResourceStateWrapper::REQUESTED_ID = 0;
+jfieldID ResourceStateWrapper::LOST_SIGNAL_ID = 0;
+jfieldID ResourceStateWrapper::DESTROYED_ID = 0;
+jfieldID ResourceStateWrapper::NONE_ID = 0;
+
+jmethodID ResourceStateWrapper::ordinal_ID = 0;
+jmethodID ResourceStateWrapper::toString_ID = 0;
+jmethodID ResourceStateWrapper::valueOf_ID = 0;
+jclass ResourceStateWrapper::clazz = 0;
+
+jobject ResourceStateWrapper::getALIVE(JNIEnv *env)
+{
+ return env->GetStaticObjectField(clazz, ALIVE_ID);
+}
+jobject ResourceStateWrapper::getREQUESTED(JNIEnv *env)
+{
+ return env->GetStaticObjectField(clazz, REQUESTED_ID);
+}
+jobject ResourceStateWrapper::getLOST_SIGNAL(JNIEnv *env)
+{
+ return env->GetStaticObjectField(clazz, LOST_SIGNAL_ID);
+}
+jobject ResourceStateWrapper::getDESTROYED(JNIEnv *env)
+{
+ return env->GetStaticObjectField(clazz, DESTROYED_ID);
+}
+jobject ResourceStateWrapper::getNONE(JNIEnv *env)
+{
+ return env->GetStaticObjectField(clazz, NONE_ID);
+}
+jint ResourceStateWrapper::ordinal(JNIEnv *env, jobject enumObj)
+{
+ return env->CallIntMethod(enumObj, ordinal_ID);
+}
+jstring ResourceStateWrapper::toString(JNIEnv *env, jobject enumObj)
+{
+ return reinterpret_cast<jstring>(env->CallObjectMethod(enumObj, toString_ID));
+}
+jobject ResourceStateWrapper::valueOf(JNIEnv *env, jstring enumName)
+{
+ return env->CallStaticObjectMethod(clazz, valueOf_ID, (jobject)enumName);
+}
+
+jobject convertNativeResourceStateToJavaResourceState(ResourceState nativeResourceState,
+ JNIEnv *env)
+{
+ LOGI("convertNativeResourceStateToJavaResourceState enter");
+
+ ResourceStateWrapper::ALIVE_ID = env->GetStaticFieldID(ResourceStateWrapper::clazz, "ALIVE",
+ "Lorg/iotivity/ResourceEncapsulation/client/RCSRemoteResourceObject$ResourceState;");
+ ResourceStateWrapper::REQUESTED_ID = env->GetStaticFieldID(ResourceStateWrapper::clazz, "REQUESTED",
+ "Lorg/iotivity/ResourceEncapsulation/client/RCSRemoteResourceObject$ResourceState;");
+ ResourceStateWrapper::LOST_SIGNAL_ID = env->GetStaticFieldID(ResourceStateWrapper::clazz,
+ "LOST_SIGNAL", "Lorg/iotivity/ResourceEncapsulation/client/RCSRemoteResourceObject$ResourceState;");
+ ResourceStateWrapper::DESTROYED_ID = env->GetStaticFieldID(ResourceStateWrapper::clazz, "DESTROYED",
+ "Lorg/iotivity/ResourceEncapsulation/client/RCSRemoteResourceObject$ResourceState;");
+ ResourceStateWrapper::NONE_ID = env->GetStaticFieldID(ResourceStateWrapper::clazz, "NONE",
+ "Lorg/iotivity/ResourceEncapsulation/client/RCSRemoteResourceObject$ResourceState;");
+
+ ResourceStateWrapper::ordinal_ID = env->GetMethodID(ResourceStateWrapper::clazz, "ordinal", "()I");
+ ResourceStateWrapper::toString_ID = env->GetMethodID(ResourceStateWrapper::clazz, "toString",
+ "()Ljava/lang/String;");
+ ResourceStateWrapper::valueOf_ID = env->GetStaticMethodID(ResourceStateWrapper::clazz, "valueOf",
+ "(Ljava/lang/String;)Lorg/iotivity/ResourceEncapsulation/client/RCSRemoteResourceObject$ResourceState;");
+
+ LOGI("convertNativeResourceStateToJavaResourceState ResourceStateWrapper::clazz == NULL first time");
+
+ switch (nativeResourceState)
+ {
+ case ResourceState::NONE:
+ return ResourceStateWrapper::getNONE(env);
+
+ case ResourceState::REQUESTED:
+ return ResourceStateWrapper::getREQUESTED(env);
+
+ case ResourceState::ALIVE:
+ return ResourceStateWrapper::getALIVE(env);
+
+ case ResourceState::LOST_SIGNAL:
+ return ResourceStateWrapper::getLOST_SIGNAL(env);
+
+ case ResourceState::DESTROYED:
+ return ResourceStateWrapper::getDESTROYED(env);
+ }
+}
+
+RCSResourceObject::AutoNotifyPolicy convertJavaNotifyPolicyToNativePolicy( int policy)
+{
+ switch (policy)
+ {
+ case 0:
+ return RCSResourceObject::AutoNotifyPolicy::NEVER;
+
+ case 1:
+ return RCSResourceObject::AutoNotifyPolicy::ALWAYS;
+
+ case 2:
+ return RCSResourceObject::AutoNotifyPolicy::UPDATED;
+ }
+}
+
+RCSResourceObject::SetRequestHandlerPolicy convertJavasetRequestHandlerPolicyToNativePolicy(
+ int policy)
+{
+ switch (policy)
+ {
+ case 0:
+ return RCSResourceObject::SetRequestHandlerPolicy::NEVER;
+
+ case 1:
+ return RCSResourceObject::SetRequestHandlerPolicy::ACCEPTANCE;
+ }
+}
+
+int convertAutoNotifyPolicyToInt(RCSResourceObject::AutoNotifyPolicy policy)
+{
+ switch (policy)
+ {
+ case RCSResourceObject::AutoNotifyPolicy::NEVER:
+ return 0;
+
+ case RCSResourceObject::AutoNotifyPolicy::ALWAYS:
+ return 1;
+
+ case RCSResourceObject::AutoNotifyPolicy::UPDATED:
+ return 2;
+ }
+ return 0;
+}
+
+int convertSetRequestHandlerPolicyToInt(RCSResourceObject::SetRequestHandlerPolicy policy)
+{
+ switch (policy)
+ {
+ case RCSResourceObject::SetRequestHandlerPolicy::NEVER:
+ return 0;
+
+ case RCSResourceObject::SetRequestHandlerPolicy::ACCEPTANCE:
+ return 1;
+ }
+ return 0;
+}
+
+void convertJavaMapToParamsMap(JNIEnv *env, jobject hashMap,
+ std::map<std::string, std::string> ¶ms)
+{
+
+ LOGI("convertJavaMapToParamsMap Enter");
+ if (!hashMap)
+ {
+ LOGI("convertJavaMapToParamsMap hashMap is NULL");
+ return;
+ }
+
+ jobject jEntrySet = env->CallObjectMethod(hashMap, g_mid_Map_entrySet);
+ jobject jIterator = env->CallObjectMethod(jEntrySet, g_mid_Set_iterator);
+ if (!jEntrySet || !jIterator || env->ExceptionCheck())
+ {
+ LOGI("convertJavaMapToParamsMap !jEntrySet || !jIterator || env->ExceptionCheck()");
+ return;
+ }
+
+ while (env->CallBooleanMethod(jIterator, g_mid_Iterator_hasNext))
+ {
+ jobject jEntry = env->CallObjectMethod(jIterator, g_mid_Iterator_next);
+ if (!jEntry) return;
+ jstring jKey = (jstring)env->CallObjectMethod(jEntry, g_mid_MapEntry_getKey);
+ if (!jKey) return;
+ jstring jValue = (jstring)env->CallObjectMethod(jEntry, g_mid_MapEntry_getValue);
+ if (!jValue) return;
+
+ LOGI("convertJavaMapToParamsMap about to insert");
+ params.insert(std::make_pair(env->GetStringUTFChars(jKey, NULL),
+ env->GetStringUTFChars(jValue, NULL)));
+
+ if (env->ExceptionCheck()) return;
+ env->DeleteLocalRef(jEntry);
+ env->DeleteLocalRef(jKey);
+ env->DeleteLocalRef(jValue);
+ }
+}
+
+jobject convertStrListToJavaStrList(JNIEnv *env, std::list<std::string> &nativeList)
+{
+ jobject jList = env->NewObject(g_cls_LinkedList, g_mid_LinkedList_ctor);
+ if (!jList) return nullptr;
+
+ for (std::list<std::string>::iterator it = nativeList.begin(); it != nativeList.end(); ++it)
+ {
+ jstring jStr = env->NewStringUTF((*it).c_str());
+ if (!jStr) return nullptr;
+ env->CallBooleanMethod(jList, g_mid_LinkedList_add_object, jStr);
+ if (env->ExceptionCheck()) return nullptr;
+ env->DeleteLocalRef(jStr);
+ }
+ return jList;
+}
\ No newline at end of file
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_attribute_updated_listener.h
+ *
+ * @brief This file contains JNI attribute update Listener class
+ */
+
+#ifndef __JNI_RE_ATTRIBUTE_UPDATED_LISTENER_H_
+#define __JNI_RE_ATTRIBUTE_UPDATED_LISTENER_H_
+
+#include <jni.h>
+
+#include "jni_re_jvm.h"
+#include "jni_re_utils.h"
+#include "jni_re_resource_attributes.h"
+
+
+class JniRCSResourceObject;
+
+/**
+ * @class JniAttributeUpdatedListener
+ * @brief This class provides functions for handling the attribute updated callback between the Java and Native layer
+ *
+ */
+class JniAttributeUpdatedListener
+{
+ public:
+ /**
+ * @brief constructor
+ */
+ JniAttributeUpdatedListener(JNIEnv *env, jobject jListener,
+ JniRCSResourceObject *resource);
+
+ /**
+ * @brief destructor
+ */
+ ~JniAttributeUpdatedListener();
+
+ /**
+ * @brief callback function that will be passed to Native layer
+ */
+ void onAttributeUpdatedCallback(OIC::Service::RCSResourceAttributes::Value oldValue,
+ OIC::Service::RCSResourceAttributes::Value newValue);
+
+ private:
+ jweak m_jwListener;
+ JniRCSResourceObject *m_ownerResource;
+ void checkExAndRemoveListener(JNIEnv *env);
+};
+
+#endif //__JNI_RE_ATTRIBUTE_UPDATED_LISTENER_H_
\ No newline at end of file
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_cache_update_listener.h
+ *
+ * @brief This file contains JNI CacheUpdate Listener class
+ */
+
+#ifndef __JNI_RE_CACHE_UPDATE_LISTENER_H_
+#define __JNI_RE_CACHE_UPDATE_LISTENER_H_
+
+#include <jni.h>
+
+#include "RCSRemoteResourceObject.h"
+
+#include "jni_re_jvm.h"
+#include "jni_re_rcs_remoteresourceobject.h"
+
+/**
+ * @class JniCacheUpdateListener
+ * @brief This class provides functions for handling the CacheUpdate Callback between the Java and Native layer
+ *
+ */
+class JniCacheUpdateListener
+{
+ public:
+ /**
+ * @brief constructor
+ */
+ JniCacheUpdateListener(JNIEnv *env, jobject jListener, JniRCSRemoteResourceObject *resource);
+
+ /**
+ * @brief destructor
+ */
+ ~JniCacheUpdateListener();
+
+ /**
+ * @brief callback function that will be passed to Native layer
+ */
+ void cacheUpdatedCallback(OIC::Service::RCSResourceAttributes attributes);
+
+ private:
+ jweak m_jwListener;
+ JniRCSRemoteResourceObject *m_ownerResource;
+ void checkExAndRemoveListener(JNIEnv *env);
+};
+#endif //__JNI_RE_CACHE_UPDATE_LISTENER_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_discover_resource_listener.h
+ *
+ * @brief This file contains JNI Discover Resource Listener class
+ */
+
+#ifndef __JNI_RE_DISCOVER_RESOURCE_LISTENER_H_
+#define __JNI_RE_DISCOVER_RESOURCE_LISTENER_H_
+
+#include <jni.h>
+
+#include "RCSRemoteResourceObject.h"
+
+#include "jni_re_jvm.h"
+#include "jni_re_rcs_remoteresourceobject.h"
+
+typedef void(*RemoveListenerCallback)(JNIEnv *env, jobject jListener);
+
+class RCSRemoteResourceObject;
+
+/**
+ * @class JniDiscoverResourceListener
+ * @brief This class provides functions for handling the Discover Resource Callback between the Java and Native layer
+ *
+ */
+class JniDiscoverResourceListener
+{
+ public:
+ /**
+ * @brief constructor
+ */
+ JniDiscoverResourceListener(JNIEnv *env, jobject jListener,
+ RemoveListenerCallback removeListenerCallback);
+
+ /**
+ * @brief destructor
+ */
+ ~JniDiscoverResourceListener();
+
+ /**
+ * @brief callback function that will be passed to Native layer
+ */
+ void discoverResourceCallback(std::shared_ptr<OIC::Service::RCSRemoteResourceObject> resource);
+
+ private:
+ RemoveListenerCallback m_removeListenerCallback;
+ jweak m_jwListener;
+ void checkExAndRemoveListener(JNIEnv *env);
+};
+#endif //__JNI_RE_DISCOVER_RESOURCE_LISTENER_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_get_request_listener.h
+ *
+ * @brief This file contains JNI get request Listener class
+ */
+
+#ifndef __JNI_RE_GET_REQUEST_LISTENER_H_
+#define __JNI_RE_GET_REQUEST_LISTENER_H_
+
+#include <jni.h>
+
+#include "jni_re_jvm.h"
+#include "jni_re_utils.h"
+#include "jni_re_resource_attributes.h"
+
+
+class JniRCSResourceObject;
+
+/**
+ * @class JniGetRequestListener
+ * @brief This class provides functions for handling the get request callback between the Java and Native layer
+ *
+ */
+class JniGetRequestListener
+{
+ public:
+ /**
+ * @brief constructor
+ */
+ JniGetRequestListener(JNIEnv *env, jobject jListener,
+ JniRCSResourceObject *resource);
+
+ /**
+ * @brief destructor
+ */
+ ~JniGetRequestListener();
+
+ /**
+ * @brief callback function that will be passed to Native layer
+ */
+ OIC::Service::RCSGetResponse onGetRequestCallback(OIC::Service::RCSRequest request,
+ OIC::Service::RCSResourceAttributes attributes);
+
+ private:
+ jweak m_jwListener;
+ JniRCSResourceObject *m_ownerResource;
+ void checkExAndRemoveListener(JNIEnv *env);
+};
+
+#endif //__JNI_RE_GET_REQUEST_LISTENER_H_
\ No newline at end of file
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_getattributes_listener.h
+ *
+ * @brief This file contains JNI get attributes Listener class
+ */
+
+#ifndef __JNI_RE_GET_ATTRIBUTES_LISTENER_H_
+#define __JNI_RE_GET_ATTRIBUTES_LISTENER_H_
+
+#include <jni.h>
+
+#include "jni_re_jvm.h"
+#include "jni_re_utils.h"
+#include "jni_re_resource_attributes.h"
+
+class JniRCSRemoteResourceObject;
+
+/**
+ * @class JniGetAttributesListener
+ * @brief This class provides functions for handling the get attribute callback between the Java and Native layer
+ *
+ */
+class JniGetAttributesListener
+{
+ public:
+ /**
+ * @brief constructor
+ */
+ JniGetAttributesListener(JNIEnv *env, jobject jListener,
+ JniRCSRemoteResourceObject *resource);
+
+ /**
+ * @brief destructor
+ */
+ ~JniGetAttributesListener();
+
+ /**
+ * @brief callback function that will be passed to Native layer
+ */
+ void onRemoteAttributesGetCallback(OIC::Service::RCSResourceAttributes attributes);
+
+ private:
+ jweak m_jwListener;
+ JniRCSRemoteResourceObject *m_ownerResource;
+ void checkExAndRemoveListener(JNIEnv *env);
+};
+
+#endif //__JNI_RE_GET_ATTRIBUTES_LISTENER_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_listener_manager.h
+ *
+ * @brief This file contains JNI Listener Manager class for client (jni_re_rcs_remoteresourceobject)
+ */
+
+#ifndef __JNI_RE_LISTENER_MANAGER_LISTENER_H_
+#define __JNI_RE_LISTENER_MANAGER_LISTENER_H_
+
+#include <mutex>
+#include <map>
+
+class JniRCSRemoteResourceObject;
+
+/**
+ * @class JniReListenerManager
+ * @brief This class provides functions for managing listeners
+ *
+ */
+template <class T>
+class JniReListenerManager
+{
+ public:
+ /**
+ * API for Adding the Listener to listener Map.
+ *
+ * @param owner - JniRCSRemoteResourceObject
+ */
+ T *addListener(JNIEnv *env, jobject jListener, JniRCSRemoteResourceObject *owner)
+ {
+ T *onEventListener = NULL;
+
+ m_mapMutex.lock();
+
+ for (auto it = m_listenerMap.begin(); it != m_listenerMap.end(); ++it)
+ {
+ if (env->IsSameObject(jListener, it->first))
+ {
+ auto refPair = it->second;
+ onEventListener = refPair.first;
+ refPair.second++;
+ it->second = refPair;
+ m_listenerMap.insert(*it);
+ LOGD("OnEventListener: ref. count is incremented");
+ break;
+ }
+ }
+ if (!onEventListener)
+ {
+ onEventListener = new T(env, jListener, owner);
+ jobject jgListener = env->NewGlobalRef(jListener);
+
+ if (jgListener)
+ {
+ m_listenerMap.insert(
+ std::pair < jobject,
+ std::pair<T *, int >> (jgListener, std::pair<T *, int>(onEventListener, 1)));
+ }
+ else
+ {
+ LOGD("OnEventListener: Failed to create global listener ref.");
+ delete onEventListener;
+ }
+ LOGD("OnEventListener: new listener");
+ }
+ m_mapMutex.unlock();
+ return onEventListener;
+ }
+
+ /**
+ * @brief API for removing the Listener from listener Map.
+ */
+ void removeListener(JNIEnv *env, jobject jListener)
+ {
+ m_mapMutex.lock();
+ for (auto it = m_listenerMap.begin(); it != m_listenerMap.end(); ++it)
+ {
+ if (env->IsSameObject(jListener, it->first))
+ {
+ auto refPair = it->second;
+ if (refPair.second > 1)
+ {
+ refPair.second--;
+ it->second = refPair;
+ m_listenerMap.insert(*it);
+ LOGI("OnEventListener: ref. count is decremented");
+ }
+ else
+ {
+ env->DeleteGlobalRef(it->first);
+ T *listener = refPair.first;
+ delete listener;
+ m_listenerMap.erase(it);
+
+ LOGI("OnEventListener is removed");
+ }
+ break;
+ }
+ }
+ m_mapMutex.unlock();
+ }
+
+ /**
+ * @brief API for removing all the Listener from listener Map.
+ */
+ void removeAllListeners(JNIEnv *env)
+ {
+ m_mapMutex.lock();
+
+ for (auto & pair : m_listenerMap)
+ {
+ env->DeleteGlobalRef(pair.first);
+ auto refPair = pair.second;
+ delete refPair.first;
+ }
+ m_listenerMap.clear();
+
+ m_mapMutex.unlock();
+ }
+
+ private:
+ std::map<jobject, std::pair<T *, int>> m_listenerMap;
+ std::mutex m_mapMutex;
+};
+
+#endif //__JNI_RE_LISTENER_MANAGER_LISTENER_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_listener_manager_server.h
+ *
+ * @brief This file contains JNI Listener Manager class for server (jni_re_rcs_resource_object)
+ */
+
+#ifndef __JNI_RE_LISTENER_MANAGER_LISTENER_H_
+#define __JNI_RE_LISTENER_MANAGER_LISTENER_H_
+
+#include <mutex>
+#include <map>
+
+class JniRemoteResourceObject;
+
+/**
+ * @class JniReListenerManagerServer
+ * @brief This class provides functions for managing listeners
+ *
+ */
+template <class T>
+class JniReListenerManagerServer
+{
+ public:
+ /**
+ * API for Adding the Listener to listener Map.
+ *
+ * @param owner - JniRCSResourceObject
+ */
+ T *addListener(JNIEnv *env, jobject jListener, JniRCSResourceObject *owner)
+ {
+ T *onEventListener = NULL;
+
+ m_mapMutex.lock();
+
+ for (auto it = m_listenerMap.begin(); it != m_listenerMap.end(); ++it)
+ {
+ if (env->IsSameObject(jListener, it->first))
+ {
+ auto refPair = it->second;
+ onEventListener = refPair.first;
+ refPair.second++;
+ it->second = refPair;
+ m_listenerMap.insert(*it);
+ LOGD("OnEventListener: ref. count is incremented");
+ break;
+ }
+ }
+ if (!onEventListener)
+ {
+ onEventListener = new T(env, jListener, owner);
+ jobject jgListener = env->NewGlobalRef(jListener);
+
+ if (jgListener)
+ {
+ m_listenerMap.insert(
+ std::pair < jobject,
+ std::pair<T *, int >> (jgListener, std::pair<T *, int>(onEventListener, 1)));
+ }
+ else
+ {
+ LOGD("OnEventListener: Failed to create global listener ref.");
+ delete onEventListener;
+ }
+ LOGD("OnEventListener: new listener");
+ }
+ m_mapMutex.unlock();
+ return onEventListener;
+ }
+
+ /**
+ * @brief API for removing the Listener from listener Map.
+ */
+ void removeListener(JNIEnv *env, jobject jListener)
+ {
+ m_mapMutex.lock();
+ for (auto it = m_listenerMap.begin(); it != m_listenerMap.end(); ++it)
+ {
+ if (env->IsSameObject(jListener, it->first))
+ {
+ auto refPair = it->second;
+ if (refPair.second > 1)
+ {
+ refPair.second--;
+ it->second = refPair;
+ m_listenerMap.insert(*it);
+ LOGI("OnEventListener: ref. count is decremented");
+ }
+ else
+ {
+ env->DeleteGlobalRef(it->first);
+ T *listener = refPair.first;
+ delete listener;
+ m_listenerMap.erase(it);
+
+ LOGI("OnEventListener is removed");
+ }
+ break;
+ }
+ }
+ m_mapMutex.unlock();
+ }
+
+ /**
+ * @brief API for removing all the Listener from listener Map.
+ */
+ void removeAllListeners(JNIEnv *env)
+ {
+ m_mapMutex.lock();
+
+ for (auto & pair : m_listenerMap)
+ {
+ env->DeleteGlobalRef(pair.first);
+ auto refPair = pair.second;
+ delete refPair.first;
+ }
+ m_listenerMap.clear();
+
+ m_mapMutex.unlock();
+ }
+
+ private:
+ std::map<jobject, std::pair<T *, int>> m_listenerMap;
+ std::mutex m_mapMutex;
+};
+
+#endif //__JNI_RE_LISTENER_MANAGER_LISTENER_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_rcs_bundle_info.h
+ *
+ * @brief This file contains the JniBundleInfo class
+ * & declaration of RCSBundleInfo APIs for JNI implementation
+ */
+
+#ifndef __JNI_RE_RCS_BUNDLE_INFO_H_
+#define __JNI_RE_RCS_BUNDLE_INFO_H_
+
+#include <jni.h>
+
+#include <RCSBundleInfo.h>
+
+using namespace OIC::Service;
+
+/**
+ * @class JniBundleInfo
+ * @brief This class provides the API for getting the RCSBundleInfo pointer
+ *
+ */
+class JniBundleInfo
+{
+ public:
+ /**
+ * @brief Get the RCSBundleInfo pointer
+ * internally get the native handle by calling REGetHandle
+ */
+ static RCSBundleInfo *getRCSBundleInfoPtr(JNIEnv *env, jobject thiz);
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* API for getting the Id of the bundle
+*
+* @return jstring - Id of the bundle
+*
+*/
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeGetID
+(JNIEnv *env, jobject jObject);
+
+/**
+* API for getting the path of the bundle
+*
+* @return jstring - path of the bundle
+*
+*/
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeGetPath
+(JNIEnv *env, jobject jObject);
+
+/**
+* API for getting the Activator name for the bundle
+*
+* @return jstring - Name of the activator
+*
+*/
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeGetActivatorName
+(JNIEnv *env, jobject jObject);
+
+/**
+* API for getting the library path for the bundle
+*
+* @return jstring - Library path in string form
+*
+*/
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeGetLibraryPath
+(JNIEnv *env, jobject jObject);
+
+/**
+* API for getting the version of the bundle
+*
+* @return jstring - version of the bundle
+*
+*/
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeGetVersion
+(JNIEnv *env, jobject jObject);
+
+
+/**
+* API for setting the Id of the bundle
+*
+* @param id - Id of the bundle in string form
+*
+*/
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeSetID
+(JNIEnv *env, jobject jObject, jstring id);
+
+/**
+* API for setting the path of the bundle
+*
+* @param path - path of the bundle in string form
+*
+*/
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeSetPath
+(JNIEnv *env, jobject jObject, jstring path);
+
+/**
+* API for setting the Activator name for the bundle
+*
+* @param activator - Activator name in string form
+*
+*/
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeSetActivatorName
+(JNIEnv *env, jobject jObject, jstring activatorname);
+
+/**
+* API for setting the library path for the bundle
+*
+* @param libpath - Library path in string form
+*
+*/
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeSetLibraryPath
+(JNIEnv *env, jobject jObject, jstring libraryPath);
+
+/**
+* API for setting the version of the bundle
+*
+* @param version - version of the bundle in string form
+*
+*/
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeSetVersion
+(JNIEnv *env, jobject jObject, jstring version);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__JNI_RE_RCS_BUNDLE_INFO_H_
+
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_rcs_discovery_manager.h
+ *
+ * @brief This file contains the declaration of Discover Resource API
+ * for JNI implementation
+ */
+
+#ifndef __JNI_RE_RCS_DISCOVERY_MANAGER_H_
+#define __JNI_RE_RCS_DISCOVERY_MANAGER_H_
+
+#include <stdio.h>
+#include <string>
+#include <mutex>
+#include <map>
+#include <jni.h>
+#include "jni_re_discover_resource_listener.h"
+
+#define LOG_TAG "JNIDM"
+
+/**
+* @brief API for adding listener to discover resource listener Map.
+*/
+JniDiscoverResourceListener *AddDiscoverResourceListener(JNIEnv *env, jobject jListener);
+
+/**
+* @brief API for removing listener from discover resource listener Map.
+*/
+void RemoveDiscoverResourceListener(JNIEnv *env, jobject jListener);
+
+/**
+* @brief discover resource listener Map.
+*/
+std::map<jobject, std::pair<JniDiscoverResourceListener *, int>> discoverResourceListenerMap;
+
+/**
+ * Mutex for thread synchronization
+ */
+std::mutex discoverResourceMapLock;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * API for discovering the resource of interest in the network
+ *
+ * @param address - address
+ * @param typeofDiscovery - multicast or unicast
+ * @param relativeURI - relative URI for the resource of interest
+ * @param resourceType - resource type
+ * @param discoveryListener - Listener to obtain discovered resource
+ *
+ * NOTE: 0 - Unicast 1 - Multicast
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSDiscoveryManager_discoverResource
+(JNIEnv *env, jclass interfaceClass, jstring address, jint typeofDiscovery, jstring relativeURI,
+ jstring resourceType, jobject discoveryListener);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__JNI_RE_RCS_DISCOVERY_MANAGER_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_rcs_remoteresourceobject.h
+ *
+ * @brief This file contains the JniRCSRemoteResourceObject class
+ * & declaration of RCSRemoteResourceObject APIs for JNI implementation
+ */
+
+#ifndef _JNI_RE_RCS_REMOTE_RESOURCE_OBJECT_H_
+#define _JNI_RE_RCS_REMOTE_RESOURCE_OBJECT_H_
+
+#include "RCSRemoteResourceObject.h"
+
+#include "jni_re_jvm.h"
+#include "jni_re_utils.h"
+#include "jni_re_listener_manager.h"
+#include "jni_re_resource_statechange_listener.h"
+#include "jni_re_cache_update_listener.h"
+#include "jni_re_getattributes_listener.h"
+#include "jni_re_setattributes_listener.h"
+
+using namespace OIC::Service;
+
+/**
+ * @class JniRCSRemoteResourceObject
+ * @brief This class contains all the APIs for RCSRemoteResourceObject
+ *
+ * NOTE: JNI APIs internally call the APIs of this class.
+ */
+class JniRCSRemoteResourceObject
+{
+ public:
+
+ /**
+ * @brief constructor
+ */
+ JniRCSRemoteResourceObject(std::shared_ptr< RCSRemoteResourceObject> resource);
+
+ /**
+ * @brief destructor
+ */
+ ~JniRCSRemoteResourceObject();
+
+ // ***** JNI APIs internally call the APIs of this class ***** //
+
+ bool isMonitoring();
+ bool isCaching();
+ bool isObservable();
+ void startMonitoring(JNIEnv *env, jobject jListener) ;
+ void stopMonitoring();
+ int getState();
+ void startCaching(JNIEnv *env, jobject jListener);
+ void startCaching(JNIEnv *env);
+ void stopCaching();
+ int getCacheState();
+ bool isCachedAvailable();
+ std::string getUri();
+ std::string getAddress();
+ jobject getInterfaces(JNIEnv *env);
+ jobject getTypes(JNIEnv *env);
+ void getRemoteAttributes(JNIEnv *env, jobject jListener);
+ void setRemoteAttributes(JNIEnv *env, jobject attribute, jobject jListener);
+ jobject getCachedAttributes(JNIEnv *env);
+ jstring getCachedAttribute(JNIEnv *env, jstring key, jobject object);
+
+ JniResourceStateChangeListener *addOnStateChangeListener(JNIEnv *env, jobject jListener);
+ JniCacheUpdateListener *addOnCacheUpdateListener(JNIEnv *env, jobject jListener);
+ JniGetAttributesListener *addOngetAttributesListener(JNIEnv *env, jobject jListener);
+ JniSetAttributesListener *addOnsetAttributesListener(JNIEnv *env, jobject jListener);
+
+ void removeOnStateChangeListener(JNIEnv *env, jobject jListener);
+ void removeCacheUpdateListener(JNIEnv *env, jobject jListener);
+ void removeOngetAttributesListener(JNIEnv *env, jobject jListener);
+ void removeOnsetAttributesListener(JNIEnv *env, jobject jListener);
+
+ std::shared_ptr< RCSRemoteResourceObject> getRCSResource();
+
+ static JniRCSRemoteResourceObject *getJniRCSRemoteResourceObject(JNIEnv *env, jobject thiz);
+
+ private:
+ JniReListenerManager<JniResourceStateChangeListener> m_onStateChange;
+ JniReListenerManager<JniCacheUpdateListener> m_onCacheUpdateChange;
+ JniReListenerManager<JniGetAttributesListener> m_ongetAttributes;
+ JniReListenerManager<JniSetAttributesListener> m_onsetAttributes;
+
+ std::shared_ptr< RCSRemoteResourceObject> m_sharedResource;
+
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * API for checking whether monitoring is enabled or not.
+ *
+ * @return jboolean - boolean value (true/false)
+ *
+ * NOTE: If monitoring is started returns true otherwise false
+ */
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeIsMonitoring
+(JNIEnv *env, jobject interfaceClass);
+
+/**
+ * API for checking whether Caching is enabled or not.
+ *
+ * @return jboolean - boolean value (true/false)
+ *
+ * NOTE: If Caching is started returns true otherwise false
+ */
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeIsCaching
+(JNIEnv *env, jobject interfaceClass);
+
+/**
+ * API for checking whether resource is observable or not.
+ *
+ * @return jboolean - boolean value (true/false)
+ *
+ * NOTE: If resource is observable returns true otherwise false
+ */
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeIsObservable
+(JNIEnv *env, jobject interfaceClass);
+
+/**
+ * Starts monitoring the resource.
+ *
+ * Monitoring provides a feature to check the presence of a resource,
+ * even when the server is not announcing Presence using startPresnece.
+ *
+ * @param stateChangedListener - Listener to obtain the changed resource state
+ *
+ * @throws RCSException If monitoring is already started.
+ *
+ * @note The callback will be invoked in an internal thread.
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeStartMonitoring
+(JNIEnv *env, jobject interfaceClass, jobject stateChangedListener);
+
+/**
+ * Stops monitoring the resource.
+ *
+ * It does nothing if monitoring is not started.
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeStopMonitoring
+(JNIEnv *env, jobject interfaceClass);
+
+/**
+ * Returns the current state of the resource.
+ *
+ */
+JNIEXPORT jint JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetState
+(JNIEnv *env, jobject interfaceClass);
+
+/**
+ * Starts caching attributes of the resource.
+ *
+ * This will start data caching for the resource.
+ * Once caching started it will look for the data updation on the resource.
+ * If this method is called with null listener it will not notify the updated value to caller.
+ * It it is called with a valid listener updated cached values will be notified to caller.
+ *
+ * @param cacheUpdateListener - Listener to obtain the updated cached data
+ *
+ * @throws RCSException If Caching is already started
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeStartCaching
+(JNIEnv *env, jobject interfaceClass, jobject cacheUpdateListener);
+
+/**
+ * Stops caching.
+ *
+ * It does nothing if caching is not started.
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeStopCaching
+(JNIEnv *env, jobject interfaceClass);
+
+/**
+ * Returns the current cache state.
+ *
+ */
+JNIEXPORT jint JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetCacheState
+(JNIEnv *env, jobject interfaceClass);
+
+/**
+ * Returns whether cached data is available.
+ *
+ * Cache will be available always after CacheState::READY even if current state is
+ * LOST_SIGNAL.
+ *
+ */
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeIsCachedAvailable
+(JNIEnv *env, jobject interfaceClass);
+
+/**
+ * Gets the cached RCSResourceAttributes data.
+ *
+ * @pre Cache should be available.
+ *
+ * @return The cached attributes.
+ *
+ * @throws RCSException If the precondition is not fulfilled.
+ *
+ */
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetCachedAttributes
+(JNIEnv *env, jobject interfaceClass);
+
+/**
+ * Gets a particular cached a ResourceAttribute Value.
+ *
+ * @pre Cache should be available.
+ *
+ * @param key - Attribute Key
+ *
+ * @return Requested attribute value.
+ *
+ * @throws RCSException If the precondition is not fulfilled or key doesn't match the key of any value.
+ *
+ */
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetCachedAttribute
+(JNIEnv *env, jobject interfaceClass, jstring key);
+
+/**
+ * Gets resource attributes directly from the server.
+ *
+ * This API send a get request to the resource of interest and provides
+ * the attributes to the caller in the RemoteAttributesReceivedCallback.
+ *
+ * @param resourceAttributesListener - Listener to get the resource attributes
+ *
+ * @note The callback will be invoked in an internal thread.
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetRemoteAttributes
+(JNIEnv *env, jobject interfaceClass, jobject resourceAttributesListener);
+
+/**
+ * Sends a set request with resource attributes to the server.
+ *
+ * The SetRequest behavior depends on the server, whether updating its attributes or not.
+ *
+ * @param resourceAttributes - Attributes to set
+ * @param resourceAttributesListener - Listener to obtain the updated cached data
+ *
+ * @note The callback will be invoked in an internal thread.
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeSetRemoteAttributes
+(JNIEnv *env, jobject interfaceClass, jobject resourceAttributes,
+ jobject resourceAttributesListener);
+
+/**
+ * Returns the uri of the resource.
+ *
+ */
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetUri
+(JNIEnv *env, jobject interfaceClass);
+
+/**
+ * Returns the address of the resource .
+ *
+ */
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetAddress
+(JNIEnv *env, jobject interfaceClass);
+
+/**
+ * Returns the resource types of the resource.
+ *
+ */
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetTypes
+(JNIEnv *env, jobject interfaceClass);
+
+/**
+ * Returns the resource interfaces of the resource.
+ *
+ */
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetInterFaces
+(JNIEnv *env, jobject interfaceClass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // _JNI_RE_RCS_REMOTE_RESOURCE_OBJECT_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_rcs_resource_container.h
+ *
+ * @brief This file contains the declaration of RCSResourceContainer
+ * APIs for JNI implementation
+ */
+
+#ifndef __JNI_RE_RCS_RESOURCE_CONTAINER_H_
+#define __JNI_RE_RCS_RESOURCE_CONTAINER_H_
+
+#include <jni.h>
+
+#include "jni_re_jvm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * API for starting the Container
+ *
+ * @details This API start the container with the provided Configuration file.
+ *
+ * @param configFile - configuration File that contains the Bundle/Bundles information.
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeStartContainer
+(JNIEnv *env, jobject jObject, jstring configFile);
+
+
+/**
+* API for stopping the Container
+*/
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeStopContainer
+(JNIEnv *env, jobject jObject);
+
+/**
+ * API for adding the bundle to the Container
+ *
+ * @param bundleId - Id of the Bundle
+ * @param bundleUri - Uri of the bundle
+ * @param bundlePath - Path of the bundle
+ * @param params - key-value pairs in string form for other Bundle parameters
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeAddBundle
+(JNIEnv *env, jobject jObject, jstring bundleId, jstring bundleUri, jstring bundlePath,
+ jobject params);
+
+
+/**
+* API for getting the list of all bundles in the container
+*
+* @return jobject -List of BundleInfo pointer each associated with a bundle
+*
+*/
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeListBundles
+(JNIEnv *env, jobject jObject);
+
+/**
+ * API for removing the bundle from the container
+ *
+ * @param bundleId - Id of the Bundle
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeRemoveBundle
+(JNIEnv *env, jobject jObject, jstring bundleId);
+
+/**
+ * API for starting the bundle.
+ *
+ * @param bundleId - Id of the Bundle
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeStartBundle
+(JNIEnv *env, jobject jObject, jstring bundleId);
+
+/**
+* API for Stopping the bundle
+*
+* @param bundleId - Id of the Bundle
+*
+*/
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeStopBundle
+(JNIEnv *env, jobject jObject, jstring bundleId);
+
+/**
+* API for adding the Resource configuration information to the bundle
+*
+* @param bundleId - Id of the Bundle
+* @param resourceUri - URI of the resource
+* @param params - key-value pairs in string form for other Bundle parameters
+*
+*/
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeAddResourceConfig
+(JNIEnv *env, jobject jObject, jstring bundleId, jstring resourceUri, jobject params);
+
+/**
+* API for removing the Resource configuration information from the bundle
+*
+* @param bundleId - Id of the Bundle
+* @param resourceUri - URI of the resource
+*
+*/
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeRemoveResourceConfig
+(JNIEnv *env, jobject jObject, jstring bundleId, jstring resourceUri);
+
+/**
+* API for getting the list of Bundle Resources
+*
+* @param bundleId - Id of the Bundle
+*
+*/
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeListBundleResources
+(JNIEnv *env, jobject jObject, jstring bundleId);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__JNI_RE_RCS_RESOURCE_CONTAINER_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_resource_attributes.h
+ *
+ * @brief This file contains the declaration of Resource Attribute APIs
+ * for JNI implementation
+ */
+
+#ifndef __JNI_RE_RCS_RESOURCE_ATTRIBUTES_H_
+#define __JNI_RE_RCS_RESOURCE_ATTRIBUTES_H_
+
+#include "jni_re_jvm.h"
+#include "jni_re_utils.h"
+
+#include <RCSResourceAttributes.h>
+
+#define JNI_EXCEPTION 1000
+#define JNI_NO_NATIVE_POINTER 1001
+#define JNI_INVALID_VALUE 1002
+#define JNI_NO_SUCH_KEY 1003
+
+struct NullType {};
+
+/**
+ * @class JniResourceAttributes
+ * @brief This class provides the API for getting the RCSResourceAttribute pointer
+ *
+ */
+class JniResourceAttributes
+{
+ public:
+ /**
+ * @brief Get the ResourceAttibute pointer
+ * internally get the native handle by calling REGetHandle
+ */
+ static RCSResourceAttributes *getResourceAttributePtr(JNIEnv *env, jobject thiz);
+};
+
+/**
+ * @brief Utility structure for jobject conversion
+ */
+struct JObjectConverter : boost::static_visitor < jobject >
+{
+ JObjectConverter(JNIEnv *env) : env(env) {}
+
+ jobject operator()(const NullType &) const { return nullptr; }
+ jobject operator()(const int &val) const
+ {
+ jobject jobj = env->NewObject(
+ g_cls_Integer,
+ g_mid_Integer_ctor,
+ static_cast<jint>(val));
+ return jobj;
+ }
+ jobject operator()(const double &val) const
+ {
+ jobject jobj = env->NewObject(
+ g_cls_Double,
+ g_mid_Double_ctor,
+ static_cast<jdouble>(val));
+ return jobj;
+ }
+ jobject operator()(const bool &val) const
+ {
+ jobject jobj = env->NewObject(
+ g_cls_Boolean,
+ g_mid_Boolean_ctor,
+ static_cast<jboolean>(val));
+ return jobj;
+ }
+ jobject operator()(const std::string &val) const
+ {
+ jstring jstr = env->NewStringUTF(val.c_str());
+ return static_cast<jobject>(jstr);
+ }
+ private:
+ JNIEnv *env;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * API for getting attribute value corresponding the requested Key
+ *
+ * @param key - Attribute key
+ *
+ */
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeGetValueN
+(JNIEnv *env, jobject interfaceObject, jstring key);
+
+/**
+ * API for setting integer value for attribute
+ *
+ * @param key - Attribute key
+ * @param value - Attribute value
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeSetValueInteger
+(JNIEnv *env, jobject interfaceObject, jstring key, jint value);
+
+/**
+ * API for setting Double value for attribute
+ *
+ * @param key - Attribute key
+ * @param value - Attribute value
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeSetValueDouble
+(JNIEnv *env, jobject interfaceObject, jstring key, jdouble value);
+
+/**
+ * API for setting Boolean value for attribute
+ *
+ * @param key - Attribute key
+ * @param value - Attribute value
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeSetValueBoolean
+(JNIEnv *env, jobject interfaceObject, jstring key, jboolean value);
+
+/**
+ * API for setting String value for attribute
+ *
+ * @param Key - Attribute key
+ * @param value - Attribute value
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeSetValueString
+(JNIEnv *env, jobject interfaceObject, jstring key, jstring value);
+
+/**
+ * API for setting IntegerArray for attribute
+ *
+ * @param key - Attribute key
+ * @param value - Attribute value
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeSetValueIntegerArray
+(JNIEnv *env, jobject interfaceObject, jstring key, jintArray value);
+
+/**
+ * API for checking whether attribute is empty or not
+ *
+ * @return jBoolean - boolean value (true/false)
+ *
+ */
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeIsEmpty
+(JNIEnv *env, jobject interfaceObject);
+
+/**
+ * API for getting the size of the attributes
+ *
+ * @return jint - size of attributes
+ *
+ */
+JNIEXPORT jint JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeSize
+(JNIEnv *env, jobject interfaceObject);
+
+/**
+ * API for removing a particular attribute
+ *
+ * @param key - Attribute key
+ *
+ * @return jBoolean - boolean value (true/false)
+ *
+ * NOTE: If requested attribute is successfully removed it will return true otherwise false
+ */
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeRemove
+(JNIEnv *env, jobject interfaceObject, jstring key);
+
+/**
+ * API for checking a particular attribute
+ *
+ * @param key - Attribute key
+ *
+ * @return jBoolean - boolean value (true/false)
+ *
+ * NOTE: If requested attribute is present it will return true otherwise false
+ */
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeHasAttribute
+(JNIEnv *env, jobject interfaceObject, jstring key);
+
+/**
+ * @brief API for creating a new RCSResourceAttributes object and setting of Native handle
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_create
+(JNIEnv *env, jobject interfaceObject);
+
+/**
+ * @brief API for deleting the RCSResourceAttributes object
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_dispose
+(JNIEnv *env, jobject interfaceObject, jboolean jNeedsDelete);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__JNI_RE_RCS_RESOURCE_ATTRIBUTES_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file jni_re_resource_builder.h
+ *
+ * @brief This file contains the resource builder function
+ * for JNI implementation
+ */
+
+#ifndef __JNI_RE_RESOURCEBUILDER_H
+#define __JNI_RE_RESOURCEBUILDER_H
+
+#include <jni.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * API for constructing a new RCSResourceObject.
+ *
+ *
+ * @param resourceURI Resource URI value to be set
+ * @param resourceType Resource type value to be set
+ * @param resourceInterface Interface value to be set
+ * @param observableFlag Whether resource should be observable or not.
+ * @param discovervableFlag Whether resource should be discovervable or not.
+ * @param attributes Attributes to be set
+ *
+ * @return RCSResourceObject object (It is the resource that is created)
+ *
+ * @throw RCSException
+ * It catches exception from registerResource API of OCPlatform and
+ * throws it to developer.
+ */
+JNIEXPORT jobject JNICALL Java_org_iotivity_ResourceEncapsulation_server_Builder_nativeBuild
+(JNIEnv *env, jobject interfaceObject, jstring resourceURI, jstring resourceType,
+ jstring resourceInterface,
+ jboolean observableFlag, jboolean discovervableFlag, jobject attributes);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__JNI_RE_RESOURCEBUILDER_H
+
+
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_resource_object.h
+ *
+ * @brief This file contains the JniResourceObject class
+ * & declaration of RCSRemoteResourceObject APIs for JNI implementation
+ */
+
+#ifndef __JNI_RE_RCS_RESOURCE_OBJECT
+#define __JNI_RE_RCS_RESOURCE_OBJECT
+
+#include <jni.h>
+
+#include "jni_re_jvm.h"
+#include "RCSResourceObject.h"
+#include "jni_re_utils.h"
+#include "jni_re_get_request_listener.h"
+#include "jni_re_set_request_listener.h"
+#include "jni_re_attribute_updated_listener.h"
+#include "jni_re_listener_manager_server.h"
+
+using namespace OIC::Service;
+
+/**
+ * @class JniRCSResourceObject
+ * @brief This class contains all the APIs for RCSResourceObject
+ *
+ * NOTE: JNI APIs internally call the APIs of this class.
+ */
+class JniRCSResourceObject
+{
+ public:
+
+ /**
+ * @brief constructor
+ */
+ JniRCSResourceObject(std::shared_ptr<RCSResourceObject> resource);
+
+ /**
+ * @brief destructor
+ */
+ ~JniRCSResourceObject();
+
+ // ***** JNI APIs internally call the APIs of this class ***** //
+
+ void setAttributeInteger(JNIEnv *env, jobject jObject, jstring key, jint value);
+ void setAttributeDouble(JNIEnv *env, jobject jObject, jstring key, jdouble value);
+ void setAttributeBool(JNIEnv *env, jobject jObject, jstring key, jboolean value);
+ void setAttributeString(JNIEnv *env, jobject jObject, jstring key, jstring value);
+ jstring getAttributeValue(JNIEnv *env, jstring jkey);
+ bool removeAttribute(JNIEnv *env, jstring key);
+ bool containsAttribute(JNIEnv *env, jstring key);
+ jobject getAttributes(JNIEnv *env, jobject jObject);
+ bool isObservable();
+ bool isDiscoverable();
+ void setGetRequestHandler(JNIEnv *env, jobject getRequestListener);
+ void setSetRequestHandler(JNIEnv *env, jobject jSetRequestListener);
+ void addAttributeUpdatedListener(JNIEnv *env, jstring key, jobject jAttributeUpdatedListener);
+ bool removeAttributeUpdatedListener(JNIEnv *env, jobject jObject, jstring key);
+ void notify();
+ void setAutoNotifyPolicy(int policy);
+ int getAutoNotifyPolicy();
+ void setSetRequestHandlerPolicy(int policy);
+ int getSetRequestHandlerPolicy();
+
+ JniGetRequestListener *addOnGetRequestListener(JNIEnv *env, jobject jListener);
+ JniSetRequestListener *addOnSetRequestListener(JNIEnv *env, jobject jListener);
+ JniAttributeUpdatedListener *addOnAttributeUpdatedListener(JNIEnv *env, jobject jListener);
+
+ void removeOnGetRequestListener(JNIEnv *env, jobject jListener);
+ void removeOnSetRequestListener(JNIEnv *env, jobject jListener);
+ void removeOnAttributeUpdatedListener(JNIEnv *env, jobject jListener);
+
+ static JniRCSResourceObject *getJniRCSResourceObject(JNIEnv *env, jobject thiz);
+
+ private:
+
+ JniReListenerManagerServer<JniGetRequestListener> m_onGetRequest;
+ JniReListenerManagerServer<JniSetRequestListener> m_onSetRequest;
+ JniReListenerManagerServer<JniAttributeUpdatedListener> m_onAttributeUpdated;
+
+ std::shared_ptr<RCSResourceObject> m_sharedResource;
+
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief API for setting a particular attribute value as a integer
+ *
+ * @param key name of attribute(used to map the attribute value).
+ * @param value integer value to be mapped against the key.
+ *
+ * It is guaranteed thread-safety about attributes.
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetAttributeInteger
+(JNIEnv *env, jobject jObject, jstring key, jint value);
+
+/**
+ * @brief API for setting a particular attribute value as a double
+ *
+ * @param key name of attribute(used to map the attribute value).
+ * @param value Double value to be mapped against the key.
+ *
+ * It is guaranteed thread-safety about attributes.
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetAttributeDouble
+(JNIEnv *env, jobject jObject, jstring key, jdouble value);
+
+/**
+ * @brief API for setting a particular attribute value as a boolean
+ *
+ * @param key name of attribute(used to map the attribute value).
+ * @param value boolean value to be mapped against the key.
+ *
+ * It is guaranteed thread-safety about attributes.
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetAttributeBool
+(JNIEnv *env, jobject jObject, jstring key, jboolean value);
+
+/**
+ * @brief API for setting a particular attribute value as a String
+ *
+ * @param key name of attribute(used to map the attribute value).
+ * @param value String value to be mapped against the key.
+ *
+ * It is guaranteed thread-safety about attributes.
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetAttributeString
+(JNIEnv *env, jobject jObject, jstring key, jstring value);
+
+/**
+ * @brief API for retrieving the attribute value associated with the supplied key.
+ *
+ * @param key Name of the attribute
+ *
+ * @return resource attributes value as a string
+ *
+ * It is guaranteed thread-safety about attributes.
+ */
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeGetAttributeValue
+(JNIEnv *env, jobject jObject, jstring key);
+
+/**
+ * @brief API for removing a particular attribute of the resource.
+ *
+ * @param key Name of the attribute.
+ *
+ * @return If the key exist and matched attribute is deleted, return true.
+ *
+ * It is guaranteed thread-safety about attributes.
+ */
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeRemoveAttribute
+(JNIEnv *env, jobject jObject, jstring key);
+
+/**
+ * @brief API for checking whether a particular attribute is there for a resource or not.
+ *
+ * @param key Name of the attribute.
+ *
+ * @return If the key exist, return true.
+ *
+ * It is guaranteed thread-safety about attributes.
+ */
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeContainsAttribute
+(JNIEnv *env, jobject jObject, jstring key);
+
+
+/**
+ * @brief API for getting all the attributes of the RCSResourceObject.
+ *
+ * @return RCSResourceAttributes
+ *
+ * @see RCSResourceAttributes
+ */
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeGetAttributes
+(JNIEnv *env, jobject jObject);
+
+/**
+* @brief API for checking whether the particular resource is observable or not
+*/
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeIsObservable
+(JNIEnv *env, jobject jObject);
+
+/**
+* @brief API for checking whether the particular resource is discoverable or not
+*/
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeIsDiscoverable
+(JNIEnv *env, jobject jObject);
+
+/**
+ * API for setting the resource's get request handler by the developer/application.
+ * If developer set this handler then all get request will come to the application &
+ * developer can send the response to the client using APIs of RCSGetResponse class.
+ *
+ * @param jGetRequestListener Request handler for get requests
+ *
+ * @see RCSGetResponse
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetGetRequestHandler
+(JNIEnv *env, jobject jObject, jobject jGetRequestListener);
+
+/**
+ * API for setting the resource's set request handler by the developer/application.
+ * If developer set this handler then all set request for the resource
+ * will come to the application & developer can send the response to the client
+ * using APIs of RCSSetResponse class.
+ *
+ * @param jSetRequestListener Request handler for set requests
+ *
+ * @see RCSSetResponse
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetSetRequestHandler
+(JNIEnv *env, jobject jObject, jobject jSetRequestListener);
+
+/**
+ * API for setting the Listener for a particular attribute update.
+ *
+ * @param key The interested attribute's key
+ * @param jAttributeUpdatedListener Listener for updation of the interested attribute
+ *
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeAddAttributeUpdatedListener
+(JNIEnv *env, jobject jObject, jstring key, jobject jAttributeUpdatedListener);
+
+/**
+* API for removing the handler for a particular attribute update.
+*
+* @param key The interested attribute's key
+*
+*/
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeRemoveAttributeUpdatedListener
+(JNIEnv *env, jobject jObject, jstring key);
+
+/**
+ * API for notifying all observers of the RCSResourceObject
+ * with the updated attributes value
+ */
+JNIEXPORT void JNICALL Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeNotify
+(JNIEnv *env, jobject jObject);
+
+/**
+* API for setting Auto notify policy
+*
+* @param policy policy to be set (Its datatype is jint we will convert it to AutoNotifyPolicy enum value using jni_re_utils)
+*
+* @see AutoNotifyPolicy
+* @see jni_re_utils
+*
+*/
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetAutoNotifyPolicy
+(JNIEnv *env, jobject jObject, jint policy);
+
+/**
+* API for getting auto notify policy
+*
+* @returns jint AntoNotify policy as a integer in java it will be converted to AutoNotifyPolicy enum.
+*
+* @see AutoNotifyPolicy
+*
+*/
+JNIEXPORT jint JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeGetAutoNotifyPolicy
+(JNIEnv *env, jobject jObject);
+
+/**
+* API for setting the policy for a setRequestHandler.
+*
+* @param policy policy to be set (Its datatype is jint we will convert it to SetRequestHandlerPolicy enum value using jni_re_utils)
+*
+* @see SetRequestHandlerPolicy
+* @see jni_re_utils
+*
+*/
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetSetRequestHandlerPolicy
+(JNIEnv *env, jobject jObject, jint policy);
+
+/**
+* API for getting the SetRequestHandler Policy.
+*
+* @returns jint SetRequestHandlerPolicy policy as a integer in java it will be converted to SetRequestHandlerPolicy enum.
+*
+* @see SetRequestHandlerPolicy
+*
+*/
+JNIEXPORT jint JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeGetSetRequestHandlerPolicy
+(JNIEnv *env, jobject jObject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+/** @file jni_re_resource_statechange_listener.h
+ *
+ * @brief This file contains JNI resource state change Listener class
+ */
+
+#ifndef __JNI_RE_RESOURCE_STATE_CHANGE_LISTENER_H_
+#define __JNI_RE_RESOURCE_STATE_CHANGE_LISTENER_H_
+
+#include <jni.h>
+
+#include "RCSRemoteResourceObject.h"
+
+#include "jni_re_jvm.h"
+#include "jni_re_utils.h"
+
+class JniRCSRemoteResourceObject;
+
+/**
+ * @class JniResourceStateChangeListener
+ * @brief This class provides functions for handling the Resource state change callback between the Java and native layer
+ *
+ */
+class JniResourceStateChangeListener
+{
+ public:
+ /**
+ * @brief constructor
+ */
+ JniResourceStateChangeListener(JNIEnv *env, jobject jListener,
+ JniRCSRemoteResourceObject *resource);
+
+ /**
+ * @brief destructor
+ */
+ ~JniResourceStateChangeListener();
+
+ /**
+ * @brief callback function that will be passed to Native layer
+ */
+ void stateChangeCallback(OIC::Service::ResourceState state);
+
+ private:
+ jweak m_jwListener;
+ JniRCSRemoteResourceObject *m_ownerResource;
+ void checkExAndRemoveListener(JNIEnv *env);
+};
+
+#endif //__JNI_RE_RESOURCE_STATE_CHANGE_LISTENER_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_set_request_listener.h
+ *
+ * @brief This file contains JNI set request Listener class
+ */
+
+#ifndef __JNI_RE_SET_REQUEST_LISTENER_H_
+#define __JNI_RE_SET_REQUEST_LISTENER_H_
+
+#include <jni.h>
+
+#include "jni_re_jvm.h"
+#include "jni_re_utils.h"
+#include "jni_re_resource_attributes.h"
+
+
+class JniRCSResourceObject;
+
+/**
+ * @class JniSetRequestListener
+ * @brief This class provides functions for handling the set request callback between the Java and Native layer
+ *
+ */
+class JniSetRequestListener
+{
+ public:
+ /**
+ * @brief constructor
+ */
+ JniSetRequestListener(JNIEnv *env, jobject jListener,
+ JniRCSResourceObject *resource);
+
+ /**
+ * @brief destructor
+ */
+ ~JniSetRequestListener();
+
+ /**
+ * @brief callback function that will be passed to Native layer
+ */
+ OIC::Service::RCSSetResponse onSetRequestCallback(OIC::Service::RCSRequest request,
+ OIC::Service::RCSResourceAttributes attributes);
+
+ private:
+ jweak m_jwListener;
+ JniRCSResourceObject *m_ownerResource;
+ void checkExAndRemoveListener(JNIEnv *env);
+};
+
+#endif //__JNI_RE_SET_REQUEST_LISTENER_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/** @file jni_re_setattributes_listener.h
+ *
+ * @brief This file contains JNI set attributes Listener class
+ */
+
+#ifndef __JNI_RE_SET_ATTRIBUTES_LISTENER_H_
+#define __JNI_RE_SET_ATTRIBUTES_LISTENER_H_
+
+#include <jni.h>
+
+#include "jni_re_jvm.h"
+#include "jni_re_utils.h"
+#include "jni_re_resource_attributes.h"
+
+class JniRCSRemoteResourceObject;
+
+/**
+ * @class JniSetAttributesListener
+ * @brief This class provides functions for handling the set attribute callback between the Java and native layer
+ *
+ */
+class JniSetAttributesListener
+{
+ public:
+ /**
+ * @brief constructor
+ */
+ JniSetAttributesListener(JNIEnv *env, jobject jListener,
+ JniRCSRemoteResourceObject *resource);
+
+ /**
+ * @brief destructor
+ */
+ ~JniSetAttributesListener();
+
+ /**
+ * @brief callback function that will be passed to Native layer
+ */
+ void onRemoteAttributesSetCallback(OIC::Service::RCSResourceAttributes attributes);
+
+ private:
+ jweak m_jwListener;
+ JniRCSRemoteResourceObject *m_ownerResource;
+ void checkExAndRemoveListener(JNIEnv *env);
+};
+
+#endif //__JNI_RE_SET_ATTRIBUTES_LISTENER_H_
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_attribute_updated_listener.h"
+#include "jni_re_resource_object.h"
+
+JniAttributeUpdatedListener::JniAttributeUpdatedListener(JNIEnv *env, jobject jListener,
+ JniRCSResourceObject *owner)
+ : m_ownerResource(owner)
+{
+ m_jwListener = env->NewWeakGlobalRef(jListener);
+}
+
+JniAttributeUpdatedListener::~JniAttributeUpdatedListener()
+{
+ LOGI("JniAttributeUpdatedListener::~JniAttributeUpdatedListener()");
+ if (m_jwListener)
+ {
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+ env->DeleteWeakGlobalRef(m_jwListener);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ }
+}
+
+void JniAttributeUpdatedListener::onAttributeUpdatedCallback(
+ OIC::Service::RCSResourceAttributes::Value oldValue,
+ OIC::Service::RCSResourceAttributes::Value newValue)
+{
+ LOGI("JniAttributeUpdatedListener::onAttributeUpdatedCallback got a callback in JNI");
+
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+
+ jobject jListener = env->NewLocalRef(m_jwListener);
+ if (!jListener)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ RCSResourceAttributes::TypeId oldValueTypeId = oldValue.getType().getId();
+ RCSResourceAttributes::TypeId newValueTypeId = newValue.getType().getId();
+ jstring javaOldValue;
+ jstring javaNewValue;
+ char buf[64]; // assumed large enough to cope with result
+ char bufValue[64];
+
+ if (oldValueTypeId == RCSResourceAttributes::TypeId::INT)
+ {
+ int oldVal = oldValue.get<int>();
+ sprintf(buf, "%d", oldVal);
+ javaOldValue = (env)->NewStringUTF(buf);
+
+ int newVal = newValue.get<int>();
+ sprintf(bufValue, "%d", newVal);
+ javaNewValue = (env)->NewStringUTF(bufValue);
+
+ }
+ else if (oldValueTypeId == RCSResourceAttributes::TypeId::DOUBLE)
+ {
+ double oldVal = oldValue.get<double>();
+ sprintf(buf, "%f", oldVal);
+ javaOldValue = (env)->NewStringUTF(buf);
+
+ double newVal = newValue.get<double>();
+ sprintf(bufValue, "%f", newVal);
+ javaNewValue = (env)->NewStringUTF(bufValue);
+
+ }
+ else if (oldValueTypeId == RCSResourceAttributes::TypeId::BOOL)
+ {
+ bool oldVal = oldValue.get<bool>();
+ sprintf(buf, "%d", oldVal);
+ javaOldValue = (env)->NewStringUTF(buf);
+
+ bool newVal = newValue.get<bool>();
+ sprintf(bufValue, "%d", newVal);
+ javaNewValue = (env)->NewStringUTF(bufValue);
+ }
+ else if (oldValueTypeId == RCSResourceAttributes::TypeId::STRING)
+ {
+ std::string oldVal = oldValue.get<std::string>();
+ javaOldValue = env->NewStringUTF(oldVal.c_str());
+
+ std::string newVal = newValue.get<std::string>();
+ javaNewValue = env->NewStringUTF(newVal.c_str());
+ }
+
+ //sending callback to application
+ jclass clsL = env->GetObjectClass(jListener);
+
+ if (!clsL)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ jmethodID midL = env->GetMethodID(clsL, "onAttributeUpdate",
+ "(Ljava/lang/String;Ljava/lang/String;)V");
+ if (!midL)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+ env->CallVoidMethod(jListener, midL, javaOldValue, javaNewValue);
+ if (env->ExceptionCheck())
+ {
+ LOGE("Java exception is thrown");
+ }
+
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGI("JniDiscoverResourceListener::cacheUpdatedCallback exit");
+
+}
+
+void JniAttributeUpdatedListener::checkExAndRemoveListener(JNIEnv *env)
+{
+ if (env->ExceptionCheck())
+ {
+ jthrowable ex = env->ExceptionOccurred();
+ env->ExceptionClear();
+ m_ownerResource->removeOnSetRequestListener(env, m_jwListener);
+ env->Throw((jthrowable)ex);
+ }
+ else
+ {
+ m_ownerResource->removeOnSetRequestListener(env, m_jwListener);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_discover_resource_listener.h"
+#include "RCSRemoteResourceObject.h"
+#include "jni_re_cache_update_listener.h"
+
+JniCacheUpdateListener::JniCacheUpdateListener(JNIEnv *env, jobject jListener,
+ JniRCSRemoteResourceObject *owner)
+ : m_ownerResource(owner)
+{
+ m_jwListener = env->NewWeakGlobalRef(jListener);
+}
+
+JniCacheUpdateListener::~JniCacheUpdateListener()
+{
+ LOGI("JniCacheUpdateListener::~JniCacheUpdateListener");
+ if (m_jwListener)
+ {
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+ env->DeleteWeakGlobalRef(m_jwListener);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ }
+}
+
+void JniCacheUpdateListener::cacheUpdatedCallback(OIC::Service::RCSResourceAttributes attributes)
+{
+ LOGI("JniDiscoverResourceListener::cacheUpdatedCallback enter");
+
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+
+ jobject jListener = env->NewLocalRef(m_jwListener);
+ if (!jListener)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ jclass clsL = env->GetObjectClass(jListener);
+
+ if (!clsL)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ RCSResourceAttributes *attributesObj = new RCSResourceAttributes(attributes);
+ jlong handle = reinterpret_cast<jlong>(attributesObj);
+ jobject jAttributes = env->NewObject(g_cls_RCSRemoteResourceAttributesObject,
+ g_mid_RCSRemoteResourceAttributesObject_ctor,
+ handle, true);
+ if (!jAttributes)
+ {
+ delete attributesObj;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ jmethodID midL = env->GetMethodID(clsL, "onCacheUpdatedCallback",
+ "(Lorg/iotivity/ResourceEncapsulation/common/RCSResourceAttributes;)V");
+
+ if (!midL)
+ {
+ delete attributesObj;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+ env->CallVoidMethod(jListener, midL, jAttributes);
+ if (env->ExceptionCheck())
+ {
+ LOGE("Java exception is thrown");
+ delete attributesObj;
+ }
+
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGI("JniDiscoverResourceListener::cacheUpdatedCallback exit");
+}
+
+void JniCacheUpdateListener::checkExAndRemoveListener(JNIEnv *env)
+{
+ if (env->ExceptionCheck())
+ {
+ jthrowable ex = env->ExceptionOccurred();
+ env->ExceptionClear();
+ m_ownerResource->removeCacheUpdateListener(env, m_jwListener);
+ env->Throw((jthrowable)ex);
+ }
+ else
+ {
+ m_ownerResource->removeCacheUpdateListener(env, m_jwListener);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "RCSRemoteResourceObject.h"
+
+#include "jni_re_discover_resource_listener.h"
+
+JniDiscoverResourceListener::JniDiscoverResourceListener(JNIEnv *env, jobject jListener,
+ RemoveListenerCallback removeListenerCallback)
+{
+ m_jwListener = env->NewWeakGlobalRef(jListener);
+ m_removeListenerCallback = removeListenerCallback;
+}
+
+JniDiscoverResourceListener::~JniDiscoverResourceListener()
+{
+ LOGI("JniDiscoverResourceListener::~jni_DiscoverResourceListener()");
+ if (m_jwListener)
+ {
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+ env->DeleteWeakGlobalRef(m_jwListener);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ }
+}
+
+void JniDiscoverResourceListener::discoverResourceCallback(
+ std::shared_ptr<OIC::Service::RCSRemoteResourceObject> resource)
+{
+ LOGI("JniDiscoverResourceListener::discoverResourceCallback enter");
+
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+
+ jobject jListener = env->NewLocalRef(m_jwListener);
+ if (!jListener)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ jobject jResource = env->NewObject(g_cls_RCSRemoteResourceObject,
+ g_mid_RCSRemoteResourceObject_ctor);
+ if (!jResource)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ JniRCSRemoteResourceObject *jniRCSRemoteResourceObject = new JniRCSRemoteResourceObject(resource);
+ RESetHandle<JniRCSRemoteResourceObject>(env, jResource, jniRCSRemoteResourceObject);
+ if (env->ExceptionCheck())
+ {
+ delete jniRCSRemoteResourceObject;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ jclass clsL = env->GetObjectClass(jListener);
+ if (!clsL)
+ {
+ delete jniRCSRemoteResourceObject;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+ jmethodID midL = env->GetMethodID(clsL, "onResourceDiscovered",
+ "(Lorg/iotivity/ResourceEncapsulation/client/RCSRemoteResourceObject;)V");
+ if (!midL)
+ {
+ delete jniRCSRemoteResourceObject;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+ env->CallVoidMethod(jListener, midL, jResource);
+ if (env->ExceptionCheck())
+ {
+ LOGE("Java exception is thrown");
+ delete jniRCSRemoteResourceObject;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGI("JniDiscoverResourceListener::discoverResourceCallback exit");
+}
+
+void JniDiscoverResourceListener::checkExAndRemoveListener(JNIEnv *env)
+{
+ if (env->ExceptionCheck())
+ {
+ jthrowable ex = env->ExceptionOccurred();
+ env->ExceptionClear();
+ m_removeListenerCallback(env, m_jwListener);
+ env->Throw((jthrowable)ex);
+ }
+ else
+ {
+ m_removeListenerCallback(env, m_jwListener);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_get_request_listener.h"
+#include "jni_re_resource_object.h"
+
+JniGetRequestListener::JniGetRequestListener(JNIEnv *env, jobject jListener,
+ JniRCSResourceObject *owner)
+ : m_ownerResource(owner)
+{
+ m_jwListener = env->NewWeakGlobalRef(jListener);
+}
+
+JniGetRequestListener::~JniGetRequestListener()
+{
+ LOGI("JniGetRequestListener::~JniGetRequestListener()");
+ if (m_jwListener)
+ {
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+ env->DeleteWeakGlobalRef(m_jwListener);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ }
+}
+
+OIC::Service::RCSGetResponse JniGetRequestListener::onGetRequestCallback(
+ OIC::Service::RCSRequest request, OIC::Service::RCSResourceAttributes attributes)
+{
+ LOGI("JniGetRequestListener::onGetRequestCallback enter");
+
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env)
+ LOGE("env is NULL");
+
+ jobject jListener = env->NewLocalRef(m_jwListener);
+ if (!jListener)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGE("jListener is NULL");
+ }
+
+ jclass clsL = env->GetObjectClass(jListener);
+
+ if (!clsL)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGE("clsL is NULL");
+ }
+
+ //constructing java attribute object
+ RCSResourceAttributes *attributesObj = new RCSResourceAttributes(attributes);
+ jlong handle = reinterpret_cast<jlong>(attributesObj);
+ jobject jAttributes = env->NewObject(g_cls_RCSRemoteResourceAttributesObject,
+ g_mid_RCSRemoteResourceAttributesObject_ctor,
+ handle, true);
+ if (!jAttributes)
+ {
+ delete attributesObj;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGI("onGetRequestCallback: jAttributes == null");
+ }
+
+ //constructing java RCSRequest object
+ std::string resourceUri = request.getResourceUri();
+ jstring javaUri = env->NewStringUTF(resourceUri.c_str());
+
+ g_mid_RCSRequest_ctor = env->GetMethodID(g_cls_RCSRequest, "<init>", "(Ljava/lang/String;)V");
+ jobject javaRCSRequestObject = env->NewObject( g_cls_RCSRequest, g_mid_RCSRequest_ctor, javaUri);
+
+ //getting the method ID
+
+ jmethodID midL = env->GetMethodID(clsL, "onGetRequest",
+ "(Lorg/iotivity/ResourceEncapsulation/server/RCSRequest;Lorg/iotivity/ResourceEncapsulation/common/RCSResourceAttributes;)Lorg/iotivity/ResourceEncapsulation/server/RCSGetResponse;");
+
+ if (!midL)
+ {
+ delete attributesObj;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGE(" midL is null");
+ }
+
+ //calling the Java method
+ jobject javaGetResponse = env->CallObjectMethod(jListener, midL, javaRCSRequestObject, jAttributes);
+
+ //getting the information related to Response
+ jclass GetResponseClass = env->GetObjectClass(javaGetResponse);
+
+ jmethodID midGetTypeOfGetResponse = env->GetMethodID(GetResponseClass, "getTypeOfGetResponse",
+ "()I");
+ jint type = env->CallIntMethod(javaGetResponse, midGetTypeOfGetResponse);
+
+ if (0 == type)
+ {
+ return OIC::Service::RCSGetResponse::defaultAction();
+ }
+ else if (1 == type)
+ {
+ LOGI("Type == 1");
+ jmethodID midGetResult = env->GetMethodID(GetResponseClass, "getResult", "()I");
+ jmethodID midGetErrorCode = env->GetMethodID(GetResponseClass, "getErrorCode", "()I");
+ jint handlerResult = env->CallIntMethod(javaGetResponse, midGetResult);
+ jint errorCode = env->CallIntMethod(javaGetResponse, midGetErrorCode);
+ OCEntityHandlerResult nativeHandlerResult = convertIntToOCEntityHandlerResult(handlerResult);
+ return OIC::Service::RCSGetResponse::create(nativeHandlerResult, errorCode);
+ }
+ else if (2 == type)
+ {
+ LOGI("Type == 2");
+ jmethodID midGetAttributes = env->GetMethodID(GetResponseClass, "getAttributes",
+ "()Lorg/iotivity/ResourceEncapsulation/common/RCSResourceAttributes;");
+ jobject attributes = env->CallObjectMethod(javaGetResponse, midGetAttributes);
+ RCSResourceAttributes *attributesObj = JniResourceAttributes::getResourceAttributePtr(env,
+ attributes);
+ return OIC::Service::RCSGetResponse::create(*attributesObj);
+ }
+ else if (3 == type)
+ {
+ LOGI("Type == 3");
+ jmethodID midGetResult = env->GetMethodID(GetResponseClass, "getResult", "()I");
+ jmethodID midGetErrorCode = env->GetMethodID(GetResponseClass, "getErrorCode", "()I");
+ jint handlerResult = env->CallIntMethod(javaGetResponse, midGetResult);
+ jint errorCode = env->CallIntMethod(javaGetResponse, midGetErrorCode);
+ OCEntityHandlerResult nativeHandlerResult = convertIntToOCEntityHandlerResult(handlerResult);
+ jmethodID midGetAttributes = env->GetMethodID(GetResponseClass, "getAttributes",
+ "()Lorg/iotivity/ResourceEncapsulation/common/RCSResourceAttributes;");
+ jobject attributes = env->CallObjectMethod(javaGetResponse, midGetAttributes);
+ RCSResourceAttributes *attributesObj = JniResourceAttributes::getResourceAttributePtr(env,
+ attributes);
+ return OIC::Service::RCSGetResponse::create(*attributesObj, nativeHandlerResult, errorCode);
+ }
+ else
+ {
+ LOGI("defaultAction");
+ return OIC::Service::RCSGetResponse::defaultAction();
+ }
+
+ if (env->ExceptionCheck())
+ {
+ LOGE("Java exception is thrown");
+ delete attributesObj;
+ }
+
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGI("JniGetRequestListener::onGetRequestCallback exit");
+}
+
+void JniGetRequestListener::checkExAndRemoveListener(JNIEnv *env)
+{
+ if (env->ExceptionCheck())
+ {
+ jthrowable ex = env->ExceptionOccurred();
+ env->ExceptionClear();
+ m_ownerResource->removeOnGetRequestListener(env, m_jwListener);
+ env->Throw((jthrowable)ex);
+ }
+ else
+ {
+ m_ownerResource->removeOnGetRequestListener(env, m_jwListener);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_getattributes_listener.h"
+#include "jni_re_rcs_remoteresourceobject.h"
+
+JniGetAttributesListener::JniGetAttributesListener(JNIEnv *env, jobject jListener,
+ JniRCSRemoteResourceObject *owner)
+ : m_ownerResource(owner)
+{
+ m_jwListener = env->NewWeakGlobalRef(jListener);
+}
+
+JniGetAttributesListener::~JniGetAttributesListener()
+{
+ LOGI("JniGetAttributesListener::~JniGetAttributesListener()");
+ if (m_jwListener)
+ {
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+ env->DeleteWeakGlobalRef(m_jwListener);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ }
+}
+
+void JniGetAttributesListener::onRemoteAttributesGetCallback(OIC::Service::RCSResourceAttributes
+ attributes)
+{
+ LOGI("JniGetAttributesListener::onRemoteAttributesGetCallback enter");
+
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+
+ jobject jListener = env->NewLocalRef(m_jwListener);
+ if (!jListener)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ jclass clsL = env->GetObjectClass(jListener);
+
+ if (!clsL)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ RCSResourceAttributes *attributesObj = new RCSResourceAttributes(attributes);
+ jlong handle = reinterpret_cast<jlong>(attributesObj);
+ jobject jAttributes = env->NewObject(g_cls_RCSRemoteResourceAttributesObject,
+ g_mid_RCSRemoteResourceAttributesObject_ctor,
+ handle, true);
+ if (!jAttributes)
+ {
+ delete attributesObj;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ jmethodID midL = env->GetMethodID(clsL, "onRemoteAttributesGetCallback",
+ "(Lorg/iotivity/ResourceEncapsulation/common/RCSResourceAttributes;)V");
+
+ if (!midL)
+ {
+ delete attributesObj;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+ env->CallVoidMethod(jListener, midL, jAttributes);
+ if (env->ExceptionCheck())
+ {
+ LOGE("Java exception is thrown");
+ delete attributesObj;
+ }
+
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGI("JniGetAttributesListener::onRemoteAttributesGetCallback exit");
+}
+
+void JniGetAttributesListener::checkExAndRemoveListener(JNIEnv *env)
+{
+ if (env->ExceptionCheck())
+ {
+ jthrowable ex = env->ExceptionOccurred();
+ env->ExceptionClear();
+ m_ownerResource->removeOngetAttributesListener(env, m_jwListener);
+ env->Throw((jthrowable)ex);
+ }
+ else
+ {
+ m_ownerResource->removeOngetAttributesListener(env, m_jwListener);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_rcs_bundle_info.h"
+#include "jni_re_jvm.h"
+#include "jni_re_utils.h"
+
+using namespace OIC::Service;
+
+RCSBundleInfo *JniBundleInfo::getRCSBundleInfoPtr(JNIEnv *env, jobject interfaceObject)
+{
+ RCSBundleInfo *rep = REGetHandle<RCSBundleInfo>(env, interfaceObject);
+ if (env->ExceptionCheck())
+ {
+ LOGE("Failed to get native handle from RCSBundleInfo");
+ }
+ if (!rep)
+ {
+ throwRCSException(env, "JNI no native pointer");
+ }
+ return rep;
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeGetID
+(JNIEnv *env, jobject jObject)
+{
+ LOGI("RCSBundleInfo_nativeGetID");
+ RCSBundleInfo *bundleInfo = JniBundleInfo::getRCSBundleInfoPtr(env, jObject);
+ std::string nativeId = bundleInfo->getID();
+ return env->NewStringUTF(nativeId.c_str());
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeGetPath
+(JNIEnv *env, jobject jObject)
+{
+ LOGI("RCSBundleInfo_nativeGetPath");
+ RCSBundleInfo *bundleInfo = JniBundleInfo::getRCSBundleInfoPtr(env, jObject);
+ std::string nativePath = bundleInfo->getPath();
+ return env->NewStringUTF(nativePath.c_str());
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeGetActivatorName
+(JNIEnv *env, jobject jObject)
+{
+ LOGI("RCSBundleInfo_nativeGetActivatorName");
+ RCSBundleInfo *bundleInfo = JniBundleInfo::getRCSBundleInfoPtr(env, jObject);
+ std::string nativeActivatorName = bundleInfo->getActivatorName();
+ return env->NewStringUTF(nativeActivatorName.c_str());
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeGetLibraryPath
+(JNIEnv *env, jobject jObject)
+{
+ LOGI("RCSBundleInfo_nativeGetLibraryPath");
+ RCSBundleInfo *bundleInfo = JniBundleInfo::getRCSBundleInfoPtr(env, jObject);
+ std::string nativeGetLibraryPath = bundleInfo->getLibraryPath();
+ return env->NewStringUTF(nativeGetLibraryPath.c_str());
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeGetVersion
+(JNIEnv *env, jobject jObject)
+{
+ LOGI("RCSBundleInfo_nativeGetVersion");
+ RCSBundleInfo *bundleInfo = JniBundleInfo::getRCSBundleInfoPtr(env, jObject);
+ std::string nativeGetVersion = bundleInfo->getVersion();
+ return env->NewStringUTF(nativeGetVersion.c_str());
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeSetID
+(JNIEnv *env, jobject jObject, jstring jId)
+{
+ LOGI("RCSBundleInfo_nativeSetID");
+ std::string id = env->GetStringUTFChars(jId, NULL);
+ RCSBundleInfo *bundleInfo = JniBundleInfo::getRCSBundleInfoPtr(env, jObject);
+ bundleInfo->setID(id);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeSetPath
+(JNIEnv *env, jobject jObject, jstring jPath)
+{
+ LOGI("RCSBundleInfo_nativeSetPath");
+ std::string path = env->GetStringUTFChars(jPath, NULL);
+ RCSBundleInfo *bundleInfo = JniBundleInfo::getRCSBundleInfoPtr(env, jObject);
+ bundleInfo->setPath(path);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeSetActivatorName
+(JNIEnv *env, jobject jObject, jstring jActivatorName)
+{
+ LOGI("RCSBundleInfo_nativeSetActivatorName");
+ std::string activatorName = env->GetStringUTFChars(jActivatorName, NULL);
+ RCSBundleInfo *bundleInfo = JniBundleInfo::getRCSBundleInfoPtr(env, jObject);
+ bundleInfo->setActivatorName(activatorName);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeSetLibraryPath
+(JNIEnv *env, jobject jObject, jstring jLibraryPath)
+{
+ LOGI("RCSBundleInfo_nativeSetLibraryPath");
+ std::string libraryPath = env->GetStringUTFChars(jLibraryPath, NULL);
+ RCSBundleInfo *bundleInfo = JniBundleInfo::getRCSBundleInfoPtr(env, jObject);
+ bundleInfo->setLibraryPath(libraryPath);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSBundleInfo_nativeSetVersion
+(JNIEnv *env, jobject jObject, jstring jVersion)
+{
+ LOGI("RCSBundleInfo_nativeSetVersion");
+ std::string version = env->GetStringUTFChars(jVersion, NULL);
+ RCSBundleInfo *bundleInfo = JniBundleInfo::getRCSBundleInfoPtr(env, jObject);
+ bundleInfo->setVersion(version);
+}
+
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_rcs_discovery_manager.h"
+
+#include "RCSDiscoveryManager.h"
+#include "RCSAddress.h"
+
+using namespace OIC::Service;
+
+JniDiscoverResourceListener *AddDiscoverResourceListener(JNIEnv *env, jobject jListener)
+{
+ JniDiscoverResourceListener *onResourceDiscovered = NULL;
+
+ discoverResourceMapLock.lock();
+
+ for (auto it = discoverResourceListenerMap.begin(); it != discoverResourceListenerMap.end(); ++it)
+ {
+ if (env->IsSameObject(jListener, it->first))
+ {
+ auto refPair = it->second;
+ onResourceDiscovered = refPair.first;
+ refPair.second++;
+ it->second = refPair;
+ discoverResourceListenerMap.insert(*it);
+ LOGD("onResourceDiscovered: ref. count incremented");
+ break;
+ }
+ }
+
+ if (!onResourceDiscovered)
+ {
+ onResourceDiscovered = new JniDiscoverResourceListener(env, jListener,
+ RemoveDiscoverResourceListener);
+ jobject jgListener = env->NewGlobalRef(jListener);
+
+ discoverResourceListenerMap.insert(std::pair < jobject, std::pair < JniDiscoverResourceListener *,
+ int >> (jgListener, std::pair<JniDiscoverResourceListener *, int>(onResourceDiscovered, 1)));
+ LOGD("onResourceDiscovered: new listener");
+ }
+ discoverResourceMapLock.unlock();
+ return onResourceDiscovered;
+}
+
+void RemoveDiscoverResourceListener(JNIEnv *env, jobject jListener)
+{
+ discoverResourceMapLock.lock();
+
+ for (auto it = discoverResourceListenerMap.begin(); it != discoverResourceListenerMap.end(); ++it)
+ {
+ if (env->IsSameObject(jListener, it->first))
+ {
+ auto refPair = it->second;
+ if (refPair.second > 1)
+ {
+ refPair.second--;
+ it->second = refPair;
+ discoverResourceListenerMap.insert(*it);
+ LOGI("OnResourceDiscoveredListener: ref. count decremented");
+ }
+ else
+ {
+ env->DeleteGlobalRef(it->first);
+ JniDiscoverResourceListener *listener = refPair.first;
+ delete listener;
+ discoverResourceListenerMap.erase(it);
+ LOGI("OnResourceDiscoveredListener removed");
+ }
+ break;
+ }
+ }
+ discoverResourceMapLock.unlock();
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSDiscoveryManager_discoverResource
+(JNIEnv *env, jclass interfaceClass, jstring jAddress, jint jTypeofDiscovery, jstring jRelativeURI,
+ jstring jresourceType, jobject jDiscoveryListener)
+{
+ LOGI("NativeInterface_discoverResource entry");
+ std::string address;
+ if (jAddress)
+ {
+ address = env->GetStringUTFChars(jAddress, NULL);
+ }
+ std::string relativeUri;
+ if (jRelativeURI)
+ {
+ relativeUri = env->GetStringUTFChars(jRelativeURI, NULL);
+ }
+ std::string resourceType;
+ if (jresourceType)
+ {
+ resourceType = env->GetStringUTFChars(jresourceType, NULL);
+ }
+
+ JniDiscoverResourceListener *onResFoundListener = AddDiscoverResourceListener(env,
+ jDiscoveryListener);
+ LOGI("NativeInterface_discoverResource onResFoundListener added");
+ RCSDiscoveryManager::ResourceDiscoveredCallback discoverCallback = [onResFoundListener](
+ std::shared_ptr< OIC::Service::RCSRemoteResourceObject> resource)
+ {
+ onResFoundListener->discoverResourceCallback(resource);
+ };
+ if ( 1 == jTypeofDiscovery )
+ {
+ RCSDiscoveryManager::getInstance()->discoverResourceByType(RCSAddress::multicast(), relativeUri,
+ resourceType, discoverCallback);
+ LOGI("NativeInterface_discoverResource multicast");
+ }
+ else if ( 0 == jTypeofDiscovery)
+ {
+ RCSDiscoveryManager::getInstance()->discoverResourceByType(RCSAddress::unicast(address),
+ relativeUri, resourceType, discoverCallback );
+ LOGI("NativeInterface_discoverResource unicast");
+ }
+
+ LOGI("NativeInterface_discoverResource exit");
+
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_rcs_remoteresourceobject.h"
+
+using namespace OIC::Service;
+JniRCSRemoteResourceObject::JniRCSRemoteResourceObject(std::shared_ptr< RCSRemoteResourceObject>
+ resource)
+ : m_sharedResource(resource)
+{}
+
+JniRCSRemoteResourceObject::~JniRCSRemoteResourceObject()
+{
+ LOGD("JniRCSRemoteResourceObject::~JniOcResource()");
+ m_sharedResource = NULL;
+
+ jint envRet;
+ JNIEnv *env = GetREJNIEnv(envRet);
+ if (NULL == env) return;
+
+ if (JNI_EDETACHED == envRet) g_jvm->DetachCurrentThread();
+}
+
+JniRCSRemoteResourceObject *JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(JNIEnv *env,
+ jobject thiz)
+{
+ JniRCSRemoteResourceObject *resource = REGetHandle<JniRCSRemoteResourceObject>(env, thiz);
+ if (env->ExceptionCheck())
+ {
+ LOGE("Failed to get native handle from RCSRemoteResourceObject");
+ }
+ if (!resource)
+ {
+ LOGE("getJniRCSRemoteResourceObject :: no resource");
+ }
+ return resource;
+}
+
+std::string JniRCSRemoteResourceObject::getUri()
+{
+ return m_sharedResource->getUri();
+}
+
+std::string JniRCSRemoteResourceObject::getAddress()
+{
+ return m_sharedResource->getAddress();
+}
+
+jobject JniRCSRemoteResourceObject::getTypes(JNIEnv *env)
+{
+ return convertStrVectorToJavaStrList( env, m_sharedResource->getTypes());
+}
+
+jobject JniRCSRemoteResourceObject::getInterfaces(JNIEnv *env)
+{
+ return convertStrVectorToJavaStrList(env, m_sharedResource->getInterfaces());
+}
+
+bool JniRCSRemoteResourceObject::isMonitoring()
+{
+ return m_sharedResource->isMonitoring();
+}
+
+bool JniRCSRemoteResourceObject::isCaching()
+{
+ return m_sharedResource->isCaching();
+}
+
+bool JniRCSRemoteResourceObject::isObservable()
+{
+ return m_sharedResource->isObservable();
+}
+
+bool JniRCSRemoteResourceObject::isCachedAvailable()
+{
+ return m_sharedResource->isCachedAvailable();
+}
+
+int JniRCSRemoteResourceObject::getState()
+{
+ ResourceState state = m_sharedResource->getState();
+ return covertResourceStateToInt(state);
+}
+
+int JniRCSRemoteResourceObject::getCacheState()
+{
+ CacheState state = m_sharedResource->getCacheState();
+ return convertCacheStateToInt(state);
+}
+
+void JniRCSRemoteResourceObject::startMonitoring(JNIEnv *env, jobject jListener)
+{
+
+ try
+ {
+ JniResourceStateChangeListener *onResourceStateChanged = addOnStateChangeListener(env, jListener);
+ RCSRemoteResourceObject::StateChangedCallback stateChangecb = [onResourceStateChanged](
+ OIC::Service::ResourceState state)
+ {
+ onResourceStateChanged->stateChangeCallback(state);
+ };
+ m_sharedResource->startMonitoring(stateChangecb);
+ }
+ catch (InvalidParameterException exception)
+ {
+ LOGE("native startMonitoring InvalidParameterException");
+ throwRCSException(env, exception.what());
+ }
+ catch (BadRequestException exception)
+ {
+ LOGE("native startMonitoring : BadRequestException ");
+ throwRCSException(env, exception.what());
+ }
+
+}
+
+void JniRCSRemoteResourceObject::stopMonitoring()
+{
+ m_sharedResource->stopMonitoring();
+}
+
+void JniRCSRemoteResourceObject::startCaching(JNIEnv *env, jobject jListener)
+{
+ JniCacheUpdateListener *onCacheUpdated = addOnCacheUpdateListener(env, jListener);
+ RCSRemoteResourceObject::CacheUpdatedCallback cacheUpdatedCallback = [onCacheUpdated](
+ OIC::Service::RCSResourceAttributes attributes)
+ {
+ onCacheUpdated->cacheUpdatedCallback(attributes);
+ };
+ try
+ {
+ m_sharedResource->startCaching(cacheUpdatedCallback);
+ }
+ catch (BadRequestException exception)
+ {
+ throwRCSException(env, exception.what());
+ }
+
+}
+
+void JniRCSRemoteResourceObject::startCaching(JNIEnv *env)
+{
+ try
+ {
+ m_sharedResource->startCaching();
+ }
+ catch (BadRequestException exception)
+ {
+ throwRCSException(env, exception.what());
+ }
+}
+
+void JniRCSRemoteResourceObject::stopCaching()
+{
+ m_sharedResource->stopCaching();
+}
+
+void JniRCSRemoteResourceObject::getRemoteAttributes(JNIEnv *env, jobject jListener)
+{
+ JniGetAttributesListener *onGetAttributes = addOngetAttributesListener(env, jListener);
+ RCSRemoteResourceObject::RemoteAttributesGetCallback getArributescb = [onGetAttributes](
+ OIC::Service::RCSResourceAttributes attributes)
+ {
+ onGetAttributes->onRemoteAttributesGetCallback(attributes);
+ };
+ m_sharedResource->getRemoteAttributes(getArributescb);
+}
+
+void JniRCSRemoteResourceObject::setRemoteAttributes(JNIEnv *env, jobject attributes,
+ jobject jListener)
+{
+ JniSetAttributesListener *onSetAttributes = addOnsetAttributesListener(env, jListener);
+ RCSRemoteResourceObject::RemoteAttributesSetCallback setArributescb = [onSetAttributes](
+ OIC::Service::RCSResourceAttributes attribute)
+ {
+ onSetAttributes->onRemoteAttributesSetCallback(attribute);
+ };
+ RCSResourceAttributes *attributesObj = JniResourceAttributes::getResourceAttributePtr(env,
+ attributes);
+ m_sharedResource->setRemoteAttributes(*attributesObj, setArributescb);
+}
+
+
+jobject JniRCSRemoteResourceObject::getCachedAttributes(JNIEnv *env)
+{
+ try
+ {
+ RCSResourceAttributes attributes = m_sharedResource->getCachedAttributes();
+ RCSResourceAttributes *attributesObj = new RCSResourceAttributes(attributes);
+ jlong handle = reinterpret_cast<jlong>(attributesObj);
+ jobject jAttributes = env->NewObject(g_cls_RCSRemoteResourceAttributesObject,
+ g_mid_RCSRemoteResourceAttributesObject_ctor,
+ handle, true);
+ return jAttributes;
+ }
+ catch (BadRequestException exception)
+ {
+ throwRCSException(env, exception.what());
+ }
+}
+
+jstring JniRCSRemoteResourceObject::getCachedAttribute(JNIEnv *env, jstring jkey,
+ jobject interfaceObject )
+{
+ const char *str = env->GetStringUTFChars(jkey , NULL);
+ std::string s(str);
+ char buf[64]; // assumed large enough to cope with result
+ env->ReleaseStringUTFChars(jkey, str);
+ RCSResourceAttributes::Value value;
+ RCSResourceAttributes::TypeId typeId;
+ try
+ {
+ value = m_sharedResource->getCachedAttribute(s);
+ typeId = value.getType().getId();
+ }
+ catch (BadRequestException exception)
+ {
+ throwRCSException(env, exception.what());
+ }
+
+ if (typeId == RCSResourceAttributes::TypeId::INT)
+ {
+ int val = value.get<int>();
+ sprintf(buf, "%d", val);
+ return (env)->NewStringUTF(buf);
+ }
+ else if (typeId == RCSResourceAttributes::TypeId::DOUBLE)
+ {
+ double val = value.get<double>();
+ sprintf(buf, "%f", val);
+ return (env)->NewStringUTF(buf);
+ }
+ else if (typeId == RCSResourceAttributes::TypeId::BOOL)
+ {
+ bool val = value.get<bool>();
+ sprintf(buf, "%d", val);
+ return (env)->NewStringUTF(buf);
+ }
+ else if (typeId == RCSResourceAttributes::TypeId::STRING)
+ {
+ std::string val = value.get<std::string>();
+ jstring jstr = env->NewStringUTF(val.c_str());
+ return jstr;
+ }
+}
+JniResourceStateChangeListener *JniRCSRemoteResourceObject::addOnStateChangeListener(JNIEnv *env,
+ jobject jListener)
+{
+ return this->m_onStateChange.addListener(env, jListener, this);
+}
+
+JniCacheUpdateListener *JniRCSRemoteResourceObject::addOnCacheUpdateListener(JNIEnv *env,
+ jobject jListener)
+{
+ return this->m_onCacheUpdateChange.addListener(env, jListener, this);
+}
+
+JniGetAttributesListener *JniRCSRemoteResourceObject::addOngetAttributesListener(JNIEnv *env,
+ jobject jListener)
+{
+ return this->m_ongetAttributes.addListener(env, jListener, this);
+}
+
+JniSetAttributesListener *JniRCSRemoteResourceObject::addOnsetAttributesListener(JNIEnv *env,
+ jobject jListener)
+{
+ return this->m_onsetAttributes.addListener(env, jListener, this);
+}
+
+void JniRCSRemoteResourceObject::removeOnStateChangeListener(JNIEnv *env, jobject jListener)
+{
+ this->m_onStateChange.removeListener(env, jListener);
+}
+
+void JniRCSRemoteResourceObject::removeCacheUpdateListener(JNIEnv *env, jobject jListener)
+{
+ this->m_onCacheUpdateChange.removeListener(env, jListener);
+}
+
+void JniRCSRemoteResourceObject::removeOngetAttributesListener(JNIEnv *env, jobject jListener)
+{
+ this->m_ongetAttributes.removeListener(env, jListener);
+}
+
+void JniRCSRemoteResourceObject::removeOnsetAttributesListener(JNIEnv *env, jobject jListener)
+{
+ this->m_onsetAttributes.removeListener(env, jListener);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeIsMonitoring
+(JNIEnv *env, jobject interfaceClass)
+{
+ LOGD("RCSRemoteResourceObject_nativeIsMonitoring");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ return (jboolean)resource->isMonitoring();
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeIsCaching
+(JNIEnv *env, jobject interfaceClass)
+{
+
+ LOGD("RCSRemoteResourceObject_nativeIsCaching");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ return (jboolean)resource->isCaching();
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeIsObservable
+(JNIEnv *env, jobject interfaceClass)
+{
+ LOGD("RCSRemoteResourceObject_nativeIsObservable");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ return (jboolean)resource->isObservable();
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeStartMonitoring
+(JNIEnv *env, jobject interfaceClass, jobject jStateChangedListener)
+{
+
+ if (!jStateChangedListener)
+ {
+ LOGE("RCSRemoteResourceObject_nativeStartMonitoring : listener is NULL");
+ throwRCSException(env, "Invalid parameter");
+ return;
+ }
+ LOGD("RCSRemoteResourceObject_nativeStartMonitoring");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ if (!resource) return;
+
+ resource->startMonitoring(env, jStateChangedListener);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeStopMonitoring
+(JNIEnv *env, jobject interfaceClass)
+{
+ LOGD("RCSRemoteResourceObject_nativeStopMonitoring");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ resource->stopMonitoring();
+}
+
+JNIEXPORT jint JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetState
+(JNIEnv *env, jobject interfaceClass)
+{
+ LOGD("RCSRemoteResourceObject_nativeGetState");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ return (jint)resource->getState();
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeStartCaching
+(JNIEnv *env, jobject interfaceClass, jobject jCacheUpdateListener)
+{
+ LOGD("RCSRemoteResourceObject_nativeStartCaching");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ if (!resource) return;
+ if (NULL == jCacheUpdateListener)
+ {
+ resource->startCaching(env);
+ }
+ else
+ {
+ resource->startCaching(env, jCacheUpdateListener);
+ }
+}
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeStopCaching
+(JNIEnv *env, jobject interfaceClass)
+{
+ LOGD("RCSRemoteResourceObject_nativeStopCaching");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ resource->stopCaching();
+}
+
+JNIEXPORT jint JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetCacheState
+(JNIEnv *env, jobject interfaceClass)
+{
+ LOGD("RCSRemoteResourceObject_nativeGetCacheState");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ return (jint)resource->getCacheState();
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeIsCachedAvailable
+(JNIEnv *env, jobject interfaceClass)
+{
+
+ LOGD("RCSRemoteResourceObject_nativeIsMonitoring");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ return (jboolean)resource->isCachedAvailable();
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetCachedAttributes
+(JNIEnv *env, jobject interfaceClass)
+{
+ LOGD("RCSRemoteResourceObject_nativeGetCachedAttributes");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ return resource->getCachedAttributes(env);
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetCachedAttribute
+(JNIEnv *env, jobject interfaceClass, jstring jKey)
+{
+ if (!jKey)
+ {
+ LOGE("RCSRemoteResourceObject_nativeGetCachedAttributes : key is NULL");
+ throwRCSException(env, "Key is empty");
+ return NULL;
+ }
+ LOGD("RCSRemoteResourceObject_nativeGetRemoteAttributes");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ return resource->getCachedAttribute(env, jKey, interfaceClass);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetRemoteAttributes
+(JNIEnv *env, jobject interfaceClass, jobject jResourceAttributesListener)
+{
+ LOGD("RCSRemoteResourceObject_nativeGetRemoteAttributes");
+ if (!jResourceAttributesListener)
+ {
+ LOGE("RCSRemoteResourceObject_nativeGetRemoteAttributes: listener is NULL");
+ throwRCSException(env, "Invalid parameter");
+ return;
+ }
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ if (!resource) return;
+
+ resource->getRemoteAttributes(env, jResourceAttributesListener);
+}
+
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeSetRemoteAttributes
+(JNIEnv *env, jobject interfaceClass, jobject jresourceAttribute,
+ jobject jResourceAttributesListener)
+{
+ LOGD("RCSRemoteResourceObject_nativeSetRemoteAttributes");
+ if (!jResourceAttributesListener)
+ {
+ LOGE("RCSRemoteResourceObject_nativeSetRemoteAttributes: listener is NULL");
+ throwRCSException(env, "Invalid parameter");
+ return;
+ }
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ if (!resource) return;
+
+ resource->setRemoteAttributes(env, jresourceAttribute, jResourceAttributesListener);
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetUri
+(JNIEnv *env, jobject interfaceClass)
+{
+ LOGD("JNI RCSRemoteResourceObjectNativeInterface_getUri");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ if (!resource) return nullptr;
+
+ return env->NewStringUTF(resource->getUri().c_str());
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetAddress
+(JNIEnv *env, jobject interfaceClass)
+{
+ LOGD("RCSRemoteResourceObject_nativeGetAddress");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ if (!resource) return nullptr;
+
+ return env->NewStringUTF(resource->getAddress().c_str());
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetTypes
+(JNIEnv *env, jobject interfaceClass)
+{
+ LOGD("RCSRemoteResourceObject_nativeGetTypes");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ if (!resource) return nullptr;
+ return resource->getTypes(env);
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetInterFaces
+(JNIEnv *env, jobject interfaceClass)
+{
+
+ LOGD("RCSRemoteResourceObject_nativeGetInterFaces");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ if (!resource) return nullptr;
+ return resource->getInterfaces(env);
+}
+
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_rcs_resource_container.h"
+#include "jni_re_utils.h"
+#include "RCSResourceContainer.h"
+#include "RCSBundleInfo.h"
+
+using namespace OIC::Service;
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeStartContainer
+(JNIEnv *env, jobject jObject, jstring configFile)
+{
+ LOGD("RCSResourceContainer_nativeStartContainer");
+ RCSResourceContainer *container = RCSResourceContainer::getInstance();
+ std::string nativeFilePath = env->GetStringUTFChars(configFile, NULL);
+ container->startContainer(nativeFilePath);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeStopContainer
+(JNIEnv *env, jobject jObject)
+{
+ LOGD("RCSResourceContainer_nativeStopContainers");
+ RCSResourceContainer *container = RCSResourceContainer::getInstance();
+ container->stopContainer();
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeAddBundle
+(JNIEnv *env, jobject jObject, jstring jBundleId, jstring jBundleUri, jstring jBundlePath,
+ jobject jParams)
+{
+ LOGD("RCSResourceContainer_nativeAddBundle");
+ std::string bundleId = env->GetStringUTFChars(jBundleId, NULL);
+ std::string bundleUri = env->GetStringUTFChars(jBundleUri, NULL);
+ std::string bundlePath = env->GetStringUTFChars(jBundlePath, NULL);
+
+ std::map<std::string, std::string> params;
+ //convert java map to native param map
+ convertJavaMapToParamsMap(env, jParams, params);
+
+ RCSResourceContainer *container = RCSResourceContainer::getInstance();
+ container->addBundle(bundleId, bundleUri, bundlePath, params);
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeListBundles
+(JNIEnv *env, jobject jObject)
+{
+ LOGD("RCSResourceContainer_nativeListBundles");
+
+ RCSResourceContainer *container = RCSResourceContainer::getInstance();
+ std::list<RCSBundleInfo *> nativeBundleInfoList = container->listBundles();
+
+ if (nativeBundleInfoList.size() == 0)
+ {
+ LOGD("RCSResourceContainer_nativeListBundles size of bundle list is zerooooo");
+ }
+ else
+ {
+ LOGD("RCSResourceContainer_nativeListBundles size of bundle list is not zerooooo");
+ }
+ //conversion from native list bundle to java list bundle...
+ jobject jList = env->NewObject(g_cls_LinkedList, g_mid_LinkedList_ctor);
+ if (!jList) return nullptr;
+
+ std::list<RCSBundleInfo *>::iterator bundleIt;
+
+ for (bundleIt = nativeBundleInfoList.begin(); bundleIt != nativeBundleInfoList.end(); bundleIt++)
+ {
+ jlong handle = reinterpret_cast<jlong>(*bundleIt);
+
+ //set native handle
+ jclass clazz = env->FindClass("org/iotivity/ResourceEncapsulation/server/RCSBundleInfo");
+ jfieldID fid = env->GetFieldID(clazz, "m_nativeHandle", "J");
+
+ //create java RCSBundleInfo Object
+ jobject resourceObj = (jobject) env->NewObject(g_cls_RCSBundleInfo, g_mid_RCSBundleInfo_ctor,
+ handle);
+
+ env->CallBooleanMethod(jList, g_mid_LinkedList_add_object, resourceObj);
+
+ if (env->ExceptionCheck()) return nullptr;
+ env->DeleteLocalRef(resourceObj);
+ }
+ return jList ;
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeRemoveBundle
+(JNIEnv *env, jobject jObject, jstring jBundleId)
+{
+ LOGD("RCSResourceContainer_nativeRemoveBundle");
+ std::string bundleId = env->GetStringUTFChars(jBundleId, NULL);
+ RCSResourceContainer *container = RCSResourceContainer::getInstance();
+ container->removeBundle(bundleId);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeStartBundle
+(JNIEnv *env, jobject jObject, jstring jBundleId)
+{
+ LOGD("RCSResourceContainer_nativeStartBundle");
+ std::string bundleId = env->GetStringUTFChars(jBundleId, NULL);
+ RCSResourceContainer *container = RCSResourceContainer::getInstance();
+ container->startBundle(bundleId);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeStopBundle
+(JNIEnv *env, jobject jObject, jstring jBundleId)
+{
+ LOGD("RCSResourceContainer_nativeStopBundle");
+ std::string bundleId = env->GetStringUTFChars(jBundleId, NULL);
+ RCSResourceContainer *container = RCSResourceContainer::getInstance();
+ container->stopBundle(bundleId);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeAddResourceConfig
+(JNIEnv *env, jobject jObject, jstring jBundleId, jstring jResourceUri, jobject jParams)
+{
+ LOGD("RCSResourceContainer_nativeAddResourceConfig");
+ std::string bundleId = env->GetStringUTFChars(jBundleId, NULL);
+ std::string resourceUri = env->GetStringUTFChars(jResourceUri, NULL);
+
+ std::map<std::string, std::string> params;
+ //convert java map to native param map
+ convertJavaMapToParamsMap(env, jParams, params);
+
+ RCSResourceContainer *container = RCSResourceContainer::getInstance();
+ container->addResourceConfig(bundleId, resourceUri, params);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeRemoveResourceConfig
+(JNIEnv *env, jobject jObject, jstring jBundleId, jstring jResourceUri)
+{
+ LOGD("RCSResourceContainer_nativeRemoveResourceConfig");
+ std::string bundleId = env->GetStringUTFChars(jBundleId, NULL);
+ std::string resourceUri = env->GetStringUTFChars(jResourceUri, NULL);
+ RCSResourceContainer *container = RCSResourceContainer::getInstance();
+ container->removeResourceConfig(bundleId, resourceUri);
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceContainer_nativeListBundleResources
+(JNIEnv *env, jobject jObject, jstring jBundleId)
+{
+ LOGD("RCSResourceContainer_nativeListBundleResources");
+ std::string bundleId = env->GetStringUTFChars(jBundleId, NULL);
+ RCSResourceContainer *container = RCSResourceContainer::getInstance();
+ std::list<std::string> nativeList = container->listBundleResources(bundleId);
+ return convertStrListToJavaStrList(env, nativeList);
+}
+
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_resource_attributes.h"
+#include "jni_re_jvm.h"
+
+RCSResourceAttributes *JniResourceAttributes::getResourceAttributePtr(JNIEnv *env,
+ jobject interfaceObject)
+{
+ RCSResourceAttributes *rep = REGetHandle<RCSResourceAttributes>(env, interfaceObject);
+ if (env->ExceptionCheck())
+ {
+ LOGE("Failed to get native handle from RCSResourceAttributes");
+ }
+ if (!rep)
+ {
+ throwRCSException(env, "JNI no native pointer");
+ }
+ return rep;
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeGetValueN
+(JNIEnv *env, jobject interfaceObject, jstring jKey)
+{
+ LOGD("RCSResourceAttributes_getValueN");
+ if (!jKey)
+ {
+ throwRCSException(env, "attributeKey cannot be null");
+ return nullptr;
+ }
+
+ RCSResourceAttributes *rep = JniResourceAttributes::getResourceAttributePtr(env, interfaceObject);
+ if (!rep) return nullptr;
+
+ std::string key = env->GetStringUTFChars(jKey, NULL);
+
+ if (! rep->contains(key)) return nullptr;
+
+ RCSResourceAttributes::Value attrValue = rep->at(key);
+ RCSResourceAttributes::TypeId typeId = attrValue.getType().getId();
+
+ if (typeId == RCSResourceAttributes::TypeId::INT)
+ {
+ int val = attrValue.get<int>();
+ jobject jobj = env->NewObject(
+ g_cls_Integer,
+ g_mid_Integer_ctor,
+ static_cast<jint>(val));
+ return jobj;
+ }
+ else if (typeId == RCSResourceAttributes::TypeId::DOUBLE)
+ {
+ double val = attrValue.get<double>();
+ jobject jobj = env->NewObject(
+ g_cls_Double,
+ g_mid_Double_ctor,
+ static_cast<jdouble>(val));
+ return jobj;
+ }
+ else if (typeId == RCSResourceAttributes::TypeId::BOOL)
+ {
+ bool val = attrValue.get<bool>();
+ jobject jobj = env->NewObject(
+ g_cls_Boolean,
+ g_mid_Boolean_ctor,
+ static_cast<jboolean>(val));
+ return jobj;
+ }
+ else if (typeId == RCSResourceAttributes::TypeId::STRING)
+ {
+ std::string val = attrValue.get<std::string>();
+ jstring jstr = env->NewStringUTF(val.c_str());
+ return static_cast<jobject>(jstr);
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeSetValueInteger
+(JNIEnv *env, jobject interfaceObject, jstring jKey, jint jValue)
+{
+ LOGD("RCSResourceAttributes_setValueInteger");
+ if (!jKey)
+ {
+ throwRCSException(env, "key cannot be null");
+ return;
+ }
+
+ RCSResourceAttributes *rep = JniResourceAttributes::getResourceAttributePtr(env, interfaceObject);
+ if (!rep) return;
+
+ std::string key = env->GetStringUTFChars(jKey, NULL);
+
+ RCSResourceAttributes setAttribute;
+ setAttribute[key] = static_cast<int>(jValue);
+ *rep = setAttribute;
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeSetValueDouble
+(JNIEnv *env, jobject interfaceObject, jstring jKey, jdouble jValue)
+{
+ LOGD("RCSResourceAttributes_setValueDouble");
+ if (!jKey)
+ {
+ throwRCSException(env, "key cannot be null");
+ return;
+ }
+
+ RCSResourceAttributes *rep = JniResourceAttributes::getResourceAttributePtr(env, interfaceObject);
+ if (!rep) return;
+
+ std::string key = env->GetStringUTFChars(jKey, NULL);
+
+ RCSResourceAttributes setAttribute;
+ setAttribute[key] = static_cast<double>(jValue);
+ *rep = setAttribute;
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeSetValueBoolean
+(JNIEnv *env, jobject interfaceObject, jstring jKey, jboolean jValue)
+{
+ LOGD("RCSResourceAttributes_setValueBoolean");
+ if (!jKey)
+ {
+ throwRCSException(env, "key cannot be null");
+ return;
+ }
+
+ RCSResourceAttributes *rep = JniResourceAttributes::getResourceAttributePtr(env, interfaceObject);
+ if (!rep) return;
+
+ std::string key = env->GetStringUTFChars(jKey, NULL);
+
+ RCSResourceAttributes setAttribute;
+ setAttribute[key] = static_cast<bool>(jValue);
+ *rep = setAttribute;
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeSetValueString
+(JNIEnv *env, jobject interfaceObject, jstring jKey, jstring jValue)
+{
+ LOGD("RCSResourceAttributes_setValueStringN");
+ if (!jKey)
+ {
+ throwRCSException(env, "key cannot be null");
+ return;
+ }
+
+ RCSResourceAttributes *rep = JniResourceAttributes::getResourceAttributePtr(env, interfaceObject);
+ if (!rep) return;
+
+ std::string key = env->GetStringUTFChars(jKey, NULL);
+ std::string value = env->GetStringUTFChars(jValue, NULL);
+
+ RCSResourceAttributes setAttribute;
+ setAttribute[key] = value;
+ *rep = setAttribute;
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeSetValueIntegerArray
+(JNIEnv *env, jobject interfaceObject, jstring jKey, jintArray jValue)
+{
+ LOGD("RCSResourceAttributes_setValueIntegerArray");
+ if (!jKey)
+ {
+ throwRCSException(env, "key cannot be null");
+ return;
+ }
+
+ const jsize len = env->GetArrayLength(jValue);
+ jint *ints = env->GetIntArrayElements(jValue, NULL);
+
+ std::vector<int> value;
+ for (jsize i = 0; i < len; ++i)
+ {
+ value.push_back(static_cast<int>(ints[i]));
+ }
+ env->ReleaseIntArrayElements(jValue, ints, JNI_ABORT);
+
+ RCSResourceAttributes *rep = JniResourceAttributes::getResourceAttributePtr(env, interfaceObject);
+ if (!rep) return;
+
+ std::string key = env->GetStringUTFChars(jKey, NULL);
+ RCSResourceAttributes setAttribute;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeIsEmpty
+(JNIEnv *env, jobject interfaceObject)
+{
+ LOGD("RCSResourceAttributes_isEmpty");
+ RCSResourceAttributes *rep = JniResourceAttributes::getResourceAttributePtr(env, interfaceObject);
+ if (!rep) return false;
+
+ return static_cast<jboolean>(rep->empty());
+}
+
+JNIEXPORT jint JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeSize
+(JNIEnv *env, jobject interfaceObject)
+{
+ LOGD("RCSResourceAttributes_size");
+ RCSResourceAttributes *rep = JniResourceAttributes::getResourceAttributePtr(env, interfaceObject);
+ if (!rep) return -1;
+
+ return static_cast<jint>(rep->size());
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeRemove
+(JNIEnv *env, jobject interfaceObject, jstring jAttributeKey)
+{
+ LOGD("RCSResourceAttributes_remove");
+ if (!jAttributeKey)
+ {
+ throwRCSException(env, "attributeKey cannot be null");
+ return false;
+ }
+
+ RCSResourceAttributes *rep = JniResourceAttributes::getResourceAttributePtr(env, interfaceObject);
+ if (!rep) return false;
+
+ std::string attributeKey = env->GetStringUTFChars(jAttributeKey, NULL);
+ return static_cast<jboolean>(rep->erase(attributeKey));
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_nativeHasAttribute
+(JNIEnv *env, jobject interfaceObject, jstring jstr)
+{
+ LOGD("RCSResourceAttributes_hasAttribute");
+ if (!jstr)
+ {
+ throwRCSException(env, "attributeKey cannot be null");
+ return false;
+ }
+
+ RCSResourceAttributes *rep = JniResourceAttributes::getResourceAttributePtr(env, interfaceObject);
+ if (!rep) return false;
+
+ std::string attributeKey = env->GetStringUTFChars(jstr, NULL);
+ return static_cast<jboolean>(rep->contains(attributeKey));
+}
+
+JNIEXPORT void JNICALL Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_create
+(JNIEnv *env, jobject interfaceObject)
+{
+ LOGD("RCSResourceAttributes_create");
+ RCSResourceAttributes *rep = new RCSResourceAttributes();
+ RESetHandle<RCSResourceAttributes>(env, interfaceObject, rep);
+ if (env->ExceptionCheck())
+ {
+ LOGE("Failed to set native handle for RCSResourceAttributes");
+ delete rep;
+ }
+}
+
+JNIEXPORT void JNICALL Java_org_iotivity_ResourceEncapsulation_common_RCSResourceAttributes_dispose
+(JNIEnv *env, jobject interfaceObject, jboolean jNeedsDelete)
+{
+ LOGD("RCSResourceAttributes_dispose");
+ RCSResourceAttributes *rep = JniResourceAttributes::getResourceAttributePtr(env, interfaceObject);
+
+ if (jNeedsDelete)
+ {
+ delete rep;
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_jvm.h"
+#include "jni_re_resource_builder.h"
+#include "jni_re_resource_object.h"
+#include "RCSResourceObject.h"
+#include "jni_re_resource_attributes.h"
+
+using namespace OIC::Service;
+
+JNIEXPORT jobject JNICALL Java_org_iotivity_ResourceEncapsulation_server_Builder_nativeBuild
+(JNIEnv *env, jobject interfaceObject, jstring jResourceURI, jstring jResourceType,
+ jstring jResourceInterface,
+ jboolean jObservableFlag, jboolean jDiscovervableFlag, jobject jAttributes)
+{
+ LOGI("nativeBuild called");
+
+ std::string resourceURI;
+ if (jResourceURI)
+ {
+ resourceURI = env->GetStringUTFChars(jResourceURI, NULL);
+ }
+ std::string resourceType;
+ if (jResourceType)
+ {
+ resourceType = env->GetStringUTFChars(jResourceType, NULL);
+ }
+ std::string resourceInterface;
+ if (jResourceInterface)
+ {
+ resourceInterface = env->GetStringUTFChars(jResourceInterface, NULL);
+ }
+
+ std::shared_ptr< RCSResourceObject > NativeRCSResourceObject;
+ try
+ {
+ if (jAttributes)
+ {
+ RCSResourceAttributes *attributesObj = JniResourceAttributes::getResourceAttributePtr(env,
+ jAttributes);
+ NativeRCSResourceObject = RCSResourceObject::Builder(resourceURI, resourceType,
+ resourceInterface).setDiscoverable((bool)jObservableFlag).setObservable((
+ bool)jObservableFlag).setAttributes(*attributesObj).build();
+
+ jobject jResource = env->NewObject(g_cls_RCSResourceObject, g_mid_RCSResourceObject_ctor);
+ JniRCSResourceObject *jniRCSResourceObject = new JniRCSResourceObject(NativeRCSResourceObject);
+ RESetHandle<JniRCSResourceObject>(env, jResource, jniRCSResourceObject);
+ return jResource;
+ }
+ else
+ {
+ NativeRCSResourceObject = RCSResourceObject::Builder(resourceURI, resourceType,
+ resourceInterface).setDiscoverable((bool)jObservableFlag).setObservable((
+ bool)jObservableFlag).build();
+
+ jobject jResource = env->NewObject(g_cls_RCSResourceObject, g_mid_RCSResourceObject_ctor);
+ JniRCSResourceObject *jniRCSResourceObject = new JniRCSResourceObject(NativeRCSResourceObject);
+ RESetHandle<JniRCSResourceObject>(env, jResource, jniRCSResourceObject);
+ return jResource;
+ }
+ }
+ catch (OIC::Service::PlatformException exception)
+ {
+ LOGE("nativeBuild : platform Exception");
+ throwRCSException(env, exception.what());
+ }
+ catch (OIC::Service::RCSException exception)
+ {
+ LOGE("nativeBuild : RCSException");
+ throwRCSException(env, exception.what());
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_resource_object.h"
+#include "jni_re_get_request_listener.h"
+#include "RCSResourceObject.h"
+
+JniRCSResourceObject::JniRCSResourceObject(std::shared_ptr< RCSResourceObject>
+ resource)
+ : m_sharedResource(resource)
+{}
+
+JniRCSResourceObject::~JniRCSResourceObject()
+{
+ LOGD("JniResourceObject::~JniResourceObject()");
+ m_sharedResource = NULL;
+
+ jint envRet;
+ JNIEnv *env = GetREJNIEnv(envRet);
+ if (NULL == env) return;
+
+ if (JNI_EDETACHED == envRet) g_jvm->DetachCurrentThread();
+}
+
+JniRCSResourceObject *JniRCSResourceObject::getJniRCSResourceObject(JNIEnv *env,
+ jobject thiz)
+{
+ JniRCSResourceObject *resource = REGetHandle<JniRCSResourceObject>(env, thiz);
+ if (env->ExceptionCheck())
+ {
+ LOGE("Failed to get native handle from RCSResourceObject");
+ }
+ if (!resource)
+ {
+ LOGE("getJniRCSResourceObject :: no resource");
+ }
+ return resource;
+}
+
+void JniRCSResourceObject::setAttributeInteger(JNIEnv *env, jobject jObject, jstring jKey,
+ jint jValue)
+{
+ LOGD("JniRCSResourceObject::setAttributeInteger");
+
+ if (!jKey)
+ {
+ throwRCSException(env, "key cannot be null");
+ return;
+ }
+ std::string key = env->GetStringUTFChars(jKey, NULL);
+ RCSResourceAttributes::Value value ;
+ RCSResourceAttributes::TypeId typeId;
+
+ try
+ {
+ value = m_sharedResource->getAttributeValue(key);
+ if (value != NULL)
+ {
+ typeId = value.getType().getId();
+ if (typeId == RCSResourceAttributes::TypeId::INT)
+ {
+ RCSResourceObject::LockGuard lock(*m_sharedResource);
+ m_sharedResource->getAttributes()[key] = (int)jValue;
+ }
+ else
+ {
+ LOGD("JniRCSResourceObject::setAttributeInteger value is not interger type");
+ }
+ }
+ }
+ catch (BadRequestException exception)
+ {
+ throwRCSException(env, exception.what());
+ }
+}
+
+void JniRCSResourceObject::setAttributeDouble(JNIEnv *env, jobject jObject, jstring jKey,
+ jdouble jValue)
+{
+ LOGD("JniRCSResourceObject::setAttributeDouble");
+
+ if (!jKey)
+ {
+ throwRCSException(env, "key cannot be null");
+ return;
+ }
+ std::string key = env->GetStringUTFChars(jKey, NULL);
+ RCSResourceAttributes::Value value ;
+ RCSResourceAttributes::TypeId typeId;
+
+ try
+ {
+ value = m_sharedResource->getAttributeValue(key);
+ if (value != NULL)
+ {
+ typeId = value.getType().getId();
+ if (typeId == RCSResourceAttributes::TypeId::DOUBLE)
+ {
+ RCSResourceObject::LockGuard lock(*m_sharedResource);
+ m_sharedResource->getAttributes()[key] = (double)jValue;
+ }
+ else
+ {
+ LOGD("JniRCSResourceObject::setAttributeInteger value is not double type");
+ }
+ }
+ }
+ catch (BadRequestException exception)
+ {
+ throwRCSException(env, exception.what());
+ }
+
+}
+
+
+void JniRCSResourceObject::setAttributeBool(JNIEnv *env, jobject jObject, jstring jKey,
+ jboolean jValue)
+{
+ LOGD("JniRCSResourceObject::setAttributeBool");
+
+ if (!jKey)
+ {
+ throwRCSException(env, "key cannot be null");
+ return;
+ }
+ std::string key = env->GetStringUTFChars(jKey, NULL);
+ RCSResourceAttributes::Value value ;
+ RCSResourceAttributes::TypeId typeId;
+
+ try
+ {
+ value = m_sharedResource->getAttributeValue(key);
+ if (value != NULL)
+ {
+ typeId = value.getType().getId();
+ if (typeId == RCSResourceAttributes::TypeId::BOOL)
+ {
+ RCSResourceObject::LockGuard lock(*m_sharedResource);
+ m_sharedResource->getAttributes()[key] = (bool)jValue;
+ }
+ else
+ {
+ LOGD("JniRCSResourceObject::setAttributeInteger value is not bool type");
+ }
+ }
+ }
+ catch (BadRequestException exception)
+ {
+ throwRCSException(env, exception.what());
+ }
+}
+
+void JniRCSResourceObject::setAttributeString(JNIEnv *env, jobject jObject, jstring jKey,
+ jstring jValue)
+{
+ LOGD("JniRCSResourceObject::setAttributeString");
+
+ if (!jKey)
+ {
+ throwRCSException(env, "key cannot be null");
+ return;
+ }
+ std::string key = env->GetStringUTFChars(jKey, NULL);
+ RCSResourceAttributes::Value value ;
+ RCSResourceAttributes::TypeId typeId;
+
+ try
+ {
+ value = m_sharedResource->getAttributeValue(key);
+ if (value != NULL)
+ {
+ typeId = value.getType().getId();
+ if (typeId == RCSResourceAttributes::TypeId::STRING)
+ {
+ RCSResourceObject::LockGuard lock(*m_sharedResource);
+ std::string nativeValue = env->GetStringUTFChars(jValue, NULL);
+ m_sharedResource->getAttributes()[key] = nativeValue;
+ }
+ else
+ {
+ LOGD("JniRCSResourceObject::setAttributeInteger value is not String type");
+ }
+ }
+ }
+ catch (BadRequestException exception)
+ {
+ throwRCSException(env, exception.what());
+ }
+}
+
+jstring JniRCSResourceObject::getAttributeValue(JNIEnv *env, jstring jKey)
+{
+ char buf[64];
+ std::string key;
+ if (jKey)
+ {
+ key = env->GetStringUTFChars(jKey, NULL);
+ }
+ else
+ {
+ LOGE("getAttributeValue Key is NULL");
+ return NULL;
+ }
+
+ RCSResourceAttributes::Value value;
+ RCSResourceAttributes::TypeId typeId;
+ try
+ {
+ value = m_sharedResource->getAttributeValue(key);
+ typeId = value.getType().getId();
+ }
+ catch (BadRequestException exception)
+ {
+ throwRCSException(env, exception.what());
+ }
+
+ if (typeId == RCSResourceAttributes::TypeId::INT)
+ {
+ int val = value.get<int>();
+ sprintf(buf, "%d", val);
+ return (env)->NewStringUTF(buf);
+ }
+ else if (typeId == RCSResourceAttributes::TypeId::DOUBLE)
+ {
+ double val = value.get<double>();
+ sprintf(buf, "%f", val);
+ return (env)->NewStringUTF(buf);
+ }
+ else if (typeId == RCSResourceAttributes::TypeId::BOOL)
+ {
+ bool val = value.get<bool>();
+ sprintf(buf, "%d", val);
+ return (env)->NewStringUTF(buf);
+ }
+ else if (typeId == RCSResourceAttributes::TypeId::STRING)
+ {
+ std::string val = value.get<std::string>();
+ jstring jstr = env->NewStringUTF(val.c_str());
+ return jstr;
+ }
+}
+
+bool JniRCSResourceObject::removeAttribute(JNIEnv *env, jstring jKey)
+{
+ std::string key;
+ if (jKey)
+ {
+ key = env->GetStringUTFChars(jKey, NULL);
+ }
+ return m_sharedResource->removeAttribute(key);
+}
+bool JniRCSResourceObject::containsAttribute(JNIEnv *env, jstring jKey)
+{
+ std::string key;
+ if (jKey)
+ {
+ key = env->GetStringUTFChars(jKey, NULL);
+ }
+ return m_sharedResource->containsAttribute(key);
+}
+
+jobject JniRCSResourceObject::getAttributes(JNIEnv *env, jobject jObject)
+{
+ RCSResourceObject::LockGuard lock(*m_sharedResource);
+ RCSResourceAttributes nativeAttributes = m_sharedResource->getAttributes();
+
+ RCSResourceAttributes *attributesObj = new RCSResourceAttributes(nativeAttributes);
+
+ jlong handle = reinterpret_cast<jlong>(attributesObj);
+ jobject jAttributes = env->NewObject(g_cls_RCSRemoteResourceAttributesObject,
+ g_mid_RCSRemoteResourceAttributesObject_ctor,
+ handle, true);
+ return jAttributes;
+}
+
+bool JniRCSResourceObject::isObservable()
+{
+ return m_sharedResource->isObservable();
+}
+
+bool JniRCSResourceObject::isDiscoverable()
+{
+ return m_sharedResource->isDiscoverable();
+}
+
+void JniRCSResourceObject::setGetRequestHandler(JNIEnv *env, jobject jGetRequestListener)
+{
+
+ JniGetRequestListener *onGetRequestListener = addOnGetRequestListener(env, jGetRequestListener);
+
+ OIC::Service::RCSResourceObject::GetRequestHandler getRequestCallback = [onGetRequestListener](
+ OIC::Service::RCSRequest request,
+ OIC::Service::RCSResourceAttributes attributes)
+ {
+ return onGetRequestListener->onGetRequestCallback(request, attributes);
+ };
+ m_sharedResource->setGetRequestHandler(getRequestCallback);
+}
+
+void JniRCSResourceObject::setSetRequestHandler(JNIEnv *env, jobject jSetRequestListener)
+{
+
+ JniSetRequestListener *onSetRequestListener = addOnSetRequestListener(env, jSetRequestListener);
+
+ OIC::Service::RCSResourceObject::SetRequestHandler setRequestCallback = [onSetRequestListener](
+ OIC::Service::RCSRequest request,
+ OIC::Service::RCSResourceAttributes attributes)
+ {
+ return onSetRequestListener->onSetRequestCallback(request, attributes);
+ };
+ m_sharedResource->setSetRequestHandler(setRequestCallback);
+}
+
+void JniRCSResourceObject::addAttributeUpdatedListener(JNIEnv *env, jstring jKey,
+ jobject jAttributeUpdatedListener)
+{
+ std::string nativeKey;
+ if (jKey)
+ {
+ nativeKey = env->GetStringUTFChars(jKey, NULL);
+ }
+ else
+ {
+ LOGE("addAttributeUpdatedListener is NULL");
+ return;
+ }
+ JniAttributeUpdatedListener *onAttributeUpdatedListener = addOnAttributeUpdatedListener(env,
+ jAttributeUpdatedListener);
+
+ OIC::Service::RCSResourceObject::AttributeUpdatedListener attributeUpdatedCallback
+ = [onAttributeUpdatedListener]( OIC::Service::RCSResourceAttributes::Value oldValue,
+ OIC::Service::RCSResourceAttributes::Value newValue)
+ {
+ onAttributeUpdatedListener->onAttributeUpdatedCallback(oldValue, newValue);
+ };
+ m_sharedResource->addAttributeUpdatedListener(nativeKey, attributeUpdatedCallback);
+}
+
+bool JniRCSResourceObject::removeAttributeUpdatedListener(JNIEnv *env, jobject jObject,
+ jstring jKey)
+{
+ std::string nativeKey;
+ if (jKey)
+ {
+ nativeKey = env->GetStringUTFChars(jKey, NULL);
+ }
+ return m_sharedResource->removeAttributeUpdatedListener(nativeKey);
+}
+
+void JniRCSResourceObject::notify()
+{
+ m_sharedResource->notify();
+}
+
+void JniRCSResourceObject::setAutoNotifyPolicy(int policy)
+{
+ RCSResourceObject::AutoNotifyPolicy nativePolicy = convertJavaNotifyPolicyToNativePolicy(policy);
+ m_sharedResource->setAutoNotifyPolicy(nativePolicy);
+}
+
+int JniRCSResourceObject::getAutoNotifyPolicy()
+{
+ return convertAutoNotifyPolicyToInt(m_sharedResource->getAutoNotifyPolicy());
+}
+
+void JniRCSResourceObject::setSetRequestHandlerPolicy(int policy)
+{
+ RCSResourceObject::SetRequestHandlerPolicy nativePolicy =
+ convertJavasetRequestHandlerPolicyToNativePolicy(policy);
+ m_sharedResource->setSetRequestHandlerPolicy(nativePolicy);
+}
+
+int JniRCSResourceObject::getSetRequestHandlerPolicy()
+{
+ return convertSetRequestHandlerPolicyToInt(m_sharedResource->getSetRequestHandlerPolicy());
+}
+
+JniGetRequestListener *JniRCSResourceObject::addOnGetRequestListener(JNIEnv *env,
+ jobject jListener)
+{
+ return this->m_onGetRequest.addListener(env, jListener, this);
+}
+
+JniSetRequestListener *JniRCSResourceObject::addOnSetRequestListener(JNIEnv *env,
+ jobject jListener)
+{
+ return this->m_onSetRequest.addListener(env, jListener, this);
+}
+
+JniAttributeUpdatedListener *JniRCSResourceObject::addOnAttributeUpdatedListener(JNIEnv *env,
+ jobject jListener)
+{
+ return this->m_onAttributeUpdated.addListener(env, jListener, this);
+}
+
+void JniRCSResourceObject::removeOnGetRequestListener(JNIEnv *env, jobject jListener)
+{
+ this->m_onGetRequest.removeListener(env, jListener);
+}
+
+void JniRCSResourceObject::removeOnSetRequestListener(JNIEnv *env, jobject jListener)
+{
+ this->m_onSetRequest.removeListener(env, jListener);
+}
+
+void JniRCSResourceObject::removeOnAttributeUpdatedListener(JNIEnv *env, jobject jListener)
+{
+ this->m_onAttributeUpdated.removeListener(env, jListener);
+}
+
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetAttributeInteger
+(JNIEnv *env, jobject jObject, jstring key, jint value)
+{
+ LOGD("RCSRemoteResourceObject_nativeSetAttributeInteger");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ resource->setAttributeInteger(env, jObject, key, value);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetAttributeDouble
+(JNIEnv *env, jobject jObject, jstring key, jdouble value)
+{
+ LOGD("RCSRemoteResourceObject_nativeSetAttributeFloat");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ resource->setAttributeDouble(env, jObject, key, value);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetAttributeBool
+(JNIEnv *env, jobject jObject, jstring key, jboolean value)
+{
+ LOGD("RCSRemoteResourceObject_nativeSetAttributeDouble");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ resource->setAttributeBool(env, jObject, key, value);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetAttributeString
+(JNIEnv *env, jobject jObject, jstring key, jstring value)
+{
+ LOGD("RCSRemoteResourceObject_nativeSetAttributeFloat");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ resource->setAttributeString(env, jObject, key, value);
+}
+
+JNIEXPORT jstring JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeGetAttributeValue
+(JNIEnv *env, jobject jObject, jstring key)
+{
+ LOGD("RCSRemoteResourceObject_nativeGetAttributeValue");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ return resource->getAttributeValue(env, key);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeRemoveAttribute
+(JNIEnv *env, jobject jObject, jstring key)
+{
+ LOGD("RCSRemoteResourceObject_nativeRemoveAttribute");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ return (jboolean)resource->removeAttribute(env, key);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeContainsAttribute
+(JNIEnv *env, jobject jObject, jstring key)
+{
+ LOGD("RCSRemoteResourceObject_nativeContainsAttribute");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ return (jboolean)resource->containsAttribute(env, key);
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeGetAttributes
+(JNIEnv *env, jobject jObject)
+{
+ LOGD("RCSRemoteResourceObject_nativeGetAttributes");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ return resource->getAttributes(env, jObject);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeIsObservable
+(JNIEnv *env, jobject jObject)
+{
+ LOGD("RCSRemoteResourceObject_nativeIsObservable");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ return (jboolean)resource->isObservable();
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeIsDiscoverable
+(JNIEnv *env, jobject jObject)
+{
+ LOGD("RCSRemoteResourceObject_nativeIsDiscoverable");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ return (jboolean)resource->isDiscoverable();
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetGetRequestHandler
+(JNIEnv *env, jobject jObject , jobject getRequestListener)
+{
+ LOGD("RCSRemoteResourceObject_nativeSetGetRequestHandler");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ resource->setGetRequestHandler(env, getRequestListener);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetSetRequestHandler
+(JNIEnv *env, jobject jObject , jobject setRequestListener)
+{
+ LOGD("RCSRemoteResourceObject_nativeSetSetRequestHandler");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ resource->setSetRequestHandler(env, setRequestListener);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeAddAttributeUpdatedListener
+(JNIEnv *env, jobject jObject, jstring key, jobject attributeUpdatedListener)
+{
+ LOGD("RCSRemoteResourceObject_nativeAddAttributeUpdatedListener");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ resource->addAttributeUpdatedListener(env, key, attributeUpdatedListener);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeRemoveAttributeUpdatedListener
+(JNIEnv *env, jobject jObject, jstring key)
+{
+ LOGD("RCSRemoteResourceObject_nativeAddAttributeUpdatedListener");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ return (jboolean)resource->removeAttributeUpdatedListener(env, jObject, key);
+}
+
+JNIEXPORT void JNICALL Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeNotify
+(JNIEnv *env, jobject jObject)
+{
+ LOGD("RCSRemoteResourceObject_nativeNotify");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ resource->notify();
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetAutoNotifyPolicy
+(JNIEnv *env, jobject jObject, jint jPolicy)
+{
+ LOGD("RCSRemoteResourceObject_nativeSetAutoNotifyPolicy");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ resource->setAutoNotifyPolicy(jPolicy);
+}
+
+JNIEXPORT jint JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeGetAutoNotifyPolicy
+(JNIEnv *env, jobject jObject)
+{
+ LOGD("RCSRemoteResourceObject_nativeGetAutoNotifyPolicy");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ return (jint)resource->getAutoNotifyPolicy();
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeSetSetRequestHandlerPolicy
+(JNIEnv *env, jobject jObject, jint jPolicy)
+{
+ LOGD("RCSRemoteResourceObject_nativeSetSetRequestHandlerPolicy");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ resource->setSetRequestHandlerPolicy(jPolicy);
+}
+
+JNIEXPORT jint JNICALL
+Java_org_iotivity_ResourceEncapsulation_server_RCSResourceObject_nativeGetSetRequestHandlerPolicy
+(JNIEnv *env, jobject jObject)
+{
+ LOGD("RCSRemoteResourceObject_nativeGetSetRequestHandlerPolicy");
+ JniRCSResourceObject *resource = JniRCSResourceObject::getJniRCSResourceObject(env, jObject);
+ return (jint)resource->getSetRequestHandlerPolicy();
+}
+
+
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_resource_statechange_listener.h"
+#include "jni_re_rcs_remoteresourceobject.h"
+
+JniResourceStateChangeListener::JniResourceStateChangeListener(JNIEnv *env, jobject jListener,
+ JniRCSRemoteResourceObject *owner)
+ : m_ownerResource(owner)
+{
+ m_jwListener = env->NewWeakGlobalRef(jListener);
+}
+
+JniResourceStateChangeListener::~JniResourceStateChangeListener()
+{
+ LOGI("~JniResourceStateChangeListener()");
+ if (m_jwListener)
+ {
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+ env->DeleteWeakGlobalRef(m_jwListener);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ }
+}
+
+void JniResourceStateChangeListener::stateChangeCallback(OIC::Service::ResourceState state)
+{
+
+ LOGI("JniResourceStateChangeListener::stateChangeCallback enter");
+
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+
+ jobject jListener = env->NewLocalRef(m_jwListener);
+ if (!jListener)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ jclass clsL = env->GetObjectClass(jListener);
+ if (!clsL)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+ jmethodID midL = env->GetMethodID(clsL, "onStateChanged",
+ "(Lorg/iotivity/ResourceEncapsulation/client/RCSRemoteResourceObject$ResourceState;)V");
+ if (!midL)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+ jobject resourcestate = convertNativeResourceStateToJavaResourceState(state, env);
+ env->CallVoidMethod(jListener, midL, resourcestate);
+
+ if (env->ExceptionCheck())
+ {
+ LOGE("Java exception is thrown");
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+}
+
+void JniResourceStateChangeListener::checkExAndRemoveListener(JNIEnv *env)
+{
+ if (env->ExceptionCheck())
+ {
+ jthrowable ex = env->ExceptionOccurred();
+ env->ExceptionClear();
+ m_ownerResource->removeOnStateChangeListener(env, m_jwListener);
+ env->Throw((jthrowable)ex);
+ }
+ else
+ {
+ m_ownerResource->removeOnStateChangeListener(env, m_jwListener);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_set_request_listener.h"
+#include "jni_re_resource_object.h"
+
+JniSetRequestListener::JniSetRequestListener(JNIEnv *env, jobject jListener,
+ JniRCSResourceObject *owner)
+ : m_ownerResource(owner)
+{
+ m_jwListener = env->NewWeakGlobalRef(jListener);
+}
+
+JniSetRequestListener::~JniSetRequestListener()
+{
+ LOGI("JniSetRequestListener::~JniSetRequestListener()");
+ if (m_jwListener)
+ {
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+ env->DeleteWeakGlobalRef(m_jwListener);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ }
+}
+
+OIC::Service::RCSSetResponse JniSetRequestListener::onSetRequestCallback(
+ OIC::Service::RCSRequest request, OIC::Service::RCSResourceAttributes attributes)
+{
+ LOGI("JniGetRequestListener::onSetRequestCallback enter");
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env)
+ LOGE("onSetRequestCallback: env is NULL");
+
+ jobject jListener = env->NewLocalRef(m_jwListener);
+ if (!jListener)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGE("onSetRequestCallback: jListener is NULL");
+ }
+
+ jclass clsL = env->GetObjectClass(jListener);
+
+ if (!clsL)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGE("onSetRequestCallback: clsL is NULL");
+ }
+
+ //constructing java attribute object..
+ RCSResourceAttributes *attributesObj = new RCSResourceAttributes(attributes);
+ jlong handle = reinterpret_cast<jlong>(attributesObj);
+ jobject jAttributes = env->NewObject(g_cls_RCSRemoteResourceAttributesObject,
+ g_mid_RCSRemoteResourceAttributesObject_ctor,
+ handle, true);
+ if (!jAttributes)
+ {
+ delete attributesObj;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGE("onGetRequestCallback: jAttributes == null");
+ }
+
+ //constructing java RCSRequest object
+ std::string resourceUri = request.getResourceUri();
+ jstring javaUri = env->NewStringUTF(resourceUri.c_str());
+
+ g_mid_RCSRequest_ctor = env->GetMethodID(g_cls_RCSRequest, "<init>", "(Ljava/lang/String;)V");
+ jobject javaRCSRequestObject = env->NewObject( g_cls_RCSRequest, g_mid_RCSRequest_ctor, javaUri);
+
+ //getting the method ID
+ jmethodID midL = env->GetMethodID(clsL, "onSetRequest",
+ "(Lorg/iotivity/ResourceEncapsulation/server/RCSRequest;Lorg/iotivity/ResourceEncapsulation/common/RCSResourceAttributes;)Lorg/iotivity/ResourceEncapsulation/server/RCSSetResponse;");
+
+ if (!midL)
+ {
+ delete attributesObj;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGI("onGetRequestCallback: midL == null");
+ }
+
+ //calling the Java method
+ jobject javaSetResponse = env->CallObjectMethod(jListener, midL, javaRCSRequestObject,
+ jAttributes); //todo
+
+ //getting the information related to Response
+ jclass SetResponseClass = env->GetObjectClass(javaSetResponse);
+
+ jmethodID midSetTypeOfGetResponse = env->GetMethodID(SetResponseClass, "getTypeOfGetResponse",
+ "()I");
+ jint type = env->CallIntMethod(javaSetResponse, midSetTypeOfGetResponse);
+
+ if (0 == type)
+ {
+ LOGI("Type == Default");
+ return OIC::Service::RCSSetResponse::defaultAction();
+ }
+ else if (1 == type)
+ {
+ LOGI("Type == 1");
+ jmethodID midGetResult = env->GetMethodID(SetResponseClass, "getResult", "()I");
+ jmethodID midGetErrorCode = env->GetMethodID(SetResponseClass, "getErrorCode", "()I");
+ jint handlerResult = env->CallIntMethod(javaSetResponse, midGetResult);
+ jint errorCode = env->CallIntMethod(javaSetResponse, midGetErrorCode);
+ OCEntityHandlerResult nativeHandlerResult = convertIntToOCEntityHandlerResult(handlerResult);
+ return OIC::Service::RCSSetResponse::create(nativeHandlerResult, errorCode);
+ }
+ else if (2 == type)
+ {
+ LOGI("Type == 2");
+ jmethodID midGetAttributes = env->GetMethodID(SetResponseClass, "getAttributes",
+ "()Lorg/iotivity/ResourceEncapsulation/common/RCSResourceAttributes;");
+ jobject attributes = env->CallObjectMethod(javaSetResponse, midGetAttributes);
+ RCSResourceAttributes *attributesObj = JniResourceAttributes::getResourceAttributePtr(env,
+ attributes);
+ return OIC::Service::RCSSetResponse::create(*attributesObj);
+ }
+ else if (3 == type)
+ {
+ LOGI("Type == 3");
+ jmethodID midGetResult = env->GetMethodID(SetResponseClass, "getResult", "()I");
+ jmethodID midGetErrorCode = env->GetMethodID(SetResponseClass, "getErrorCode", "()I");
+ jint handlerResult = env->CallIntMethod(javaSetResponse, midGetResult);
+ jint errorCode = env->CallIntMethod(javaSetResponse, midGetErrorCode);
+ OCEntityHandlerResult nativeHandlerResult = convertIntToOCEntityHandlerResult(handlerResult);
+ jmethodID midGetAttributes = env->GetMethodID(SetResponseClass, "getAttributes",
+ "()Lorg/iotivity/ResourceEncapsulation/common/RCSResourceAttributes;");
+ jobject attributes = env->CallObjectMethod(javaSetResponse, midGetAttributes);
+ RCSResourceAttributes *attributesObj = JniResourceAttributes::getResourceAttributePtr(env,
+ attributes);
+ return OIC::Service::RCSSetResponse::create(*attributesObj, nativeHandlerResult, errorCode);
+ }
+ else if (4 == type)
+ {
+ LOGI("Type == 4");
+ return OIC::Service::RCSSetResponse::accept();
+ }
+ else if (5 == type)
+ {
+ LOGI("Type == 5");
+ jmethodID midGetResult = env->GetMethodID(SetResponseClass, "getResult", "()I");
+ jmethodID midGetErrorCode = env->GetMethodID(SetResponseClass, "getErrorCode", "()I");
+ jint handlerResult = env->CallIntMethod(javaSetResponse, midGetResult);
+ jint errorCode = env->CallIntMethod(javaSetResponse, midGetErrorCode);
+ OCEntityHandlerResult nativeHandlerResult = convertIntToOCEntityHandlerResult(handlerResult);
+ return OIC::Service::RCSSetResponse::accept(nativeHandlerResult, errorCode);
+ }
+ else if (6 == type)
+ {
+ LOGI("Type == 6");
+ return OIC::Service::RCSSetResponse::ignore();
+ }
+ else if (7 == type)
+ {
+ LOGI("Type == 7");
+ jmethodID midGetResult = env->GetMethodID(SetResponseClass, "getResult", "()I");
+ jmethodID midGetErrorCode = env->GetMethodID(SetResponseClass, "getErrorCode", "()I");
+ jint handlerResult = env->CallIntMethod(javaSetResponse, midGetResult);
+ jint errorCode = env->CallIntMethod(javaSetResponse, midGetErrorCode);
+ OCEntityHandlerResult nativeHandlerResult = convertIntToOCEntityHandlerResult(handlerResult);
+ return OIC::Service::RCSSetResponse::ignore(nativeHandlerResult, errorCode);
+ }
+ else
+ {
+ LOGI("Default action");
+ return OIC::Service::RCSSetResponse::defaultAction();
+ }
+
+ if (env->ExceptionCheck())
+ {
+ LOGE("Java exception is thrown");
+ delete attributesObj;
+ }
+
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ LOGI("JniGetRequestListener::onSetRequestCallback exit");
+}
+
+void JniSetRequestListener::checkExAndRemoveListener(JNIEnv *env)
+{
+ if (env->ExceptionCheck())
+ {
+ jthrowable ex = env->ExceptionOccurred();
+ env->ExceptionClear();
+ m_ownerResource->removeOnSetRequestListener(env, m_jwListener);
+ env->Throw((jthrowable)ex);
+ }
+ else
+ {
+ m_ownerResource->removeOnSetRequestListener(env, m_jwListener);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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 "jni_re_setattributes_listener.h"
+#include "jni_re_rcs_remoteresourceobject.h"
+
+JniSetAttributesListener::JniSetAttributesListener(JNIEnv *env, jobject jListener,
+ JniRCSRemoteResourceObject *owner)
+ : m_ownerResource(owner)
+{
+ m_jwListener = env->NewWeakGlobalRef(jListener);
+}
+
+JniSetAttributesListener::~JniSetAttributesListener()
+{
+ LOGI("~JniGetAttributesListener()");
+ if (m_jwListener)
+ {
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+ env->DeleteWeakGlobalRef(m_jwListener);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ }
+}
+
+void JniSetAttributesListener::onRemoteAttributesSetCallback(OIC::Service::RCSResourceAttributes
+ attributes)
+{
+
+ LOGI("JniSetAttributesListener::onRemoteAttributesSetCallback : got attributes");
+
+ jint ret;
+ JNIEnv *env = GetREJNIEnv(ret);
+ if (NULL == env) return;
+
+ jobject jListener = env->NewLocalRef(m_jwListener);
+ if (!jListener)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ jclass clsL = env->GetObjectClass(jListener);
+
+ if (!clsL)
+ {
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ RCSResourceAttributes *attributesObj = new RCSResourceAttributes(attributes);
+ jlong handle = reinterpret_cast<jlong>(attributesObj);
+ jobject jAttributes = env->NewObject(g_cls_RCSRemoteResourceAttributesObject,
+ g_mid_RCSRemoteResourceAttributesObject_ctor,
+ handle, true);
+ if (!jAttributes)
+ {
+ delete attributesObj;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+
+ jmethodID midL = env->GetMethodID(clsL, "onRemoteAttributesSetCallback",
+ "(Lorg/iotivity/ResourceEncapsulation/common/RCSResourceAttributes;)V");
+
+ if (!midL)
+ {
+ delete attributesObj;
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ return;
+ }
+ env->CallVoidMethod(jListener, midL, jAttributes);
+ if (env->ExceptionCheck())
+ {
+ LOGE("Java exception is thrown");
+ delete attributesObj;
+ }
+
+ checkExAndRemoveListener(env);
+ if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+}
+
+void JniSetAttributesListener::checkExAndRemoveListener(JNIEnv *env)
+{
+ if (env->ExceptionCheck())
+ {
+ jthrowable ex = env->ExceptionOccurred();
+ env->ExceptionClear();
+ m_ownerResource->removeOnsetAttributesListener(env, m_jwListener);
+ env->Throw((jthrowable)ex);
+ }
+ else
+ {
+ m_ownerResource->removeOnsetAttributesListener(env, m_jwListener);
+ }
+}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-21
+android.library=true
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+/**
+ * @file
+ * This file provides a class for a set of APIs relating to resource address and the
+ * the type of discovery request for a resource of interest.
+ */
+
+package org.iotivity.ResourceEncapsulation.client;
+
+import org.iotivity.ResourceEncapsulation.utils.DiscoveryType;
+
+/**
+ * This class provides a set of APIs for constructing RCSAddress object.
+ *
+ * <p>
+ * RCSAddress object is the first parameter for Discover Resource APIs of
+ * RCSDiscoveryManager Class.
+ * <p>
+ * {@link RCSDiscoveryManager}
+ */
+public class RCSAddress {
+
+ static {
+ System.loadLibrary("gnustl_shared");
+ System.loadLibrary("oc_logger");
+ System.loadLibrary("connectivity_abstraction");
+ System.loadLibrary("ca-interface");
+ System.loadLibrary("octbstack");
+ System.loadLibrary("oc");
+ System.loadLibrary("ocstack-jni");
+ System.loadLibrary("rcs_common");
+ System.loadLibrary("rcs_client");
+ System.loadLibrary("rcs_server");
+ System.loadLibrary("rcs_container");
+ System.loadLibrary("re-jni");
+ }
+
+ private String m_address;
+ private DiscoveryType m_typeOfDiscovery;
+ private static RCSAddress m_rcsAddressInstance;
+
+ private RCSAddress(String addr, DiscoveryType discoveryType) {
+ m_address = addr;
+ m_typeOfDiscovery = discoveryType;
+ }
+
+ /**
+ * Constructs a RCSAddress object for multicast discovery.
+ *
+ * @return RCSAddress - Instance of RCSAddress.
+ *
+ * {@link RCSAddress}
+ */
+ public static RCSAddress multicast() {
+ m_rcsAddressInstance = new RCSAddress("", DiscoveryType.MULTICAST);
+ return m_rcsAddressInstance;
+ }
+
+ /**
+ * Constructs a RCSAddress object for setting unicast discovery.
+ *
+ * @param address
+ * required discovery address for the unicast resource discovery.
+ *
+ * @return RCSAddress -Instance of RCSAddress.
+ *
+ * {@link RCSAddress}
+ */
+ public static RCSAddress unicast(String address) {
+ m_rcsAddressInstance = new RCSAddress(address, DiscoveryType.UNICAST);
+ return m_rcsAddressInstance;
+ }
+
+ // APIs used by DiscoveryManager class for getting the address information.
+
+ /**
+ * Get the discovery resource address in string format.
+ *
+ * @return String - Discovery address in string format.
+ */
+ public String getAddress() {
+ return m_address;
+ }
+
+ /**
+ * Get the resource discovery type(unicast or multicast).
+ *
+ * @return int - 0 for unicast and 1 for multicast.
+ */
+ public DiscoveryType getTypeOfDiscovery() {
+ return m_typeOfDiscovery;
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+/**
+ * @file
+ * This file provides a class for a set of APIs relating to discovery of a particular
+ * resource in the network
+ */
+
+package org.iotivity.ResourceEncapsulation.client;
+
+import org.iotivity.ResourceEncapsulation.common.RCSException;
+import org.iotivity.ResourceEncapsulation.utils.DiscoveryType;
+
+import android.util.Log;
+
+/**
+ * This class contains the resource discovery method.
+ *
+ * {@link RCSRemoteResourceObject}
+ */
+public class RCSDiscoveryManager {
+
+ private IDiscoverResourceListener m_discoverListener;
+ private static RCSDiscoveryManager m_rcsDiscoveryManagerInstacne;
+ private final String OC_RSRVD_WELL_KNOWN_URI = "/oic/res";
+ private final String LOG_TAG = this.getClass()
+ .getSimpleName();
+
+ private native void discoverResource(String address, int typeOfDiscovery,
+ String relativeUri, String resourceType,
+ IDiscoverResourceListener listener);
+
+ /**
+ * Constructor for RCSDiscoveryManager. Set listener to null on constructing
+ * new RCSDiscoveryManager.
+ */
+ private RCSDiscoveryManager() {
+ }
+
+ /**
+ * Returns RCSDiscoveryManager instance if already present else creates a
+ * new instance of RCSDiscoveryManager.
+ *
+ * @return RCSDiscoveryManager - Instance of RCSDiscoveryManager.
+ */
+ public static RCSDiscoveryManager getInstance() {
+ if (null == m_rcsDiscoveryManagerInstacne) {
+ m_rcsDiscoveryManagerInstacne = new RCSDiscoveryManager();
+ }
+ return m_rcsDiscoveryManagerInstacne;
+ }
+
+ /**
+ * Provides interface for receiving the callback for discovering a resource
+ * of interest.
+ */
+ public interface IDiscoverResourceListener {
+
+ /**
+ * This callback method is called when a asynchronous response for the
+ * discoverResource request is received.
+ *
+ * @param rcsRemoteResourceObject
+ * It is the resource for which discovery is requested..
+ *
+ * {@link RCSDiscoveryManager}
+ * {@link RCSRemoteResourceObject}
+ */
+ public void onResourceDiscovered(
+ RCSRemoteResourceObject rcsRemoteResourceObject);
+
+ }
+
+ /**
+ * Set listener for receiving asynchronous response for resource discovery
+ * request.
+ *
+ * @param listener
+ * setDiscoverResourceListener to receive the discovered
+ * resources.
+ */
+ public void setDiscoverResourceListener(IDiscoverResourceListener listener) {
+ m_discoverListener = listener;
+ }
+
+ /**
+ * API for discovering the resource of Interest, regardless of URI and
+ * resource type
+ *
+ * @param address
+ * A RCSAddress object
+ *
+ * @throws RCSException
+ * {@link RCSAddress}
+ */
+ public void discoverResource(RCSAddress address) throws RCSException {
+
+ Log.i(LOG_TAG, "discoverResource called");
+ discoverResourceByType(address, OC_RSRVD_WELL_KNOWN_URI, "");
+ }
+
+ /**
+ * API for discovering the resource of Interest, regardless of resource
+ * type.
+ *
+ * @param address
+ * A RCSAddress object
+ * @param relativeURI
+ * The relative uri of resource to be searched
+ *
+ * @throws RCSException
+ * {@link RCSAddress}
+ */
+ public void discoverResource(RCSAddress address, String relativeURI)
+ throws RCSException {
+
+ Log.i(LOG_TAG, "discoverResource called");
+ discoverResourceByType(address, relativeURI, "");
+ }
+
+ /**
+ * API for discovering the resource of Interest by resource type.
+ *
+ * @param address
+ * A RCSAddress object
+ * @param resourceType
+ * Ressource Type
+ *
+ * @throws RCSException
+ * {@link RCSAddress}
+ */
+ public void discoverResourceByType(RCSAddress address, String resourceType)
+ throws RCSException {
+
+ Log.i(LOG_TAG, "discoverResource called");
+ discoverResourceByType(address, OC_RSRVD_WELL_KNOWN_URI, resourceType);
+ }
+
+ /**
+ * API for discovering the resource of Interest by Resource type with
+ * provided relativeURI
+ *
+ * @param address
+ * A RCSAddress object
+ * @param relativeURI
+ * The relative uri of resource to be searched
+ * @param resourceType
+ * Ressource Type
+ *
+ * @throws RCSException
+ * {@link RCSAddress}
+ */
+ public void discoverResourceByType(RCSAddress address, String relativeURI,
+ String resourceType) throws RCSException {
+
+ Log.i(LOG_TAG, "discoverResource called");
+
+ if(null == address){
+ Log.e(LOG_TAG, "Empty Address");
+ throw (new RCSException("Empty Address"));
+ }
+ String addr = address.getAddress();
+
+ if(null == relativeURI || "" == relativeURI){
+ Log.e(LOG_TAG, "Empty URI");
+ throw (new RCSException("Empty URI"));
+ }
+
+ DiscoveryType typeOfDiscovery = address.getTypeOfDiscovery();
+ this.discoverResource(addr, typeOfDiscovery.ordinal(), relativeURI,
+ resourceType, m_discoverListener);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+/**
+ * @file
+ * This file provides a class which provides a set of native functions and API's
+ * of resource client, provided to the developers.
+ */
+
+package org.iotivity.ResourceEncapsulation.client;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.iotivity.ResourceEncapsulation.common.RCSException;
+import org.iotivity.ResourceEncapsulation.common.RCSResourceAttributes;
+
+import android.util.Log;
+
+/**
+ *
+ * The resource can be discovered with discoverResource. On successful resource
+ * discovery an instance of this class is returned. This class is an interaction
+ * point between Resource and the developers. Developer will get the
+ * RCSRemoteResourceObject by calling RCSDiscoveryManager's discoverResource
+ * API.
+ *
+ * {@link RCSDiscoveryManager}
+ */
+public class RCSRemoteResourceObject {
+
+ private IStateChangedCallbackListener m_stateChangedListener;
+ private ICacheUpdateListener m_cacheUpdateListener;
+ private IGetRemoteAttributeListener m_getremoteAttributeListener;
+ private ISetRemoteAttributeListener m_setremoteAttributeListener;
+ private long m_nativeHandle;
+ private String LOG_TAG = this.getClass()
+ .getSimpleName();
+
+ // native methods
+ private native boolean nativeIsMonitoring();
+
+ private native boolean nativeIsCaching();
+
+ private native boolean nativeIsObservable();
+
+ private native void nativeStartMonitoring(
+ IStateChangedCallbackListener listener);
+
+ private native void nativeStopMonitoring();
+
+ private native int nativeGetState();
+
+ private native void nativeStartCaching(ICacheUpdateListener listener);
+
+ private native void nativeStopCaching();
+
+ private native int nativeGetCacheState();
+
+ private native boolean nativeIsCachedAvailable();
+
+ private native RCSResourceAttributes nativeGetCachedAttributes();
+
+ private native String nativeGetCachedAttribute(String key);
+
+ private native void nativeGetRemoteAttributes(
+ IGetRemoteAttributeListener listener);
+
+ private native void nativeSetRemoteAttributes(
+ RCSResourceAttributes attributes,
+ ISetRemoteAttributeListener listener);
+
+ private native String nativeGetUri();
+
+ private native String nativeGetAddress();
+
+ private native List<String> nativeGetTypes();
+
+ private native List<String> nativeGetInterFaces();
+
+ private RCSRemoteResourceObject(long nativeHandle) {
+ this.m_nativeHandle = nativeHandle;
+ }
+
+ /**
+ * This Enum contains Status codes for resource state.
+ *
+ * <p>
+ * Developer will get the ResoureState as a result of getState API of
+ * RCSRemoteResourceObject class and as a callback result of startMonitoring
+ * API
+ *
+ * {@link RCSRemoteResourceObject}
+ */
+ public enum ResourceState {
+
+ NONE, /* < Monitoring is not started. */
+ REQUESTED, /*
+ * < Monitoring is started and checking state is in progress.
+ * This is the default state after startMonitoring.
+ */
+ ALIVE, /* < The resource is alive. */
+ LOST_SIGNAL, /* < Failed to reach the resource. */
+ DESTROYED;
+ /* < The resource is deleted. */
+
+ /*
+ * Utility API for integer to enum conversion.
+ */
+ public static ResourceState getResourceState(int ordinal) {
+
+ if (ordinal == 0)
+ return ResourceState.values()[0];
+ else if (ordinal == 1)
+ return ResourceState.values()[1];
+ else if (ordinal == 2)
+ return ResourceState.values()[2];
+ else if (ordinal == 3)
+ return ResourceState.values()[3];
+ else if (ordinal == 4)
+ return ResourceState.values()[4];
+
+ return null;
+ }
+ }
+
+ /**
+ * This Enum contains Status codes for cache state.
+ *
+ * <p>
+ * Application will get this CacheState as a result of getCacheState API of
+ * RCSRemoteResourceObject class
+ *
+ * {@link RCSRemoteResourceObject}
+ */
+ public enum CacheState {
+
+ NONE, /* < Caching is not started. */
+ UNREADY, /*
+ * < Caching is started, but the data is not ready yet. This is
+ * the default state after startCaching.
+ */
+ READY, /* < The data is ready. */
+ LOST_SIGNAL;
+ /* < Failed to reach the resource. */
+
+ /*
+ * Utility API for int to enum conversion.
+ */
+ public static CacheState getCacheState(int ordinal) {
+
+ if (ordinal == 0)
+ return CacheState.values()[0];
+ else if (ordinal == 1)
+ return CacheState.values()[1];
+ else if (ordinal == 2)
+ return CacheState.values()[2];
+ else if (ordinal == 3)
+ return CacheState.values()[3];
+
+ return null;
+ }
+ }
+
+ /**
+ * Provides interface for receiving the callback on cache update.
+ */
+ public interface ICacheUpdateListener {
+
+ /**
+ * This callback method is called when a asynchronous response for
+ * startCaching request is received. Listener should be set to receive
+ * this callback.
+ *
+ * @param attributes
+ * It is the updated resource attributes.
+ *
+ * {@link RCSResourceAttributes}
+ */
+ public void onCacheUpdatedCallback(RCSResourceAttributes attributes);
+
+ }
+
+ /**
+ * Provides interface for receiving the callback for the getRemoteAttributes
+ * requested action.
+ */
+ public interface IGetRemoteAttributeListener {
+
+ /**
+ * This callback method is called when a asynchronous response for the
+ * getRemoteAttributes request is received.
+ *
+ * @param attributes
+ * It is the updated resource attributes value received from
+ * the remote resource.
+ *
+ * {@link RCSResourceAttributes}
+ */
+ public void onRemoteAttributesGetCallback(
+ RCSResourceAttributes attributes);
+
+ }
+
+ /**
+ * Provides interface for receiving the callback for the setRemoteAttributes
+ * requested action.
+ */
+ public interface ISetRemoteAttributeListener {
+
+ /**
+ * This callback method is called when a asynchronous response for the
+ * setRemoteAttributes request is received.
+ *
+ * @param attributes
+ * It is the updated resource attributes value received from
+ * the remote resource.
+ *
+ * {@link RCSResourceAttributes}
+ */
+ public void onRemoteAttributesSetCallback(
+ RCSResourceAttributes attributes);
+
+ }
+
+ /**
+ * Provides interface for receiving the callback for the startMonitoring
+ * This callback is received on remote resource state change.
+ */
+ public interface IStateChangedCallbackListener {
+
+ /**
+ * This callback method is called when a asynchronous response for the
+ * startMonitoring request is received.
+ *
+ * @param resourceState
+ * It gives the current remote resource state.
+ *
+ * {@link ResourceState}
+ */
+ public void onStateChanged(ResourceState resourceState);
+ }
+
+ /**
+ * Set listener for receiving asynchronous response for cache updates.
+ *
+ * @param listener
+ * ICacheUpdateListener to receive asynchronous response for
+ * cache updates.
+ */
+ public void setCacheUpdateListener(ICacheUpdateListener listener) {
+ m_cacheUpdateListener = listener;
+ }
+
+ /**
+ * Set listener for receiving asynchronous response for remote resource
+ * state changes.
+ *
+ * @param listener
+ * IStateChangedCallbackListener to receive asynchronous response
+ * for remote resource state changes.
+ */
+ public void setStateChangedListener(IStateChangedCallbackListener listener) {
+ m_stateChangedListener = listener;
+ }
+
+ /**
+ * Set listener for receiving asynchronous response for resource attributes
+ * GET request.
+ *
+ * @param listener
+ * IGetRemoteAttributeListener to receive asynchronous response
+ * for resource attributes SET and GET request.
+ */
+ public void setGetRemoteAttributesListener(
+ IGetRemoteAttributeListener listener) {
+ m_getremoteAttributeListener = listener;
+ }
+
+ /**
+ * Set listener for receiving asynchronous response for resource attributes
+ * SET request.
+ *
+ * @param listener
+ * IGetRemoteAttributeListener to receive asynchronous response
+ * for resource attributes SET and GET request.
+ */
+ public void setSetRemoteAttributesListener(
+ ISetRemoteAttributeListener listener) {
+ m_setremoteAttributeListener = listener;
+ }
+
+ /**
+ * Returns whether monitoring is enabled.
+ *
+ * @return boolean - true if monitoring the resource.
+ *
+ * {@link #startMonitoring()}
+ */
+ public boolean isMonitoring() {
+
+ Log.i(LOG_TAG, "isMonitoring called");
+ return this.nativeIsMonitoring();
+ }
+
+ /**
+ * Returns whether caching is enabled.
+ *
+ * @return boolean - true if caching the resource.
+ *
+ * {@link #startCaching()}
+ */
+ public boolean isCaching() {
+
+ Log.i(LOG_TAG, "isCaching called");
+ return this.nativeIsCaching();
+ }
+
+ /**
+ * Returns whether resource is observable.
+ *
+ * @return boolean - true if resource is observable.
+ *
+ */
+ public boolean isObservable() {
+
+ Log.i(LOG_TAG, "isObservable called");
+ return this.nativeIsObservable();
+ }
+
+ /**
+ * Starts monitoring the resource.
+ * <p>
+ * Monitoring provides a feature to check the presence of a resource, even
+ * when the server is not announcing Presence using startPresnece.
+ * <p>
+ * StateChangedListener should be set before calling this API
+ *
+ * @throws RCSException
+ * If monitoring is already started.
+ *
+ * {@link IStateChangedCallbackListener} {@link ResourceState}
+ * {@link #isMonitoring()} {@link #stopMonitoring()}
+ */
+ public void startMonitoring() throws RCSException {
+
+ Log.i(LOG_TAG, "startMonitoring called");
+ this.nativeStartMonitoring(m_stateChangedListener);
+ }
+
+ /**
+ * Stop monitoring the resource.
+ * <p>
+ * It does nothing if monitoring is not started.
+ * <p>
+ * {@link #startMonitoring()}
+ *
+ */
+ public void stopMonitoring() {
+
+ Log.i(LOG_TAG, "stopMonitoring called");
+ this.nativeStopMonitoring();
+ }
+
+ /**
+ * Returns the current state of the resource.
+ *
+ * @return ResourceState - current resource state
+ *
+ * {@link #startMonitoring()} {@link ResourceState}
+ */
+ public ResourceState getState() {
+
+ Log.i(LOG_TAG, "getState called");
+ int state = this.nativeGetState();
+
+ return ResourceState.getResourceState(state);
+ }
+
+ /**
+ * Starts caching attributes of the resource.
+ *
+ * This will start data caching for the resource. Once caching started it
+ * will look for the data updation on the resource and updates the cache
+ * data accordingly.
+ *
+ * @throws RCSException
+ *
+ * <p>
+ * If this method is called with null listener it will not
+ * notify the updated value to caller. It it is called with a
+ * valid listener updated cached values will be notified to
+ * caller.
+ *
+ * {@link #getCacheState()} {@link #getCachedAttributes()}
+ */
+ public void startCaching() throws RCSException {
+
+ if (null == m_cacheUpdateListener) {
+ Log.i(LOG_TAG, "startCaching WITHOUT callback");
+ } else {
+ Log.i(LOG_TAG, "startCaching WITH callback");
+ }
+
+ this.nativeStartCaching(m_cacheUpdateListener);
+ }
+
+ /**
+ * Stops caching.
+ *
+ * It does nothing if caching is not started.
+ *
+ * {@link #startCaching()}
+ */
+ public void stopCaching() {
+
+ Log.i(LOG_TAG, "stopCaching called");
+ this.nativeStopCaching();
+ }
+
+ /**
+ * Returns the current cache state.
+ *
+ * @return CacheState - current cache state.
+ *
+ * {@link CacheState}
+ */
+ public CacheState getCacheState() {
+
+ Log.i(LOG_TAG, "getCacheState called");
+ return CacheState.getCacheState(this.nativeGetCacheState());
+ }
+
+ /**
+ * Returns whether cached data is available.
+ *
+ * Cache will be available always after cache state READY even if current
+ * state is LOST_SIGNAL.
+ *
+ * @return boolean - true if cache data is available.
+ *
+ * {@link #startCaching()} {@link CacheState}
+ */
+ public boolean isCachedAvailable() {
+
+ Log.i(LOG_TAG, "isCachedAvailable called");
+ return this.nativeIsCachedAvailable();
+ }
+
+ /**
+ * Gets the cached RCSResourceAttributes data.
+ *
+ * <p>
+ * Cache should be available.
+ *
+ * @return The cached attributes.
+ *
+ * @throws RCSException
+ * If the Cache is not started.
+ *
+ * {@link RCSResourceAttributes} {@link #isCachedAvailable()}
+ * {@link #startCaching()}
+ */
+ public RCSResourceAttributes getCachedAttributes() throws RCSException {
+
+ Log.i(LOG_TAG, "getCachedAttributes called");
+ return this.nativeGetCachedAttributes();
+ }
+
+ /**
+ * Gets a particular cached ResourceAttribute Value.
+ *
+ * <p>
+ * Cache should be available.
+ *
+ * @param key
+ * particular attribute name as a string to get the value for.
+ *
+ * @return String - Requested attribute value in string.
+ *
+ * @throws RCSException
+ * If the Cache is not started or InvalidKeyException If @a key
+ * doesn't match the key of any value.
+ *
+ * {@link RCSResourceAttributes} {@link #isCachedAvailable()}
+ * {@link #startCaching()}
+ */
+ public String getCachedAttribute(String key) throws RCSException {
+
+ Log.i(LOG_TAG, "getCachedAttribute called");
+ return this.nativeGetCachedAttribute(key);
+ }
+
+ /**
+ * Gets resource attributes directly from the server.
+ *
+ * This API send a get request to the resource of interest and provides the
+ * attributes to the caller in the RemoteAttributesReceivedCallback.
+ *
+ * <p>
+ * IGetRemoteAttributeListener should be set to get the attributes
+ *
+ * @throws RCSException
+ * {@link IGetRemoteAttributeListener}
+ */
+ public void getRemoteAttributes() throws RCSException {
+
+ Log.i(LOG_TAG, "getRemoteAttributes called");
+ this.nativeGetRemoteAttributes(m_getremoteAttributeListener);
+ }
+
+ /**
+ * Sends a set request with resource attributes to the server.
+ *
+ * The SetRequest behavior depends on the server, whether updating its
+ * attributes or not.
+ *
+ * @param attributes
+ * Attribute value to set for the remote resource.
+ *
+ * <p>
+ * ISetRemoteAttributeListener should be set to call this API
+ *
+ * @throws RCSException
+ * {@link ISetRemoteAttributeListener}
+ */
+ public void setRemoteAttributes(RCSResourceAttributes attributes)
+ throws RCSException {
+
+ Log.i(LOG_TAG, "getRemoteAttributes called");
+ this.nativeSetRemoteAttributes(attributes, m_setremoteAttributeListener);
+ }
+
+ /**
+ * Returns the uri of the resource.
+ *
+ * @return Uri of the resource
+ */
+ public String getUri() {
+
+ Log.i(LOG_TAG, "getUri called");
+ return this.nativeGetUri();
+ }
+
+ /**
+ * Returns the address of the resource .
+ *
+ * @return Address of the resource
+ */
+ public String getAddress() {
+
+ Log.i(LOG_TAG, "getAddress called");
+ return this.nativeGetAddress();
+ }
+
+ /**
+ * Returns the resource types of the resource.
+ *
+ * @return vector containing resource types
+ */
+ public Vector<String> getTypes() {
+
+ Log.i(LOG_TAG, "getTypes called");
+ List<String> types = this.nativeGetTypes();
+ Vector<String> resourceType = new Vector<String>();
+ resourceType.addAll(types);
+ return resourceType;
+ }
+
+ /**
+ * Returns the resource interfaces of the resource.
+ *
+ * @return vector containing resource Interfaces
+ */
+ public Vector<String> getInterFaces() {
+
+ Log.i(LOG_TAG, "getInterFaces called");
+ List<String> interfaces = this.nativeGetInterFaces();
+ Vector<String> resourceInterfaces = new Vector<String>();
+ resourceInterfaces.addAll(interfaces);
+ return resourceInterfaces;
+ }
+}
*
******************************************************************/
/**
- * @file IFindCandidateResourceListener.java
- *
- * @brief This file provides interface for getting notification when resources are
- * discovered in network.
+ * @file
+ *This file provides RCSException class for RE layer
*/
-package org.iotivity.service.tm;
-
-import java.util.Vector;
-
-import org.iotivity.base.OcResource;
+package org.iotivity.ResourceEncapsulation.common;
/**
- * Provides interface for getting notification when resources are
- * discovered in network.
+ * This is the Exception class for the Resource Encapsulation APIs
*/
-public interface IFindCandidateResourceListener {
- /**
- * This callback method will be called whenever resource is discovered in
- * the network.
- *
- * @param resources
- * List of resources discovered in the network
- */
- public void onResourceCallback(Vector<OcResource> resources);
+public class RCSException extends Exception {
+
+ public RCSException(String exception) {
+ super(exception);
+ }
}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+/**
+ * @file
+ * This file provides a class which represents the attributes for a resource.
+ */
+
+package org.iotivity.ResourceEncapsulation.common;
+
+import org.iotivity.ResourceEncapsulation.client.RCSDiscoveryManager;
+import org.iotivity.ResourceEncapsulation.client.RCSRemoteResourceObject;
+import org.iotivity.ResourceEncapsulation.server.RCSResourceObject;
+
+/**
+ * RCSResourceAttributes represents the attributes for a resource.
+ *
+ * An attribute value can be one of various types : integer, double, boolean,
+ * String.
+ *
+ * <p>
+ * If developer on client side wants to get the RCSResourceAttributes for the
+ * resource of interest following are the steps: - first call the discover API
+ * of DiscoveryManager class. - After getting the RemoteResourceObject, call
+ * getRemoteAttributes() API of RemoteResourceObject class
+ *
+ * If the developer on server side wants to get the attributes following are the
+ * steps: Call the getAttributes() API of RCSResourceObject class.
+ *
+ * {@link RCSDiscoveryManager} {@link RCSRemoteResourceObject}
+ * {@link RCSResourceObject}
+ */
+public class RCSResourceAttributes {
+
+ private long m_nativeHandle;
+ private boolean m_nativeNeedsDelete;
+
+ // native methods
+ private native Object nativeGetValueN(String key);
+
+ private native void nativeSetValueInteger(String key, int value);
+
+ private native void nativeSetValueDouble(String key, double value);
+
+ private native void nativeSetValueBoolean(String key, boolean value);
+
+ private native void nativeSetValueString(String key, String value);
+
+ private native boolean nativeIsEmpty();
+
+ private native int nativeSize();
+
+ private native boolean nativeRemove(String key);
+
+ private native boolean nativeHasAttribute(String key);
+
+ private native void create();
+
+ private native void dispose(boolean needsDelete);
+
+ /**
+ * Constructor for RCSResourceAttributes. Invokes create() which internally
+ * constructs a new RCSResourceAttributes and sets its handle.
+ *
+ * <p>
+ * Native RCSResourceAttributes object was created using "new" and needs to
+ * be deleted
+ */
+ public RCSResourceAttributes() {
+ create();
+ this.m_nativeNeedsDelete = true;
+ }
+
+ private RCSResourceAttributes(long nativeHandle) {
+ this.m_nativeHandle = nativeHandle;
+ this.m_nativeNeedsDelete = false;
+ }
+
+ private RCSResourceAttributes(long nativeHandle, boolean nativeNeedsDelete) {
+ this.m_nativeHandle = nativeHandle;
+ this.m_nativeNeedsDelete = nativeNeedsDelete;
+ }
+
+ private <T> T getValue(String key) throws RCSException {
+ Object obj = this.nativeGetValueN(key);
+ T t = (T) obj;
+ return t;
+ }
+
+ /**
+ * get attribute value as an integer
+ *
+ * @param key
+ * - Key of the element.
+ *
+ * @return int - integer value of key provided.
+ */
+ public int getValueInt(String key) {
+ Integer value = 0;
+ try {
+ value = this.getValue(key);
+ } catch (RCSException e) {
+ e.printStackTrace();
+ }
+ return value;
+ }
+
+ /**
+ * get attribute value as a double
+ *
+ * @param key
+ * - Key of the element.
+ *
+ * @return boolean - boolean value of key provided.
+ */
+ public double getValueDouble(String key) {
+ double value = 0;
+ try {
+ value = this.getValue(key);
+ } catch (RCSException e) {
+ e.printStackTrace();
+ }
+ return value;
+ }
+
+ /**
+ * get attribute value as a boolean
+ *
+ * @param key
+ * - Key of the element.
+ *
+ * @return boolean - boolean value of key provided.
+ */
+ public boolean getValueBool(String key) {
+ Boolean value = false;
+ try {
+ value = this.getValue(key);
+ } catch (RCSException e) {
+ e.printStackTrace();
+ }
+ return value;
+ }
+
+ /**
+ * get attribute value as a string
+ *
+ * @param key
+ * - Key of the element.
+ *
+ * @return String - String value of key provided.
+ */
+ public String getValueString(String key) {
+ String value = "";
+ try {
+ value = this.getValue(key);
+ } catch (RCSException e) {
+ e.printStackTrace();
+ }
+ return value;
+ }
+
+ /**
+ * set an integer type attribute value.
+ *
+ * @param key
+ * - Key of the element to be added.
+ *
+ * @param value
+ * - integer value of key to be set.
+ *
+ * @throws RCSException
+ */
+ public void setValueInt(String key, int value) throws RCSException {
+ try {
+ this.nativeSetValueInteger(key, value);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * set a double attribute value.
+ *
+ * @param key
+ * - Key of the element to be added.
+ *
+ * @param value
+ * - double value of key to be set.
+ *
+ * @throws RCSException
+ */
+ public void setValueDouble(String key, double value) throws RCSException {
+ try {
+ this.nativeSetValueDouble(key, value);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * set a boolean attribute value.
+ *
+ * @param key
+ * - Key of the element to be added.
+ *
+ * @param value
+ * - integer value of key to be set.
+ *
+ * @throws RCSException
+ */
+ public void setValueBool(String key, boolean value) throws RCSException {
+ try {
+ this.nativeSetValueBoolean(key, value);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * set a string attribute value.
+ *
+ * @param key
+ * - Key of the element to be added.
+ *
+ * @param value
+ * - integer value of key to be set.
+ *
+ * @throws RCSException
+ */
+ public void setValueString(String key, String value) throws RCSException {
+ try {
+ this.nativeSetValueString(key, value);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Returns whether attribute is empty.
+ *
+ * @return boolean
+ */
+ public boolean isEmpty() {
+ return this.nativeIsEmpty();
+ }
+
+ /**
+ * Returns the number of elements.
+ *
+ * @return boolean
+ */
+ public int size() {
+ return this.nativeSize();
+ }
+
+ /**
+ * Removes a single attribute
+ *
+ * @param key
+ * Key to be removed.
+ *
+ * @return true if an attribute is removed, false otherwise.
+ */
+ public boolean remove(String key) {
+ return this.nativeRemove(key);
+ }
+
+ /**
+ * Checks the container has an attribute with a Key equivalent to the
+ * provided key.
+ *
+ * @param key
+ * Key to check.
+ *
+ * @return true if an attribute with requests key exists, false otherwise.
+ */
+ public boolean hasAttribute(String key) {
+ return this.nativeHasAttribute(key);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ dispose(this.m_nativeNeedsDelete);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+/**
+ * @file
+ * This file contains Builder class which provides the easy creation of Resource.
+ */
+
+package org.iotivity.ResourceEncapsulation.server;
+
+import org.iotivity.ResourceEncapsulation.common.RCSException;
+import org.iotivity.ResourceEncapsulation.common.RCSResourceAttributes;
+
+/**
+ * This class provides APIs for resource creation, setting properties and
+ * attributes for the constructed resource. It provides the build() API which
+ * builds a resource and returns RCSResourceObject.
+ *
+ * {@link RCSResourceObject}
+ */
+public class Builder {
+ static {
+ System.loadLibrary("gnustl_shared");
+ System.loadLibrary("oc_logger");
+ System.loadLibrary("connectivity_abstraction");
+ System.loadLibrary("ca-interface");
+ System.loadLibrary("octbstack");
+ System.loadLibrary("oc");
+ System.loadLibrary("ocstack-jni");
+ System.loadLibrary("rcs_common");
+ System.loadLibrary("rcs_client");
+ System.loadLibrary("rcs_server");
+ System.loadLibrary("rcs_container");
+ System.loadLibrary("re-jni");
+ }
+
+ private String m_resourceUri;
+ private String m_resourceType;
+ private String m_resourceInterface;
+ private boolean m_observableFlag;
+ private boolean m_discovervableFlag;
+ private RCSResourceAttributes m_attributes;
+
+ /**
+ * Native method for creation of Resource
+ */
+ private native RCSResourceObject nativeBuild(String resourceURI,
+ String resourceType, String resourceInterface,
+ boolean observableFlag, boolean discovervableFlag,
+ RCSResourceAttributes attributes);
+
+ /**
+ * Constructor
+ *
+ * @param resourceURI
+ * Resource URI value to be set
+ * @param resourceType
+ * Resource type value to be set
+ * @param resourceInterface
+ * Interface value to be set
+ */
+ public Builder(String resourceURI, String resourceType,
+ String resourceInterface) {
+ m_resourceUri = resourceURI;
+ m_resourceType = resourceType;
+ m_resourceInterface = resourceInterface;
+ }
+
+ /**
+ * Sets the discoverable(OC_DISCOVERABLE) property for the resource.
+ *
+ * @param isDiscoverable
+ * Whether to be discovered or not
+ */
+ public void setDiscoverable(boolean isDiscoverable) {
+ m_discovervableFlag = isDiscoverable;
+ }
+
+ /**
+ * Sets the observable(OC_OBSERVABLE) property of the resource.
+ *
+ * @param isObservable
+ * Whether to be observed or not
+ */
+ public void setObservable(boolean isObservable) {
+ m_observableFlag = isObservable;
+ }
+
+ /**
+ * API for setting attributes of the resource.
+ *
+ * @param attributes
+ * Resource Attributes to set
+ *
+ * {@link RCSResourceAttributes}
+ */
+ public void setAttributes(RCSResourceAttributes attributes) {
+ m_attributes = attributes;
+ }
+
+ /**
+ * API for constructing a new RCSResourceObject.
+ *
+ * @return RCSResourceObject object (It is the resource that is created)
+ *
+ * @throws RCSException
+ * It catches exception from registerResource API of OCPlatform
+ * and throws it to developer.
+ *
+ * <p>
+ * Steps for creation of Resource : - Get the object of this
+ * class by calling Constructor with resourceURI, resourceType,
+ * resourceInterface - Using the object set the Discoverable and
+ * Observable as needed. [optional] - Set the attributes for the
+ * resource. [optional] - At last call the build() method to
+ * create the resource.
+ */
+ public RCSResourceObject build() throws RCSException {
+ return this.nativeBuild(m_resourceUri, m_resourceType,
+ m_resourceInterface, m_observableFlag, m_discovervableFlag,
+ m_attributes);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+/**
+ * @file
+ * This file contains RCSBundleInfo class, which provides APIs related to Bundle information.
+ */
+
+package org.iotivity.ResourceEncapsulation.server;
+
+/**
+ * This class provides APIs for getting and setting the Bundle Information
+ */
+public class RCSBundleInfo {
+
+ private long m_nativeHandle;
+ private boolean m_nativeNeedsDelete;
+
+ // native methods
+ private native String nativeGetID();
+
+ private native String nativeGetPath();
+
+ private native String nativeGetActivatorName();
+
+ private native String nativeGetLibraryPath();
+
+ private native String nativeGetVersion();
+
+ private native void nativeSetID(String id);
+
+ private native void nativeSetPath(String path);
+
+ private native void nativeSetActivatorName(String activatorName);
+
+ private native void nativeSetLibraryPath(String libraryPath);
+
+ private native void nativeSetVersion(String version);
+
+ private RCSBundleInfo(long nativeHandle) {
+ this.m_nativeHandle = nativeHandle;
+ }
+
+ /**
+ * API for getting the Id of the bundle
+ *
+ * @return string - Id of the bundle
+ */
+ public String getID() {
+ return this.nativeGetID();
+ }
+
+ /**
+ * API for getting the path of the bundle
+ *
+ * @return path - path of the bundle
+ */
+ public String getPath() {
+ return this.nativeGetPath();
+ }
+
+ /**
+ * API for setting the Activator name for the bundle
+ *
+ * @return string - Name of the activator
+ */
+ public String getActivatorName() {
+ return nativeGetActivatorName();
+ }
+
+ /**
+ * API for getting the library path for the bundle
+ *
+ * @return string - Library path in string form
+ */
+ public String getLibraryPath() {
+ return nativeGetLibraryPath();
+ }
+
+ /**
+ * API for getting the version of the bundle
+ *
+ * @return string - version of the bundle
+ */
+ public String getVersion() {
+ return nativeGetVersion();
+ }
+
+ /**
+ * API for setting the Id of the bundle
+ *
+ * @param id
+ * - Id of the bundle in string form
+ */
+ public void setID(String id) {
+ this.nativeSetID(id);
+ }
+
+ /**
+ * API for setting the path of the bundle
+ *
+ * @param path
+ * - path of the bundle in string form
+ */
+ public void setPath(String path) {
+ this.nativeSetPath(path);
+ }
+
+ /**
+ * API for setting the Activator name for the bundle
+ *
+ * @param activatorName
+ * - Activator name in string form
+ */
+ public void setActivatorName(String activatorName) {
+ this.nativeSetActivatorName(activatorName);
+ }
+
+ /**
+ * API for setting the library path for the bundle
+ *
+ * @param libraryPath
+ * - Library path in string form
+ */
+ public void setLibraryPath(String libraryPath) {
+ this.nativeSetLibraryPath(libraryPath);
+ }
+
+ /**
+ * API for setting the version of the bundle
+ *
+ * @param version
+ * - version of the bundle in string form
+ */
+ public void setVersion(String version) {
+ this.nativeSetVersion(version);
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+/**
+ * @file
+ * This file contains the class for creating a Get response
+ * for the received Get request.
+ *
+ */
+
+package org.iotivity.ResourceEncapsulation.server;
+
+import org.iotivity.ResourceEncapsulation.common.RCSResourceAttributes;
+import org.iotivity.ResourceEncapsulation.utils.EntityHandlerResult;
+
+/**
+ * This class provides methods to create the response for a received get
+ * request.
+ *
+ * {@link RCSResourceObject}
+ */
+public class RCSGetResponse {
+
+ private int m_typeOfGetResponse;
+ private int m_handlerResult;
+ private int m_errorCode;
+ private RCSResourceAttributes m_attributes;
+
+ private final static int DEFAULT_RESPONSE = 0;
+ private final static int CREATE_WITH_RESULT = 1;
+ private final static int CREATE_WITH_ATTRIBUTE = 2;
+ private final static int CREATE_WITH_ATTRIBUTE_AND_RESULT = 3;
+
+ /**
+ * Creates a default RCSGetResponse. The response will have OC_EH_OK for the
+ * result and 200 for the errorCode. The attributes of RCSResourceObject
+ * will be set as the result attributes.
+ *
+ * @return RCSGetResponse
+ */
+ public static RCSGetResponse defaultAction() {
+ return new RCSGetResponse();
+ }
+
+ /**
+ * Creates a RCSGetResponse with a result and error code passed. The
+ * attributes of the RCSResourceObject will be set as the result attributes.
+ *
+ * @param result
+ * The response result.
+ * @param errorCode
+ * The error code to set in response.
+ *
+ * @return RCSGetResponse
+ *
+ * {@link EntityHandlerResult}
+ */
+ public static RCSGetResponse create(EntityHandlerResult result,
+ int errorCode) {
+ return new RCSGetResponse(result.ordinal(), errorCode);
+
+ }
+
+ /**
+ * Creates a RCSGetResponse with custom attributes. This sends the passed
+ * attributes as the result attributes instead of the one the
+ * RCSResourceObject holds.
+ *
+ * @param attributes
+ * The attributes to send in response.
+ *
+ * @return RCSGetResponse
+ *
+ * {@link RCSResourceAttributes}
+ */
+ public static RCSGetResponse create(RCSResourceAttributes attributes) {
+ return new RCSGetResponse(attributes);
+ }
+
+ /**
+ * Creates a RCSGetResponse with a result and error code passed. This sends
+ * the passed attributes as the result attributes instead of one the
+ * RCSResourceObject holds.
+ *
+ * @param attributes
+ * The attributes to send in response.
+ * @param result
+ * The response result.
+ * @param errorCode
+ * The error code for response.
+ *
+ * {@link RCSResourceAttributes}
+ *
+ * @return RCSGetResponse
+ */
+ public static RCSGetResponse create(RCSResourceAttributes attributes,
+ EntityHandlerResult result, int errorCode) {
+ return new RCSGetResponse(attributes, result.ordinal(), errorCode);
+ }
+
+ // ******* JNI UTILTY FUNCTIONS ******* //
+
+ private RCSGetResponse() {
+ m_typeOfGetResponse = DEFAULT_RESPONSE;
+ }
+
+ private RCSGetResponse(int handlerResult, int errorCode) {
+ m_typeOfGetResponse = CREATE_WITH_RESULT;
+ this.m_handlerResult = handlerResult;
+ this.m_errorCode = errorCode;
+ }
+
+ private RCSGetResponse(RCSResourceAttributes attributes) {
+ m_typeOfGetResponse = CREATE_WITH_ATTRIBUTE;
+ this.m_attributes = attributes;
+ }
+
+ private RCSGetResponse(RCSResourceAttributes attributes, int handlerResult,
+ int errorCode) {
+ m_typeOfGetResponse = CREATE_WITH_ATTRIBUTE_AND_RESULT;
+ this.m_attributes = attributes;
+ this.m_handlerResult = handlerResult;
+ this.m_errorCode = errorCode;
+ }
+
+ private int getTypeOfGetResponse() {
+ return m_typeOfGetResponse;
+ }
+
+ private int getResult() {
+ return m_handlerResult;
+ }
+
+ private int getErrorCode() {
+ return m_errorCode;
+ }
+
+ private RCSResourceAttributes getAttributes() {
+ return m_attributes;
+ }
+}
*
******************************************************************/
/**
- * @file IFindGroupListener.java
- *
- * @brief This file provides interface for getting group discovery status.
- *
+ * @file
+ * This file provides RCSRequest class which will describes the request.
*/
-package org.iotivity.service.tm;
-
-import org.iotivity.base.OcResource;
+package org.iotivity.ResourceEncapsulation.server;
/**
- * Provides interface for getting group discovery status.
+ * This class describes the request.
*/
-public interface IFindGroupListener {
+public class RCSRequest {
+
+ private String m_resourceUri;
+
+ private RCSRequest(String resourceUri) {
+ m_resourceUri = resourceUri;
+ }
+
/**
- * This callback method will be called to notify whether group is found or
- * not.
+ * Returns the URI of the request.
*
- * @param resource
- * URI of resource.
+ * @return Uri of the request in string form
*/
- public void onGroupFindCallback(OcResource resource);
-}
\ No newline at end of file
+ public String getResourceUri() {
+ return m_resourceUri;
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+/**
+ * @file
+ * This file contains the Resource Container APIs
+ */
+
+package org.iotivity.ResourceEncapsulation.server;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class provides APIs for managing the container and bundles in the
+ * container.
+ */
+public class RCSResourceContainer {
+
+ static {
+ System.loadLibrary("gnustl_shared");
+ System.loadLibrary("oc_logger");
+ System.loadLibrary("oc_logger_core");
+ System.loadLibrary("connectivity_abstraction");
+ System.loadLibrary("ca-interface");
+ System.loadLibrary("octbstack");
+ System.loadLibrary("oc");
+ System.loadLibrary("ocstack-jni");
+ System.loadLibrary("rcs_client");
+ System.loadLibrary("rcs_server");
+ System.loadLibrary("rcs_common");
+ System.loadLibrary("rcs_container");
+ System.loadLibrary("re-jni");
+ }
+
+ private static RCSResourceContainer rcsResourceContainerInstance;
+
+ // native methods
+ private native void nativeStartContainer(String configFile);
+
+ private native void nativeStopContainer();
+
+ private native void nativeAddBundle(String bundleId, String bundleUri,
+ String bundlePath, Map<String, String> params);
+
+ private native void nativeRemoveBundle(String bundleId);
+
+ private native List<RCSBundleInfo> nativeListBundles();
+
+ private native void nativeStartBundle(String bundleId);
+
+ private native void nativeStopBundle(String bundleId);
+
+ private native void nativeAddResourceConfig(String bundleId,
+ String resourceUri, Map<String, String> params);
+
+ private native void nativeRemoveResourceConfig(String bundleId,
+ String resourceUri);
+
+ private native List<String> nativeListBundleResources(String bundleId);
+
+ /**
+ * API for getting the Instance of ResourceContainer class
+ *
+ * @return RCSResourceContainer - Instance of the "RCSResourceContainer"
+ * class
+ *
+ */
+ public static RCSResourceContainer getInstance() {
+ if (null == rcsResourceContainerInstance) {
+ rcsResourceContainerInstance = new RCSResourceContainer();
+ }
+ return rcsResourceContainerInstance;
+ }
+
+ /**
+ * API for starting the Container
+ *
+ * <p>
+ * This API start the container with the provided Configuration file.
+ *
+ * @param configFile
+ * - configuration File that contains the Bundle/Bundles
+ * information.
+ *
+ */
+ public void startContainer(String configFile) {
+ this.nativeStartContainer(configFile);
+ }
+
+ /**
+ * API for stopping the Container
+ */
+ public void stopContainer() {
+ this.nativeStopContainer();
+ }
+
+ /**
+ * API for getting the list of all bundles in the container
+ *
+ * @return list -List of BundleInfo objects each associated with a bundle
+ *
+ * {@link RCSBundleInfo}
+ */
+ public List<RCSBundleInfo> listBundles() {
+ return this.nativeListBundles();
+ }
+
+ /**
+ * API for adding the bundle to the Container
+ *
+ * @param bundleId
+ * - Id of the Bundle
+ * @param bundleUri
+ * - Uri of the bundle
+ * @param bundlePath
+ * - Path of the bundle
+ * @param params
+ * - key-value pairs in string form for other Bundle parameters
+ *
+ * <p>
+ * It is dynamic configuration
+ */
+ public void addBundle(String bundleId, String bundleUri, String bundlePath,
+ Map<String, String> params) {
+ this.nativeAddBundle(bundleId, bundleUri, bundlePath, params);
+ }
+
+ /**
+ * API for removing the bundle from the container
+ *
+ * @param bundleId
+ * - Id of the Bundle
+ *
+ */
+ public void removeBundle(String bundleId) {
+ this.nativeRemoveBundle(bundleId);
+ }
+
+ /**
+ * API for starting the bundle.
+ *
+ * @param bundleId
+ * - Id of the Bundle
+ *
+ */
+ public void startBundle(String bundleId) {
+ this.nativeStartBundle(bundleId);
+ }
+
+ /**
+ * API for Stopping the bundle
+ *
+ * @param bundleId
+ * - Id of the Bundle
+ *
+ */
+ public void stopBundle(String bundleId) {
+ this.nativeStopBundle(bundleId);
+ }
+
+ /**
+ * API for adding the Resource configuration information to the bundle
+ *
+ * @param bundleId
+ * - Id of the Bundle
+ * @param resourceUri
+ * - URI of the resource
+ * @param params
+ * - key-value pairs in string form for other Bundle parameters
+ *
+ */
+ public void addResourceConfig(String bundleId, String resourceUri,
+ Map<String, String> params) {
+ this.nativeAddResourceConfig(bundleId, resourceUri, params);
+ }
+
+ /**
+ * API for removing the Resource configuration information from the bundle
+ *
+ * @param bundleId
+ * - Id of the Bundle
+ * @param resourceUri
+ * - URI of the resource
+ *
+ */
+ public void removeResourceConfig(String bundleId, String resourceUri) {
+ this.nativeRemoveResourceConfig(bundleId, resourceUri);
+ }
+
+ /**
+ * API for getting the list of Bundle Resources
+ *
+ * @param bundleId
+ * - Id of the Bundle
+ *
+ * @return List All the bundle resources
+ */
+ public List<String> listBundleResources(String bundleId) {
+ return this.nativeListBundleResources(bundleId);
+ }
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+/**
+ * @file
+ * This file contains the resource object APIs provided to the developers.
+ * RCSResourceObject is a part of the server builder module.
+ */
+
+package org.iotivity.ResourceEncapsulation.server;
+
+import org.iotivity.ResourceEncapsulation.common.RCSResourceAttributes;
+
+import android.util.Log;
+
+/**
+ * RCSResourceObject represents a resource. It handles any requests from clients
+ * automatically with attributes.
+ * <p>
+ * It also provides an auto notification mechanism that notifies to the
+ * observers. Requests are handled automatically by defaultAction of
+ * RCSGetResponse and RCSSetResponse. Developer can override them and send your
+ * own response.
+ * <p>
+ * For simple resources, developer may want to know whenever attributes are
+ * changed by a set request. In this case, add an AttributeUpdatedListener with
+ * a key interested in instead of overriding SetRequestHandler.
+ *
+ * <p>
+ * Developer will get the object of this when they call the build() API of
+ * Builder class
+ *
+ * {@link Builder}
+ */
+public class RCSResourceObject {
+
+ private long m_nativeHandle;
+ private IGetRequestHandler m_getRequestListener;
+ private ISetRequestHandler m_setRequestListener;
+ private IAttributeUpdatedListener m_attributeUpdatedListener;
+ private final String LOG_TAG = this.getClass().getSimpleName();
+
+ // native methods
+ private native void nativeSetAttributeInteger(String key, int value);
+
+ private native void nativeSetAttributeDouble(String key, double value);
+
+ private native void nativeSetAttributeBool(String key, boolean value);
+
+ private native void nativeSetAttributeString(String key, String value);
+
+ private native String nativeGetAttributeValue(String key);
+
+ private native boolean nativeRemoveAttribute(String key);
+
+ private native boolean nativeContainsAttribute(String key);
+
+ private native RCSResourceAttributes nativeGetAttributes();
+
+ private native boolean nativeIsObservable();
+
+ private native boolean nativeIsDiscoverable();
+
+ private native void nativeNotify();
+
+ private native void nativeSetAutoNotifyPolicy(int policy);
+
+ private native int nativeGetAutoNotifyPolicy();
+
+ private native void nativeSetSetRequestHandlerPolicy(int policy);
+
+ private native int nativeGetSetRequestHandlerPolicy();
+
+ private native void nativeSetGetRequestHandler(IGetRequestHandler handler);
+
+ private native void nativeSetSetRequestHandler(ISetRequestHandler handler);
+
+ private native void nativeAddAttributeUpdatedListener(String key,
+ IAttributeUpdatedListener listener);
+
+ private native boolean nativeRemoveAttributeUpdatedListener(String key);
+
+ private RCSResourceObject(long nativeHandle) {
+ m_nativeHandle = nativeHandle;
+ }
+
+ /**
+ * Represents the policy of AutoNotify function of RCSResourceObject class
+ * In accord with this policy, observers are notified of attributes that are
+ * changed or updated.
+ *
+ * <p>
+ * Attributes are changed or updated according to execution of some
+ * functions or receipt of 'set-request'.
+ *
+ * {@link RCSResourceObject}
+ */
+ public enum AutoNotifyPolicy {
+ NEVER, /* < Never notify. */
+ ALWAYS, /* < Always notify. */
+ UPDATED;
+ /* < When attributes are changed, notify. */
+
+ /*
+ * Utility API for integer to enum conversion.
+ */
+ public static AutoNotifyPolicy getAutoNotifyPolicy(int ordinal) {
+ if (ordinal == 0)
+ return AutoNotifyPolicy.values()[0];
+ else if (ordinal == 1)
+ return AutoNotifyPolicy.values()[1];
+ else if (ordinal == 2)
+ return AutoNotifyPolicy.values()[2];
+ return null;
+ }
+ }
+
+ public enum SetRequestHandlerPolicy {
+
+ NEVER, /*
+ * < Server ignore when server is received set-request of
+ * attributes of the new key.
+ */
+ ACCEPTANCE;
+ /*
+ * < Server creates attributes of the new key When server is received
+ * set-request of attributes of the new key.
+ */
+
+ /*
+ * Utility API for integer to enum conversion.
+ */
+ public static SetRequestHandlerPolicy getSetRequestHandlerPolicy(
+ int ordinal) {
+
+ if (ordinal == 0)
+ return SetRequestHandlerPolicy.values()[0];
+ else if (ordinal == 1)
+ return SetRequestHandlerPolicy.values()[1];
+ return null;
+ }
+ }
+
+ /**
+ * Provides interface for receiving the callback on receiving a Get request
+ * from the client
+ */
+ public interface IGetRequestHandler {
+
+ /**
+ * This callback method is called when received a get request from the
+ * client. Listener should be set to receive this callback.
+ *
+ * @param request
+ * Request for the resource
+ * @param attributes
+ * Resource Attributes
+ *
+ * @return RCSGetResponse Response to be sent.
+ *
+ * {@link RCSResourceObject} {@link RCSGetResponse}
+ * {@link RCSResourceAttributes}
+ */
+ RCSGetResponse onGetRequest(RCSRequest request,
+ RCSResourceAttributes attributes);
+
+ }
+
+ /**
+ * Provides interface for receiving the callback on receiving a Set request
+ * from the client
+ */
+ public interface ISetRequestHandler {
+
+ /**
+ * This callback method is called when received a set request from the
+ * client. Listener should be set to receive this callback.
+ *
+ * @param request
+ * Request for the resource
+ * @param attributes
+ * Resource Attributes to set
+ *
+ * @return RCSSetResponse Response to be sent.
+ *
+ * {@link RCSResourceObject} {{@link RCSSetResponse}
+ * {@link RCSResourceAttributes}
+ */
+ RCSSetResponse onSetRequest(RCSRequest request,
+ RCSResourceAttributes attributes);
+
+ }
+
+ /**
+ * Provides interface for receiving the callback on update of requested
+ * attribute.
+ */
+ public interface IAttributeUpdatedListener {
+
+ /**
+ * This callback method is called when a requested attribute value is
+ * updated. Listener should be set to receive this callback.
+ *
+ * @param oldValue
+ * It is the attribute value before updation.
+ * @param newValue
+ * It is the current resource attribute value.
+ *
+ * {@link RCSResourceAttributes}
+ */
+ void onAttributeUpdate(String oldValue, String newValue);
+ }
+
+ /**
+ * Set listener for receiving get request from the client asynchronously.
+ *
+ * @param listener
+ * IGetRequestHandler to receive asynchronous get request from
+ * client.
+ *
+ * {@link IGetRequestHandler}
+ */
+ public void setGetRequestListener(IGetRequestHandler listener) {
+ m_getRequestListener = listener;
+ }
+
+ /**
+ * Set listener for receiving set request from the client asynchronously.
+ *
+ * @param listener
+ * ISetRequestHandler to receive asynchronous set request from
+ * client.
+ *
+ * {@link ISetRequestHandler}
+ */
+ public void setSetRequestListener(ISetRequestHandler listener) {
+ m_setRequestListener = listener;
+ }
+
+ /**
+ * Set listener for receiving the updated attribute value asynchronously.
+ *
+ * @param listener
+ * IAttributeUpdatedListener to receive updated attribute value
+ * asynchronously.
+ *
+ * {@link IAttributeUpdatedListener}
+ */
+ public void setAttributeUpdatedListener(IAttributeUpdatedListener listener) {
+ m_attributeUpdatedListener = listener;
+ }
+
+ /**
+ * API for setting a particular attribute value as a integer
+ *
+ * @param key
+ * name of attribute(used to map the attribute value).
+ * @param value
+ * integer value to be mapped against the key.
+ *
+ * The thread-safety for attributes is taken care internally.
+ */
+ public void setAttribute(String key, int value) {
+ Log.i(LOG_TAG, "setAttribute (integer) called");
+ this.nativeSetAttributeInteger(key, value);
+ }
+
+ /**
+ * API for setting a particular attribute value as a double
+ *
+ * @param key
+ * name of attribute(used to map the attribute value).
+ * @param value
+ * Double value to be mapped against the key.
+ *
+ * The thread-safety for attributes is taken care internally.
+ */
+ public void setAttribute(String key, double value) {
+ Log.i(LOG_TAG, "setAttribute (float) called");
+ this.nativeSetAttributeDouble(key, value);
+ }
+
+ /**
+ * API for setting a particular attribute value as a boolean
+ *
+ * @param key
+ * name of attribute(used to map the attribute value).
+ * @param value
+ * boolean value to be mapped against the key.
+ *
+ * The thread-safety for attributes is taken care internally.
+ */
+ public void setAttribute(String key, boolean value) {
+ Log.i(LOG_TAG, "setAttribute (double) called ");
+ this.nativeSetAttributeBool(key, value);
+ }
+
+ /**
+ * API for setting a particular attribute value as a String
+ *
+ * @param key
+ * name of attribute(used to map the attribute value).
+ * @param value
+ * String value to be mapped against the key.
+ *
+ * The thread-safety for attributes is taken care internally.
+ */
+ public void setAttribute(String key, String value) {
+ Log.i(LOG_TAG, "setAttribute (String) called ");
+ this.nativeSetAttributeString(key, value);
+ }
+
+ /**
+ * API for retrieving the attribute value associated with the supplied key.
+ *
+ * @param key
+ * Name of the attribute
+ *
+ * @return resource attributes value as a string
+ *
+ * The thread-safety for attributes is taken care internally.
+ */
+ public String getAttributeValue(String key) {
+ Log.i(LOG_TAG, "getAttributeValue called");
+ return this.nativeGetAttributeValue(key);
+ }
+
+ /**
+ * API for removing a particular attribute of the resource.
+ *
+ * @param key
+ * Name of the attribute.
+ *
+ * @return If the key exist and matched attribute is deleted, return true.
+ *
+ * The thread-safety for attributes is taken care internally.
+ */
+ public boolean removeAttribute(String key) {
+ Log.i(LOG_TAG, "removeAttribute called");
+ return this.nativeRemoveAttribute(key);
+ }
+
+ /**
+ * API for checking whether a particular attribute is there for a resource
+ * or not.
+ *
+ * @param key
+ * Name of the attribute.
+ *
+ * @return If the key exist, return true.
+ *
+ * The thread-safety for attributes is taken care internally.
+ */
+ public boolean containsAttribute(String key) {
+ Log.i(LOG_TAG, "containsAttribute called");
+ return this.nativeContainsAttribute(key);
+ }
+
+ /**
+ * API for getting all the attributes of the RCSResourceObject.
+ *
+ * @return RCSResourceAttributes
+ *
+ * {@link RCSResourceAttributes}
+ */
+ public RCSResourceAttributes getAttributes() {
+ Log.i(LOG_TAG, "getAttributes called");
+ return this.nativeGetAttributes();
+ }
+
+ /**
+ * API for checking whether the particular resource is observable or not
+ *
+ * @return true if observable otherwise false
+ */
+ public boolean isObservable() {
+ Log.i(LOG_TAG, "isObservable called");
+ return this.nativeIsObservable();
+ }
+
+ /**
+ * API for checking whether the particular resource is discoverable or not
+ *
+ * @return true if discoverable else false
+ */
+ public boolean isDiscoverable() {
+ Log.i(LOG_TAG, "isDiscoverable called");
+ return this.nativeIsDiscoverable();
+ }
+
+ /**
+ * API for setting the resource's get request handler by the
+ * developer/application. If developer set this handler then all get request
+ * will come to the application and developer can send the response to the
+ * client using APIs of RCSGetResponse class.
+ *
+ * <p>
+ * IGetRequestHandler should be set to call this API. For setting the
+ * listener call setGetRequestListener() API
+ *
+ * {@link RCSGetResponse} {@link #setGetRequestListener(IGetRequestHandler)}
+ */
+ public void setGetRequestHandler() {
+ if (null == m_getRequestListener) {
+ Log.i(LOG_TAG, "getRequestListener is not set");
+ return;
+ } else {
+ this.nativeSetGetRequestHandler(m_getRequestListener);
+ }
+ }
+
+ /**
+ * API for setting the resource's set request handler by the
+ * developer/application. If developer set this handler then all set request
+ * will come to the application and developer can send the response to the
+ * client using APIs of RCSSetResponse class.
+ *
+ * <p>
+ * ISetRequestHandler should be set to call this API. For setting the
+ * listener call setSetRequestListener() API
+ *
+ * {@link RCSSetResponse} {@link #setSetRequestListener(ISetRequestHandler)}
+ */
+ public void setSetRequestHandler() {
+ if (null == m_setRequestListener) {
+ Log.i(LOG_TAG, "setRequestListener is not set");
+ return;
+ } else {
+ this.nativeSetSetRequestHandler(m_setRequestListener);
+ }
+ }
+
+ /**
+ * API for setting the Listener for a particular attribute update.
+ *
+ * @param key
+ * The interested attribute's key
+ *
+ * <p>
+ * IAttributeUpdatedListener should be set to call this API. For
+ * setting the listener call setAttributeUpdatedListener() API
+ */
+ public void addAttributeUpdatedListener(String key) {
+ if (null == m_attributeUpdatedListener) {
+ Log.i(LOG_TAG, "addAttributeUpdatedListener is not set");
+ return;
+ } else {
+ this.nativeAddAttributeUpdatedListener(key,
+ m_attributeUpdatedListener);
+ }
+ }
+
+ /**
+ * API for removing the handler for a particular attribute update.
+ *
+ * @param key
+ * The interested attribute's key
+ *
+ * @return true if requested attribute is removed successfully else false
+ */
+ public boolean removeAttributeUpdatedListener(String key) {
+ return this.nativeRemoveAttributeUpdatedListener(key);
+ }
+
+ /**
+ * API for notifying all observers of the RCSResourceObject with the updated
+ * attributes value
+ */
+ public void notifyObservers() {
+ Log.i(LOG_TAG, "notifyObservers called");
+ this.nativeNotify();
+ }
+
+ /**
+ * API for setting Auto notify policy
+ *
+ * @param policy
+ * policy to be set
+ *
+ * {@link AutoNotifyPolicy}
+ */
+ public void setAutoNotifyPolicy(AutoNotifyPolicy policy) {
+ Log.i(LOG_TAG, "setAutoNotifyPolicy called");
+ this.nativeSetAutoNotifyPolicy(policy.ordinal());
+ }
+
+ /**
+ * API for getting auto notify policy
+ *
+ * @return AutoNotifyPolicy
+ *
+ * {@link AutoNotifyPolicy}
+ */
+ public AutoNotifyPolicy getAutoNotifyPolicy() {
+ Log.i(LOG_TAG, "getAutoNotifyPolicy called");
+ return AutoNotifyPolicy.getAutoNotifyPolicy(this
+ .nativeGetAutoNotifyPolicy());
+ }
+
+ /**
+ * API for setting the policy for a setRequestHandler.
+ *
+ * @param policy
+ * policy to be set
+ *
+ * {@link SetRequestHandlerPolicy}
+ */
+ public void setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy) {
+ Log.i(LOG_TAG, "setSetRequestHandlerPolicy called");
+ this.nativeSetSetRequestHandlerPolicy(policy.ordinal());
+ }
+
+ /**
+ * API for getting the SetRequestHandler Policy.
+ *
+ * @return SetRequestHandlerPolicy
+ *
+ * {@link SetRequestHandlerPolicy}
+ */
+ public SetRequestHandlerPolicy getSetRequestHandlerPolicy() {
+ Log.i(LOG_TAG, "getSetRequestHandlerPolicy called");
+ return SetRequestHandlerPolicy.getSetRequestHandlerPolicy(this
+ .nativeGetSetRequestHandlerPolicy());
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+/**
+ * @file
+ * This file contains the class for creating a Set response
+ * for the received Set request.
+ */
+
+package org.iotivity.ResourceEncapsulation.server;
+
+import org.iotivity.ResourceEncapsulation.common.RCSResourceAttributes;
+import org.iotivity.ResourceEncapsulation.utils.EntityHandlerResult;
+import org.iotivity.ResourceEncapsulation.server.RCSResourceObject;
+
+/**
+ * This class provides methods to create the response for a received set
+ * request.
+ *
+ * {@link RCSResourceObject}
+ */
+public class RCSSetResponse {
+
+ private int m_typeOfSetResponse;
+ private int m_handlerResult;
+ private int m_errorCode;
+ private RCSResourceAttributes m_attributes;
+
+ private final static int DEFAULT_RESPONSE = 0;
+ private final static int CREATE_WITH_RESULT = 1;
+ private final static int CREATE_WITH_ATTRIBUTE = 2;
+ private final static int CREATE_WITH_ATTRIBUTE_AND_RESULT = 3;
+ private final static int ACCEPT = 4;
+ private final static int ACCEPT_WITH_RESULT = 5;
+ private final static int IGNORE = 6;
+ private final static int IGNORE_WIH_RESULT = 7;
+
+ /**
+ * Creates a default RCSSetResponse with DEFAULT acceptance method. The
+ * response will have OC_EH_OK for the result and 200 for the errorCode. The
+ * attributes of RCSResourceObject will be set as the result attributes.
+ *
+ * <p>
+ * DEFAULT : Follow SetRequestHandlerPolicy of the RCSResourceObject.
+ */
+ public static RCSSetResponse defaultAction() {
+ return new RCSSetResponse(DEFAULT_RESPONSE);
+ }
+
+ /**
+ * Creates a default RCSSetResponse with ACCEPT acceptance method. The
+ * response will have OC_EH_OK for the result and 200 for the errorCode. The
+ * attributes of RCSResourceObject will be set as the result attributes.
+ *
+ * <p>
+ * ACCEPT : Accept the request attributes even if there is an unknown key or
+ * mismatched type.
+ *
+ * @return RCSSetResponse
+ */
+ public static RCSSetResponse accept() {
+ return new RCSSetResponse(ACCEPT);
+ }
+
+ /**
+ * Creates a RCSSetResponse with ACCEPT acceptance method. with a result and
+ * error code passed. The attributes of the RCSResourceObject will be set as
+ * the result attributes.
+ *
+ * @param result
+ * The response result.
+ * @param errorCode
+ * The error code to set in response.
+ *
+ * <p>
+ * ACCEPT : Accept the request attributes even if there is an
+ * unknown key or mismatched type.
+ *
+ * @return RCSSetResponse
+ */
+ public static RCSSetResponse accept(EntityHandlerResult result,
+ int errorCode) {
+ return new RCSSetResponse(result.ordinal(), errorCode,
+ ACCEPT_WITH_RESULT);
+ }
+
+ /**
+ * Creates a default RCSSetResponse with IGNORE acceptance method. The
+ * response will have OC_EH_OK for the result and 200 for the errorCode. The
+ * attributes of RCSResourceObject will be set as the result attributes.
+ *
+ * <p>
+ * IGNORE : Ignore the request attributes.
+ *
+ * @return RCSSetResponse
+ */
+ public static RCSSetResponse ignore() {
+ return new RCSSetResponse(IGNORE);
+ }
+
+ /**
+ * Creates a RCSSetResponse with IGNORE acceptance method. with a result and
+ * error code passed. The attributes of the RCSResourceObject will be set as
+ * the result attributes.
+ *
+ * @param result
+ * The response result.
+ * @param errorCode
+ * The error code to set in response.
+ *
+ * <p>
+ * IGNORE : Ignore the request attributes.
+ *
+ * @return RCSSetResponse
+ */
+ public static RCSSetResponse ignore(EntityHandlerResult result,
+ int errorCode) {
+ return new RCSSetResponse(result.ordinal(), errorCode,
+ IGNORE_WIH_RESULT);
+ }
+
+ /**
+ * Creates a RCSSetResponse with a result and error code passed and has
+ * DEFAULT acceptance method. The attributes of the RCSResourceObject will
+ * be set as the result attributes.
+ *
+ * <p>
+ * DEFAULT : Follow SetRequestHandlerPolicy of the RCSResourceObject.
+ *
+ * @param result
+ * The response result.
+ * @param errorCode
+ * The error code to set in response.
+ *
+ * {@link EntityHandlerResult}
+ *
+ * @return RCSSetResponse
+ */
+ public static RCSSetResponse create(EntityHandlerResult result,
+ int errorCode) {
+ return new RCSSetResponse(result.ordinal(), errorCode,
+ CREATE_WITH_RESULT);
+ }
+
+ /**
+ * Creates a RCSSetResponse with custom attributes and has DEFAULT
+ * acceptance method. This sends the passed attributes as the result
+ * attributes instead of one the RCSResourceObject holds.
+ *
+ * <p>
+ * DEFAULT : Follow SetRequestHandlerPolicy of the RCSResourceObject.
+ *
+ * @param attributes
+ * The attributes to send in response.
+ *
+ * {@link RCSResourceAttributes}
+ *
+ * @return RCSSetResponse
+ */
+ public static RCSSetResponse create(RCSResourceAttributes attributes) {
+ return new RCSSetResponse(attributes);
+ }
+
+ /**
+ * Creates a RCSSetResponse with a result and error code passed. This sends
+ * the passed attributes as the result attributes instead of one the
+ * RCSResourceObject holds.
+ *
+ * @param attributes
+ * The attributes to send in response.
+ * @param result
+ * The response result.
+ * @param errorCode
+ * The error code for response.
+ *
+ * <p>
+ * RCSResourceAttributes
+ *
+ * @return RCSSetResponse
+ */
+ public static RCSSetResponse create(RCSResourceAttributes attributes,
+ EntityHandlerResult result, int errorCode) {
+ return new RCSSetResponse(attributes, result.ordinal(), errorCode);
+ }
+
+ // ******* JNI UTILTY FUNCTIONS ******* //
+
+ private RCSSetResponse(int typeOfSetResponse) {
+ this.m_typeOfSetResponse = typeOfSetResponse;
+ }
+
+ private RCSSetResponse(int handlerResult, int errorCode, int typeOfRequest) {
+ m_typeOfSetResponse = typeOfRequest;
+ m_handlerResult = handlerResult;
+ m_errorCode = errorCode;
+ }
+
+ private RCSSetResponse(RCSResourceAttributes attributes) {
+ m_typeOfSetResponse = CREATE_WITH_ATTRIBUTE;
+ this.m_attributes = attributes;
+ }
+
+ private RCSSetResponse(RCSResourceAttributes attributes, int handlerResult,
+ int errorCode) {
+ m_typeOfSetResponse = CREATE_WITH_ATTRIBUTE_AND_RESULT;
+ m_attributes = attributes;
+ m_handlerResult = handlerResult;
+ m_errorCode = errorCode;
+ }
+
+ private int getTypeOfGetResponse() {
+ return m_typeOfSetResponse;
+ }
+
+ private int getResult() {
+ return m_handlerResult;
+ }
+
+ private int getErrorCode() {
+ return m_errorCode;
+ }
+
+ private RCSResourceAttributes getAttributes() {
+ return m_attributes;
+ }
+}
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+/**
+ * @file
+ * This file provides a Enum to handle unicast or multicast discovery.
+ * @link RCSAddress
+ */
+
+package org.iotivity.ResourceEncapsulation.utils;
+
+import org.iotivity.ResourceEncapsulation.client.RCSAddress;
+
+/**
+ * This Enum discovery codes for different discovery types.
+ *
+ * <p>
+ * Application will get this DiscoveryType as a result of getTypeOfDiscovery API
+ * of RCSAddress class
+ *
+ * {@link RCSAddress}
+ */
+public enum DiscoveryType {
+
+ UNICAST, /* < Unicast type discovery. */
+ MULTICAST;
+ /* < Multicast type discovery. */
+
+ /*
+ * Utility API for integer to enum conversion.
+ */
+ public static DiscoveryType getDiscoveryType(int ordinal) {
+
+ if (ordinal == 0)
+ return DiscoveryType.values()[0];
+ if (ordinal == 1)
+ return DiscoveryType.values()[1];
+
+ return null;
+ }
+}
*
******************************************************************/
/**
- * @file ISubscribePresenceListener.java
- *
- * @brief This file provides interface for getting child resource presence status.
- *
+ * @file
+ * This file provides EntityHandlerResult Enum & utility function.
*/
-package org.iotivity.service.tm;
+package org.iotivity.ResourceEncapsulation.utils;
+
+import org.iotivity.ResourceEncapsulation.server.*;
/**
- * Provides interface for getting child resource presence status.
+ * Represents the EntityHandlerResult, that application can send for a Get or a
+ * Set request.
+ *
+ * {@link RCSResourceObject} {@link RCSGetResponse} {@link RCSSetResponse}
*/
-public interface ISubscribePresenceListener {
- /**
- * This callback method will be called for child resource presence status.
- *
- * @param resource
- * URI of resource.
- * @param result
- * error code.
- */
- public void onPresenceCallback(String resource, int result);
+public enum EntityHandlerResult {
+
+ OC_EH_OK, OC_EH_ERROR, OC_EH_RESOURCE_CREATED, OC_EH_RESOURCE_DELETED, OC_EH_SLOW, OC_EH_FORBIDDEN, OC_EH_RESOURCE_NOT_FOUND;
}
env.get('SRC_DIR')+'/extlibs',
'../../include',
'primitiveResource/include'])
-
+
rcs_common_env.AppendUnique(CPPPATH = [
'expiryTimer/include',
'expiryTimer/src'])
if target_os == 'android':
rcs_common_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
- rcs_common_env.PrependUnique(LIBS = ['gnustl_shared', 'compatibility', 'log'])
+ rcs_common_env.PrependUnique(LIBS = ['gnustl_shared', 'log'])
rcs_common_env.AppendUnique(LIBS = ['dl', 'oc'])
TIMER_SRC_DIR = 'expiryTimer/src/'
RESOURCE_SRC = 'primitiveResource/src/'
rcs_common_src = [
- TIMER_SRC_DIR + 'ExpiryTimerImpl.cpp',
+ TIMER_SRC_DIR + 'ExpiryTimerImpl.cpp',
TIMER_SRC_DIR + 'ExpiryTimer.cpp',
RESOURCE_SRC + 'PresenceSubscriber.cpp',
RESOURCE_SRC + 'PrimitiveResource.cpp',
RESOURCE_SRC + 'RCSResourceAttributes.cpp',
RESOURCE_SRC + 'ResponseStatement.cpp'
]
-
+
rcs_common_static = rcs_common_env.StaticLibrary('rcs_common', rcs_common_src)
rcs_common_shared = rcs_common_env.SharedLibrary('rcs_common', rcs_common_src)
rcs_common_env.InstallTarget([rcs_common_static,rcs_common_shared], 'rcs_common')
######################################################################
-# Build Test primitive Resource
+# Build Test Expiry Timer and primitive Resource
######################################################################
-rcs_common_test_env = rcs_common_env.Clone();
-
-rcs_common_test_env.PrependUnique(CPPPATH = [
- env.get('SRC_DIR')+'/extlibs/hippomocks-master',
- gtest_dir + '/include',
- 'utils/include'
- ])
-
-gtest = File(gtest_dir + '/lib/.libs/libgtest.a')
-gtest_main = File(gtest_dir + '/lib/.libs/libgtest_main.a')
-
-rcs_common_test_env.PrependUnique(LIBS = [
- 'octbstack',
- 'oc_logger',
- 'connectivity_abstraction',
- 'coap',
- 'rcs_common',
- gtest,
- gtest_main,
- 'pthread'
- ])
-
-rcs_common_test_src = [
- env.Glob('primitiveResource/unittests/*.cpp'),
- 'expiryTimer/unittests/ExpiryTimerTest.cpp'
- ]
-
-rcs_common_test = rcs_common_test_env.Program('rcs_common_test', rcs_common_test_src)
-Alias("rcs_common_test", rcs_common_test)
-env.AppendTarget('rcs_common_test')
-
-if env.get('TEST') == '1':
- target_os = env.get('TARGET_OS')
- if target_os == 'linux':
- from tools.scons.RunTest import *
- run_test(rcs_common_test_env, '',
- 'service/resource-encapsulation/src/common/rcs_common_test')
+if target_os == 'linux':
+ rcs_common_test_env = rcs_common_env.Clone();
+
+ rcs_common_test_env.PrependUnique(CPPPATH = [
+ env.get('SRC_DIR')+'/extlibs/hippomocks-master',
+ gtest_dir + '/include',
+ 'utils/include'
+ ])
+
+ gtest = File(gtest_dir + '/lib/.libs/libgtest.a')
+ gtest_main = File(gtest_dir + '/lib/.libs/libgtest_main.a')
+
+ rcs_common_test_env.PrependUnique(LIBS = [
+ 'octbstack',
+ 'oc_logger',
+ 'connectivity_abstraction',
+ 'coap',
+ 'rcs_common',
+ gtest,
+ gtest_main,
+ 'pthread'
+ ])
+
+ rcs_common_test_src = [
+ env.Glob('primitiveResource/unittests/*.cpp'),
+ 'expiryTimer/unittests/ExpiryTimerTest.cpp'
+ ]
+
+ rcs_common_test = rcs_common_test_env.Program('rcs_common_test', rcs_common_test_src)
+ Alias("rcs_common_test", rcs_common_test)
+ env.AppendTarget('rcs_common_test')
+
+ if env.get('TEST') == '1':
+ from tools.scons.RunTest import *
+ run_test(rcs_common_test_env, '',
+ 'service/resource-encapsulation/src/common/rcs_common_test')
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#ifndef COMMON_INTERNAL_RESOURCEATTRIBUTESCONVERTER_H
-#define COMMON_INTERNAL_RESOURCEATTRIBUTESCONVERTER_H
+#ifndef COMMON_RESOURCEATTRIBUTESCONVERTER_H
+#define COMMON_RESOURCEATTRIBUTESCONVERTER_H
#include <RCSResourceAttributes.h>
{
namespace Service
{
+ namespace Detail
+ {
+ template< int >
+ struct Int2Type {};
+
+ template < typename T >
+ struct TypeDef
+ {
+ typedef T type;
+ };
+
+ template< OC::AttributeType TYPE >
+ struct OCBaseType;
+
+ template< >
+ struct OCBaseType< OC::AttributeType::Integer > : TypeDef< int >{ };
+
+ template< >
+ struct OCBaseType< OC::AttributeType::Double > : TypeDef< double > { };
+
+ template< >
+ struct OCBaseType< OC::AttributeType::Boolean > : TypeDef< bool > { };
+
+ template< >
+ struct OCBaseType< OC::AttributeType::String > : TypeDef< std::string > { };
+
+ template< >
+ struct OCBaseType< OC::AttributeType::OCRepresentation >
+ : TypeDef< OC::OCRepresentation >
+ {};
+
+ template< int DEPTH, typename BASE_TYPE >
+ struct SeqType
+ {
+ typedef std::vector< typename SeqType< DEPTH - 1, BASE_TYPE >::type > type;
+ };
+
+ template< typename BASE_TYPE >
+ struct SeqType< 0, BASE_TYPE >
+ {
+ typedef BASE_TYPE type;
+ };
+
+ template< int DEPTH, OC::AttributeType BASE_TYPE >
+ struct OCItemType
+ {
+ typedef typename SeqType< DEPTH,
+ typename OCBaseType< BASE_TYPE >::type >::type type;
+ };
+
+ template< typename T >
+ struct TypeInfo
+ {
+ typedef T type;
+ typedef T base_type;
+ constexpr static size_t depth = 0;
+ };
+
+ template< typename T >
+ struct TypeInfo< std::vector< T > >
+ {
+ typedef T type;
+ typedef typename TypeInfo< T >::base_type base_type;
+ constexpr static size_t depth = 1 + TypeInfo< T >::depth;
+ };
+ }
class ResourceAttributesConverter
{
class ResourceAttributesBuilder
{
- public:
- ResourceAttributesBuilder() = default;
-
- void insertItemTo(const OC::OCRepresentation::AttributeItem& item)
+ private:
+ template < int DEPTH >
+ void insertItem(Detail::Int2Type< DEPTH >,
+ const OC::OCRepresentation::AttributeItem& item)
{
- switch (item.type())
- {
+ switch (item.base_type()) {
case OC::AttributeType::Null:
return putValue(item.attrname(), nullptr);
case OC::AttributeType::Integer:
- return putValue(item.attrname(), item.getValue< int >());
+ return insertItem< DEPTH, OC::AttributeType::Integer >(item);
case OC::AttributeType::Double:
- return putValue(item.attrname(), item.getValue< double >());
+ return insertItem< DEPTH, OC::AttributeType::Double >(item);
case OC::AttributeType::Boolean:
- return putValue(item.attrname(), item.getValue< bool >());
+ return insertItem< DEPTH, OC::AttributeType::Boolean >(item);
case OC::AttributeType::String:
- return putValue(item.attrname(), item.getValue< std::string >());
+ return insertItem< DEPTH, OC::AttributeType::String >(item);
case OC::AttributeType::OCRepresentation:
- return putValue(item.attrname(),
- ResourceAttributesConverter::fromOCRepresentation(
- item.getValue< OC::OCRepresentation >()));
+ return insertOcRep(Detail::Int2Type< DEPTH >{ }, item);
- case OC::AttributeType::Vector:
- // RCSResourceAttributes doesn't support vector yet!
- return;
+ default:
+ assert("There must be no another base type!");
+ }
+ }
+
+ template< int DEPTH, OC::AttributeType BASE_TYPE >
+ void insertItem(const OC::OCRepresentation::AttributeItem& item)
+ {
+ typedef typename Detail::OCItemType< DEPTH, BASE_TYPE >::type ItemType;
+ putValue(item.attrname(), item.getValue< ItemType >());
+ }
+
+ RCSResourceAttributes insertOcRep(Detail::Int2Type< 0 >,
+ const OC::OCRepresentation& ocRep)
+ {
+ return ResourceAttributesConverter::fromOCRepresentation(ocRep);
+ }
+
+ template< int DEPTH, typename OCREPS,
+ typename ATTRS = typename Detail::SeqType< DEPTH, RCSResourceAttributes >::type >
+ ATTRS insertOcRep(Detail::Int2Type< DEPTH >, const OCREPS& ocRepVec)
+ {
+ ATTRS result;
+
+ for (const auto& nested : ocRepVec)
+ {
+ result.push_back(insertOcRep(Detail::Int2Type< DEPTH - 1 >{ }, nested));
+ }
+
+ return result;
+ }
+
+ template< int DEPTH >
+ void insertOcRep(Detail::Int2Type< DEPTH >,
+ const OC::OCRepresentation::AttributeItem& item)
+ {
+ typedef typename Detail::OCItemType< DEPTH,
+ OC::AttributeType::OCRepresentation >::type ItemType;
+
+ putValue(item.attrname(),
+ insertOcRep(Detail::Int2Type< DEPTH >{ }, item.getValue< ItemType >()));
+ }
+
+ public:
+ ResourceAttributesBuilder() = default;
+
+ void insertItem(const OC::OCRepresentation::AttributeItem& item)
+ {
+ switch (item.depth())
+ {
+ case 0:
+ return insertItem(Detail::Int2Type< 0 >{ }, item);
+ case 1:
+ return insertItem(Detail::Int2Type< 1 >{ }, item);
+ case 2:
+ return insertItem(Detail::Int2Type< 2 >{ }, item);
+ case 3:
+ return insertItem(Detail::Int2Type< 3 >{ }, item);
+
+ default:
+ assert("There must be no another depth!");
}
}
private:
template< typename T >
- typename std::enable_if<RCSResourceAttributes::is_supported_type< T >::value >::type
- putValue(const std::string& key, T && value)
+ void putValue(const std::string& key, T&& value)
{
m_target[key] = std::forward< T >(value);
}
- template< typename T >
- typename std::enable_if<!RCSResourceAttributes::is_supported_type< T >::value >::type
- putValue(const std::string& key, T && value)
- {
- }
-
private:
RCSResourceAttributes m_target;
};
public:
OCRepresentationBuilder() = default;
- template< typename T >
- void operator()(const std::string& key, const T& value)
+ template< typename T, typename B = typename Detail::TypeInfo< T >::base_type >
+ typename std::enable_if< !std::is_same< B, RCSResourceAttributes >::value >::type
+ operator()(const std::string& key, const T& value)
{
m_target[key] = value;
}
+ template< typename T, typename I = Detail::TypeInfo< T > >
+ typename std::enable_if< std::is_same< typename I::base_type,
+ RCSResourceAttributes >::value >::type
+ operator()(const std::string& key, const T& value)
+ {
+ m_target[key] = convertAttributes(Detail::Int2Type< I::depth >{ }, value);
+ }
+
void operator()(const std::string& key, const std::nullptr_t&)
{
m_target.setNULL(key);
}
- void operator()(const std::string& key, const RCSResourceAttributes& value)
+ OC::OCRepresentation convertAttributes(Detail::Int2Type< 0 >,
+ const RCSResourceAttributes& attrs)
+ {
+ return ResourceAttributesConverter::toOCRepresentation(attrs);
+ }
+
+ template< int DEPTH, typename ATTRS, typename OCREPS = typename Detail::SeqType<
+ DEPTH, OC::OCRepresentation >::type >
+ OCREPS convertAttributes(Detail::Int2Type< DEPTH >, const ATTRS& attrs)
{
- m_target[key] = ResourceAttributesConverter::toOCRepresentation(value);
+ OCREPS result;
+
+ for (const auto& nested : attrs)
+ {
+ result.push_back(
+ convertAttributes(Detail::Int2Type< DEPTH - 1 >{ }, nested));
+ }
+
+ return result;
}
OC::OCRepresentation&& extract()
for (const auto& item : ocRepresentation)
{
- builder.insertItemTo(item);
+ builder.insertItem(item);
}
return builder.extract();
}
}
-#endif // COMMON_INTERNAL_RESOURCEATTRIBUTESCONVERTER_H
+#endif // COMMON_RESOURCEATTRIBUTESCONVERTER_H
return boost::lexical_cast<std::string>(value);
}
+ template< typename T >
+ std::string operator()(const std::vector< T >&) const
+ {
+ return "Vector";
+ }
+
std::string operator()(std::nullptr_t) const
{
return "";
template< >
struct TypeInfoConverter< std::nullptr_t >
{
- static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::NULL_T;
+ static constexpr RCSResourceAttributes::TypeId typeId =
+ RCSResourceAttributes::TypeId::NULL_T;
};
template< >
struct TypeInfoConverter< double >
{
- static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::DOUBLE;
+ static constexpr RCSResourceAttributes::TypeId typeId =
+ RCSResourceAttributes::TypeId::DOUBLE;
};
template< >
template< >
struct TypeInfoConverter< std::string >
{
- static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::STRING;
+ static constexpr RCSResourceAttributes::TypeId typeId =
+ RCSResourceAttributes::TypeId::STRING;
};
template< >
struct TypeInfoConverter< RCSResourceAttributes >
{
- static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::ATTRIBUTES;
+ static constexpr RCSResourceAttributes::TypeId typeId =
+ RCSResourceAttributes::TypeId::ATTRIBUTES;
+ };
+
+ template< typename T >
+ struct TypeInfoConverter< std::vector< T > >
+ {
+ static constexpr RCSResourceAttributes::TypeId typeId =
+ RCSResourceAttributes::TypeId::VECTOR;
+ };
+
+ template< typename T >
+ struct SequenceTraits
+ {
+ static constexpr size_t depth = 0;
+ typedef T base_type;
+ };
+
+ template< typename T >
+ struct SequenceTraits< std::vector< T > >
+ {
+ static constexpr size_t depth = SequenceTraits< T >::depth + 1;
+ typedef typename SequenceTraits< T >::base_type base_type;
};
struct TypeInfo
{
- RCSResourceAttributes::TypeId typeId;
+ RCSResourceAttributes::TypeId m_typeId;
+ RCSResourceAttributes::Type m_baseType;
+ size_t m_depth;
- template< typename TRAIT >
- constexpr TypeInfo(TRAIT) :
- typeId{ TRAIT::typeId }
+ template< typename T, typename ST = SequenceTraits < T > >
+ constexpr static TypeInfo get()
{
+ return { TypeInfoConverter< T >::typeId ,
+ RCSResourceAttributes::Type::typeOf< typename ST::base_type >(), ST::depth };
}
template< typename VARIANT, int POS >
- static constexpr TypeInfo get()
+ constexpr static TypeInfo get()
{
- return TypeInfo(TypeInfoConverter<
- typename boost::mpl::deref<
- typename boost::mpl::advance<
- typename boost::mpl::begin< typename VARIANT::types>::type,
- boost::mpl::int_< POS >
- >::type
- >::type >{ });
+ typedef typename boost::mpl::begin< typename VARIANT::types >::type mpl_begin;
+ typedef typename boost::mpl::advance< mpl_begin, boost::mpl::int_< POS > >::type iter;
+
+ return get< typename boost::mpl::deref< iter >::type >();
}
};
template< typename VARIANT, int POS >
- constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< POS >)
+ constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< POS >) noexcept
{
- auto&& vec = getTypeInfo< VARIANT >(Int2Type< POS - 1 >{ });
+ auto vec = getTypeInfo< VARIANT >(Int2Type< POS - 1 >{ });
vec.push_back(TypeInfo::get< VARIANT, POS >());
return vec;
}
template< typename VARIANT >
- constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< 0 >)
+ constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< 0 >) noexcept
{
return { TypeInfo::get< VARIANT, 0 >() };
}
template< typename VARIANT >
- inline TypeInfo getTypeInfo(int which)
+ inline TypeInfo getTypeInfo(int which) noexcept
{
- static constexpr int variantEnd = boost::mpl::size< typename VARIANT::types >::value - 1;
+ static constexpr size_t variantSize = boost::mpl::size< typename VARIANT::types >::value;
+ static constexpr size_t variantEnd = variantSize - 1;
static const std::vector< TypeInfo > typeInfos = getTypeInfo< VARIANT >(
Int2Type< variantEnd >{ });
+ static_assert(variantSize > 0, "Variant has no type!");
+
return typeInfos[which];
}
return *m_valueRef.m_data == *rhs.m_valueRef.m_data;
}
- bool operator==(const RCSResourceAttributes::Type& lhs, const RCSResourceAttributes::Type& rhs)
+ bool operator==(const RCSResourceAttributes::Type& lhs,
+ const RCSResourceAttributes::Type& rhs) noexcept
{
return lhs.m_which == rhs.m_which;
}
- bool operator!=(const RCSResourceAttributes::Type& lhs, const RCSResourceAttributes::Type& rhs)
+ bool operator!=(const RCSResourceAttributes::Type& lhs,
+ const RCSResourceAttributes::Type& rhs) noexcept
{
return !(lhs == rhs);
}
return !(lhs == rhs);
}
- auto RCSResourceAttributes::Type::getId() const -> TypeId
+ auto RCSResourceAttributes::Type::getId() const noexcept -> TypeId
+ {
+ return ::getTypeInfo< ValueVariant >(m_which).m_typeId;
+ }
+
+ auto RCSResourceAttributes::Type::getBaseTypeId(const Type& t) noexcept -> TypeId
+ {
+ return ::getTypeInfo< ValueVariant >(t.m_which).m_baseType.getId();
+ }
+
+ size_t RCSResourceAttributes::Type::getDepth(const Type& t) noexcept
{
- return ::getTypeInfo< ValueVariant >(m_which).typeId;
+ return ::getTypeInfo< ValueVariant >(t.m_which).m_depth;
}
+
RCSResourceAttributes::Value::Value() :
m_data{ new ValueVariant{} }
{
{
}
- RCSResourceAttributes::Value::Value(Value&& from) :
+ RCSResourceAttributes::Value::Value(Value&& from) noexcept :
m_data{ new ValueVariant{} }
{
- m_data->swap(*from.m_data);
+ m_data.swap(from.m_data);
}
RCSResourceAttributes::Value::Value(const char* value) :
return boost::apply_visitor(ToStringVisitor(), *m_data);
}
- void RCSResourceAttributes::Value::swap(Value& rhs)
+ void RCSResourceAttributes::Value::swap(Value& rhs) noexcept
{
m_data.swap(rhs.m_data);
}
auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()(
- iterator* iter) const -> result_type
+ iterator* iter) const noexcept -> result_type
{
return iter->m_cur->first;
}
auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()(
- const_iterator* iter) const -> result_type
+ const_iterator* iter) const noexcept -> result_type
{
return iter->m_cur->first;
}
- auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (iterator* iter)
+ auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (iterator* iter) noexcept
-> result_type
{
return iter->m_cur->second;
}
auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()(
- iterator*iter) const -> result_type
+ iterator*iter) const noexcept -> result_type
{
return iter->m_cur->second;
}
auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()(
- const_iterator* iter) const -> result_type
+ const_iterator* iter) const noexcept -> result_type
{
return iter->m_cur->second;
}
- auto RCSResourceAttributes::KeyValuePair::key() const -> const std::string&
+ auto RCSResourceAttributes::KeyValuePair::key() const noexcept -> const std::string&
{
return boost::apply_visitor(m_keyVisitor, m_iterRef);
}
- auto RCSResourceAttributes::KeyValuePair::value() const -> const Value&
+ auto RCSResourceAttributes::KeyValuePair::value() const noexcept -> const Value&
{
return boost::apply_visitor(m_constValueVisitor, m_iterRef);
}
}
RCSResourceAttributes::KeyValuePair::KeyValuePair(boost::variant<iterator*,
- const_iterator*>&& ref) :
+ const_iterator*>&& ref) noexcept :
m_iterRef{ ref }
{
}
{
}
- auto RCSResourceAttributes::const_iterator::operator=(const RCSResourceAttributes::iterator& iter)
- -> const_iterator& {
+ auto RCSResourceAttributes::const_iterator::operator=(
+ const RCSResourceAttributes::iterator& iter) -> const_iterator&
+ {
m_cur = iter.m_cur;
return *this;
}
{
return m_keyValuePair;
}
+
auto RCSResourceAttributes::const_iterator::operator->() const -> pointer
{
return &m_keyValuePair;
return !(*this == rhs);
}
- auto RCSResourceAttributes::begin() -> iterator
+
+ auto RCSResourceAttributes::begin() noexcept -> iterator
{
return iterator{ m_values.begin() };
}
- auto RCSResourceAttributes::end() -> iterator
+ auto RCSResourceAttributes::end() noexcept -> iterator
{
return iterator{ m_values.end() };
}
- auto RCSResourceAttributes::begin() const -> const_iterator
+ auto RCSResourceAttributes::begin() const noexcept -> const_iterator
{
return const_iterator{ m_values.begin() };
}
- auto RCSResourceAttributes::end() const -> const_iterator
+ auto RCSResourceAttributes::end() const noexcept -> const_iterator
{
return const_iterator{ m_values.end() };
}
- auto RCSResourceAttributes::cbegin() const -> const_iterator
+ auto RCSResourceAttributes::cbegin() const noexcept -> const_iterator
{
return const_iterator{ m_values.begin() };
}
- auto RCSResourceAttributes::cend() const -> const_iterator
+ auto RCSResourceAttributes::cend() const noexcept -> const_iterator
{
return const_iterator{ m_values.end() };
}
}
}
- void RCSResourceAttributes::clear()
+ void RCSResourceAttributes::clear() noexcept
{
return m_values.clear();
}
return m_values.find(key) != m_values.end();
}
- bool RCSResourceAttributes::empty() const
+ bool RCSResourceAttributes::empty() const noexcept
{
return m_values.empty();
}
- size_t RCSResourceAttributes::size() const
+ size_t RCSResourceAttributes::size() const noexcept
{
return m_values.size();
}
return replacedList;
}
+
}
}
{
resourceAttributes[KEY] = 1;
- ASSERT_TRUE(resourceAttributes[KEY] == 1);
+ ASSERT_EQ(resourceAttributes[KEY], 1);
}
TEST_F(ResourceAttributesTest, ValueThrowsIfTypeDoesNotMatch)
RCSResourceAttributes::Value copied { resourceAttributes[KEY] };
copied = arbitraryStr;
- ASSERT_TRUE(resourceAttributes[KEY] == 1);
- ASSERT_TRUE(copied == arbitraryStr);
+ ASSERT_EQ(resourceAttributes[KEY], 1);
+ ASSERT_EQ(copied, arbitraryStr);
}
TEST_F(ResourceAttributesTest, IsNullWhenAssignmentNullptr)
{
resourceAttributes[KEY] = nullptr;
- ASSERT_TRUE(resourceAttributes[KEY] == nullptr);
+ ASSERT_EQ(resourceAttributes[KEY], nullptr);
}
TEST_F(ResourceAttributesTest, ValueChangedIfPutWithSameKey)
resourceAttributes[KEY] = "string";
resourceAttributes[KEY] = true;
- ASSERT_TRUE(resourceAttributes[KEY] == true);
+ ASSERT_EQ(resourceAttributes[KEY], true);
}
TEST_F(ResourceAttributesTest, ObjectIsEmptyAfterMoved)
resourceAttributes.at(KEY) = "after";
- ASSERT_TRUE(resourceAttributes[KEY] == "after");
+ ASSERT_EQ(resourceAttributes[KEY], "after");
}
TEST_F(ResourceAttributesTest, CanHaveNestedResourceAttributes)
{
+ constexpr char nestedKey[]{ "nested" };
+ constexpr char value[]{ "nested_value" };
+
RCSResourceAttributes nested;
- nested["nested"] = "nested_value";
+ nested[nestedKey] = value;
resourceAttributes[KEY] = nested;
- ASSERT_TRUE("nested_value" == resourceAttributes[KEY].get<RCSResourceAttributes>()["nested"]);
+ ASSERT_EQ(value, resourceAttributes[KEY].get<RCSResourceAttributes>()[nestedKey]);
}
TEST_F(ResourceAttributesTest, ToStringReturnsStringForValue)
i.value() = arbitraryStr;
}
- ASSERT_TRUE(resourceAttributes[KEY] == arbitraryStr);
+ ASSERT_EQ(resourceAttributes[KEY], arbitraryStr);
}
TEST_F(ResourceAttributesIteratorTest, IteratorIsCopyable)
it = resourceAttributes.begin();
- ASSERT_EQ(it, resourceAttributes.begin());
+ ASSERT_TRUE(it == resourceAttributes.begin());
}
TEST_F(ResourceAttributesIteratorTest, IteratorIndicateNextItemAfterIncreased)
ASSERT_EQ(intValue.getType(), t);
}
+TEST(ResourceAttributesTypeTest, DepthOfNonSequceTypeIsZero)
+{
+ RCSResourceAttributes::Value intValue { 1 };
+
+ RCSResourceAttributes::Type t = intValue.getType();
+
+ ASSERT_EQ(0U, RCSResourceAttributes::Type::getDepth(t));
+}
+
+TEST(ResourceAttributesTypeTest, DepthOfSequceTypeIsNumberOfNested)
+{
+ typedef std::vector< std::vector< std::vector< int > > > NestedVector;
+
+ RCSResourceAttributes::Type t = RCSResourceAttributes::Type::typeOf(NestedVector{ });
+
+ ASSERT_EQ(3U, RCSResourceAttributes::Type::getDepth(t));
+}
+
+TEST(ResourceAttributesTypeTest, BaseTypeOfNonSequceTypeIsItself)
+{
+ RCSResourceAttributes::Value intValue { 1 };
+
+ RCSResourceAttributes::Type t = intValue.getType();
+
+ ASSERT_EQ(RCSResourceAttributes::TypeId::INT, RCSResourceAttributes::Type::getBaseTypeId(t));
+}
+
+TEST(ResourceAttributesTypeTest, BaseTypeOfSequceTypeIsMostNestedType)
+{
+ typedef std::vector< std::vector< std::vector< RCSResourceAttributes > > > NestedVector;
+
+ RCSResourceAttributes::Type t = RCSResourceAttributes::Type::typeOf(NestedVector{ });
+
+ ASSERT_EQ(RCSResourceAttributes::TypeId::ATTRIBUTES,
+ RCSResourceAttributes::Type::getBaseTypeId(t));
+}
+
+
TEST(ResourceAttributesConverterTest, OCRepresentationCanBeConvertedIntoResourceAttributes)
{
constexpr double value = 9876;
RCSResourceAttributes resourceAttributes{
ResourceAttributesConverter::fromOCRepresentation(ocRep) };
- ASSERT_TRUE(nested_value == resourceAttributes[KEY].get<RCSResourceAttributes>()[KEY]);
+ ASSERT_EQ(nested_value, resourceAttributes[KEY].get<RCSResourceAttributes>()[KEY]);
}
OC::OCRepresentation ocRep{
ResourceAttributesConverter::toOCRepresentation(resourceAttributes) };
- ASSERT_TRUE(value == ocRep[KEY].getValue<double>());
+ ASSERT_EQ(value, ocRep[KEY].getValue<double>());
}
TEST(ResourceAttributesConverterTest, NestedResourceAttributesCanBeConvertedIntoOCRepresentation)
ASSERT_TRUE(ocRep.isNULL(KEY));
}
+TEST(ResourceAttributesConverterTest, ResourceAttributesWithSequenceTypeCanBeConverted)
+{
+ typedef std::vector< std::vector< std::vector< int > > > NestedVector;
+ constexpr int value { 3453453 };
+
+ RCSResourceAttributes resourceAttributes;
+ NestedVector seq(10);
+ seq[1].resize(10, std::vector< int >(10));
+ seq[1][2][3] = value;
+ resourceAttributes[KEY] = seq;
+
+ NestedVector ocSeq = ResourceAttributesConverter::toOCRepresentation(resourceAttributes)[KEY];
+
+ ASSERT_EQ(ocSeq[1][2][3], value);
+}
+
+TEST(ResourceAttributesConverterTest, OCRepresentationWithSequenceTypeCanBeConverted)
+{
+ typedef std::vector< std::vector< std::vector< std::string > > > NestedVector;
+ constexpr char value[]{ "some_string" };
+
+ OC::OCRepresentation ocRep;
+ NestedVector seq(10);
+ seq[1].resize(10, std::vector< std::string >(10));
+ seq[1][2][3] = value;
+ ocRep[KEY] = seq;
+
+ RCSResourceAttributes resourceAttributes{
+ ResourceAttributesConverter::fromOCRepresentation(ocRep) };
+
+ ASSERT_EQ(seq, resourceAttributes[KEY]);
+}
class ResourceAttributesUtilTest: public Test
--- /dev/null
+//******************************************************************
+//
+// 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 COMMON_UTILS_ATOMICHELPER_H
+#define COMMON_UTILS_ATOMICHELPER_H
+
+#include <atomic>
+#include <boost/version.hpp>
+
+#ifdef __GNUC__
+#define RCS_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif
+
+#if defined(RCS_GCC_VERSION) && RCS_GCC_VERSION >= 40700
+#define RCS_USE_STD_ATOMIC
+#elif BOOST_VERSION >= 105300
+#include <boost/atomic.hpp>
+#define RCS_USE_BOOST_ATOMIC
+#else
+#define RCS_USE_CUSTOM_ATOMIC
+#endif
+
+namespace OIC
+{
+ namespace Service
+ {
+ namespace Detail
+ {
+
+ class ScopedLock
+ {
+ public:
+ explicit ScopedLock(std::atomic_flag& flag) noexcept :
+ m_flag(flag)
+ {
+ while (m_flag.test_and_set(std::memory_order_acquire));
+ }
+
+ ~ScopedLock() noexcept
+ {
+ m_flag.clear(std::memory_order_release);
+ }
+
+ ScopedLock(const ScopedLock&) = delete;
+ ScopedLock& operator=(const ScopedLock&) = delete;
+
+ private:
+ std::atomic_flag& m_flag;
+ };
+
+ template< typename T >
+ class CustomAtomic
+ {
+ public:
+ CustomAtomic() noexcept :
+ m_value { },
+ m_flag { ATOMIC_FLAG_INIT }
+ {
+
+ }
+ ~CustomAtomic() = default;
+
+ CustomAtomic(const CustomAtomic&) = delete;
+
+ CustomAtomic& operator=(const CustomAtomic&) = delete;
+ CustomAtomic& operator=(const CustomAtomic&) volatile = delete;
+
+ explicit CustomAtomic(T v) noexcept :
+ m_value{ v },
+ m_flag { ATOMIC_FLAG_INIT }
+ {
+ }
+
+ operator T() const noexcept
+ {
+ return load();
+ }
+
+ operator T() const volatile noexcept
+ {
+ return load();
+ }
+
+ T operator=(T v) noexcept
+ {
+ store(v);
+ return v;
+ }
+
+ T operator=(T v) volatile noexcept
+ {
+ store(v);
+ return v;
+ }
+
+ bool is_lock_free() const noexcept
+ {
+ return false;
+ }
+
+ bool is_lock_free() const volatile noexcept
+ {
+ return false;
+ }
+
+ void store(T v, std::memory_order = std::memory_order_seq_cst) noexcept
+ {
+ ScopedLock guard(m_flag);
+ memcpy(&m_value, &v, sizeof(T));
+ }
+
+ void store(T v, std::memory_order = std::memory_order_seq_cst) volatile noexcept
+ {
+ ScopedLock guard(m_flag);
+ memcpy(&m_value, &v, sizeof(T));
+ }
+
+ T load(std::memory_order = std::memory_order_seq_cst) const noexcept
+ {
+ ScopedLock guard(m_flag);
+
+ T v;
+ memcpy(&v, &m_value, sizeof(T));
+ return v;
+ }
+
+ T load(std::memory_order = std::memory_order_seq_cst) const volatile noexcept
+ {
+ ScopedLock guard(m_flag);
+
+ T v;
+ memcpy(&v, &m_value, sizeof(T));
+ return v;
+ }
+
+ T exchange(T v, std::memory_order = std::memory_order_seq_cst) noexcept
+ {
+ ScopedLock guard(m_flag);
+
+ T tmp;
+ memcpy(&tmp, &m_value, sizeof(T));
+
+ memcpy(&m_value, &v, sizeof(T));
+ return tmp;
+ }
+
+ T exchange(T v, std::memory_order = std::memory_order_seq_cst) volatile noexcept
+ {
+ ScopedLock guard(m_flag);
+
+ T tmp;
+ memcpy(&tmp, &m_value, sizeof(T));
+
+ memcpy(&m_value, &v, sizeof(T));
+ return tmp;
+ }
+
+ bool compare_exchange_weak(T& expected, T desired, std::memory_order success,
+ std::memory_order failure) volatile noexcept
+ {
+ return compare_exchange_strong(expected, desired, success, failure);
+ }
+
+ bool compare_exchange_weak(T& expected, T desired,
+ std::memory_order m = std::memory_order_seq_cst) volatile noexcept
+ {
+ return compare_exchange_weak(expected, desired, m, m);
+ }
+
+ bool compare_exchange_strong(T& expected, T desired, std::memory_order /*success*/,
+ std::memory_order /*failure*/) volatile noexcept
+ {
+ ScopedLock guard(m_flag);
+
+ if (memcmp(&m_value, &expected, sizeof(T)) == 0) {
+ memcpy(&m_value, &desired, sizeof(T));
+ return true;
+ } else {
+ memcpy(&expected, &m_value, sizeof(T));
+ return false;
+ }
+ }
+
+ bool compare_exchange_strong(T& expected, T desired,
+ std::memory_order m = std::memory_order_seq_cst) volatile noexcept
+ {
+ return compare_exchange_strong(expected, desired, m, m);
+ }
+
+ private:
+ T m_value;
+ mutable std::atomic_flag m_flag;
+ };
+
+#if defined(RCS_USE_BOOST_ATOMIC)
+ inline boost::memory_order convertMemoryOrder(std::memory_order m) noexcept
+ {
+ switch(m)
+ {
+ case std::memory_order_relaxed: return boost::memory_order_relaxed;
+ case std::memory_order_consume: return boost::memory_order_consume;
+ case std::memory_order_acquire: return boost::memory_order_acquire;
+ case std::memory_order_release: return boost::memory_order_release;
+ case std::memory_order_acq_rel: return boost::memory_order_acq_rel;
+ case std::memory_order_seq_cst: return boost::memory_order_seq_cst;
+ }
+ return boost::memory_order_seq_cst;
+ }
+#else
+ inline std::memory_order convertMemoryOrder(std::memory_order m) noexcept
+ {
+ return m;
+ }
+#endif
+
+ } // namespace detail
+
+ template < typename T >
+ struct AtomicBase
+ {
+#if defined(RCS_USE_STD_ATOMIC)
+ typedef std::atomic< T > type;
+#elif defined(RCS_USE_BOOST_ATOMIC)
+ typedef boost::atomic< T > type;
+#else
+ typedef typename std::conditional< std::is_integral< T >::value, std::atomic< T >,
+ Detail::CustomAtomic< T > >::type type;
+#endif
+ };
+
+ template< typename T >
+ class AtomicWrapper
+ {
+ public:
+ AtomicWrapper() = default;
+
+ AtomicWrapper(T v) :
+ m_base{ v }
+ {
+ }
+
+ AtomicWrapper(const AtomicWrapper&) = delete;
+ AtomicWrapper& operator=(const AtomicWrapper&) = delete;
+
+ operator T() const noexcept
+ {
+ return load();
+ }
+
+ operator T() const volatile noexcept
+ {
+ return load();
+ }
+
+ T operator=(T v) noexcept
+ {
+ store(v);
+ return v;
+ }
+
+ T operator=(T v) volatile noexcept
+ {
+ store(v);
+ return v;
+ }
+
+ T load(std::memory_order order = std::memory_order_seq_cst) const noexcept
+ {
+ return m_base.load(Detail::convertMemoryOrder(order));
+ }
+
+ T load(std::memory_order order = std::memory_order_seq_cst) const volatile noexcept
+ {
+ return m_base.load(Detail::convertMemoryOrder(order));
+ }
+
+ void store(T v, std::memory_order order = std::memory_order_seq_cst) noexcept
+ {
+ m_base.store(v, Detail::convertMemoryOrder(order));
+ }
+
+ private:
+ typename AtomicBase< T >::type m_base;
+ };
+
+ }
+}
+
+#endif // COMMON_UTILS_ATOMICHELPER_H
{
namespace Service
{
- #define BROKER_TAG PCF("BROKER")
+ #define BROKER_TAG "BROKER"
#define BROKER_DEVICE_PRESENCE_TIMEROUT (15000l)
#define BROKER_SAFE_SECOND (5l)
#define BROKER_SAFE_MILLISECOND (BROKER_SAFE_SECOND * (1000))
#include <list>
#include <string>
-#include <boost/atomic.hpp>
+#include <atomic>
#include "BrokerTypes.h"
#include "ResourcePresence.h"
bool isEmptyResourcePresence() const;
const std::string getAddress() const;
- DEVICE_STATE getDeviceState() const;
+ DEVICE_STATE getDeviceState() const noexcept;
+
private:
std::list<ResourcePresence * > resourcePresenceList;
std::string address;
- boost::atomic<DEVICE_STATE> state;
- boost::atomic_bool isRunningTimeOut;
+ std::atomic_int state;
+ std::atomic_bool isRunningTimeOut;
std::mutex timeoutMutex;
std::condition_variable condition;
void changeAllPresenceMode(BROKER_MODE mode);
void subscribeCB(OCStackResult ret,const unsigned int seq, const std::string& Hostaddress);
void timeOutCB(TimerID id);
+
+ void setDeviceState(DEVICE_STATE);
};
} // namespace Service
} // namespace OIC
#include <functional>
#include <list>
#include <string>
-#include <boost/atomic.hpp>
+#include <atomic>
#include <mutex>
#include <condition_variable>
BROKER_MODE mode;
bool isWithinTime;
- boost::atomic_long receivedTime;
+ std::atomic_long receivedTime;
std::mutex cbMutex;
unsigned int timeoutHandle;
{
DevicePresence::DevicePresence()
{
- state = DEVICE_STATE::REQUESTED;
+ setDeviceState(DEVICE_STATE::REQUESTED);
presenceTimerHandle = 0;
isRunningTimeOut = false;
presenceTimerHandle
= presenceTimer.post(BROKER_DEVICE_PRESENCE_TIMEROUT, pTimeoutCB);
}
- DEVICE_STATE DevicePresence::getDeviceState() const
+
+ DEVICE_STATE DevicePresence::getDeviceState() const noexcept
{
- return state;
+ return static_cast< DEVICE_STATE >(state.load());
}
+
+ void DevicePresence::setDeviceState(DEVICE_STATE newState)
+ {
+ state = static_cast< int >(newState);
+ }
+
const std::string DevicePresence::getAddress() const
{
OC_LOG_V(DEBUG, BROKER_TAG, "getAddress()");
case OC_STACK_CONTINUE:
{
OC_LOG_V(DEBUG, BROKER_TAG, "SEQ# %d",seq);
- state = DEVICE_STATE::ALIVE;
+ setDeviceState(DEVICE_STATE::ALIVE);
OC_LOG_V(DEBUG, BROKER_TAG, "device state : %d",
- (int)(state.load(boost::memory_order_consume)));
+ (int)getDeviceState());
changeAllPresenceMode(BROKER_MODE::DEVICE_PRESENCE_MODE);
presenceTimerHandle
= presenceTimer.post(BROKER_DEVICE_PRESENCE_TIMEROUT, pTimeoutCB);
case OC_STACK_PRESENCE_TIMEOUT:
case OC_STACK_PRESENCE_DO_NOT_HANDLE:
{
- state = DEVICE_STATE::LOST_SIGNAL;
+ setDeviceState(DEVICE_STATE::LOST_SIGNAL);
changeAllPresenceMode(BROKER_MODE::NON_PRESENCE_MODE);
break;
}
default:
{
OC_LOG_V(DEBUG, BROKER_TAG, "Presence Lost Signal because unknown type");
- state = DEVICE_STATE::LOST_SIGNAL;
+ setDeviceState(DEVICE_STATE::LOST_SIGNAL);
changeAllPresenceMode(BROKER_MODE::NON_PRESENCE_MODE);
break;
}
OC_LOG_V(DEBUG, BROKER_TAG,
"Timeout execution. will be discard after receiving cb message");
- state = DEVICE_STATE::LOST_SIGNAL;
+ setDeviceState(DEVICE_STATE::LOST_SIGNAL);
changeAllPresenceMode(BROKER_MODE::NON_PRESENCE_MODE);
isRunningTimeOut = false;
time(¤tTime);
currentTime += 0L;
- if((receivedTime.load(boost::memory_order_consume) == 0) ||
- ((receivedTime + BROKER_SAFE_SECOND) > currentTime ))
+ if((receivedTime == 0) || ((receivedTime + BROKER_SAFE_SECOND) > currentTime ))
{
this->isWithinTime = true;
return;
instance->addDevice(device);
}
- void SetUp()
+ void SetUp()
{
TestWithMock::SetUp();
instance = DeviceAssociation::getInstance();
pResource = PrimitiveResource::Ptr(mocks.Mock< PrimitiveResource >(), [](PrimitiveResource*){});
}
- void TearDown()
+ void TearDown()
{
TestWithMock::TearDown();
device.reset();
SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
######################################################################
-#unit test setting
+#unit test setting
######################################################################
src_dir = lib_env.get('SRC_DIR')
gtest_dir = src_dir + '/extlibs/gtest/gtest-1.7.0'
class DataCache;
-#define CACHE_TAG PCF("CACHE")
+#define CACHE_TAG "CACHE"
#define CACHE_DEFAULT_REPORT_MILLITIME 10000
#define CACHE_DEFAULT_EXPIRED_MILLITIME 15000
SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
######################################################################
-# unit test setting
+# unit test setting
######################################################################
src_dir = lib_env.get('SRC_DIR')
gtest_dir = src_dir + '/extlibs/gtest/gtest-1.7.0'
#include "ScopeLogger.h"
-#define TAG PCF("RCSDiscoveryManager")
+#define TAG "RCSDiscoveryManager"
using namespace OIC::Service;
}
void RCSDiscoveryManager::discoverResource(const RCSAddress& address,
- const std::string& resourceURI, ResourceDiscoveredCallback cb)
+ ResourceDiscoveredCallback cb)
{
- SCOPE_LOG_F(DEBUG, TAG);
+ discoverResourceByType(address, OC_RSRVD_WELL_KNOWN_URI, "", std::move(cb));
+ }
+
+ void RCSDiscoveryManager::discoverResource(const RCSAddress& address,
+ const std::string& relativeURI, ResourceDiscoveredCallback cb)
+ {
+ discoverResourceByType(address, relativeURI, "", std::move(cb));
+ }
+
+ void RCSDiscoveryManager::discoverResourceByType(const RCSAddress& address,
+ const std::string& resourceType,
+ ResourceDiscoveredCallback cb)
+ {
+ discoverResourceByType(address, OC_RSRVD_WELL_KNOWN_URI, resourceType, std::move(cb));
+ }
+ void RCSDiscoveryManager::discoverResourceByType(const RCSAddress& address,
+ const std::string& relativeURI, const std::string& resourceType,
+ ResourceDiscoveredCallback cb)
+ {
if (!cb)
{
- OC_LOG(ERROR, TAG, "discoverResource NULL Callback");
- throw InvalidParameterException{ "discoverResource NULL Callback'" };
+ OC_LOG(ERROR, TAG, "discoverResourceByType NULL Callback");
+ throw InvalidParameterException { "discoverResourceByType NULL Callback'" };
}
-
- OIC::Service::discoverResource(address, resourceURI,
+ else
+ {
+ std::string resourceURI = relativeURI + "?rt=" + resourceType;
+ OIC::Service::discoverResource(address, resourceURI,
std::bind(findCallback, std::placeholders::_1, std::move(cb)));
+ }
}
}
}
#include "ScopeLogger.h"
-#define TAG PCF("RCSRemoteResourceObject")
+#define TAG "RCSRemoteResourceObject"
namespace
{
{
SCOPE_LOG_F(DEBUG, TAG);
- return getCachedAttributes().at(key);
+ //check whether key is available or not
+ RCSResourceAttributes cachedAttributes= getCachedAttributes();
+ if(cachedAttributes.contains(key))
+ {
+ return getCachedAttributes().at(key);
+ }
+ else
+ {
+ throw BadRequestException{ "Requested Attribute is not present" };
+ }
}
std::string RCSRemoteResourceObject::getUri() const
except KeyError:
print '''
*********************************** Error *************************************
- * Building resource container without Java support. JAVA_HOME or JAVA_LIB are not set properly
- * Please configure JAVA_HOME to point to your Java 7 JDK and
+ * Building resource container without Java support. JAVA_HOME or JAVA_LIB are not set properly
+ * Please configure JAVA_HOME to point to your Java 7 JDK and
* JAVA_LIB to your folder containing libjvm
* Example: export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-i386
* export JAVA_LIB=/usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/server
- *******************************************************************************
+ *******************************************************************************
'''
resource_container_env.Append(CPPDEFINES={'JAVA_SUPPORT':0})
-
+
resource_container_env.AppendUnique(
CPPPATH = [
- env.get('SRC_DIR')+'/extlibs',
+ env.get('SRC_DIR')+'/extlibs',
'../../include',
'include',
'bundle-api/include',
- 'src'
+ 'src'
])
if int(containerJavaSupport):
resource_container_env.AppendUnique(
CPPPATH = [
os.environ['JAVA_HOME']+'/include',
- os.environ['JAVA_HOME']+'/include/linux'
+ os.environ['JAVA_HOME']+'/include/linux'
])
except KeyError:
print ''
-
+
if target_os not in ['windows', 'winrt']:
resource_container_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall'])
if target_os == 'android':
resource_container_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
- resource_container_env.PrependUnique(LIBS = ['gnustl_shared', 'compatibility', 'log'])
-
+ resource_container_env.PrependUnique(LIBS = ['gnustl_shared', 'log'])
+
try:
resource_container_env.AppendUnique(LIBPATH = [os.environ['JAVA_LIB']])
except KeyError:
print ''
-
+
resource_container_env.PrependUnique(LIBS = ['rcs_server', 'rcs_common', 'oc','octbstack', 'oc_logger', 'oc_logger_core', 'connectivity_abstraction'])
-resource_container_env.AppendUnique(LIBS = ['dl'])
+resource_container_env.AppendUnique(LIBS = ['dl'])
if int(containerJavaSupport):
- try:
+ try:
print 'Java Lib: ', os.environ['JAVA_LIB']
- resource_container_env.AppendUnique(LIBS = ['jvm'])
+ resource_container_env.AppendUnique(LIBS = ['jvm'])
except KeyError:
print ''
######################################################################
# Source files and Targets
######################################################################
-res_container_src = ['src/BaseActivator.cpp','src/BundleActivator.cpp','src/RCSBundleInfo.cpp',
+res_container_src = ['src/BaseActivator.cpp','src/BundleActivator.cpp','src/RCSBundleInfo.cpp',
'src/BundleInfoInternal.cpp', 'src/BundleResource.cpp', 'src/Configuration.cpp', 'src/JavaBundleResource.cpp', 'src/ProtocolBridgeResource.cpp',
- 'src/ProtocolBridgeConnector.cpp', 'src/RCSResourceContainer.cpp', 'src/ResourceContainerBundleAPI.cpp', 'src/ResourceContainerImpl.cpp',
+ 'src/ProtocolBridgeConnector.cpp', 'src/RCSResourceContainer.cpp', 'src/ResourceContainerBundleAPI.cpp', 'src/ResourceContainerImpl.cpp',
'src/SoftSensorResource.cpp']
-
+
res_container_static = resource_container_env.StaticLibrary('rcs_container', res_container_src)
res_container_shared = resource_container_env.SharedLibrary('rcs_container', res_container_src)
######################################################################
# build soft sensor sample bundle
######################################################################
+if target_os in ['linux', 'android']:
+ ss_resource_bundle_env = resource_container_env.Clone()
+ ss_resource_bundle_env.AppendUnique(CCFLAGS = ['-fPIC'])
-ss_resource_bundle_env = resource_container_env.Clone()
-ss_resource_bundle_env.AppendUnique(CCFLAGS = ['-fPIC'])
+ SS_RESOURCE_BUNDLE_DIR = 'examples/SoftSensorSampleBundle/'
+ ss_resource_bundle_env.AppendUnique(CPPPATH = [
+ SS_RESOURCE_BUNDLE_DIR + 'include',
+ 'include/',
+ '../../include',
+ ])
-SS_RESOURCE_BUNDLE_DIR = 'examples/SoftSensorSampleBundle/'
-ss_resource_bundle_env.AppendUnique(CPPPATH = [
- SS_RESOURCE_BUNDLE_DIR + 'include',
- 'include/',
- '../../include',
- ])
-
-ss_resource_bundle_env.PrependUnique(LIBS = ['rcs_container'])
-
-ss_resource_bundle_src = [ Glob(SS_RESOURCE_BUNDLE_DIR + 'src/*.cpp')]
+ ss_resource_bundle_env.PrependUnique(LIBS = ['rcs_container'])
-SoftSensorBundle = ss_resource_bundle_env.SharedLibrary('SoftSensorBundle', ss_resource_bundle_src)
-ss_resource_bundle_env.InstallTarget(SoftSensorBundle, 'libSoftSensorBundle')
+ ss_resource_bundle_src = [ Glob(SS_RESOURCE_BUNDLE_DIR + 'src/*.cpp')]
+ SoftSensorBundle = ss_resource_bundle_env.SharedLibrary('SoftSensorBundle', ss_resource_bundle_src)
+ ss_resource_bundle_env.InstallTarget(SoftSensorBundle, 'libSoftSensorBundle')
+
######################################################################
# build hue sample bundle
######################################################################
print '''X
*********************************** Error *************************************
* Cannot build hue sample. Please install libcurl.
-* Example (Ubuntu):
+* Example (Ubuntu):
* sudo apt-get install libcurl4-openssl-dev
* sudo ldconfig
* Hint: check with pkg-config --libs libcurl and clear scons cache.
* Skipping hue sample build.
-*******************************************************************************
+*******************************************************************************
'''
else:
hue_resource_bundle_env = resource_container_env.Clone()
hue_resource_bundle_env.AppendUnique(CCFLAGS = ['-fPIC'])
-
+
HUE_RESOURCE_BUNDLE_DIR = 'examples/HueSampleBundle/'
hue_resource_bundle_env.AppendUnique(CPPPATH = [
HUE_RESOURCE_BUNDLE_DIR + 'include',
'include/'
- ])
-
+ ])
+
hue_resource_bundle_env.PrependUnique(LIBS = ['curl', 'rcs_container'])
-
+
hue_resource_bundle_src = [ Glob(HUE_RESOURCE_BUNDLE_DIR + 'src/*.cpp')]
-
+
HueBundle = hue_resource_bundle_env.SharedLibrary('HueBundle', hue_resource_bundle_src)
hue_resource_bundle_env.InstallTarget(HueBundle, 'libHueBundle')
- lib_env = conf2.Finish()
+lib_env = conf2.Finish()
######################################################################
# build resource container unit tests
######################################################################
-SConscript('unittests/SConscript')
+if target_os == 'linux':
+ SConscript('unittests/SConscript')
######################################################################
# Build Container Sample
#include "SoftSensorBundleActivator.h"
#include "DiscomfortIndexSensorResource.h"
#include <algorithm>
+#include <sstream>
SoftSensorBundleActivator *bundle;
DiscomfortIndexSensorResource *newResource = new DiscomfortIndexSensorResource();
newResource->m_bundleId = m_bundleId;
- newResource->m_uri = "/softsensor/discomfortIndex/" + std::to_string(
- discomfortIndexSensorCount++);
+
+ std::string indexCount;//string which will contain the indexCount
+ stringstream convert; // stringstream used for the conversion
+ convert << discomfortIndexSensorCount++;//add the value of Number to the characters in the stream
+ indexCount = convert.str();//set indexCount to the content of the stream
+
+ newResource->m_uri = "/softsensor/discomfortIndex/" + indexCount;
+
newResource->m_resourceType = resourceInfo.resourceType;
newResource->m_mapResourceProperty = resourceInfo.resourceProperty;
void *bundleHandle = m_bundles[id]->getBundleHandle();
info_logger() << "Unregister bundle: " << m_bundles[id]->getID() << ", "
<< m_bundles[id]->getID() << endl;
- char *error;
+ const char *error;
dlclose(bundleHandle);
if ((error = dlerror()) != NULL)
{
void ResourceContainerImpl::registerSoBundle(RCSBundleInfo *bundleInfo)
{
- char *error;
+ const char *error;
activator_t *bundleActivator = NULL;
deactivator_t *bundleDeactivator = NULL;
if env.get('LOGGING'):
env.AppendUnique(CPPDEFINES = ['TB_LOG'])
-
-
+
+
# Add third party libraries
except KeyError:
print '''
*********************************** Error *************************************
- * Building resource container without Java support. JAVA_HOME or JAVA_LIB are not set properly
- * Please configure JAVA_HOME to point to your Java 7 JDK and
+ * Building resource container without Java support. JAVA_HOME or JAVA_LIB are not set properly
+ * Please configure JAVA_HOME to point to your Java 7 JDK and
* JAVA_LIB to your folder containing libjvm
* Example: export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-i386
* export JAVA_LIB=/usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/server/
- *******************************************************************************
+ *******************************************************************************
'''
container_gtest_env.Append(CPPDEFINES={'JAVA_SUPPORT_TEST':0})
-
+
target_os = env.get('TARGET_OS')
container_gtest_env.AppendUnique(
CPPPATH = [
- env.get('SRC_DIR')+'/extlibs',
+ env.get('SRC_DIR')+'/extlibs',
'../include',
'../../../include',
'../include/internal',
'../../common/utils/include',
- '../bundle-api/include'
+ '../bundle-api/include'
])
-if int(containerJavaSupport):
+if int(containerJavaSupport):
try:
container_gtest_env.AppendUnique(
CPPPATH = [
os.environ['JAVA_HOME']+'/include',
- os.environ['JAVA_HOME']+'/include/linux'
+ os.environ['JAVA_HOME']+'/include/linux'
])
except KeyError:
print ''
container_gtest_env.PrependUnique(CPPPATH = [env.get('SRC_DIR')+'/extlibs/hippomocks-master',
gtest_dir + '/include'])
-
+
if int(containerJavaSupport):
try:
container_gtest_env.AppendUnique(LIBPATH = [os.environ['JAVA_LIB']])
except KeyError:
print ''
-container_gtest_env.AppendUnique(CCFLAGS = ['-Wnoexcept'])
+container_gtest_env.AppendUnique(CCFLAGS = ['-Wnoexcept'])
container_gtest_env.PrependUnique(LIBS = ['rcs_container', 'rcs_server', 'rcs_common', 'oc','octbstack', 'oc_logger', 'oc_logger_core', 'connectivity_abstraction', gtest, gtest_main])
container_gtest_env.AppendUnique(LIBS = ['dl'])
if int(containerJavaSupport):
- try:
+ try:
print 'Java Lib: ', os.environ['JAVA_LIB']
- container_gtest_env.AppendUnique(LIBS = ['jvm'])
+ container_gtest_env.AppendUnique(LIBS = ['jvm'])
except KeyError:
print ''
test_bundle_env.AppendUnique(CPPPATH = [
TEST_BUNDLE_DIR + 'include',
'../include/'
- ])
+ ])
test_bundle_src = [ Glob(TEST_BUNDLE_DIR + 'src/*.cpp'), Glob('src/*.cpp')]
######################################################################
server_builder_env.AppendUnique(CPPPATH = [
'../common/primitiveResource/include',
+ '../common/utils/include',
'../../include',
])
if target_os == 'android':
server_builder_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
- server_builder_env.PrependUnique(LIBS = ['gnustl_shared', 'compatibility', 'log'])
+ server_builder_env.PrependUnique(LIBS = ['gnustl_shared', 'log'])
server_builder_env.AppendUnique(LIBS = ['dl', 'oc', 'rcs_common'])
######################################################################
# Build Test
######################################################################
-server_builder_test_env = server_builder_env.Clone();
-
-server_builder_test_env.AppendUnique(CPPPATH = [
- env.get('SRC_DIR')+'/extlibs/hippomocks-master',
- gtest_dir + '/include',
- '../common/utils/include'
- ])
-
-gtest = File(gtest_dir + '/lib/.libs/libgtest.a')
-gtest_main = File(gtest_dir + '/lib/.libs/libgtest_main.a')
-
-server_builder_test_env.PrependUnique(LIBS = [
- 'rcs_server',
- 'octbstack',
- 'oc_logger',
- 'connectivity_abstraction',
- 'coap',
- gtest,
- gtest_main,
- 'pthread',
- ])
-
-server_builder_test_src = env.Glob('unittests/*.cpp')
-
-server_builder_test = server_builder_test_env.Program('rcs_server_test', server_builder_test_src)
-Alias("rcs_server_test", server_builder_test)
-env.AppendTarget('rcs_server_test')
-
-if env.get('TEST') == '1':
- target_os = env.get('TARGET_OS')
- if target_os == 'linux':
- from tools.scons.RunTest import *
- run_test(server_builder_test_env, '',
- 'service/resource-encapsulation/src/serverBuilder/rcs_server_test')
\ No newline at end of file
+if target_os == 'linux':
+ server_builder_test_env = server_builder_env.Clone();
+
+ server_builder_test_env.AppendUnique(CPPPATH = [
+ env.get('SRC_DIR')+'/extlibs/hippomocks-master',
+ gtest_dir + '/include',
+ '../common/utils/include'
+ ])
+
+ gtest = File(gtest_dir + '/lib/.libs/libgtest.a')
+ gtest_main = File(gtest_dir + '/lib/.libs/libgtest_main.a')
+
+ server_builder_test_env.PrependUnique(LIBS = [
+ 'rcs_server',
+ 'octbstack',
+ 'oc_logger',
+ 'connectivity_abstraction',
+ 'coap',
+ gtest,
+ gtest_main,
+ 'pthread',
+ ])
+
+ server_builder_test_src = env.Glob('unittests/*.cpp')
+
+ server_builder_test = server_builder_test_env.Program('rcs_server_test', server_builder_test_src)
+ Alias("rcs_server_test", server_builder_test)
+ env.AppendTarget('rcs_server_test')
+
+ if env.get('TEST') == '1':
+ from tools.scons.RunTest import *
+ run_test(server_builder_test_env, '',
+ 'service/resource-encapsulation/src/serverBuilder/rcs_server_test')
#include <RequestHandler.h>
#include <AssertUtils.h>
+#include <AtomicHelper.h>
#include <ResourceAttributesConverter.h>
#include <logger.h>
m_mutex{ },
m_mutexKeyAttributeUpdate{ }
{
+ m_lockOwner.reset(new AtomicThreadId);
}
RCSResourceObject::~RCSResourceObject()
void RCSResourceObject::expectOwnLock() const
{
- if (m_lockOwner != std::this_thread::get_id())
+ if (getLockOwner() != std::this_thread::get_id())
{
throw NoLockException{ "Must acquire the lock first using LockGuard." };
}
}
+ std::thread::id RCSResourceObject::getLockOwner() const noexcept
+ {
+ return *m_lockOwner;
+ }
+
+ void RCSResourceObject::setLockOwner(std::thread::id&& id) const noexcept
+ {
+ m_lockOwner->store(std::move(id));
+ }
+
bool RCSResourceObject::isObservable() const
{
return ::hasProperty(m_properties, OC_OBSERVABLE);
AttrKeyValuePairs replaced = requestHandler->applyAcceptanceMethod(
response.getAcceptanceMethod(), *this, attrs);
- for (const auto& it : replaced)
+ for (const auto& attrKeyValPair : replaced)
{
std::lock_guard<std::mutex> lock(m_mutexKeyAttributeUpdate);
- auto keyAttribute = m_keyAttributesUpdatedListeners.find(it.first);
- if(keyAttribute != m_keyAttributesUpdatedListeners.end())
+ auto keyAttrListener = m_keyAttributesUpdatedListeners.find(attrKeyValPair.first);
+ if(keyAttrListener != m_keyAttributesUpdatedListeners.end())
{
- keyAttribute-> second(it.second, attrs[it.first]);
+ keyAttrListener-> second(attrKeyValPair.second, attrs[attrKeyValPair.first]);
}
}
}
OCEntityHandlerResult RCSResourceObject::handleObserve(
- std::shared_ptr< OC::OCResourceRequest > request)
+ std::shared_ptr< OC::OCResourceRequest >)
{
- assert(request != nullptr);
-
if (!isObservable())
{
return OC_EH_ERROR;
if (m_isOwningLock)
{
- m_resourceObject.m_lockOwner = std::thread::id{ };
+ m_resourceObject.setLockOwner(std::thread::id{ });
m_resourceObject.m_mutex.unlock();
}
}
void RCSResourceObject::LockGuard::init()
{
- if (m_resourceObject.m_lockOwner != std::this_thread::get_id())
+ if (m_resourceObject.getLockOwner() != std::this_thread::get_id())
{
m_resourceObject.m_mutex.lock();
- m_resourceObject.m_lockOwner = std::this_thread::get_id();
+ m_resourceObject.setLockOwner(std::this_thread::get_id());
m_isOwningLock = true;
}
m_autoNotifyFunc = ::createAutoNotifyInvoker(&RCSResourceObject::autoNotify,
m_isOwningLock{ false },
m_resourceObject(resourceObject)
{
- if (resourceObject.m_lockOwner != std::this_thread::get_id())
+ if (m_resourceObject.getLockOwner() != std::this_thread::get_id())
{
m_resourceObject.m_mutex.lock();
- m_resourceObject.m_lockOwner = std::this_thread::get_id();
+ m_resourceObject.setLockOwner(std::this_thread::get_id());
m_isOwningLock = true;
}
}
{
if (m_isOwningLock)
{
- m_resourceObject.m_lockOwner = std::thread::id{ };
+ m_resourceObject.setLockOwner(std::thread::id{ });
m_resourceObject.m_mutex.unlock();
}
}
{
return m_isOwningLock;
}
+
}
}
ASSERT_EQ(value, server->getAttribute<int>(KEY));
}
+TEST_F(ResourceObjectTest, SettingNestedAttributesIsSameToGettingNestedAttributes)
+{
+ RCSResourceAttributes lightAttributes;
+
+ lightAttributes["red"]=50;
+ lightAttributes["blue"]=100;
+ lightAttributes["green"]=150;
+
+ server->setAttribute(KEY, lightAttributes);
+
+ ASSERT_EQ(lightAttributes, server->getAttribute<RCSResourceAttributes>(KEY));
+}
class AutoNotifyTest: public ResourceObjectTest
{
{
auto request = make_shared<OCResourceRequest>();
- OCEntityHandlerRequest ocEntityHandlerRequest { 0 };
+ OCEntityHandlerRequest ocEntityHandlerRequest;
+ memset(&ocEntityHandlerRequest, 0, sizeof(OCEntityHandlerRequest));
OC::MessageContainer mc;
mc.addRepresentation(ocRep);
{
while (checkObject())
{
- RCSDiscoveryManager::getInstance()->discoverResource(RCSAddress::multicast(),
- "/oic/res?rt=Resource.Hosting", std::bind(resourceDiscovered, this, finished,
- std::placeholders::_1));
-
+ const std::string uri = "/oic/res";
+ const std::string type = "Resource.Hosting";
+ RCSDiscoveryManager::getInstance()->discoverResourceByType(RCSAddress::multicast(),
+ uri, type, std::bind(resourceDiscovered, this, finished,
+ std::placeholders::_1));
Wait(1000);
}
}
ResourceClient_gtest_env.AppendUnique(
CPPPATH = [
- src_dir + '/extlibs/hippomocks-master',
+ src_dir + '/extlibs/hippomocks-master',
src_dir + '/extlibs/gtest/gtest-1.7.0/include',
'../include',
'../src/common/utils/include',
gtest,
gtest_main])
-ResourceClient_gtest_env.AppendUnique(LIBS = ['dl'])
+ResourceClient_gtest_env.AppendUnique(LIBS = ['dl'])
######################################################################
# Build Test
== How to Build SoftSensorManager ==
===============================================================================
-Once the source code is downloaded in your local specific folder, you may follow
-the steps to build and execute Soft Sensor Manager and its applications.
+Once the source code is downloaded in your local specific folder, you may follow
+the steps to build and execute Soft Sensor Manager and its applications.
In this context, we assume that the code was downloaded into 'oic' folder.
1. Download source code
=======================================
-Once you download the codes, please make sure that the downloaded code structure is as follows;
+Once you download the codes, please make sure that the downloaded code structure is as follows;
-oic/resource
+oic/resource
oic/service
oic/utilities
-
-
+
+
The path for Soft Sensor Manager is as following;
oic/service/soft-sensor-manager
-
+
The SoftSensorManager directory includes following sub directories;
Directories Description
-oic/service/soft-sensor-manager/build : There are makefiles for different platform; Linux, Tizen, and Arduino.
+oic/service/soft-sensor-manager/build : There are makefiles for different platform; Linux, Tizen, and Arduino.
oic/service/soft-sensor-manager/doc : SSM developer's guide and Getting started documents
oic/service/soft-sensor-manager/SampleApp : There are two types of sample applications; application for UI, and application for physical sensors.
For UI application, there are SSMTesterApp in /linux, and /Tizen.
- For physical sensors,
+ For physical sensors,
1) Temperature and Humidity sensors, THSensorApp, in \linux and \arduino.
- In the two directories, in \linux and \arduino , there are two TemperaterHumiditySensor applications,
- THSensorApp and THSensorApp1, and they are for DiscomfortSoftSensor which aggregates
+ In the two directories, in \linux and \arduino , there are two TemperaterHumiditySensor applications,
+ THSensorApp and THSensorApp1, and they are for DiscomfortSoftSensor which aggregates
two TemperaterHumiditySensors to calculate current discomfort index in the given room.
2) Trackee_Thing for IndoorTrajectorySensor in \linux and \arduino
-
+
oic/service/soft-sensor-manager/SDK : The SDK APIs for applications is located.
-oic/service/soft-sensor-manager/SSMCore : The SSM service codes
-oic/service/soft-sensor-manager/SoftSensorPlugin : The source codes for soft sensors can be located in this folder.
+oic/service/soft-sensor-manager/SSMCore : The SSM service codes
+oic/service/soft-sensor-manager/SoftSensorPlugin : The source codes for soft sensors can be located in this folder.
Examples of soft sensors are DiscomfortIndexSensor and IndoorTrajectorySensor.
=======================================
-2. Refer readme files in each build
+2. Refer readme files in each build
directory for each module.
=======================================
-There are readme files in the build directories for each module (e.g. \SDK, \ SSMCore, \SampleApp).
+There are readme files in the build directories for each module (e.g. \SDK, \ SSMCore, \SampleApp).
Please refer the files for specific setup.
3. Run make
=======================================
-3.1 Run make for SoftSensorManager & App in Ubuntu.
+3.1 Run make for SoftSensorManager & App in Ubuntu.
-3.1.1 Before running make for SoftSensorManager & App in Ubuntu, resource should be built in advance.
+3.1.1 Before running make for SoftSensorManager & App in Ubuntu, resource should be built in advance.
Please refer to ¡®Build the IoTivity project for Linux¡¯ in previous section
-3.1.2 If you type "make" at ¡°soft-sensor-manager/build/linux¡±, all packages will be pushed to "/soft-sensor-manager/build/linux/release".
+3.1.2 If you type "make" at ¡°soft-sensor-manager/build/linux¡±, all packages will be pushed to "/soft-sensor-manager/build/linux/release".
You can also found other packages in the folder
+--------------------------------------------------------------+
3.2 Run make for App in Arduino
-3.2.1 If you want to build for Arduino, download Arduino IDE (Arduino 1.0.6) from following url.
+3.2.1 If you want to build for Arduino, download Arduino IDE (Arduino 1.0.6) from following url.
Extract ¡®arduino-1.0.6-linux32.tgz¡¯ and change folder name from ¡®arduino-1.0.6¡¯ to ¡®arduino¡¯ and then move to "/usr/share/".
url: http://arduino.cc/en/Main/Software
| $ mv arduino-1.0.6 arduino |
| $ sudo cp -Rdp ./arduino /usr/share/ |
+--------------------------------------------------------------------+
-
-3.2.2 Download Time library (Time.zip, Click ¡°The download¡±) from following url.
- Unzip Time.zip and move them to /usr/share/arduino/libraries.
+
+3.2.2 Download Time library (Time.zip, Click ¡°The download¡±) from following url.
+ Unzip Time.zip and move them to /usr/share/arduino/libraries.
url: http://playground.arduino.cc/Code/Time
+--------------------------------------------------------------------+
| ARDUINO_DIR = /usr/share/arduino |
| ARDUINO_TOOLS_DIR = $(ARDUINO_DIR)/hardware/tools/avr/bin |
+------------------------------------------------------------------------------------+
- If you have a problem with compiling ¡®resource¡¯ when you compile arduino application,
+ If you have a problem with compiling ¡®resource¡¯ when you compile arduino application,
you may need to check 'local.properties' which is written in the readme file, '/oic/resource/csdk/README'.
-3.2.4 Before running make for application, you need to build resource with arduino platform first.
+3.2.4 Before running make for application, you need to build resource with arduino platform first.
Please refer to below example.
+------------------------------------------------------------------------------------------+
PLATFORM : arduinomega or arduinodue.
ARDUINOWIFI : 0 (Ethernet), 1(Wifi)
-3.2.5 Now, you are ready to build sample arduino application.
+3.2.5 Now, you are ready to build sample arduino application.
To build all sample applications for arduino, just do as below.
+------------------------------------------------------------------------------------------------+
-|~/oic/service/soft-sensor-manager/ build/Arduino$ make PLATFORM=arduinomega ARDUINOWIFI=1 |
-+------------------------------------------------------------------------------------------------+
+|~/oic/service/soft-sensor-manager/ build/Arduino$ make PLATFORM=arduinomega ARDUINOWIFI=1 |
++------------------------------------------------------------------------------------------------+
- If you want to build each sample application separately, go to build directory for sample application.
- Belowing is example for THSensor App.
-
+ If you want to build each sample application separately, go to build directory for sample application.
+ Belowing is example for THSensor App.
+
++-------------------------------------------------------------------------------------------------------------------+
+|~/oic/service/soft-sensor-manager/SampleApp/arduino/THSensorApp/build$ make PLATFORM=arduinomega ARDUINOWIFI=1 |
+-------------------------------------------------------------------------------------------------------------------+
-|~/oic/service/soft-sensor-manager/SampleApp/arduino/THSensorApp/build$ make PLATFORM=arduinomega ARDUINOWIFI=1 |
-+-------------------------------------------------------------------------------------------------------------------+
-3.2.6. To build and deploy the binary into the target hardware board, Aruino in this case, you need 'install' option.
+3.2.6. To build and deploy the binary into the target hardware board, Aruino in this case, you need 'install' option.
Please refer to below example for THSensorApp;
+--------------------------------------------------------------------------------------------------------------------------+
-|~/oic/service/soft-sensor-manager/SampleApp/arduino/THSensorApp/build$ make install PLATFORM=arduinomega ARDUINOWIFI=1 |
-+--------------------------------------------------------------------------------------------------------------------------+
- Before ¡®make install¡¯, you need to check the file located at "/oic/service/soft-sensor-manager/SampleApp/arduino/THSensorApp/build/Makefile".
- Line 26, ARDUINO_PORT is the serial port path, which has to be aligned on your system.
+|~/oic/service/soft-sensor-manager/SampleApp/arduino/THSensorApp/build$ make install PLATFORM=arduinomega ARDUINOWIFI=1 |
++--------------------------------------------------------------------------------------------------------------------------+
+ Before ¡®make install¡¯, you need to check the file located at "/oic/service/soft-sensor-manager/SampleApp/arduino/THSensorApp/build/Makefile".
+ Line 26, ARDUINO_PORT is the serial port path, which has to be aligned on your system.
=======================================
If you want to check how soft-sensor-manager is working, you can run simple applications - THSensorApp and SSMTesterApp
-4.1 To initiate THSensorApp, please enter as following;
+4.1 To initiate THSensorApp, please enter as following;
+------------------------------------------------------------------------+
-|~/oic/service/soft-sensor-manager/build/linux/release$ ./THSensorApp |
-|~/oic/service/soft-sensor-manager/build/linux/release$ ./THSensorApp1 |
+|~/oic/service/soft-sensor-manager/build/linux/release$ ./THSensorApp |
+|~/oic/service/soft-sensor-manager/build/linux/release$ ./THSensorApp1 |
+------------------------------------------------------------------------+
-
+
4.2 To initiate SSMTesterApp, please enter as following;
+--------------------------------------------------------------------------+
liboc.so
liboctbstack.so
liboc_logger.so
-
+
5.2.2 To export the shared libraries, please enter as following;
+---------------------------------------------------------------------------------------------------------------------------+
5.4 To initiate THSensorApp, please enter as following;
+------------------------------------------------------------------------------------------+
-|~/oic/out/<target_os>/<target_arch>/release/service/soft-sensor-manager$ ./THSensorApp |
-|~/oic/out/<target_os>/<target_arch>/release/service/soft-sensor-manager$ ./THSensorApp1 |
+|~/oic/out/<target_os>/<target_arch>/release/service/soft-sensor-manager$ ./THSensorApp |
+|~/oic/out/<target_os>/<target_arch>/release/service/soft-sensor-manager$ ./THSensorApp1 |
+------------------------------------------------------------------------------------------+
5.5 To initiate SSMTesterApp, please enter as following;
BMISensor = BMISensor_env.SharedLibrary('BMISensor', BMISensor_src)
BMISensor_env.InstallTarget(BMISensor, 'libBMISensor')
BMISensor_env.UserInstallTargetLib(BMISensor, 'libBMISensor')
-
-
+BMISensor_env.UserInstallTargetHeader('SDK/cpp/include/SSMInterface.h', 'service/soft-sensor-manager', 'SSMInterface.h')
######################################################################
# build SSM CORE
* Get affected DataId. ContextModel has plenty of data so \n
* returned data is matched from given condition
*
- * @return int - the affected DataId
+ * @return the affected DataId
*/
virtual int getDataId() = 0;
* ContextModel has at least one property that contains data \n
* property is described from its specification.
*
- * @return int - number of properties
+ * @return number of properties
*/
virtual int getPropertyCount() = 0;
/**
* Retrieve propertyName
*
- * @param propertyIndex - index of property to read
+ * @param propertyIndex index of property to read
*
- * @return std::string - property name
+ * @return property name
*/
virtual std::string getPropertyName(int propertyIndex) = 0;
*
* @param propertyIndex index of property to read
*
- * @return std::string - property value
+ * @return property value
*/
virtual std::string getPropertyValue(int propertyIndex) = 0;
/**
* Retrieve propertyValue using given name
*
- * @param propertyName - property name looking for
+ * @param propertyName property name looking for
*
- * @return std::string - property name
+ * @return property value
*/
virtual std::string getPropertyValueByName(std::string propertyName) = 0;
protected:
/**
* Get affected ContextModels. The query can specify multiple ContextModels for retrieving data.
*
- * @param pAffectedModels - affected ContextModel list
+ * @param pAffectedModels affected ContextModel list
*
- * @return SSMRESULT - return value of the API. Returns SSM_S_OK if success
+ * @return Returns ::SSM_S_OK if success, some other value upon failure.
*/
virtual SSMRESULT getAffectedModels(std::vector<std::string> *pAffectedModels) = 0;
/**
* Get affected data count. There are multiple data can exist from given condition.
*
- * @param modelName - affected ContextModel name
+ * @param modelName affected ContextModel name
*
- * @param pDataCount - affected dataId count
+ * @param pDataCount affected dataId count
*
- * @return SSMRESULT - return value of the API. Returns SSM_S_OK if success
+ * @return Returns ::SSM_S_OK if success, some other value upon failure.
*/
virtual SSMRESULT getModelDataCount(std::string modelName, int *pDataCount) = 0;
/**
* Get actual Context Model data
*
- * @param modelName - affected ContextModel name
+ * @param modelName affected ContextModel name
*
- * @param dataIndex - affected dataId index
+ * @param dataIndex affected dataId index
*
- * @param ppModelData - affected ContextModel data reader
+ * @param ppModelData affected ContextModel data reader
*
- * @return SSMRESULT - return value of the API. Returns SSM_S_OK if success
+ * @return Returns ::SSM_S_OK if success, some other value upon failure.
*/
virtual SSMRESULT getModelData(std::string modelName, int dataIndex, IModelData **ppModelData) = 0;
protected:
/**
* Transmit result of SSMCore to Application layer
*
- * @param cqid - entered ContextQuery ID
+ * @param cqid entered ContextQuery ID
*
- * @param pResult - result of SSMCore
+ * @param pResult result of SSMCore
*
- * @return SSMRESULT - return value of the API. Returns SSM_S_OK if success
+ * @return Returns ::SSM_S_OK if success, some other value upon failure.
*/
virtual SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult) = 0;
protected:
/**
* Initialize Soft sensor manager using given configuration information.
*
- * @param xmlDescription - specification described in XML
+ * @param xmlDescription specification described in XML
*
- * @return SSMRESULT - return value of the API. Returns SSM_S_OK if success
+ * @return Returns ::SSM_S_OK if success, some other value upon failure.
*/
SSMRESULT InitializeSSM(std::string xmlDescription);
/**
* Terminates Soft sensor manager
*
- * @return SSMRESULT - return value of the API. Returns SSM_S_OK if success
+ * @return Returns ::SSM_S_OK if success,some other value upon failure.
*/
SSMRESULT TerminateSSM();
/**
* Execute query and return ContextQuery ID
*
- * @param queryString - query for requesting data
+ * @param queryString query for requesting data
*
- * @param listener - listener for receiving data related to query
+ * @param listener listener for receiving data related to query
*
- * @param cqid - ID of ContextQuery
+ * @param cqid ID of ContextQuery
*
- * @return SSMRESULT - return value of the API. Returns SSM_S_OK if success
+ * @return Returns ::SSM_S_OK if success, some other value upon failure.
*/
SSMRESULT RegisterQuery(std::string queryString, IQueryEngineEvent *listener, int &cqid);
/**
* Unregister registered query according to cqid
*
- * @param cqid - Query corresponding to the cqid will be terminated
+ * @param cqid Query corresponding to the cqid will be terminated
*
- * @return SSMRESULT - return value of the API. Returns SSM_S_OK if success
+ * @return Returns ::SSM_S_OK if success, some other value upon failure.
*/
SSMRESULT UnregisterQuery(int cqid);
}
-#endif
\ No newline at end of file
+#endif
public class DataReader
{
- private int pDataReaderInstance;
+ private long pDataReaderInstance;
- public DataReader(int dataReaderInstance)
+ private DataReader(long dataReaderInstance)
{
pDataReaderInstance = dataReaderInstance;
}
public class ModelData
{
- private int pIModelDataInstance;
+ private long pIModelDataInstance;
- public ModelData(int iModelDataInstance)
+ private ModelData(long iModelDataInstance)
{
pIModelDataInstance = iModelDataInstance;
}
return CoreController.getInstance().getPropertyValue(
pIModelDataInstance, propertyIndex);
}
-}
\ No newline at end of file
+}
*/
public class QueryEngine
{
- private int pQueryEngineInstance;
+ private long pQueryEngineInstance;
- public QueryEngine(int queryEngineInstance)
+ private QueryEngine(long queryEngineInstance)
{
pQueryEngineInstance = queryEngineInstance;
}
* @return int - Instance of the query engine object, set on object's creation
*
*/
- public int getQueryEngineInstance()
+ public long getQueryEngineInstance()
{
return pQueryEngineInstance;
}
CoreController.getInstance().killContextQuery(pQueryEngineInstance,
cqid);
}
-}
\ No newline at end of file
+}
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.7.17. By combining all the individual C code files into this
+** version 3.7.17. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
**
** This file is all you need to compile SQLite. To use SQLite in other
** programs, you need this file and the "sqlite3.h" header file that defines
-** the programming interface to the SQLite library. (If you do not have
+** the programming interface to the SQLite library. (If you do not have
** the "sqlite3.h" header file at hand, you will find a copy embedded within
** the text of this file. Search for "Begin file sqlite3.h" to find the start
** of the embedded sqlite3.h header file.) Additional code files may be needed
** May you share freely, never taking more than you give.
**
*************************************************************************
-**
+**
** This file defines various limits of what SQLite can process.
*/
#endif
/*
-** The maximum depth of an expression tree. This is limited to
-** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
-** want to place more severe limits on the complexity of an
+** The maximum depth of an expression tree. This is limited to
+** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
+** want to place more severe limits on the complexity of an
** expression.
**
** A value of 0 used to mean that the limit was not enforced.
**
** Earlier versions of SQLite allowed the user to change this value at
** compile time. This is no longer permitted, on the grounds that it creates
-** a library that is technically incompatible with an SQLite library
-** compiled with a different limit. If a process operating on a database
-** with a page-size of 65536 bytes crashes, then an instance of SQLite
-** compiled with the default page-size limit will not be able to rollback
+** a library that is technically incompatible with an SQLite library
+** compiled with a different limit. If a process operating on a database
+** with a page-size of 65536 bytes crashes, then an instance of SQLite
+** compiled with the default page-size limit will not be able to rollback
** the aborted transaction. This could lead to database corruption.
*/
#ifdef SQLITE_MAX_PAGE_SIZE
** Maximum depth of recursion for triggers.
**
** A value of 1 means that a trigger program will not be able to itself
-** fire any triggers. A value of 0 means that no trigger programs at all
+** fire any triggers. A value of 0 means that no trigger programs at all
** may be executed.
*/
#ifndef SQLITE_MAX_TRIGGER_DEPTH
** to the next, so we have developed the following set of #if statements
** to generate appropriate macros for a wide range of compilers.
**
-** The correct "ANSI" way to do this is to use the intptr_t type.
+** The correct "ANSI" way to do this is to use the intptr_t type.
** Unfortunately, that typedef is not available on all compilers, or
** if it is available, it requires an #include of specific headers
** that vary from one machine to the next.
/*
** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
-** It determines whether or not the features related to
+** It determines whether or not the features related to
** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
** be overridden at runtime using the sqlite3_config() API.
*/
** is set. Thus NDEBUG becomes an opt-in rather than an opt-out
** feature.
*/
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
#if defined(NDEBUG) && defined(SQLITE_DEBUG)
#endif
/*
-** The testcase() macro is used to aid in coverage testing. When
+** The testcase() macro is used to aid in coverage testing. When
** doing coverage testing, the condition inside the argument to
** testcase() must be evaluated both true and false in order to
** get full branch coverage. The testcase() macro is inserted
#endif
/*
-** The ALWAYS and NEVER macros surround boolean expressions which
+** The ALWAYS and NEVER macros surround boolean expressions which
** are intended to always be true or false, respectively. Such
** expressions could be omitted from the code completely. But they
** are included in a few cases in order to enhance the resilience
** function is provided for use in DLLs since DLL users usually do not have
** direct access to string constants within the DLL. ^The
** sqlite3_libversion_number() function returns an integer equal to
-** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns
-** a pointer to a string constant whose value is the same as the
+** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns
+** a pointer to a string constant whose value is the same as the
** [SQLITE_SOURCE_ID] C preprocessor macro.
**
** See also: [sqlite_version()] and [sqlite_source_id()].
/*
** CAPI3REF: Run-Time Library Compilation Options Diagnostics
**
-** ^The sqlite3_compileoption_used() function returns 0 or 1
-** indicating whether the specified option was defined at
-** compile time. ^The SQLITE_ prefix may be omitted from the
-** option name passed to sqlite3_compileoption_used().
+** ^The sqlite3_compileoption_used() function returns 0 or 1
+** indicating whether the specified option was defined at
+** compile time. ^The SQLITE_ prefix may be omitted from the
+** option name passed to sqlite3_compileoption_used().
**
** ^The sqlite3_compileoption_get() function allows iterating
** over the list of options that were defined at compile time by
** returning the N-th compile time option string. ^If N is out of range,
-** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_
-** prefix is omitted from any strings returned by
+** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_
+** prefix is omitted from any strings returned by
** sqlite3_compileoption_get().
**
** ^Support for the diagnostic functions sqlite3_compileoption_used()
-** and sqlite3_compileoption_get() may be omitted by specifying the
+** and sqlite3_compileoption_get() may be omitted by specifying the
** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time.
**
** See also: SQL functions [sqlite_compileoption_used()] and
** SQLite can be compiled with or without mutexes. When
** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes
** are enabled and SQLite is threadsafe. When the
-** [SQLITE_THREADSAFE] macro is 0,
+** [SQLITE_THREADSAFE] macro is 0,
** the mutexes are omitted. Without the mutexes, it is not safe
** to use SQLite concurrently from more than one thread.
**
**
** ^The sqlite3_int64 and sqlite_int64 types can store integer values
** between -9223372036854775808 and +9223372036854775807 inclusive. ^The
-** sqlite3_uint64 and sqlite_uint64 types can store integer values
+** sqlite3_uint64 and sqlite_uint64 types can store integer values
** between 0 and +18446744073709551615 inclusive.
*/
#ifdef SQLITE_INT64_TYPE
** destructors are called is arbitrary.
**
** Applications should [sqlite3_finalize | finalize] all [prepared statements],
-** [sqlite3_blob_close | close] all [BLOB handles], and
+** [sqlite3_blob_close | close] all [BLOB handles], and
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
** with the [sqlite3] object prior to attempting to close the object. ^If
** sqlite3_close_v2() is called on a [database connection] that still has
** The sqlite3_exec() interface is a convenience wrapper around
** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
** that allows an application to run multiple statements of SQL
-** without having to use a lot of C code.
+** without having to use a lot of C code.
**
** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded,
** semicolon-separate SQL statements passed into its 2nd argument,
** from [sqlite3_column_name()].
**
** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
-** to an empty string, or a pointer that contains only whitespace and/or
+** to an empty string, or a pointer that contains only whitespace and/or
** SQL comments, then no SQL statements are evaluated and the database
** is not changed.
**
/*
** CAPI3REF: OS Interface Open File Handle
**
-** An [sqlite3_file] object represents an open file in the
+** An [sqlite3_file] object represents an open file in the
** [sqlite3_vfs | OS interface layer]. Individual OS interface
** implementations will
** want to subclass this object by appending additional fields
** This object defines the methods used to perform various operations
** against the open file represented by the [sqlite3_file] object.
**
-** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
+** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The
** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
** extends and truncates the database file in chunks of a size specified
-** by the user. The fourth argument to [sqlite3_file_control()] should
+** by the user. The fourth argument to [sqlite3_file_control()] should
** point to an integer (type int) containing the new chunk-size to use
** for the nominated database. Allocating database file space in large
** chunks (say 1MB at a time), may reduce file-system fragmentation and
** SQLite and sent to all VFSes in place of a call to the xSync method
** when the database connection has [PRAGMA synchronous] set to OFF.)^
** Some specialized VFSes need this signal in order to operate correctly
-** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
+** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
** VFSes do not need this signal and should silently ignore this opcode.
** Applications should not call [sqlite3_file_control()] with this
** opcode as doing so may disrupt the operation of the specialized VFSes
-** that do require it.
+** that do require it.
**
** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
** <li>[[SQLITE_FCNTL_OVERWRITE]]
** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
** a write transaction to indicate that, unless it is rolled back for some
-** reason, the entire database file will be overwritten by the current
+** reason, the entire database file will be overwritten by the current
** transaction. This is used by VACUUM operations.
**
** <li>[[SQLITE_FCNTL_VFSNAME]]
** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
** all [VFSes] in the VFS stack. The names are of all VFS shims and the
-** final bottom-level VFS are written into memory obtained from
+** final bottom-level VFS are written into memory obtained from
** [sqlite3_malloc()] and the result is stored in the char* variable
** that the fourth parameter of [sqlite3_file_control()] points to.
** The caller is responsible for freeing the memory when done. As with
** is intended for diagnostic use only.
**
** <li>[[SQLITE_FCNTL_PRAGMA]]
-** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
+** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
** file control is sent to the open [sqlite3_file] object corresponding
** to the database file to which the pragma statement refers. ^The argument
** to the [SQLITE_FCNTL_PRAGMA] file control is an array of
** of the char** argument point to a string obtained from [sqlite3_mprintf()]
** or the equivalent and that string will become the result of the pragma or
** the error message if the pragma fails. ^If the
-** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
+** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
** file control returns [SQLITE_OK], then the parser assumes that the
** VFS has handled the PRAGMA itself and the parser generates a no-op
** The argument is a pointer to a value of type sqlite3_int64 that
** is an advisory maximum number of bytes in the file to memory map. The
** pointer is overwritten with the old value. The limit is not changed if
-** the value originally pointed to is negative, and so the current limit
+** the value originally pointed to is negative, and so the current limit
** can be queried by passing in a pointer to a negative number. This
** file-control is used internally to implement [PRAGMA mmap_size].
**
** the [sqlite3_file] can safely store a pointer to the
** filename if it needs to remember the filename for some reason.
** If the zFilename parameter to xOpen is a NULL pointer then xOpen
-** must invent its own temporary name for the file. ^Whenever the
+** must invent its own temporary name for the file. ^Whenever the
** xFilename parameter is NULL it will also be the case that the
** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE].
**
** The flags argument to xOpen() includes all bits set in
** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()]
** or [sqlite3_open16()] is used, then flags includes at least
-** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE].
+** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE].
** If xOpen() opens a file read-only then it sets *pOutFlags to
** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set.
**
** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction
** with the [SQLITE_OPEN_CREATE] flag, which are both directly
** analogous to the O_EXCL and O_CREAT flags of the POSIX open()
-** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the
+** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the
** SQLITE_OPEN_CREATE, is used to indicate that file should always
** be created, and that it is an error if it already exists.
-** It is <i>not</i> used to indicate the file should be opened
+** It is <i>not</i> used to indicate the file should be opened
** for exclusive access.
**
** ^At least szOsFile bytes of memory are allocated by SQLite
** method returns a Julian Day Number for the current date and time as
** a floating point value.
** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
-** Day Number multiplied by 86400000 (the number of milliseconds in
-** a 24-hour day).
+** Day Number multiplied by 86400000 (the number of milliseconds in
+** a 24-hour day).
** ^SQLite will use the xCurrentTimeInt64() method to get the current
-** date and time if that method is available (if iVersion is 2 or
+** date and time if that method is available (if iVersion is 2 or
** greater and the function pointer is not NULL) and will fall back
** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
**
** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces
** are not used by the SQLite core. These optional interfaces are provided
-** by some VFSes to facilitate testing of the VFS code. By overriding
+** by some VFSes to facilitate testing of the VFS code. By overriding
** system calls with functions under its control, a test program can
** simulate faults and error conditions that would otherwise be difficult
** or impossible to induce. The set of system calls that can be overridden
/*
** The methods above are in versions 1 through 3 of the sqlite_vfs object.
** New fields may be appended in figure versions. The iVersion
- ** value will increment whenever this happens.
+ ** value will increment whenever this happens.
*/
};
** </ul>
**
** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as
-** was given no the corresponding lock.
+** was given no the corresponding lock.
**
** The xShmLock method can transition between unlocked and SHARED or
** between unlocked and EXCLUSIVE. It cannot transition between SHARED
** [database connection] (specified in the first argument).
**
** The second argument to sqlite3_db_config(D,V,...) is the
-** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code
+** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code
** that indicates what aspect of the [database connection] is being configured.
** Subsequent arguments vary depending on the configuration verb.
**
** This object is used in only one place in the SQLite interface.
** A pointer to an instance of this object is the argument to
** [sqlite3_config()] when the configuration option is
-** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC].
+** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC].
** By creating an instance of this object
** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC])
** during configuration, an application can specify an alternative
** allocators round up memory allocations at least to the next multiple
** of 8. Some allocators round up to a larger multiple or to a power of 2.
** Every memory allocation request coming in through [sqlite3_malloc()]
-** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0,
+** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0,
** that causes the corresponding memory allocation to fail.
**
** The xInit method initializes the memory allocator. (For example,
** by a single thread. ^If SQLite is compiled with
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
** it is not possible to change the [threading mode] from its default
-** value of Single-thread and so [sqlite3_config()] will return
+** value of Single-thread and so [sqlite3_config()] will return
** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
** configuration option.</dd>
**
** tracks memory usage, for example. </dd>
**
** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
-** <dd> ^This option takes single argument of type int, interpreted as a
-** boolean, which enables or disables the collection of memory allocation
-** statistics. ^(When memory allocation statistics are disabled, the
+** <dd> ^This option takes single argument of type int, interpreted as a
+** boolean, which enables or disables the collection of memory allocation
+** statistics. ^(When memory allocation statistics are disabled, the
** following SQLite interfaces become non-operational:
** <ul>
** <li> [sqlite3_memory_used()]
** N should be set to twice the expected maximum number of threads.
** ^SQLite will never require a scratch buffer that is more than 6
** times the database page size. ^If SQLite needs needs additional
-** scratch memory beyond what is provided by this configuration option, then
+** scratch memory beyond what is provided by this configuration option, then
** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
**
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
** <dd> ^This option specifies a static memory buffer that SQLite can use for
-** the database page cache with the default page cache implementation.
+** the database page cache with the default page cache implementation.
** This configuration should not be used if an application-define page
** cache implementation is loaded using the SQLITE_CONFIG_PCACHE2 option.
** There are three arguments to this option: A pointer to 8-byte aligned
** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite
** global [error log].
** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
-** function with a call signature of void(*)(void*,int,const char*),
+** function with a call signature of void(*)(void*,int,const char*),
** and a pointer to void. ^If the function pointer is not NULL, it is
** invoked by [sqlite3_log()] to process each logging event. ^If the
** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size
** cannot be changed at run-time. Nor may the maximum allowed mmap size
** exceed the compile-time maximum mmap size set by the
-** [SQLITE_MAX_MMAP_SIZE] compile-time option.
+** [SQLITE_MAX_MMAP_SIZE] compile-time option.
** If either argument to this option is negative, then that argument is
** changed to its compile-time default.
** </dl>
#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
-/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
+/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
#define SQLITE_CONFIG_PCACHE 14 /* no-op */
#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */
**
** <dl>
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
-** <dd> ^This option takes three additional arguments that determine the
+** <dd> ^This option takes three additional arguments that determine the
** [lookaside memory allocator] configuration for the [database connection].
** ^The first argument (the third parameter to [sqlite3_db_config()] is a
** pointer to a memory buffer to use for lookaside memory.
** when the "current value" returned by
** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero.
** Any attempt to change the lookaside memory configuration when lookaside
-** memory is in use leaves the configuration unchanged and returns
+** memory is in use leaves the configuration unchanged and returns
** [SQLITE_BUSY].)^</dd>
**
** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
** method, then this routine will return the [rowid] of the inserted
** row as long as the trigger or virtual table method is running.
-** But once the trigger or virtual table method ends, the value returned
+** But once the trigger or virtual table method ends, the value returned
** by this routine reverts to what it was before the trigger or virtual
** table method began.)^
**
** mechanisms do not count as direct row changes.)^
**
** A "trigger context" is a scope of execution that begins and
-** ends with the script of a [CREATE TRIGGER | trigger].
+** ends with the script of a [CREATE TRIGGER | trigger].
** Most SQL statements are
** evaluated outside of any trigger. This is the "top level"
** trigger context. If a trigger fires from the top level, a
** the count does not include changes used to implement [REPLACE] constraints,
** do rollbacks or ABORT processing, or [DROP TABLE] processing. The
** count does not include rows of views that fire an [INSTEAD OF trigger],
-** though if the INSTEAD OF trigger makes changes of its own, those changes
+** though if the INSTEAD OF trigger makes changes of its own, those changes
** are counted.)^
** ^The sqlite3_total_changes() function counts the changes as soon as
** the statement that makes them is completed (when the statement handle
**
** ^The sqlite3_interrupt(D) call is in effect until all currently running
** SQL statements on [database connection] D complete. ^Any new SQL statements
-** that are started after the sqlite3_interrupt() call and before the
+** that are started after the sqlite3_interrupt() call and before the
** running statements reaches zero are interrupted as if they had been
** running prior to the sqlite3_interrupt() call. ^New SQL statements
** that are started after the running statement count reaches zero are
** ^These routines do not parse the SQL statements thus
** will not detect syntactically incorrect SQL.
**
-** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
+** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
** automatically by sqlite3_complete16(). If that initialization fails,
** then the return value from sqlite3_complete16() will be non-zero
** The busy callback should not take any actions which modify the
** database connection that invoked the busy handler. Any such actions
** result in undefined behavior.
-**
+**
** A busy handler must not close the database connection
** or [prepared statement] that invoked the busy handler.
*/
** requested is ok. ^When the callback returns [SQLITE_DENY], the
** [sqlite3_prepare_v2()] or equivalent call that triggered the
** authorizer will fail with an error message explaining that
-** access is denied.
+** access is denied.
**
** ^The first parameter to the authorizer callback is a copy of the third
** parameter to the sqlite3_set_authorizer() interface. ^The second parameter
** database connections for the meaning of "modify" in this paragraph.
**
** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the
-** statement might be re-prepared during [sqlite3_step()] due to a
+** statement might be re-prepared during [sqlite3_step()] due to a
** schema change. Hence, the application should ensure that the
** correct authorizer callback remains in place during the [sqlite3_step()].
**
** database connection D. An example use for this
** interface is to keep a GUI updated during a large query.
**
-** ^The parameter P is passed through as the only parameter to the
-** callback function X. ^The parameter N is the number of
+** ^The parameter P is passed through as the only parameter to the
+** callback function X. ^The parameter N is the number of
** [virtual machine instructions] that are evaluated between successive
** invocations of the callback X.
**
/*
** CAPI3REF: Opening A New Database Connection
**
-** ^These routines open an SQLite database file as specified by the
+** ^These routines open an SQLite database file as specified by the
** filename argument. ^The filename argument is interpreted as UTF-8 for
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
** order for sqlite3_open16(). ^(A [database connection] handle is usually
** except that it accepts two additional parameters for additional control
** over the new database connection. ^(The flags parameter to
** sqlite3_open_v2() can take one of
-** the following three values, optionally combined with the
+** the following three values, optionally combined with the
** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
**
** information.
**
** URI filenames are parsed according to RFC 3986. ^If the URI contains an
-** authority, then it must be either an empty string or the string
-** "localhost". ^If the authority is not an empty string or "localhost", an
-** error is returned to the caller. ^The fragment component of a URI, if
+** authority, then it must be either an empty string or the string
+** "localhost". ^If the authority is not an empty string or "localhost", an
+** error is returned to the caller. ^The fragment component of a URI, if
** present, is ignored.
**
** ^SQLite uses the path component of the URI as the name of the disk file
-** which contains the database. ^If the path begins with a '/' character,
-** then it is interpreted as an absolute path. ^If the path does not begin
+** which contains the database. ^If the path begins with a '/' character,
+** then it is interpreted as an absolute path. ^If the path does not begin
** with a '/' (meaning that the authority section is omitted from the URI)
-** then the path is interpreted as a relative path.
-** ^On windows, the first component of an absolute path
+** then the path is interpreted as a relative path.
+** ^On windows, the first component of an absolute path
** is a drive specification (e.g. "C:").
**
** [[core URI query parameters]]
**
** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw",
** "rwc", or "memory". Attempting to set it to any other value is
-** an error)^.
-** ^If "ro" is specified, then the database is opened for read-only
-** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
-** third argument to sqlite3_open_v2(). ^If the mode option is set to
-** "rw", then the database is opened for read-write (but not create)
-** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
-** been set. ^Value "rwc" is equivalent to setting both
+** an error)^.
+** ^If "ro" is specified, then the database is opened for read-only
+** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
+** third argument to sqlite3_open_v2(). ^If the mode option is set to
+** "rw", then the database is opened for read-write (but not create)
+** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
+** been set. ^Value "rwc" is equivalent to setting both
** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is
** set to "memory" then a pure [in-memory database] that never reads
** or writes from disk is used. ^It is an error to specify a value for
** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
** "private". ^Setting it to "shared" is equivalent to setting the
** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
-** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
+** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
** a URI filename, its value overrides any behavior requested by setting
**
** <table border="1" align=center cellpadding=5>
** <tr><th> URI filenames <th> Results
-** <tr><td> file:data.db <td>
+** <tr><td> file:data.db <td>
** Open the file "data.db" in the current directory.
** <tr><td> file:/home/fred/data.db<br>
-** file:///home/fred/data.db <br>
-** file://localhost/home/fred/data.db <br> <td>
+** file:///home/fred/data.db <br>
+** file://localhost/home/fred/data.db <br> <td>
** Open the database file "/home/fred/data.db".
-** <tr><td> file://darkstar/home/fred/data.db <td>
+** <tr><td> file://darkstar/home/fred/data.db <td>
** An error. "darkstar" is not a recognized authority.
-** <tr><td style="white-space:nowrap">
+** <tr><td style="white-space:nowrap">
** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
** <td> Windows only: Open the file "data.db" on fred's desktop on drive
-** C:. Note that the %20 escaping in this example is not strictly
+** C:. Note that the %20 escaping in this example is not strictly
** necessary - space characters can be used literally
** in URI filenames.
-** <tr><td> file:data.db?mode=ro&cache=private <td>
+** <tr><td> file:data.db?mode=ro&cache=private <td>
** Open file "data.db" in the current directory for read-only access.
** Regardless of whether or not shared-cache mode is enabled by
** default, use a private cache.
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
-** <tr><td> file:data.db?mode=readonly <td>
+** <tr><td> file:data.db?mode=readonly <td>
** An error. "readonly" is not a valid option for the "mode" parameter.
** </table>
**
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
** query components of a URI. A hexadecimal escape sequence consists of a
-** percent sign - "%" - followed by exactly two hexadecimal digits
+** percent sign - "%" - followed by exactly two hexadecimal digits
** specifying an octet value. ^Before the path or query components of a
-** URI filename are interpreted, they are encoded using UTF-8 and all
+** URI filename are interpreted, they are encoded using UTF-8 and all
** hexadecimal escape sequences replaced by a single byte containing the
** corresponding octet. If this process generates an invalid UTF-8 encoding,
** the results are undefined.
** CAPI3REF: Obtain Values For URI Parameters
**
** These are utility routines, useful to VFS implementations, that check
-** to see if a database file was a URI that contained a specific query
+** to see if a database file was a URI that contained a specific query
** parameter, and if so obtains the value of that query parameter.
**
-** If F is the database filename pointer passed into the xOpen() method of
-** a VFS implementation when the flags parameter to xOpen() has one or
+** If F is the database filename pointer passed into the xOpen() method of
+** a VFS implementation when the flags parameter to xOpen() has one or
** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
** P is the name of the query parameter, then
** sqlite3_uri_parameter(F,P) returns the value of the P
-** parameter if it exists or a NULL pointer if P does not appear as a
+** parameter if it exists or a NULL pointer if P does not appear as a
** query parameter on F. If P is a query parameter of F
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
** a pointer to an empty string.
** parameter and returns true (1) or false (0) according to the value
** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the
** value of query parameter P is one of "yes", "true", or "on" in any
-** case or if the value begins with a non-zero number. The
+** case or if the value begins with a non-zero number. The
** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
** query parameter P is one of "no", "false", or "off" in any case or
** if the value begins with a numeric zero. If P is not a query
** 64-bit signed integer and returns that integer, or D if P does not
** exist. If the value of P is something other than an integer, then
** zero is returned.
-**
+**
** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and
** is not a database file pathname pointer that SQLite passed into the xOpen
** associated with a [database connection]. If a prior API call failed
** but the most recent API call succeeded, the return value from
** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode()
-** interface is the same except that it always returns the
+** interface is the same except that it always returns the
** [extended result code] even when extended result codes are
** disabled.
**
** new limit for that construct.)^
**
** ^If the new limit is a negative number, the limit is unchanged.
-** ^(For each limit category SQLITE_LIMIT_<i>NAME</i> there is a
+** ^(For each limit category SQLITE_LIMIT_<i>NAME</i> there is a
** [limits | hard upper bound]
** set at compile-time by a C preprocessor macro called
** [limits | SQLITE_MAX_<i>NAME</i>].
** ^Attempts to increase a limit above its hard upper bound are
** silently truncated to the hard upper bound.
**
-** ^Regardless of whether or not the limit was changed, the
+** ^Regardless of whether or not the limit was changed, the
** [sqlite3_limit()] interface returns the prior value of the limit.
** ^Hence, to find the current value of a limit without changing it,
** simply invoke this interface with the third parameter set to -1.
** </li>
**
** <li>
-** ^If the specific value bound to [parameter | host parameter] in the
+** ^If the specific value bound to [parameter | host parameter] in the
** WHERE clause might influence the choice of query plan for a statement,
-** then the statement will be automatically recompiled, as if there had been
+** then the statement will be automatically recompiled, as if there had been
** a schema change, on the first [sqlite3_step()] call following any change
-** to the [sqlite3_bind_text | bindings] of that [parameter].
-** ^The specific value of WHERE-clause [parameter] might influence the
+** to the [sqlite3_bind_text | bindings] of that [parameter].
+** ^The specific value of WHERE-clause [parameter] might influence the
** choice of query plan if the parameter is the left-hand side of a [LIKE]
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
-** the
+** the
** </li>
** </ol>
*/
** the content of the database file.
**
** Note that [application-defined SQL functions] or
-** [virtual tables] might change the database indirectly as a side effect.
-** ^(For example, if an application defines a function "eval()" that
+** [virtual tables] might change the database indirectly as a side effect.
+** ^(For example, if an application defines a function "eval()" that
** calls [sqlite3_exec()], then the following SQL statement would
** change the database file through side-effects:
**
** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK],
** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true,
** since the statements themselves do not actually modify the database but
-** rather they control the timing of when other statements modify the
+** rather they control the timing of when other statements modify the
** database. ^The [ATTACH] and [DETACH] statements also cause
** sqlite3_stmt_readonly() to return true since, while those statements
-** change the configuration of a database connection, they do not make
+** change the configuration of a database connection, they do not make
** changes to the content of the database files on disk.
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
-** [prepared statement] S has been stepped at least once using
-** [sqlite3_step(S)] but has not run to completion and/or has not
+** [prepared statement] S has been stepped at least once using
+** [sqlite3_step(S)] but has not run to completion and/or has not
** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S)
-** interface returns false if S is a NULL pointer. If S is not a
+** interface returns false if S is a NULL pointer. If S is not a
** NULL pointer and is not a pointer to a valid [prepared statement]
** object, then the behavior is undefined and probably undesirable.
**
** This interface can be used in combination [sqlite3_next_stmt()]
-** to locate all prepared statements associated with a database
+** to locate all prepared statements associated with a database
** connection that are in need of being reset. This can be used,
-** for example, in diagnostic routines to search for prepared
+** for example, in diagnostic routines to search for prepared
** statements that are holding a transaction open.
*/
SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
** sqlite3_value object but no mutex is held for an unprotected
** sqlite3_value object. If SQLite is compiled to be single-threaded
** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0)
-** or if SQLite is run in one of reduced mutex modes
+** or if SQLite is run in one of reduced mutex modes
** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD]
** then there is no distinction between protected and unprotected
** sqlite3_value objects and they can be used interchangeably. However,
** If a non-negative fourth parameter is provided to sqlite3_bind_text()
** or sqlite3_bind_text16() then that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
-** terminated. If any NUL characters occur at byte offsets less than
+** terminated. If any NUL characters occur at byte offsets less than
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined.
** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
** string after SQLite has finished with it. ^The destructor is called
** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(),
-** sqlite3_bind_text(), or sqlite3_bind_text16() fails.
+** sqlite3_bind_text(), or sqlite3_bind_text16() fails.
** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.
** For all versions of SQLite up to and including 3.6.23.1, a call to
** [sqlite3_reset()] was required after sqlite3_step() returned anything
** other than [SQLITE_ROW] before any subsequent invocation of
-** sqlite3_step(). Failure to reset the prepared statement using
+** sqlite3_step(). Failure to reset the prepared statement using
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began
** calling [sqlite3_reset()] automatically in this circumstance rather
** the number of bytes in that string.
** ^If the result is NULL, then sqlite3_column_bytes16() returns zero.
**
-** ^The values returned by [sqlite3_column_bytes()] and
+** ^The values returned by [sqlite3_column_bytes()] and
** [sqlite3_column_bytes16()] do not include the zero terminators at the end
** of the string. ^For clarity: the values returned by
** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of
** ^The second parameter is the name of the SQL function to be created or
** redefined. ^The length of the name is limited to 255 bytes in a UTF-8
** representation, exclusive of the zero-terminator. ^Note that the name
-** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes.
+** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes.
** ^Any attempt to create a function with a longer name
** will result in [SQLITE_MISUSE] being returned.
**
** callbacks.
**
** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL,
-** then it is destructor for the application data pointer.
+** then it is destructor for the application data pointer.
** The destructor is invoked when the function is deleted, either by being
** overloaded or when the database connection closes.)^
** ^The destructor is also invoked if the call to
** sqlite3_create_function_v2() fails.
** ^When the destructor callback of the tenth parameter is invoked, it
-** is passed a single argument which is a copy of the application data
+** is passed a single argument which is a copy of the application data
** pointer which was the fifth parameter to sqlite3_create_function_v2().
**
** ^It is permitted to register multiple implementations of the same
** nArg parameter is a better match than a function implementation with
** a negative nArg. ^A function where the preferred text encoding
** matches the database encoding is a better
-** match than a function where the encoding is different.
+** match than a function where the encoding is different.
** ^A function where the encoding difference is between UTF16le and UTF16be
** is a closer match than a function where the encoding difference is
** between UTF8 and UTF16.
** DEPRECATED
**
** These functions are [deprecated]. In order to maintain
-** backwards compatibility with older code, these functions continue
+** backwards compatibility with older code, these functions continue
** to be supported. However, new applications should avoid
** the use of these functions. To help encourage people to avoid
** using these functions, we are not going to tell you what they do.
** Implementations of aggregate SQL functions use this
** routine to allocate memory for storing their state.
**
-** ^The first time the sqlite3_aggregate_context(C,N) routine is called
+** ^The first time the sqlite3_aggregate_context(C,N) routine is called
** for a particular aggregate function, SQLite
** allocates N of memory, zeroes out that memory, and returns a pointer
** to the new memory. ^On second and subsequent calls to
** In those cases, sqlite3_aggregate_context() might be called for the
** first time from within xFinal().)^
**
-** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer
+** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer
** when first called if N is less than or equal to zero or if a memory
** allocate error occurs.
**
** value of N in subsequent call to sqlite3_aggregate_context() within
** the same aggregate function instance will not resize the memory
** allocation.)^ Within the xFinal callback, it is customary to set
-** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
+** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
** pointless memory allocations occur.
**
-** ^SQLite automatically frees the memory allocated by
+** ^SQLite automatically frees the memory allocated by
** sqlite3_aggregate_context() when the aggregate query concludes.
**
** The first parameter must be a copy of the
** deleted. ^When all collating functions having the same name are deleted,
** that collation is no longer usable.
**
-** ^The collating function callback is invoked with a copy of the pArg
+** ^The collating function callback is invoked with a copy of the pArg
** application data pointer and with two strings in the encoding specified
** by the eTextRep argument. The collating function must return an
** integer that is negative, zero, or positive
** calls to the collation creation functions or when the
** [database connection] is closed using [sqlite3_close()].
**
-** ^The xDestroy callback is <u>not</u> called if the
+** ^The xDestroy callback is <u>not</u> called if the
** sqlite3_create_collation_v2() function fails. Applications that invoke
-** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should
+** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should
** check the return code and dispose of the application data pointer
** themselves rather than expecting SQLite to deal with it for them.
-** This is different from every other SQLite interface. The inconsistency
-** is unfortunate but cannot be changed without breaking backwards
+** This is different from every other SQLite interface. The inconsistency
+** is unfortunate but cannot be changed without breaking backwards
** compatibility.
**
** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()].
*/
SQLITE_API int sqlite3_create_collation(
- sqlite3*,
- const char *zName,
- int eTextRep,
+ sqlite3*,
+ const char *zName,
+ int eTextRep,
void *pArg,
int(*xCompare)(void*,int,const void*,int,const void*)
);
SQLITE_API int sqlite3_create_collation_v2(
- sqlite3*,
- const char *zName,
- int eTextRep,
+ sqlite3*,
+ const char *zName,
+ int eTextRep,
void *pArg,
int(*xCompare)(void*,int,const void*,int,const void*),
void(*xDestroy)(void*)
);
SQLITE_API int sqlite3_create_collation16(
- sqlite3*,
+ sqlite3*,
const void *zName,
- int eTextRep,
+ int eTextRep,
void *pArg,
int(*xCompare)(void*,int,const void*,int,const void*)
);
** [sqlite3_create_collation_v2()].
*/
SQLITE_API int sqlite3_collation_needed(
- sqlite3*,
- void*,
+ sqlite3*,
+ void*,
void(*)(void*,sqlite3*,int eTextRep,const char*)
);
SQLITE_API int sqlite3_collation_needed16(
- sqlite3*,
+ sqlite3*,
void*,
void(*)(void*,sqlite3*,int eTextRep,const void*)
);
);
/*
-** Specify the activation key for a SEE database. Unless
+** Specify the activation key for a SEE database. Unless
** activated, none of the SEE routines will work.
*/
SQLITE_API void sqlite3_activate_see(
#ifdef SQLITE_ENABLE_CEROD
/*
-** Specify the activation key for a CEROD database. Unless
+** Specify the activation key for a CEROD database. Unless
** activated, none of the CEROD routines will work.
*/
SQLITE_API void sqlite3_activate_cerod(
** ^The [temp_store_directory pragma] may modify this variable and cause
** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
** the [temp_store_directory pragma] always assumes that any string
-** that this variable points to is held in memory obtained from
+** that this variable points to is held in memory obtained from
** [sqlite3_malloc] and the pragma may attempt to free that memory
** using [sqlite3_free].
** Hence, if this variable is modified directly, either it should be
** ^The [data_store_directory pragma] may modify this variable and cause
** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
** the [data_store_directory pragma] always assumes that any string
-** that this variable points to is held in memory obtained from
+** that this variable points to is held in memory obtained from
** [sqlite3_malloc] and the pragma may attempt to free that memory
** using [sqlite3_free].
** Hence, if this variable is modified directly, either it should be
** interfaces.
*/
SQLITE_API void *sqlite3_update_hook(
- sqlite3*,
+ sqlite3*,
void(*)(void *,int ,char const *,char const *,sqlite3_int64),
void*
);
** as heap memory usages approaches the limit.
** ^The soft heap limit is "soft" because even though SQLite strives to stay
** below the limit, it will exceed the limit rather than generate
-** an [SQLITE_NOMEM] error. In other words, the soft heap limit
+** an [SQLITE_NOMEM] error. In other words, the soft heap limit
** is advisory only.
**
** ^The return value from sqlite3_soft_heap_limit64() is the size of
** CAPI3REF: Virtual Table Object
** KEYWORDS: sqlite3_module {virtual table module}
**
-** This structure, sometimes called a "virtual table module",
-** defines the implementation of a [virtual tables].
+** This structure, sometimes called a "virtual table module",
+** defines the implementation of a [virtual tables].
** This structure consists mostly of methods for the module.
**
** ^A virtual table module is created by filling in a persistent
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
void **ppArg);
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
- /* The methods above are in version 1 of the sqlite_module object. Those
+ /* The methods above are in version 1 of the sqlite_module object. Those
** below are for version 2 and greater. */
int (*xSavepoint)(sqlite3_vtab *pVTab, int);
int (*xRelease)(sqlite3_vtab *pVTab, int);
** preexisting [virtual table] for the module.
**
** ^The module name is registered on the [database connection] specified
-** by the first parameter. ^The name of the module is given by the
+** by the first parameter. ^The name of the module is given by the
** second parameter. ^The third parameter is a pointer to
** the implementation of the [virtual table module]. ^The fourth
** parameter is an arbitrary client data pointer that is passed through
** CAPI3REF: Overload A Function For A Virtual Table
**
** ^(Virtual tables can provide alternative implementations of functions
-** using the [xFindFunction] method of the [virtual table module].
+** using the [xFindFunction] method of the [virtual table module].
** But global versions of those functions
** must exist in order to be overloaded.)^
**
**
** ^If the flags parameter is non-zero, then the BLOB is opened for read
** and write access. ^If it is zero, the BLOB is opened for read access.
-** ^It is not possible to open a column that is part of an index or primary
-** key for writing. ^If [foreign key constraints] are enabled, it is
+** ^It is not possible to open a column that is part of an index or primary
+** key for writing. ^If [foreign key constraints] are enabled, it is
** not possible to open a column that is part of a [child key] for writing.
**
** ^Note that the database name is not the filename that contains
/*
** CAPI3REF: Return The Size Of An Open BLOB
**
-** ^Returns the size in bytes of the BLOB accessible via the
+** ^Returns the size in bytes of the BLOB accessible via the
** successfully opened [BLOB handle] in its only argument. ^The
** incremental blob I/O routines can only read or overwriting existing
** blob content; they cannot change the size of a blob.
/*
** CAPI3REF: Retrieve the mutex for a database connection
**
-** ^This interface returns a pointer the [sqlite3_mutex] object that
+** ^This interface returns a pointer the [sqlite3_mutex] object that
** serializes access to the [database connection] given in the argument
** when the [threading mode] is Serialized.
** ^If the [threading mode] is Single-thread or Multi-thread then this
** <dd>This parameter records the largest memory allocation request
** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
** internal equivalents). Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.
+** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
**
** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
** <dd>This parameter returns the number of pages used out of the
-** [pagecache memory allocator] that was configured using
+** [pagecache memory allocator] that was configured using
** [SQLITE_CONFIG_PAGECACHE]. The
** value returned is in pages, not in bytes.</dd>)^
**
-** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
+** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
** <dd>This parameter returns the number of bytes of page cache
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [pagecache memory allocator]. Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.
+** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [scratch memory allocator]. Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.
+** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
/*
** CAPI3REF: Database Connection Status
**
-** ^This interface is used to retrieve runtime status information
+** ^This interface is used to retrieve runtime status information
** about a single [database connection]. ^The first argument is the
** database connection object to be interrogated. ^The second argument
** is an integer constant, taken from the set of
** [SQLITE_DBSTATUS options], that
-** determines the parameter to interrogate. The set of
+** determines the parameter to interrogate. The set of
** [SQLITE_DBSTATUS options] is likely
** to grow in future releases of SQLite.
**
** checked out.</dd>)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
-** <dd>This parameter returns the number malloc attempts that were
+** <dd>This parameter returns the number malloc attempts that were
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.)^
**
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used to store the schema for all databases associated
-** with the connection - main, temp, and any [ATTACH]-ed databases.)^
+** with the connection - main, temp, and any [ATTACH]-ed databases.)^
** ^The full amount of memory used by the schemas is reported, even if the
** schema memory is shared with other database connections due to
** [shared cache mode] being enabled.
**
** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(<dt>SQLITE_DBSTATUS_CACHE_HIT</dt>
** <dd>This parameter returns the number of pager cache hits that have
-** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT
** is always 0.
** </dd>
**
** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
** <dd>This parameter returns the number of pager cache misses that have
-** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
+** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
** is always 0.
** </dd>
**
** statements. For example, if the number of table steps greatly exceeds
** the number of table searches or result rows, that would tend to indicate
** that the prepared statement is using a full table scan rather than
-** an index.
+** an index.
**
** ^(This interface is used to retrieve and reset counter values from
** a [prepared statement]. The first argument is the prepared statement
** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
** <dd>^This is the number of times that SQLite has stepped forward in
** a table as part of a full table scan. Large numbers for this counter
-** may indicate opportunities for performance improvement through
+** may indicate opportunities for performance improvement through
** careful use of indices.</dd>
**
** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
** KEYWORDS: {page cache}
**
** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can
-** register an alternative page cache implementation by passing in an
+** register an alternative page cache implementation by passing in an
** instance of the sqlite3_pcache_methods2 structure.)^
-** In many applications, most of the heap memory allocated by
+** In many applications, most of the heap memory allocated by
** SQLite is used for the page cache.
-** By implementing a
+** By implementing a
** custom page cache using this API, an application can better control
-** the amount of memory consumed by SQLite, the way in which
-** that memory is allocated and released, and the policies used to
-** determine exactly which parts of a database file are cached and for
+** the amount of memory consumed by SQLite, the way in which
+** that memory is allocated and released, and the policies used to
+** determine exactly which parts of a database file are cached and for
** how long.
**
** The alternative page cache mechanism is an
** [sqlite3_config()] returns.)^
**
** [[the xInit() page cache method]]
-** ^(The xInit() method is called once for each effective
+** ^(The xInit() method is called once for each effective
** call to [sqlite3_initialize()])^
** (usually only once during the lifetime of the process). ^(The xInit()
** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^
-** The intent of the xInit() method is to set up global data structures
-** required by the custom page cache implementation.
-** ^(If the xInit() method is NULL, then the
+** The intent of the xInit() method is to set up global data structures
+** required by the custom page cache implementation.
+** ^(If the xInit() method is NULL, then the
** built-in default page cache is used instead of the application defined
** page cache.)^
**
** [[the xShutdown() page cache method]]
** ^The xShutdown() method is called by [sqlite3_shutdown()].
-** It can be used to clean up
+** It can be used to clean up
** any outstanding resources before process shutdown, if required.
** ^The xShutdown() method may be NULL.
**
** though this is not guaranteed. ^The
** first parameter, szPage, is the size in bytes of the pages that must
** be allocated by the cache. ^szPage will always a power of two. ^The
-** second parameter szExtra is a number of bytes of extra storage
+** second parameter szExtra is a number of bytes of extra storage
** associated with each page cache entry. ^The szExtra parameter will
** a number less than 250. SQLite will use the
** extra szExtra bytes on each page to store metadata about the underlying
** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will
** never invoke xUnpin() except to deliberately delete a page.
** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
-** false will always have the "discard" flag set to true.
+** false will always have the "discard" flag set to true.
** ^Hence, a cache created with bPurgeable false will
** never contain any unpinned pages.
**
** [[the xPagecount() page cache methods]]
** The xPagecount() method must return the number of pages currently
** stored in the cache, both pinned and unpinned.
-**
+**
** [[the xFetch() page cache methods]]
-** The xFetch() method locates a page in the cache and returns a pointer to
+** The xFetch() method locates a page in the cache and returns a pointer to
** an sqlite3_pcache_page object associated with that page, or a NULL pointer.
** The pBuf element of the returned sqlite3_pcache_page object will be a
-** pointer to a buffer of szPage bytes used to store the content of a
+** pointer to a buffer of szPage bytes used to store the content of a
** single database page. The pExtra element of sqlite3_pcache_page will be
** a pointer to the szExtra bytes of extra storage that SQLite has requested
** for each entry in the page cache.
** page cache implementation. ^The page cache implementation
** may choose to evict unpinned pages at any time.
**
-** The cache must not perform any reference counting. A single
-** call to xUnpin() unpins the page regardless of the number of prior calls
+** The cache must not perform any reference counting. A single
+** call to xUnpin() unpins the page regardless of the number of prior calls
** to xFetch().
**
** [[the xRekey() page cache methods]]
int (*xPagecount)(sqlite3_pcache*);
sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
- void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
+ void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
unsigned oldKey, unsigned newKey);
void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
void (*xDestroy)(sqlite3_pcache*);
**
** The backup API copies the content of one database into another.
** It is useful either for creating backups of databases or
-** for copying in-memory databases to or from persistent files.
+** for copying in-memory databases to or from persistent files.
**
** See Also: [Using the SQLite Online Backup API]
**
** ^Thus, the backup may be performed on a live source database without
** preventing other database connections from
** reading or writing to the source database while the backup is underway.
-**
-** ^(To perform a backup operation:
+**
+** ^(To perform a backup operation:
** <ol>
** <li><b>sqlite3_backup_init()</b> is called once to initialize the
-** backup,
-** <li><b>sqlite3_backup_step()</b> is called one or more times to transfer
+** backup,
+** <li><b>sqlite3_backup_step()</b> is called one or more times to transfer
** the data between the two databases, and finally
-** <li><b>sqlite3_backup_finish()</b> is called to release all resources
-** associated with the backup operation.
+** <li><b>sqlite3_backup_finish()</b> is called to release all resources
+** associated with the backup operation.
** </ol>)^
** There should be exactly one call to sqlite3_backup_finish() for each
** successful call to sqlite3_backup_init().
**
** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
**
-** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
-** [database connection] associated with the destination database
+** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
+** [database connection] associated with the destination database
** and the database name, respectively.
** ^The database name is "main" for the main database, "temp" for the
** temporary database, or the name specified after the AS keyword in
** an [ATTACH] statement for an attached database.
-** ^The S and M arguments passed to
+** ^The S and M arguments passed to
** sqlite3_backup_init(D,N,S,M) identify the [database connection]
** and database name of the source database, respectively.
** ^The source and destination [database connections] (parameters S and D)
** ^A successful call to sqlite3_backup_init() returns a pointer to an
** [sqlite3_backup] object.
** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
-** sqlite3_backup_finish() functions to perform the specified backup
+** sqlite3_backup_finish() functions to perform the specified backup
** operation.
**
** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
**
-** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
+** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
** the source and destination databases specified by [sqlite3_backup] object B.
-** ^If N is negative, all remaining source pages are copied.
+** ^If N is negative, all remaining source pages are copied.
** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
** are still more pages to be copied, then the function returns [SQLITE_OK].
** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages
**
** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then
** the [sqlite3_busy_handler | busy-handler function]
-** is invoked (if one is specified). ^If the
-** busy-handler returns non-zero before the lock is available, then
+** is invoked (if one is specified). ^If the
+** busy-handler returns non-zero before the lock is available, then
** [SQLITE_BUSY] is returned to the caller. ^In this case the call to
** sqlite3_backup_step() can be retried later. ^If the source
** [database connection]
** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this
** case the call to sqlite3_backup_step() can be retried later on. ^(If
** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or
-** [SQLITE_READONLY] is returned, then
-** there is no point in retrying the call to sqlite3_backup_step(). These
-** errors are considered fatal.)^ The application must accept
-** that the backup operation has failed and pass the backup operation handle
+** [SQLITE_READONLY] is returned, then
+** there is no point in retrying the call to sqlite3_backup_step(). These
+** errors are considered fatal.)^ The application must accept
+** that the backup operation has failed and pass the backup operation handle
** to the sqlite3_backup_finish() to release associated resources.
**
** ^The first call to sqlite3_backup_step() obtains an exclusive lock
-** on the destination file. ^The exclusive lock is not released until either
-** sqlite3_backup_finish() is called or the backup operation is complete
+** on the destination file. ^The exclusive lock is not released until either
+** sqlite3_backup_finish() is called or the backup operation is complete
** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to
** sqlite3_backup_step() obtains a [shared lock] on the source database that
** lasts for the duration of the sqlite3_backup_step() call.
** through the backup process. ^If the source database is modified by an
** external process or via a database connection other than the one being
** used by the backup operation, then the backup will be automatically
-** restarted by the next call to sqlite3_backup_step(). ^If the source
+** restarted by the next call to sqlite3_backup_step(). ^If the source
** database is modified by the using the same database connection as is used
** by the backup operation, then the backup database is automatically
** updated at the same time.
**
** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
**
-** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
+** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
** application wishes to abandon the backup operation, the application
** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
** ^The sqlite3_backup_finish() interfaces releases all
-** resources associated with the [sqlite3_backup] object.
+** resources associated with the [sqlite3_backup] object.
** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any
** active write-transaction on the destination database is rolled back.
** The [sqlite3_backup] object is invalid
** connections, then the source database connection may be used concurrently
** from within other threads.
**
-** However, the application must guarantee that the destination
-** [database connection] is not passed to any other API (by any thread) after
+** However, the application must guarantee that the destination
+** [database connection] is not passed to any other API (by any thread) after
** sqlite3_backup_init() is called and before the corresponding call to
** sqlite3_backup_finish(). SQLite does not currently check to see
** if the application incorrectly accesses the destination [database connection]
** If running in [shared cache mode], the application must
** guarantee that the shared cache used by the destination database
** is not accessed while the backup is running. In practice this means
-** that the application must guarantee that the disk file being
+** that the application must guarantee that the disk file being
** backed up to is not accessed by any connection within the process,
** not just the specific connection that was passed to sqlite3_backup_init().
**
-** The [sqlite3_backup] object itself is partially threadsafe. Multiple
+** The [sqlite3_backup] object itself is partially threadsafe. Multiple
** threads may safely make multiple concurrent calls to sqlite3_backup_step().
** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount()
** APIs are not strictly speaking threadsafe. If they are invoked at the
** ^When running in shared-cache mode, a database operation may fail with
** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
** individual tables within the shared-cache cannot be obtained. See
-** [SQLite Shared-Cache Mode] for a description of shared-cache locking.
-** ^This API may be used to register a callback that SQLite will invoke
+** [SQLite Shared-Cache Mode] for a description of shared-cache locking.
+** ^This API may be used to register a callback that SQLite will invoke
** when the connection currently holding the required lock relinquishes it.
** ^This API is only available if the library was compiled with the
** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined.
** See Also: [Using the SQLite Unlock Notification Feature].
**
** ^Shared-cache locks are released when a database connection concludes
-** its current transaction, either by committing it or rolling it back.
+** its current transaction, either by committing it or rolling it back.
**
** ^When a connection (known as the blocked connection) fails to obtain a
** shared-cache lock and SQLITE_LOCKED is returned to the caller, the
** identity of the database connection (the blocking connection) that
-** has locked the required resource is stored internally. ^After an
+** has locked the required resource is stored internally. ^After an
** application receives an SQLITE_LOCKED error, it may call the
-** sqlite3_unlock_notify() method with the blocked connection handle as
+** sqlite3_unlock_notify() method with the blocked connection handle as
** the first argument to register for a callback that will be invoked
** when the blocking connections current transaction is concluded. ^The
** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
**
** ^If the blocked connection is attempting to obtain a write-lock on a
** shared-cache table, and more than one other connection currently holds
-** a read-lock on the same table, then SQLite arbitrarily selects one of
+** a read-lock on the same table, then SQLite arbitrarily selects one of
** the other connections to use as the blocking connection.
**
-** ^(There may be at most one unlock-notify callback registered by a
+** ^(There may be at most one unlock-notify callback registered by a
** blocked connection. If sqlite3_unlock_notify() is called when the
** blocked connection already has a registered unlock-notify callback,
** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is
** called with a NULL pointer as its second argument, then any existing
-** unlock-notify callback is canceled. ^The blocked connections
+** unlock-notify callback is canceled. ^The blocked connections
** unlock-notify callback may also be canceled by closing the blocked
** connection using [sqlite3_close()].
**
**
** <b>Callback Invocation Details</b>
**
-** When an unlock-notify callback is registered, the application provides a
+** When an unlock-notify callback is registered, the application provides a
** single void* pointer that is passed to the callback when it is invoked.
** However, the signature of the callback function allows SQLite to pass
** it an array of void* context pointers. The first argument passed to
** same callback function, then instead of invoking the callback function
** multiple times, it is invoked once with the set of void* context pointers
** specified by the blocked connections bundled together into an array.
-** This gives the application an opportunity to prioritize any actions
+** This gives the application an opportunity to prioritize any actions
** related to the set of unblocked database connections.
**
** <b>Deadlock Detection</b>
**
-** Assuming that after registering for an unlock-notify callback a
+** Assuming that after registering for an unlock-notify callback a
** database waits for the callback to be issued before taking any further
** action (a reasonable assumption), then using this API may cause the
** application to deadlock. For example, if connection X is waiting for
**
** <b>The "DROP TABLE" Exception</b>
**
-** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost
+** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost
** always appropriate to call sqlite3_unlock_notify(). There is however,
** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement,
** SQLite checks if there are any currently executing SELECT statements
** One way around this problem is to check the extended error code returned
** by an sqlite3_step() call. ^(If there is a blocking connection, then the
** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in
-** the special "DROP TABLE/INDEX" case, the extended error code is just
+** the special "DROP TABLE/INDEX" case, the extended error code is just
** SQLITE_LOCKED.)^
*/
SQLITE_API int sqlite3_unlock_notify(
** ^The [sqlite3_wal_hook()] function is used to register a callback that
** will be invoked each time a database connection commits data to a
** [write-ahead log] (i.e. whenever a transaction is committed in
-** [journal_mode | journal_mode=WAL mode]).
+** [journal_mode | journal_mode=WAL mode]).
**
-** ^The callback is invoked by SQLite after the commit has taken place and
-** the associated write-lock on the database released, so the implementation
+** ^The callback is invoked by SQLite after the commit has taken place and
+** the associated write-lock on the database released, so the implementation
** may read, write or [checkpoint] the database as required.
**
** ^The first parameter passed to the callback function when it is invoked
** that does not correspond to any valid SQLite error code, the results
** are undefined.
**
-** A single database handle may have at most a single write-ahead log callback
+** A single database handle may have at most a single write-ahead log callback
** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
** previously registered write-ahead log callback. ^Note that the
** [sqlite3_wal_autocheckpoint()] interface and the
** those overwrite any prior [sqlite3_wal_hook()] settings.
*/
SQLITE_API void *sqlite3_wal_hook(
- sqlite3*,
+ sqlite3*,
int(*)(void *,sqlite3*,const char*,int),
void*
);
** [sqlite3_wal_hook()] that causes any database on [database connection] D
** to automatically [checkpoint]
** after committing a transaction if there are N or
-** more frames in the [write-ahead log] file. ^Passing zero or
+** more frames in the [write-ahead log] file. ^Passing zero or
** a negative value as the nFrame parameter disables automatic
** checkpoints entirely.
**
/*
** CAPI3REF: Checkpoint a database
**
-** Run a checkpoint operation on WAL database zDb attached to database
-** handle db. The specific operation is determined by the value of the
+** Run a checkpoint operation on WAL database zDb attached to database
+** handle db. The specific operation is determined by the value of the
** eMode parameter:
**
** <dl>
** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
-** Checkpoint as many frames as possible without waiting for any database
+** Checkpoint as many frames as possible without waiting for any database
** readers or writers to finish. Sync the db file if all frames in the log
-** are checkpointed. This mode is the same as calling
+** are checkpointed. This mode is the same as calling
** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
**
** <dt>SQLITE_CHECKPOINT_FULL<dd>
** but not database readers.
**
** <dt>SQLITE_CHECKPOINT_RESTART<dd>
-** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
+** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
** checkpointing the log file it blocks (calls the busy-handler callback)
-** until all readers are reading from the database file only. This ensures
-** that the next client to write to the database file restarts the log file
+** until all readers are reading from the database file only. This ensures
+** that the next client to write to the database file restarts the log file
** from the beginning. This call blocks database writers while it is running,
** but not database readers.
** </dl>
** before returning to communicate this to the caller.
**
** All calls obtain an exclusive "checkpoint" lock on the database file. If
-** any other process is running a checkpoint operation at the same time, the
-** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a
+** any other process is running a checkpoint operation at the same time, the
+** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a
** busy-handler configured, it will not be invoked in this case.
**
-** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive
+** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive
** "writer" lock on the database file. If the writer lock cannot be obtained
** immediately, and a busy-handler is configured, it is invoked and the writer
** lock retried until either the busy-handler returns 0 or the lock is
** successfully obtained. The busy-handler is also invoked while waiting for
** database readers as described above. If the busy-handler returns 0 before
** the writer lock is obtained or while waiting for database readers, the
-** checkpoint operation proceeds from that point in the same way as
-** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
+** checkpoint operation proceeds from that point in the same way as
+** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
** without blocking any further. SQLITE_BUSY is returned in this case.
**
** If parameter zDb is NULL or points to a zero length string, then the
** specified operation is attempted on all WAL databases. In this case the
-** values written to output parameters *pnLog and *pnCkpt are undefined. If
-** an SQLITE_BUSY error is encountered when processing one or more of the
-** attached WAL databases, the operation is still attempted on any remaining
-** attached databases and SQLITE_BUSY is returned to the caller. If any other
-** error occurs while processing an attached database, processing is abandoned
-** and the error code returned to the caller immediately. If no error
-** (SQLITE_BUSY or otherwise) is encountered while processing the attached
+** values written to output parameters *pnLog and *pnCkpt are undefined. If
+** an SQLITE_BUSY error is encountered when processing one or more of the
+** attached WAL databases, the operation is still attempted on any remaining
+** attached databases and SQLITE_BUSY is returned to the caller. If any other
+** error occurs while processing an attached database, processing is abandoned
+** and the error code returned to the caller immediately. If no error
+** (SQLITE_BUSY or otherwise) is encountered while processing the attached
** databases, SQLITE_OK is returned.
**
** If database zDb is the name of an attached database that is not in WAL
** If X is non-zero, then the virtual table implementation guarantees
** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
** any modifications to internal or persistent data structures have been made.
-** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
+** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
** is able to roll back a statement or database transaction, and abandon
-** or continue processing the current SQL statement as appropriate.
+** or continue processing the current SQL statement as appropriate.
** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
** had been ABORT.
**
** Virtual table implementations that are required to handle OR REPLACE
-** must do so within the [xUpdate] method. If a call to the
-** [sqlite3_vtab_on_conflict()] function indicates that the current ON
-** CONFLICT policy is REPLACE, the virtual table implementation should
+** must do so within the [xUpdate] method. If a call to the
+** [sqlite3_vtab_on_conflict()] function indicates that the current ON
+** CONFLICT policy is REPLACE, the virtual table implementation should
** silently replace the appropriate rows within the xUpdate callback and
** return SQLITE_OK. Or, if this is not possible, it may return
-** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
+** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
** constraint handling.
** </dl>
*/
** element pointed to plus the next _ht.count-1 elements in the list.
**
** Hash.htsize and Hash.ht may be zero. In that case lookup is done
-** by a linear search of the global list. For small tables, the
+** by a linear search of the global list. For small tables, the
** Hash.ht table is never allocated because if there are few elements
** in the table, it is faster to do a linear search than to manage
** the hash table.
} *ht;
};
-/* Each element in the hash table is an instance of the following
+/* Each element in the hash table is an instance of the following
** structure. All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
/*
** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0
-** afterward. Having this macro allows us to cause the C compiler
+** afterward. Having this macro allows us to cause the C compiler
** to omit code used by TEMP tables without messy #ifndef statements.
*/
#ifdef SQLITE_OMIT_TEMPDB
#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
-/*
+/*
** Round up a number to the next larger multiple of 8. This is used
** to force 8-byte alignment on 64-bit architectures.
*/
/*
** An instance of the following structure is used to store the busy-handler
-** callback for a given sqlite handle.
+** callback for a given sqlite handle.
**
** The sqlite.busyHandler member of the sqlite struct contains the busy
** callback for the database handle. Each pager opened via the sqlite
/*
** The following value as a destructor means to use sqlite3DbFree().
-** The sqlite3DbFree() routine requires two parameters instead of the
-** one parameter that destructors normally want. So we have to introduce
-** this magic value that the code knows to handle differently. Any
+** The sqlite3DbFree() routine requires two parameters instead of the
+** one parameter that destructors normally want. So we have to introduce
+** this magic value that the code knows to handle differently. Any
** pointer will work here as long as it is distinct from SQLITE_STATIC
** and SQLITE_TRANSIENT.
*/
SQLITE_API int sqlite3_wsd_init(int N, int J);
SQLITE_API void *sqlite3_wsd_find(void *K, int L);
#else
- #define SQLITE_WSD
+ #define SQLITE_WSD
#define GLOBAL(t,v) v
#define sqlite3GlobalConfig sqlite3Config
#endif
/*
** The following macros are used to suppress compiler warnings and to
-** make it clear to human readers when a function parameter is deliberately
+** make it clear to human readers when a function parameter is deliberately
** left unused within the body of a function. This usually happens when
-** a function is called via a function pointer. For example the
+** a function is called via a function pointer. For example the
** implementation of an SQL aggregate step callback may not use the
** parameter indicating the number of arguments passed to the aggregate,
** if it knows that this is enforced elsewhere.
typedef struct WhereLevel WhereLevel;
/*
-** Defer sourcing vdbe.h and btree.h until after the "u8" and
+** Defer sourcing vdbe.h and btree.h until after the "u8" and
** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
** pointer types (i.e. FuncDef) defined above.
*/
/*
** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
-** should be one of the following values. The integer values are assigned
+** should be one of the following values. The integer values are assigned
** to constants so that the offset of the corresponding field in an
** SQLite database header may be found using the following formula:
**
SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*);
SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*);
#else
-# define sqlite3BtreeEnter(X)
+# define sqlite3BtreeEnter(X)
# define sqlite3BtreeEnterAll(X)
#endif
#define P4_KEYINFO_STATIC (-17)
/*
-** The Vdbe.aColName array contains 5n Mem structures, where n is the
+** The Vdbe.aColName array contains 5n Mem structures, where n is the
** number of columns of data returned by the statement.
*/
#define COLNAME_NAME 0
/*
** The following macro converts a relative address in the p2 field
-** of a VdbeOp structure into a negative number so that
+** of a VdbeOp structure into a negative number so that
** sqlite3VdbeAddOpList() knows that the address is relative. Calling
** the macro again restores the address.
*/
#define _PAGER_H_
/*
-** Default maximum size for persistent journal files. A negative
-** value means no limit. This value may be overridden using the
+** Default maximum size for persistent journal files. A negative
+** value means no limit. This value may be overridden using the
** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit".
*/
#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
/*
** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
** reserved for working around a windows/posix incompatibility). It is
-** used in the journal to signify that the remainder of the journal file
+** used in the journal to signify that the remainder of the journal file
** is devoted to storing a master journal name - there are no more pages to
-** roll back. See comments for function writeMasterJournal() in pager.c
+** roll back. See comments for function writeMasterJournal() in pager.c
** for details.
*/
#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
#define PAGER_LOCKINGMODE_EXCLUSIVE 1
/*
-** Numeric constants that encode the journalmode.
+** Numeric constants that encode the journalmode.
*/
#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */
#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */
/*
** The remainder of this file contains the declarations of the functions
-** that make up the Pager sub-system API. See source code comments for
+** that make up the Pager sub-system API. See source code comments for
** a detailed description of each routine.
*/
-/* Open and close a Pager connection. */
+/* Open and close a Pager connection. */
SQLITE_PRIVATE int sqlite3PagerOpen(
sqlite3_vfs*,
Pager **ppPager,
SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
-/* Functions used to obtain and release page references. */
+/* Functions used to obtain and release page references. */
SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0)
SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*);
SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int);
SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*);
-SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *);
-SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *);
+SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *);
+SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *);
/* Functions used to manage pager transactions and savepoints. */
SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*);
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
-** subsystem.
+** subsystem.
*/
#ifndef _PCACHE_H_
SQLITE_PRIVATE int sqlite3PcacheSize(void);
/* One release per successful fetch. Page is pinned until released.
-** Reference counted.
+** Reference counted.
*/
SQLITE_PRIVATE int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**);
SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*);
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
/* Iterate through all dirty pages currently stored in the cache. This
-** interface is only available if SQLITE_CHECK_PAGES is defined when the
+** interface is only available if SQLITE_CHECK_PAGES is defined when the
** library is built.
*/
SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *));
/*
** Figure out if we are dealing with Unix, Windows, or some other
** operating system. After the following block of preprocess macros,
-** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER
-** will defined to either 1 or 0. One of the four will be 1. The other
+** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER
+** will defined to either 1 or 0. One of the four will be 1. The other
** three will be 0.
*/
#if defined(SQLITE_OS_OTHER)
** 2006-10-31: The default prefix used to be "sqlite_". But then
** Mcafee started using SQLite in their anti-virus product and it
** started putting files with the "sqlite" name in the c:/temp folder.
-** This annoyed many windows users. Those users would then do a
+** This annoyed many windows users. Those users would then do a
** Google search for "sqlite", find the telephone numbers of the
** developers and call to wake them up at night and complain.
-** For this reason, the default name prefix is changed to be "sqlite"
+** For this reason, the default name prefix is changed to be "sqlite"
** spelled backwards. So the temp files are still identified, but
** anybody smart enough to figure out the code is also likely smart
** enough to know that calling the developer will not help get rid
** UnlockFile().
**
** LockFile() prevents not just writing but also reading by other processes.
-** A SHARED_LOCK is obtained by locking a single randomly-chosen
-** byte out of a specific range of bytes. The lock byte is obtained at
-** random so two separate readers can probably access the file at the
+** A SHARED_LOCK is obtained by locking a single randomly-chosen
+** byte out of a specific range of bytes. The lock byte is obtained at
+** random so two separate readers can probably access the file at the
** same time, unless they are unlucky and choose the same lock byte.
** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range.
** There can only be one writer. A RESERVED_LOCK is obtained by locking
** The following #defines specify the range of bytes used for locking.
** SHARED_SIZE is the number of bytes available in the pool from which
** a random byte is selected for a shared lock. The pool of bytes for
-** shared locks begins at SHARED_FIRST.
+** shared locks begins at SHARED_FIRST.
**
** The same locking strategy and
** byte ranges are used for Unix. This leaves open the possiblity of having
** that all locks will fit on a single page even at the minimum page size.
** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE
** is set high so that we don't have to allocate an unused page except
-** for very large databases. But one should test the page skipping logic
+** for very large databases. But one should test the page skipping logic
** by setting PENDING_BYTE low and running the entire regression suite.
**
** Changing the value of PENDING_BYTE results in a subtly incompatible
*/
SQLITE_PRIVATE int sqlite3OsInit(void);
-/*
-** Functions for accessing sqlite3_file methods
+/*
+** Functions for accessing sqlite3_file methods
*/
SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file*);
SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
-/*
-** Functions for accessing sqlite3_vfs methods
+/*
+** Functions for accessing sqlite3_vfs methods
*/
SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
/*
-** Convenience functions for opening and closing files using
+** Convenience functions for opening and closing files using
** sqlite3_malloc() to obtain space for the file-handle structure.
*/
SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
*/
#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
#define sqlite3_mutex_free(X)
-#define sqlite3_mutex_enter(X)
+#define sqlite3_mutex_enter(X)
#define sqlite3_mutex_try(X) SQLITE_OK
-#define sqlite3_mutex_leave(X)
+#define sqlite3_mutex_leave(X)
#define sqlite3_mutex_held(X) ((void)(X),1)
#define sqlite3_mutex_notheld(X) ((void)(X),1)
#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8)
** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing.
** In shared cache mode, a single Schema object can be shared by multiple
** Btrees that refer to the same underlying BtShared object.
-**
+**
** Schema objects are automatically deallocated when the last Btree that
** references them is destroyed. The TEMP Schema is manually freed by
** sqlite3_close().
};
/*
-** These macros can be used to test, set, or clear bits in the
+** These macros can be used to test, set, or clear bits in the
** Db.pSchema->flags field.
*/
#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P))
void *pTraceArg; /* Argument to the trace function */
void (*xProfile)(void*,const char*,u64); /* Profiling function */
void *pProfileArg; /* Argument to profile function */
- void *pCommitArg; /* Argument to xCommitCallback() */
+ void *pCommitArg; /* Argument to xCommitCallback() */
int (*xCommitCallback)(void*); /* Invoked at every commit. */
- void *pRollbackArg; /* Argument to xRollbackCallback() */
+ void *pRollbackArg; /* Argument to xRollbackCallback() */
void (*xRollbackCallback)(void*); /* Invoked at every commit. */
void *pUpdateArg;
void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
- /* The following variables are all protected by the STATIC_MASTER
- ** mutex, not by sqlite3.mutex. They are used by code in notify.c.
+ /* The following variables are all protected by the STATIC_MASTER
+ ** mutex, not by sqlite3.mutex. They are used by code in notify.c.
**
** When X.pUnlockConnection==Y, that means that X is waiting for Y to
** unlock so that it can proceed.
** This structure encapsulates a user-function destructor callback (as
** configured using create_function_v2()) and a reference counter. When
** create_function_v2() is called to create a function with a destructor,
-** a single object of this type is allocated. FuncDestructor.nRef is set to
+** a single object of this type is allocated. FuncDestructor.nRef is set to
** the number of FuncDef objects created (either 1 or 3, depending on whether
** or not the specified encoding is SQLITE_ANY). The FuncDef.pDestructor
** member of each of the new FuncDef objects is set to point to the allocated
** used to create the initializers for the FuncDef structures.
**
** FUNCTION(zName, nArg, iArg, bNC, xFunc)
-** Used to create a scalar function definition of a function zName
+** Used to create a scalar function definition of a function zName
** implemented by C function xFunc that accepts nArg arguments. The
** value passed as iArg is cast to a (void*) and made available
-** as the user-data (sqlite3_user_data()) for the function. If
+** as the user-data (sqlite3_user_data()) for the function. If
** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set.
**
** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
** FUNCTION().
**
** LIKEFUNC(zName, nArg, pArg, flags)
-** Used to create a scalar function definition of a function zName
-** that accepts nArg arguments and is implemented by a call to C
+** Used to create a scalar function definition of a function zName
+** that accepts nArg arguments and is implemented by a call to C
** function likeFunc. Argument pArg is cast to a (void *) and made
** available as the function user-data (sqlite3_user_data()). The
** FuncDef.flags variable is set to the value passed as the flags
**
** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and
** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve
-** the speed a little by numbering the values consecutively.
+** the speed a little by numbering the values consecutively.
**
** But rather than start with 0 or 1, we begin with 'a'. That way,
** when multiple affinity types are concatenated into a string and
/*
** The SQLITE_AFF_MASK values masks off the significant bits of an
-** affinity value.
+** affinity value.
*/
#define SQLITE_AFF_MASK 0x67
/*
** An object of this type is created for each virtual table present in
-** the database schema.
+** the database schema.
**
** If the database schema is shared, then there is one instance of this
** structure for each database connection (sqlite3*) that uses the shared
** schema. This is because each database connection requires its own unique
-** instance of the sqlite3_vtab* handle used to access the virtual table
-** implementation. sqlite3_vtab* handles can not be shared between
-** database connections, even when the rest of the in-memory database
+** instance of the sqlite3_vtab* handle used to access the virtual table
+** implementation. sqlite3_vtab* handles can not be shared between
+** database connections, even when the rest of the in-memory database
** schema is shared, as the implementation often stores the database
** connection handle passed to it via the xConnect() or xCreate() method
** during initialization internally. This database connection handle may
-** then be used by the virtual table implementation to access real tables
-** within the database. So that they appear as part of the callers
-** transaction, these accesses need to be made via the same database
+** then be used by the virtual table implementation to access real tables
+** within the database. So that they appear as part of the callers
+** transaction, these accesses need to be made via the same database
** connection as that used to execute SQL operations on the virtual table.
**
** All VTable objects that correspond to a single table in a shared
** sqlite3_vtab* handle in the compiled query.
**
** When an in-memory Table object is deleted (for example when the
-** schema is being reloaded for some reason), the VTable objects are not
-** deleted and the sqlite3_vtab* handles are not xDisconnect()ed
+** schema is being reloaded for some reason), the VTable objects are not
+** deleted and the sqlite3_vtab* handles are not xDisconnect()ed
** immediately. Instead, they are moved from the Table.pVTable list to
** another linked list headed by the sqlite3.pDisconnect member of the
-** corresponding sqlite3 structure. They are then deleted/xDisconnected
+** corresponding sqlite3 structure. They are then deleted/xDisconnected
** next time a statement is prepared using said sqlite3*. This is done
** to avoid deadlock issues involving multiple sqlite3.mutex mutexes.
** Refer to comments above function sqlite3VtabUnlockList() for an
** explanation as to why it is safe to add an entry to an sqlite3.pDisconnect
** list without holding the corresponding sqlite3.mutex mutex.
**
-** The memory for objects of this type is always allocated by
-** sqlite3DbMalloc(), using the connection handle stored in VTable.db as
+** The memory for objects of this type is always allocated by
+** sqlite3DbMalloc(), using the connection handle stored in VTable.db as
** the first argument.
*/
struct VTable {
** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that
** holds temporary tables and indices. If TF_Ephemeral is set
** then the table is stored in a file that is automatically deleted
-** when the VDBE cursor to the table is closed. In this case Table.tnum
+** when the VDBE cursor to the table is closed. In this case Table.tnum
** refers VDBE cursor number that holds the table open, not to the root
** page number. Transient tables are used to hold the results of a
-** sub-query that appears instead of a real table name in the FROM clause
+** sub-query that appears instead of a real table name in the FROM clause
** of a SELECT statement.
*/
struct Table {
** key is set to NULL. CASCADE means that a DELETE or UPDATE of the
** referenced table row is propagated into the row that holds the
** foreign key.
-**
+**
** The following symbolic values are used to record which type
** of action to take.
*/
/*
** An instance of the following structure is passed as the first
-** argument to sqlite3VdbeKeyCompare and is used to control the
+** argument to sqlite3VdbeKeyCompare and is used to control the
** comparison of the two index keys.
*/
struct KeyInfo {
** In the Table structure describing Ex1, nCol==3 because there are
** three columns in the table. In the Index structure describing
** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed.
-** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the
+** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the
** first column to be indexed (c3) has an index of 2 in Ex1.aCol[].
** The second column to be indexed (c1) has an index of 0 in
** Ex1.aCol[], hence Ex2.aiColumn[1]==0.
** The Index.onError field determines whether or not the indexed columns
** must be unique and what to do if they are not. When Index.onError=OE_None,
** it means this is not a unique index. Otherwise it is a unique index
-** and the value of Index.onError indicate the which conflict resolution
+** and the value of Index.onError indicate the which conflict resolution
** algorithm to employ whenever an attempt is made to insert a non-unique
** element.
*/
};
/*
-** Each sample stored in the sqlite_stat3 table is represented in memory
+** Each sample stored in the sqlite_stat3 table is represented in memory
** using a structure of this type. See documentation at the top of the
** analyze.c source file for additional information.
*/
** to represent the greater-than-or-equal-to operator in the expression
** tree.
**
-** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB,
+** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB,
** or TK_STRING), then Expr.token contains the text of the SQL literal. If
-** the expression is a variable (TK_VARIABLE), then Expr.token contains the
+** the expression is a variable (TK_VARIABLE), then Expr.token contains the
** variable name. Finally, if the expression is an SQL function (TK_FUNCTION),
** then Expr.token contains the name of the function.
**
** a CASE expression or an IN expression of the form "<lhs> IN (<y>, <z>...)".
** Expr.x.pSelect is used if the expression is a sub-select or an expression of
** the form "<lhs> IN (SELECT ...)". If the EP_xIsSelect bit is set in the
-** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is
+** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is
** valid.
**
** An expression of the form ID or ID.ID refers to a column in a table.
** value is also stored in the Expr.iAgg column in the aggregate so that
** it can be accessed after all aggregates are computed.
**
-** If the expression is an unbound variable marker (a question mark
-** character '?' in the original SQL) then the Expr.iTable holds the index
+** If the expression is an unbound variable marker (a question mark
+** character '?' in the original SQL) then the Expr.iTable holds the index
** number for that variable.
**
** If the expression is a subquery then Expr.iColumn holds an integer
/* If the EP_TokenOnly flag is set in the Expr.flags mask, then no
** space is allocated for the fields below this point. An attempt to
- ** access them will result in a segfault or malfunction.
+ ** access them will result in a segfault or malfunction.
*********************************************************************/
Expr *pLeft; /* Left subnode */
#endif
/*
-** These macros can be used to test, set, or clear bits in the
+** These macros can be used to test, set, or clear bits in the
** Expr.flags field.
*/
#define ExprHasProperty(E,P) (((E)->flags&(P))==(P))
#define ExprClearProperty(E,P) (E)->flags&=~(P)
/*
-** Macros to determine the number of bytes required by a normal Expr
-** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
+** Macros to determine the number of bytes required by a normal Expr
+** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
** and an Expr struct with the EP_TokenOnly flag set.
*/
#define EXPR_FULLSIZE sizeof(Expr) /* Full size */
#define EXPR_TOKENONLYSIZE offsetof(Expr,pLeft) /* Fewer features */
/*
-** Flags passed to the sqlite3ExprDup() function. See the header comment
+** Flags passed to the sqlite3ExprDup() function. See the header comment
** above sqlite3ExprDup() for details.
*/
#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */
** pEList corresponds to the result set of a SELECT and is NULL for
** other statements.
**
-** NameContexts can be nested. When resolving names, the inner-most
+** NameContexts can be nested. When resolving names, the inner-most
** context is searched first. If no match is found, the next outer
** context is checked. If there is still no match, the next context
** is checked. This process continues until either a match is found
** or all contexts are check. When a match is found, the nRef member of
-** the context containing the match is incremented.
+** the context containing the match is incremented.
**
** Each subquery gets a new NameContext. The pNext field points to the
** NameContext in the parent query. Thus the process of scanning the
};
/*
-** During code generation of statements that do inserts into AUTOINCREMENT
+** During code generation of statements that do inserts into AUTOINCREMENT
** tables, the following information is attached to the Table.u.autoInc.p
** pointer of each autoincrement table to record some side information that
** the code generator needs. We have to keep per-table autoincrement
#endif
/*
-** At least one instance of the following structure is created for each
+** At least one instance of the following structure is created for each
** trigger that may be fired while parsing an INSERT, UPDATE or DELETE
** statement. All such objects are stored in the linked list headed at
** Parse.pTriggerPrg and deleted once statement compilation has been
** values for both pTrigger and orconf.
**
** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns
-** accessed (or set to 0 for triggers fired as a result of INSERT
+** accessed (or set to 0 for triggers fired as a result of INSERT
** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to
** a mask of new.* columns used by the program.
*/
** is constant but the second part is reset at the beginning and end of
** each recursion.
**
-** The nTableLock and aTableLock variables are only used if the shared-cache
+** The nTableLock and aTableLock variables are only used if the shared-cache
** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are
** used to store the set of table-locks required by the statement being
** compiled. Function sqlite3TableLock() is used to add entries to the
/*
* Each trigger present in the database schema is stored as an instance of
- * struct Trigger.
+ * struct Trigger.
*
* Pointers to instances of struct Trigger are stored in two ways.
- * 1. In the "trigHash" hash table (part of the sqlite3* that represents the
+ * 1. In the "trigHash" hash table (part of the sqlite3* that represents the
* database). This allows Trigger structures to be retrieved by name.
* 2. All triggers associated with a single table form a linked list, using the
* pNext member of struct Trigger. A pointer to the first element of the
/*
** A trigger is either a BEFORE or an AFTER trigger. The following constants
-** determine which.
+** determine which.
**
** If there are multiple triggers, you might of some BEFORE and some AFTER.
** In that cases, the constants below can be ORed together.
/*
* An instance of struct TriggerStep is used to store a single SQL statement
- * that is a part of a trigger-program.
+ * that is a part of a trigger-program.
*
* Instances of struct TriggerStep are stored in a singly linked list (linked
- * using the "pNext" member) referenced by the "step_list" member of the
+ * using the "pNext" member) referenced by the "step_list" member of the
* associated struct Trigger instance. The first element of the linked list is
* the first step of the trigger-program.
- *
+ *
* The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
- * "SELECT" statement. The meanings of the other members is determined by the
+ * "SELECT" statement. The meanings of the other members is determined by the
* value of "op" as follows:
*
* (op == TK_INSERT)
* target -> A token holding the quoted name of the table to insert into.
* pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
* this stores values to be inserted. Otherwise NULL.
- * pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
+ * pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
* statement, then this stores the column-names to be
* inserted into.
*
* target -> A token holding the quoted name of the table to delete from.
* pWhere -> The WHERE clause of the DELETE statement if one is specified.
* Otherwise NULL.
- *
+ *
* (op == TK_UPDATE)
* target -> A token holding the quoted name of the table to update rows of.
* pWhere -> The WHERE clause of the UPDATE statement if one is specified.
* pExprList -> A list of the columns to update and the expressions to update
* them to. See sqlite3Update() documentation of "pChanges"
* argument.
- *
+ *
*/
struct TriggerStep {
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
-** explicit.
+** explicit.
*/
typedef struct DbFixer DbFixer;
struct DbFixer {
#ifdef SQLITE_USE_ALLOCA
# define sqlite3StackAllocRaw(D,N) alloca(N)
# define sqlite3StackAllocZero(D,N) memset(alloca(N), 0, N)
-# define sqlite3StackFree(D,P)
+# define sqlite3StackFree(D,P)
#else
# define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N)
# define sqlite3StackAllocZero(D,N) sqlite3DbMallocZero(D,N)
** Routines to read and write variable-length integers. These used to
** be defined locally, but now we use the varint routines in the util.c
** file. Code should use the MACRO forms below, as the Varint32 versions
-** are coded to assume the single byte case is already handled (which
+** are coded to assume the single byte case is already handled (which
** the MACRO form does).
*/
SQLITE_PRIVATE int sqlite3PutVarint(unsigned char*, u64);
SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
-SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
+SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
void(*)(void*));
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);
SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *);
-SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
+SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
void (*)(sqlite3_context*,int,sqlite3_value **),
void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*),
FuncDestructor *pDestructor
# define sqlite3VtabRollback(X)
# define sqlite3VtabCommit(X)
# define sqlite3VtabInSync(db) 0
-# define sqlite3VtabLock(X)
+# define sqlite3VtabLock(X)
# define sqlite3VtabUnlock(X)
# define sqlite3VtabUnlockList(X)
# define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
** key functionality is available. If OMIT_TRIGGER is defined but
** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In
-** this case foreign keys are parsed, but no other functionality is
+** this case foreign keys are parsed, but no other functionality is
** provided (enforcement of FK constraints requires the triggers sub-system).
*/
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
/*
** If the SQLITE_ENABLE IOTRACE exists then the global variable
** sqlite3IoTrace is a pointer to a printf-like routine used to
-** print I/O tracing messages.
+** print I/O tracing messages.
*/
#ifdef SQLITE_ENABLE_IOTRACE
# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; }
** that allocations that might have been satisfied by lookaside are not
** passed back to non-lookaside free() routines. Asserts such as the
** example above are placed on the non-lookaside free() routines to verify
-** this constraint.
+** this constraint.
**
** All of this is no-op for a production build. It only comes into
** play when the SQLITE_MEMDEBUG compile-time option is used.
*/
/* An array to map all upper-case characters into their corresponding
-** lower-case character.
+** lower-case character.
**
** SQLite only considers US-ASCII (or EBCDIC) characters. We do not
** handle case conversions for the UTF character set since the tables
** Standard function tolower() is implemented using the sqlite3UpperToLower[]
** array. tolower() is used more often than toupper() by SQLite.
**
-** Bit 0x40 is set if the character non-alphanumeric and can be used in an
+** Bit 0x40 is set if the character non-alphanumeric and can be used in an
** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
** non-ASCII UTF character. Hence the test for whether or not a character is
** part of an identifier is 0x46.
** Properties of opcodes. The OPFLG_INITIALIZER macro is
** created by mkopcodeh.awk during compilation. Data is obtained
** from the comments following the "case OP_xxxx:" statements in
-** the vdbe.c file.
+** the vdbe.c file.
*/
SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
/*
-** An array of names of all compile-time options. This array should
+** An array of names of all compile-time options. This array should
** be sorted A-Z.
**
** This array looks large, but in a typical installation actually uses
** loop over all entries of the Btree. You can also insert new BTree
** entries or retrieve the key or data from the entry that the cursor
** is currently pointing to.
-**
+**
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
*/
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
- /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
+ /* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
** OP_IsUnique opcode on this cursor. */
int seekResult;
** When a sub-program is executed (OP_Program), a structure of this type
** is allocated to store the current value of the program counter, as
** well as the current memory cell array and various other frame specific
-** values stored in the Vdbe struct. When the sub-program is finished,
+** values stored in the Vdbe struct. When the sub-program is finished,
** these values are copied back to the Vdbe from the VdbeFrame structure,
** restoring the state of the VM to as it was before the sub-program
** began executing.
** If the MEM_Str flag is set then Mem.z points at a string representation.
** Usually this is encoded in the same unicode encoding as the main
** database (see below for exceptions). If the MEM_Term flag is also
-** set, then the string is nul terminated. The MEM_Int and MEM_Real
+** set, then the string is nul terminated. The MEM_Int and MEM_Real
** flags may coexist with the MEM_Str flag.
*/
#define MEM_Null 0x0001 /* Value is NULL */
** set to 2 for xDestroy method calls and 1 for all other methods. This
** variable is used for two purposes: to allow xDestroy methods to execute
** "DROP TABLE" statements and to prevent some nasty side effects of
-** malloc failure when SQLite is invoked recursively by a virtual table
+** malloc failure when SQLite is invoked recursively by a virtual table
** method function.
*/
struct Vdbe {
break;
}
- /*
+ /*
** Return an approximation for the amount of memory currently used
** by all pagers associated with the given database connection. The
** highwater mark is meaningless and is returned as zero.
HashElem *p;
nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
- pSchema->tblHash.count
+ pSchema->tblHash.count
+ pSchema->trigHash.count
+ pSchema->idxHash.count
+ pSchema->fkeyHash.count
/*
** Set *pCurrent to the total cache hits or misses encountered by all
- ** pagers the database handle is connected to. *pHighwater is always set
+ ** pagers the database handle is connected to. *pHighwater is always set
** to zero.
*/
case SQLITE_DBSTATUS_CACHE_HIT:
**
*************************************************************************
** This file contains the C functions that implement date and time
-** functions for SQLite.
+** functions for SQLite.
**
** There is only one exported symbol in this file - the function
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
** SQLite processes all times and dates as Julian Day numbers. The
** dates and times are stored as the number of days since noon
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
-** calendar system.
+** calendar system.
**
** 1970-01-01 00:00:00 is JD 2440587.5
** 2000-01-01 00:00:00 is JD 2451544.5
** The following are acceptable forms for the input string:
**
** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM
-** DDDD.DD
+** DDDD.DD
** now
**
** In the first form, the +/-HH:MM is always optional. The fractional
** as there is a year and date.
*/
static int parseDateOrTime(
- sqlite3_context *context,
- const char *zDate,
+ sqlite3_context *context,
+ const char *zDate,
DateTime *p
){
double r;
/*
** On recent Windows platforms, the localtime_s() function is available
-** as part of the "Secure CRT". It is essentially equivalent to
-** localtime_r() available under most POSIX platforms, except that the
+** as part of the "Secure CRT". It is essentially equivalent to
+** localtime_r() available under most POSIX platforms, except that the
** order of the parameters is reversed.
**
** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
**
** If the user has not indicated to use localtime_r() or localtime_s()
-** already, check for an MSVC build environment that provides
+** already, check for an MSVC build environment that provides
** localtime_s().
*/
#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
/*
** Compute the difference (in milliseconds) between localtime and UTC
** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
-** return this value and set *pRc to SQLITE_OK.
+** return this value and set *pRc to SQLITE_OK.
**
** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
** is undefined in this case.
** then assume a default value of "now" for argv[0].
*/
static int isDate(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv,
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv,
DateTime *p
){
int i;
** So we test the effects of a malloc() failing and the sqlite3OsXXX()
** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
**
-** The following functions are instrumented for malloc() failure
+** The following functions are instrumented for malloc() failure
** testing:
**
** sqlite3OsRead()
** VFS methods.
*/
SQLITE_PRIVATE int sqlite3OsOpen(
- sqlite3_vfs *pVfs,
- const char *zPath,
- sqlite3_file *pFile,
- int flags,
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ sqlite3_file *pFile,
+ int flags,
int *pFlagsOut
){
int rc;
return pVfs->xDelete(pVfs, zPath, dirSync);
}
SQLITE_PRIVATE int sqlite3OsAccess(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int flags,
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ int flags,
int *pResOut
){
DO_OS_MALLOC_TEST(0);
return pVfs->xAccess(pVfs, zPath, flags, pResOut);
}
SQLITE_PRIVATE int sqlite3OsFullPathname(
- sqlite3_vfs *pVfs,
- const char *zPath,
- int nPathOut,
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ int nPathOut,
char *zPathOut
){
DO_OS_MALLOC_TEST(0);
}
SQLITE_PRIVATE int sqlite3OsOpenMalloc(
- sqlite3_vfs *pVfs,
- const char *zFile,
- sqlite3_file **ppFile,
+ sqlite3_vfs *pVfs,
+ const char *zFile,
+ sqlite3_file **ppFile,
int flags,
int *pOutFlags
){
**
*************************************************************************
**
-** This file contains code to support the concept of "benign"
+** This file contains code to support the concept of "benign"
** malloc failures (when the xMalloc() or xRealloc() method of the
** sqlite3_mem_methods structure fails to allocate a block of memory
-** and returns 0).
+** and returns 0).
**
** Most malloc failures are non-benign. After they occur, SQLite
** abandons the current operation and returns an error code (usually
** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily
-** fatal. For example, if a malloc fails while resizing a hash table, this
-** is completely recoverable simply by not carrying out the resize. The
-** hash table will continue to function normally. So a malloc failure
+** fatal. For example, if a malloc fails while resizing a hash table, this
+** is completely recoverable simply by not carrying out the resize. The
+** hash table will continue to function normally. So a malloc failure
** during a hash table resize is a benign fault.
*/
#else /* if not __APPLE__ */
/*
-** Use standard C library malloc and free on non-Apple systems.
+** Use standard C library malloc and free on non-Apple systems.
** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
*/
#define SQLITE_MALLOC(x) malloc(x)
/* defer MT decisions to system malloc */
_sqliteZone_ = malloc_default_zone();
}else{
- /* only 1 core, use our own zone to contention over global locks,
+ /* only 1 core, use our own zone to contention over global locks,
** e.g. we have our own dedicated locks */
bool success;
malloc_zone_t* newzone = malloc_create_zone(4096, 0);
malloc_set_zone_name(newzone, "Sqlite_Heap");
do{
- success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone,
+ success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone,
(void * volatile *)&_sqliteZone_);
}while(!_sqliteZone_);
if( !success ){
** when this module is combined with other in the amalgamation.
*/
static struct {
-
+
/*
** Mutex to control access to the memory allocation subsystem.
*/
*/
struct MemBlockHdr *pFirst;
struct MemBlockHdr *pLast;
-
+
/*
** The number of levels of backtrace to save in new allocations.
*/
int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */
char zTitle[100]; /* The title text */
- /*
+ /*
** sqlite3MallocDisallow() increments the following counter.
** sqlite3MallocAllow() decrements it.
*/
pU8 = (u8*)pAllocation;
assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD );
/* This checks any of the "extra" bytes allocated due
- ** to rounding up to an 8 byte boundary to ensure
+ ** to rounding up to an 8 byte boundary to ensure
** they haven't been overwritten.
*/
while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 );
p = (void*)pInt;
}
sqlite3_mutex_leave(mem.mutex);
- return p;
+ return p;
}
/*
struct MemBlockHdr *pHdr;
void **pBt;
char *z;
- assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
+ assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
|| mem.mutex!=0 );
pHdr = sqlite3MemsysGetHeader(pPrior);
pBt = (void**)pHdr;
randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
pHdr->iSize + sizeof(int) + pHdr->nTitle);
free(z);
- sqlite3_mutex_leave(mem.mutex);
+ sqlite3_mutex_leave(mem.mutex);
}
/*
** Change the size of an existing memory allocation.
**
** For this debugging implementation, we *always* make a copy of the
-** allocation into a new place in memory. In this way, if the
-** higher level code is using pointer to the old allocation, it is
+** allocation into a new place in memory. In this way, if the
+** higher level code is using pointer to the old allocation, it is
** much more likely to break and we are much more liking to find
** the error.
*/
}
/*
-** Open the file indicated and write a log of all unfreed memory
+** Open the file indicated and write a log of all unfreed memory
** allocations into that log.
*/
SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
char *z = (char*)pHdr;
z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
- fprintf(out, "**** %lld bytes at %p from %s ****\n",
+ fprintf(out, "**** %lld bytes at %p from %s ****\n",
pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
if( pHdr->nBacktrace ){
fflush(out);
fprintf(out, "COUNTS:\n");
for(i=0; i<NCSIZE-1; i++){
if( mem.nAlloc[i] ){
- fprintf(out, " %5d: %10d %10d %10d\n",
+ fprintf(out, " %5d: %10d %10d %10d\n",
i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]);
}
}
**
*************************************************************************
** This file contains the C functions that implement a memory
-** allocation subsystem for use by SQLite.
+** allocation subsystem for use by SQLite.
**
** This version of the memory allocation subsystem omits all
** use of malloc(). The SQLite user supplies a block of memory
** before calling sqlite3_initialize() from which allocations
-** are made and returned by the xMalloc() and xRealloc()
+** are made and returned by the xMalloc() and xRealloc()
** implementations. Once sqlite3_initialize() has been called,
** the amount of memory available to SQLite is fixed and cannot
** be changed.
#define N_HASH 61
/*
-** A memory allocation (also called a "chunk") consists of two or
-** more blocks where each block is 8 bytes. The first 8 bytes are
+** A memory allocation (also called a "chunk") consists of two or
+** more blocks where each block is 8 bytes. The first 8 bytes are
** a header that is not returned to the user.
**
** A chunk is two or more blocks that is either checked out or
**
** The second block of free chunks is of the form u.list. The
** two fields form a double-linked list of chunks of related sizes.
-** Pointers to the head of the list are stored in mem3.aiSmall[]
+** Pointers to the head of the list are stored in mem3.aiSmall[]
** for smaller chunks and mem3.aiHash[] for larger chunks.
**
-** The second block of a chunk is user data if the chunk is checked
+** The second block of a chunk is user data if the chunk is checked
** out. If a chunk is checked out, the user data may extend into
** the u.hdr.prevSize value of the following chunk.
*/
** True if we are evaluating an out-of-memory callback.
*/
int alarmBusy;
-
+
/*
** Mutex to control access to the memory allocation subsystem.
*/
sqlite3_mutex *mutex;
-
+
/*
** The minimum amount of free space that we have seen.
*/
u32 szMaster;
/*
- ** Array of lists of free blocks according to the block size
+ ** Array of lists of free blocks according to the block size
** for smaller chunks, or a hash on the block size for larger
** chunks.
*/
}
/*
-** Unlink the chunk at index i from
+** Unlink the chunk at index i from
** whatever list is currently a member of.
*/
static void memsys3Unlink(u32 i){
/*
-** Chunk i is a free chunk that has been unlinked. Adjust its
-** size parameters for check-out and return a pointer to the
+** Chunk i is a free chunk that has been unlinked. Adjust its
+** size parameters for check-out and return a pointer to the
** user portion of the chunk.
*/
static void *memsys3Checkout(u32 i, u32 nBlock){
/*
** *pRoot is the head of a list of free chunks of the same size
** or same size hash. In other words, *pRoot is an entry in either
-** mem3.aiSmall[] or mem3.aiHash[].
+** mem3.aiSmall[] or mem3.aiHash[].
**
** This routine examines all entries on the given list and tries
-** to coalesce each entries with adjacent free chunks.
+** to coalesce each entries with adjacent free chunks.
**
-** If it sees a chunk that is larger than mem3.iMaster, it replaces
+** If it sees a chunk that is larger than mem3.iMaster, it replaces
** the current mem3.iMaster with the new larger chunk. In order for
** this mem3.iMaster replacement to work, the master chunk must be
** linked into the hash tables. That is not the normal state of
}
- /* STEP 3:
+ /* STEP 3:
** Loop through the entire memory pool. Coalesce adjacent free
** chunks. Recompute the master chunk as the largest free chunk.
** Then try again to satisfy the allocation by carving a piece off
memsys3Enter();
p = memsys3MallocUnsafe(nBytes);
memsys3Leave();
- return (void*)p;
+ return (void*)p;
}
/*
/*
-** Open the file indicated and write a log of all unfreed memory
+** Open the file indicated and write a log of all unfreed memory
** allocations into that log.
*/
SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
fprintf(out, " %p(%d)", &mem3.aPool[j],
(mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
}
- fprintf(out, "\n");
+ fprintf(out, "\n");
}
for(i=0; i<N_HASH; i++){
if( mem3.aiHash[i]==0 ) continue;
fprintf(out, " %p(%d)", &mem3.aPool[j],
(mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
}
- fprintf(out, "\n");
+ fprintf(out, "\n");
}
fprintf(out, "master=%d\n", mem3.iMaster);
fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8);
}
/*
-** This routine is the only routine in this file with external
+** This routine is the only routine in this file with external
** linkage.
**
** Populate the low-level memory allocation function pointers in
**
*************************************************************************
** This file contains the C functions that implement a memory
-** allocation subsystem for use by SQLite.
+** allocation subsystem for use by SQLite.
**
** This version of the memory allocation subsystem omits all
** use of malloc(). The application gives SQLite a block of memory
** before calling sqlite3_initialize() from which allocations
-** are made and returned by the xMalloc() and xRealloc()
+** are made and returned by the xMalloc() and xRealloc()
** implementations. Once sqlite3_initialize() has been called,
** the amount of memory available to SQLite is fixed and cannot
** be changed.
** This algorithm is described in: J. M. Robson. "Bounds for Some Functions
** Concerning Dynamic Storage Allocation". Journal of the Association for
** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
-**
+**
** Let n be the size of the largest allocation divided by the minimum
** allocation size (after rounding all sizes up to a power of 2.) Let M
** be the maximum amount of memory ever outstanding at one time. Let
** N be the total amount of memory available for allocation. Robson
-** proved that this memory allocator will never breakdown due to
+** proved that this memory allocator will never breakdown due to
** fragmentation as long as the following constraint holds:
**
** N >= M*(1 + log2(n)/2) - n + 1
*/
/*
-** This version of the memory allocator is used only when
+** This version of the memory allocator is used only when
** SQLITE_ENABLE_MEMSYS5 is defined.
*/
#ifdef SQLITE_ENABLE_MEMSYS5
int szAtom; /* Smallest possible allocation in bytes */
int nBlock; /* Number of szAtom sized blocks in zPool */
u8 *zPool; /* Memory available to be allocated */
-
+
/*
** Mutex to control access to the memory allocation subsystem.
*/
u32 maxOut; /* Maximum instantaneous currentOut */
u32 maxCount; /* Maximum instantaneous currentCount */
u32 maxRequest; /* Largest allocation (exclusive of internal frag) */
-
+
/*
** Lists of free blocks. aiFreelist[0] is a list of free blocks of
** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2.
/*
** Find the first entry on the freelist iLogsize. Unlink that
-** entry and return its index.
+** entry and return its index.
*/
static int memsys5UnlinkFirst(int iLogsize){
int i;
u32 size, iLogsize;
int iBlock;
- /* Set iBlock to the index of the block pointed to by pOld in
+ /* Set iBlock to the index of the block pointed to by pOld in
** the array of mem5.szAtom byte blocks pointed to by mem5.zPool.
*/
iBlock = ((u8 *)pOld-mem5.zPool)/mem5.szAtom;
p = memsys5MallocUnsafe(nBytes);
memsys5Leave();
}
- return (void*)p;
+ return (void*)p;
}
/*
assert( pPrior!=0 );
memsys5Enter();
memsys5FreeUnsafe(pPrior);
- memsys5Leave();
+ memsys5Leave();
}
/*
** Change the size of an existing memory allocation.
**
** The outer layer memory allocator prevents this routine from
-** being called with pPrior==0.
+** being called with pPrior==0.
**
** nBytes is always a value obtained from a prior call to
** memsys5Round(). Hence nBytes is always a non-negative power
#ifdef SQLITE_TEST
/*
-** Open the file indicated and write a log of all unfreed memory
+** Open the file indicated and write a log of all unfreed memory
** allocations into that log.
*/
SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){
#endif
/*
-** This routine is the only routine in this file with external
+** This routine is the only routine in this file with external
** linkage. It returns a pointer to a static sqlite3_mem_methods
** struct populated with the memsys5 methods.
*/
/*
** Initialize the mutex system.
*/
-SQLITE_PRIVATE int sqlite3MutexInit(void){
+SQLITE_PRIVATE int sqlite3MutexInit(void){
int rc = SQLITE_OK;
if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
/* If the xMutexAlloc method has not been set, then the user did not
- ** install a mutex implementation via sqlite3_config() prior to
+ ** install a mutex implementation via sqlite3_config() prior to
** sqlite3_initialize() being called. This block copies pointers to
** the default implementation into the sqlite3GlobalConfig structure.
*/
/*
** The sqlite3_mutex_leave() routine exits a mutex that was previously
-** entered by the same thread. The behavior is undefined if the mutex
+** entered by the same thread. The behavior is undefined if the mutex
** is not currently entered. If a NULL pointer is passed as an argument
** this function is a no-op.
*/
*/
static int noopMutexInit(void){ return SQLITE_OK; }
static int noopMutexEnd(void){ return SQLITE_OK; }
-static sqlite3_mutex *noopMutexAlloc(int id){
+static sqlite3_mutex *noopMutexAlloc(int id){
UNUSED_PARAMETER(id);
- return (sqlite3_mutex*)8;
+ return (sqlite3_mutex*)8;
}
static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
/*
** The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. If it returns NULL
-** that means that a mutex could not be allocated.
+** that means that a mutex could not be allocated.
*/
static sqlite3_mutex *debugMutexAlloc(int id){
static sqlite3_debug_mutex aStatic[6];
** there might be race conditions that can cause these routines to
** deliver incorrect results. In particular, if pthread_equal() is
** not an atomic operation, then these routines might delivery
-** incorrect results. On most platforms, pthread_equal() is a
+** incorrect results. On most platforms, pthread_equal() is a
** comparison of two integers and is therefore atomic. But we are
** told that HPUX is not such a platform. If so, then these routines
** will not always work correctly on HPUX.
**
** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
-** returns a different mutex on every call. But for the static
+** returns a different mutex on every call. But for the static
** mutex types, the same mutex is returned on every call that has
** the same type number.
*/
** is atomic - that it cannot be deceived into thinking self
** and p->owner are equal if p->owner changes between two values
** that are not equal to self while the comparison is taking place.
- ** This implementation also assumes a coherent cache - that
+ ** This implementation also assumes a coherent cache - that
** separate processes cannot read different values from the same
** address at the same time. If either of these two conditions
** are not met, then the mutexes will fail and problems will result.
** is atomic - that it cannot be deceived into thinking self
** and p->owner are equal if p->owner changes between two values
** that are not equal to self while the comparison is taking place.
- ** This implementation also assumes a coherent cache - that
+ ** This implementation also assumes a coherent cache - that
** separate processes cannot read different values from the same
** address at the same time. If either of these two conditions
** are not met, then the mutexes will fail and problems will result.
** the LockFileEx() API.
**
** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
-** which is only available if your application was compiled with
+** which is only available if your application was compiled with
** _WIN32_WINNT defined to a value >= 0x0400. Currently, the only
-** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef
+** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef
** this out as well.
*/
#if 0
return p->nRef==0 || p->owner!=tid;
}
static int winMutexNotheld(sqlite3_mutex *p){
- DWORD tid = GetCurrentThreadId();
+ DWORD tid = GetCurrentThreadId();
return winMutexNotheld2(p, tid);
}
#endif
SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
-static int winMutexInit(void){
+static int winMutexInit(void){
/* The first to increment to 1 does actual initialization */
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
int i;
sqlite3_win32_sleep(1);
}
}
- return SQLITE_OK;
+ return SQLITE_OK;
}
-static int winMutexEnd(void){
- /* The first to decrement to 0 does actual shutdown
+static int winMutexEnd(void){
+ /* The first to decrement to 0 does actual shutdown
** (which should be the last to shutdown.) */
if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
if( winMutex_isInit==1 ){
winMutex_isInit = 0;
}
}
- return SQLITE_OK;
+ return SQLITE_OK;
}
/*
**
** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
-** returns a different mutex on every call. But for the static
+** returns a different mutex on every call. But for the static
** mutex types, the same mutex is returned on every call that has
** the same type number.
*/
case SQLITE_MUTEX_FAST:
case SQLITE_MUTEX_RECURSIVE: {
p = sqlite3MallocZero( sizeof(*p) );
- if( p ){
+ if( p ){
#ifdef SQLITE_DEBUG
p->id = iType;
#endif
*/
static void winMutexEnter(sqlite3_mutex *p){
#ifdef SQLITE_DEBUG
- DWORD tid = GetCurrentThreadId();
+ DWORD tid = GetCurrentThreadId();
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
#endif
EnterCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
assert( p->nRef>0 || p->owner==0 );
- p->owner = tid;
+ p->owner = tid;
p->nRef++;
if( p->trace ){
printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
}
static int winMutexTry(sqlite3_mutex *p){
#ifndef NDEBUG
- DWORD tid = GetCurrentThreadId();
+ DWORD tid = GetCurrentThreadId();
#endif
int rc = SQLITE_BUSY;
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
/*
** The sqlite3_mutex_try() routine is very rarely used, and when it
** is used it is merely an optimization. So it is OK for it to always
- ** fail.
+ ** fail.
**
** The TryEnterCriticalSection() interface is only available on WinNT.
** And some windows compilers complain if you try to use it without
** limit.
*/
static void softHeapLimitEnforcer(
- void *NotUsed,
+ void *NotUsed,
sqlite3_int64 NotUsed2,
int allocSize
){
#endif
/*
-** Set the soft heap-size limit for the library. Passing a zero or
+** Set the soft heap-size limit for the library. Passing a zero or
** negative value indicates no limit.
*/
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
}
/*
-** Trigger the alarm
+** Trigger the alarm
*/
static void sqlite3MallocAlarm(int nByte){
void (*xCallback)(void*,sqlite3_int64,int);
*/
SQLITE_PRIVATE void *sqlite3Malloc(int n){
void *p;
- if( n<=0 /* IMP: R-65312-04917 */
+ if( n<=0 /* IMP: R-65312-04917 */
|| n>=0x7fffff00
){
/* A memory allocation of a number of bytes which is near the maximum
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
nDiff = nNew - nOld;
- if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
+ if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nDiff);
}
/*
** Allocate and zero memory.
-*/
+*/
SQLITE_PRIVATE void *sqlite3MallocZero(int n){
void *p = sqlite3Malloc(n);
if( p ){
sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
db->mallocFailed = 1;
}
- sqlite3MemdebugSetType(pNew, MEMTYPE_DB |
+ sqlite3MemdebugSetType(pNew, MEMTYPE_DB |
(db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
}
}
}
/*
-** Make a copy of a string in memory obtained from sqliteMalloc(). These
+** Make a copy of a string in memory obtained from sqliteMalloc(). These
** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This
-** is because when memory debugging is turned on, these two functions are
+** is because when memory debugging is turned on, these two functions are
** called via macros that record the current file and line number in the
** ThreadData structure.
*/
/*
-** This function must be called before exiting any API function (i.e.
+** This function must be called before exiting any API function (i.e.
** returning control to the user) that has called sqlite3_malloc or
** sqlite3_realloc.
**
** The returned value is normally a copy of the second argument to this
** function. However, if a malloc() failure has occurred since the previous
-** invocation SQLITE_NOMEM is returned instead.
+** invocation SQLITE_NOMEM is returned instead.
**
** If the first argument, db, is not NULL and a malloc() error has occurred,
** then the connection error-code (the value returned by sqlite3_errcode())
*/
SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
/* If the db handle is not NULL, then we must hold the connection handle
- ** mutex here. Otherwise the read (and possible write) of db->mallocFailed
+ ** mutex here. Otherwise the read (and possible write) of db->mallocFailed
** is unsafe, as is the call to sqlite3Error().
*/
assert( !db || sqlite3_mutex_held(db->mutex) );
break;
}
/* Find out what flags are present */
- flag_leftjustify = flag_plussign = flag_blanksign =
+ flag_leftjustify = flag_plussign = flag_blanksign =
flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
do{
** May you share freely, never taking more than you give.
**
*************************************************************************
-** This file contains routines used to translate between UTF-8,
+** This file contains routines used to translate between UTF-8,
** UTF-16, UTF-16BE, and UTF-16LE.
**
** Notes on UTF-8:
/*
** If the TRANSLATE_TRACE macro is defined, the value of each Mem is
** printed on stderr on the way into and out of sqlite3VdbeMemTranslate().
-*/
+*/
/* #define TRANSLATE_TRACE 1 */
#ifndef SQLITE_OMIT_UTF16
}
#endif
- /* If the translation is between UTF-16 little and big endian, then
+ /* If the translation is between UTF-16 little and big endian, then
** all that is required is to swap the byte order. This case is handled
** differently from the others.
*/
if( pMem->enc==SQLITE_UTF16LE ){
/* UTF-16 Little-endian -> UTF-8 */
while( zIn<zTerm ){
- READ_UTF16LE(zIn, zIn<zTerm, c);
+ READ_UTF16LE(zIn, zIn<zTerm, c);
WRITE_UTF8(z, c);
}
}else{
/* UTF-16 Big-endian -> UTF-8 */
while( zIn<zTerm ){
- READ_UTF16BE(zIn, zIn<zTerm, c);
+ READ_UTF16BE(zIn, zIn<zTerm, c);
WRITE_UTF8(z, c);
}
}
}
/*
-** This routine checks for a byte-order mark at the beginning of the
+** This routine checks for a byte-order mark at the beginning of the
** UTF-16 string stored in *pMem. If one is present, it is removed and
** the encoding of the Mem adjusted. This routine does not do any
** byte-swapping, it just sets Mem.enc appropriately.
bom = SQLITE_UTF16LE;
}
}
-
+
if( bom ){
rc = sqlite3VdbeMemMakeWriteable(pMem);
if( rc==SQLITE_OK ){
** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
** return the number of unicode characters in pZ up to (but not including)
** the first 0x00 byte. If nByte is not less than zero, return the
-** number of unicode characters in the first nByte of pZ (or up to
+** number of unicode characters in the first nByte of pZ (or up to
** the first 0x00, whichever comes first).
*/
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){
return r;
}
-/* This test function is not currently used by the automated test-suite.
+/* This test function is not currently used by the automated test-suite.
** Hence it is only available in debug builds.
*/
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
** is set to the length of the returned string in bytes. The call should
** arrange to call sqlite3DbFree() on the returned pointer when it is
** no longer required.
-**
+**
** If a malloc failure occurs, NULL is returned and the db.mallocFailed
** flag set.
*/
int c;
unsigned char const *z = zIn;
int n = 0;
-
+
if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
while( n<nChar ){
READ_UTF16BE(z, 1, c);
**
** This option [-ffast-math] should never be turned on by any
** -O option since it can result in incorrect output for programs
- ** which depend on an exact implementation of IEEE or ISO
+ ** which depend on an exact implementation of IEEE or ISO
** rules/specifications for math functions.
**
** Under MSVC, this NaN test may fail if compiled with a floating-
- ** point precision mode other than /fp:precise. From the MSDN
+ ** point precision mode other than /fp:precise. From the MSDN
** documentation:
**
- ** The compiler [with /fp:precise] will properly handle comparisons
- ** involving NaN. For example, x != x evaluates to true if x is NaN
+ ** The compiler [with /fp:precise] will properly handle comparisons
+ ** involving NaN. For example, x != x evaluates to true if x is NaN
** ...
*/
#ifdef __FAST_MATH__
result = 1e308*1e308*s; /* Infinity */
}
}else{
- /* 1.0e+22 is the largest power of 10 than can be
+ /* 1.0e+22 is the largest power of 10 than can be
** represented exactly. */
while( e%22 ) { scale *= 1.0e+1; e -= 1; }
while( e>0 ) { scale *= 1.0e+22; e -= 22; }
/*
** Convert zNum to a 64-bit signed integer.
**
-** If the zNum value is representable as a 64-bit twos-complement
+** If the zNum value is representable as a 64-bit twos-complement
** integer, then write that value into *pNum and return 0.
**
** If zNum is exactly 9223372036854665808, return 2. This special
-** case is broken out because while 9223372036854665808 cannot be a
+** case is broken out because while 9223372036854665808 cannot be a
** signed 64-bit integer, its negative -9223372036854665808 can be.
**
** If zNum is too big for a 64-bit integer and is not
v >>= 7;
}
return 9;
- }
+ }
n = 0;
do{
buf[n++] = (u8)((v & 0x7f) | 0x80);
** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned
** integer, then set *v to 0xffffffff.
**
-** A MACRO version, getVarint32, is provided which inlines the
-** single-byte case. All code should use the MACRO version as
+** A MACRO version, getVarint32, is provided which inlines the
+** single-byte case. All code should use the MACRO version as
** this function assumes the single-byte case has already been handled.
*/
SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
** argument. The zType is a word like "NULL" or "closed" or "invalid".
*/
static void logBadConnection(const char *zType){
- sqlite3_log(SQLITE_MISUSE,
+ sqlite3_log(SQLITE_MISUSE,
"API call with %s database connection pointer",
zType
);
if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
*pA += iB;
}
- return 0;
+ return 0;
}
SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
testcase( iB==SMALLEST_INT64+1 );
}
/*
-** Compute the absolute value of a 32-bit signed integer, of possible. Or
+** Compute the absolute value of a 32-bit signed integer, of possible. Or
** if the integer has a value of -2147483648, return +2147483647
*/
SQLITE_PRIVATE int sqlite3AbsInt32(int x){
/* The inability to allocates space for a larger hash table is
** a performance hit but it is not a fatal error. So mark the
- ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of
+ ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of
** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero()
** only zeroes the requested number of bytes whereas this module will
** use the actual amount of space allocated for the hash table (which
count = pH->count;
}
while( count-- && ALWAYS(elem) ){
- if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
+ if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
return elem;
}
elem = elem->next;
){
struct _ht *pEntry;
if( elem->prev ){
- elem->prev->next = elem->next;
+ elem->prev->next = elem->next;
}else{
pH->first = elem->next;
}
** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE
** is defined to 1. The SQLITE_ENABLE_LOCKING_STYLE also enables automatic
** selection of the appropriate locking style based on the filesystem
-** where the database is located.
+** where the database is located.
*/
#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
# if defined(__APPLE__)
#endif
/*
-** Define the OS_VXWORKS pre-processor macro to 1 if building on
+** Define the OS_VXWORKS pre-processor macro to 1 if building on
** vxworks, or 0 otherwise.
*/
#ifndef OS_VXWORKS
#define MAX_PATHNAME 512
/*
-** Only set the lastErrno if the error code is a real error and not
+** Only set the lastErrno if the error code is a real error and not
** a normal expected return code of SQLITE_BUSY or SQLITE_OK
*/
#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))
** whenever any part of the database changes. An assertion fault will
** occur if a file is updated without also updating the transaction
** counter. This test is made to avoid new problems similar to the
- ** one described by ticket #3584.
+ ** one described by ticket #3584.
*/
unsigned char transCntrChng; /* True if the transaction counter changed */
unsigned char dbUpdate; /* True if any part of database file changed */
#endif
#ifdef SQLITE_TEST
- /* In test mode, increase the size of this structure a bit so that
+ /* In test mode, increase the size of this structure a bit so that
** it is larger than the struct CrashFile defined in test6.c.
*/
char aPadding[32];
*/
#ifdef SQLITE_PERFORMANCE_TRACE
-/*
-** hwtime.h contains inline assembler code for implementing
+/*
+** hwtime.h contains inline assembler code for implementing
** high-performance timing routines.
*/
/************** Include hwtime.h in the middle of os_common.h ****************/
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
}
-
+
#elif (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
#ifdef __DJGPP__
{ "fstat", 0, 0 },
#define osFstat(a,b,c) 0
-#else
+#else
{ "fstat", (sqlite3_syscall_ptr)fstat, 0 },
#define osFstat ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
#endif
if( fd>=0 ){
if( m!=0 ){
struct stat statbuf;
- if( osFstat(fd, &statbuf)==0
+ if( osFstat(fd, &statbuf)==0
&& statbuf.st_size==0
- && (statbuf.st_mode&0777)!=m
+ && (statbuf.st_mode&0777)!=m
){
osFchmod(fd, m);
}
/*
** Helper functions to obtain and relinquish the global mutex. The
** global mutex is used to protect the unixInodeInfo and
-** vxworksFileId objects used by this file, all of which may be
+** vxworksFileId objects used by this file, all of which may be
** shared by multiple threads.
**
-** Function unixMutexHeld() is used to assert() that the global mutex
-** is held when required. This function is only used as part of assert()
+** Function unixMutexHeld() is used to assert() that the global mutex
+** is held when required. This function is only used as part of assert()
** statements. e.g.
**
** unixEnterMutex()
** This routine translates a standard POSIX errno code into something
** useful to the clients of the sqlite3 functions. Specifically, it is
** intended to translate a variety of "try again" errors into SQLITE_BUSY
-** and a variety of "please close the file descriptor NOW" errors into
+** and a variety of "please close the file descriptor NOW" errors into
** SQLITE_IOERR
-**
+**
** Errors during initialization of locks, or file system support for locks,
** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
*/
** propagated back to the caller. Commenting this branch out means errno==0
** will be handled by the "default:" case below.
*/
- case 0:
+ case 0:
return SQLITE_OK;
#endif
case ETIMEDOUT:
case EBUSY:
case EINTR:
- case ENOLCK:
- /* random NFS retry error, unless during file system support
+ case ENOLCK:
+ /* random NFS retry error, unless during file system support
* introspection, in which it actually means what it says */
return SQLITE_BUSY;
-
- case EACCES:
+
+ case EACCES:
/* EACCES is like EAGAIN during locking operations, but not any other time*/
- if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
- (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
+ if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
return SQLITE_BUSY;
}
/* else fall through */
- case EPERM:
+ case EPERM:
return SQLITE_PERM;
-
+
/* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
- ** this module never makes such a call. And the code in SQLite itself
+ ** this module never makes such a call. And the code in SQLite itself
** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
** this case is also commented out. If the system does set errno to EDEADLK,
** the default SQLITE_IOERR_XXX code will be returned. */
case EDEADLK:
return SQLITE_IOERR_BLOCKED;
#endif
-
+
#if EOPNOTSUPP!=ENOTSUP
- case EOPNOTSUPP:
- /* something went terribly awry, unless during file system support
+ case EOPNOTSUPP:
+ /* something went terribly awry, unless during file system support
* introspection, in which it actually means what it says */
#endif
#ifdef ENOTSUP
- case ENOTSUP:
- /* invalid fd, unless during file system support introspection, in which
+ case ENOTSUP:
+ /* invalid fd, unless during file system support introspection, in which
* it actually means what it says */
#endif
case EIO:
#endif
case ENOSYS:
/* these should force the client to close the file and reconnect */
-
- default:
+
+ default:
return sqliteIOErr;
}
}
**
** A pointer to an instance of the following structure can be used as a
** unique file ID in VxWorks. Each instance of this structure contains
-** a copy of the canonical filename. There is also a reference count.
+** a copy of the canonical filename. There is also a reference count.
** The structure is reclaimed when the number of pointers to it drops to
** zero.
**
};
#if OS_VXWORKS
-/*
+/*
** All unique filenames are held on a linked list headed by this
** variable:
*/
*/
unixEnterMutex();
for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
- if( pCandidate->nName==n
+ if( pCandidate->nName==n
&& memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
){
sqlite3_free(pNew);
** cnt>0 means there are cnt shared locks on the file.
**
** Any attempt to lock or unlock a file first checks the locking
-** structure. The fcntl() system call is only invoked to set a
+** structure. The fcntl() system call is only invoked to set a
** POSIX lock if the internal lock structure transitions between
** a locked and an unlocked state.
**
**
** SQLite used to support LinuxThreads. But support for LinuxThreads
** was dropped beginning with version 3.7.0. SQLite will still work with
-** LinuxThreads provided that (1) there is no more than one connection
+** LinuxThreads provided that (1) there is no more than one connection
** per database file in the same process and (2) database connections
** do not move across threads.
*/
** strerror_r().
**
** The first argument passed to the macro should be the error code that
-** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
+** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
** The two subsequent arguments should be the name of the OS function that
** failed (e.g. "unlink", "open") and the associated file-system path,
** if any.
/* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
** the strerror() function to obtain the human-readable error message
** equivalent to errno. Otherwise, use strerror_r().
- */
+ */
#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
char aErr[80];
memset(aErr, 0, sizeof(aErr));
/* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
** assume that the system provides the GNU version of strerror_r() that
- ** returns a pointer to a buffer containing the error message. That pointer
- ** may point to aErr[], or it may point to some static storage somewhere.
- ** Otherwise, assume that the system provides the POSIX version of
+ ** returns a pointer to a buffer containing the error message. That pointer
+ ** may point to aErr[], or it may point to some static storage somewhere.
+ ** Otherwise, assume that the system provides the POSIX version of
** strerror_r(), which always writes an error message into aErr[].
**
** If the code incorrectly assumes that it is the POSIX version that is
** available, the error message will often be an empty string. Not a
- ** huge problem. Incorrectly concluding that the GNU version is available
+ ** huge problem. Incorrectly concluding that the GNU version is available
** could lead to a segfault though.
*/
#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
- zErr =
+ zErr =
# endif
strerror_r(iErrno, aErr, sizeof(aErr)-1);
/*
** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
-*/
+*/
static void closePendingFds(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
UnixUnusedFd *p;
}
}
#endif
-
+
unixLeaveMutex();
OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
}
/*
-** Attempt to set a system-lock on the file pFile. The lock is
+** Attempt to set a system-lock on the file pFile. The lock is
** described by pLock.
**
** If the pFile was opened read/write from unix-excl, then the only lock
**
** A process may only obtain a RESERVED lock after it has a SHARED lock.
** A RESERVED lock is implemented by grabbing a write-lock on the
- ** 'reserved byte'.
+ ** 'reserved byte'.
**
** A process may only obtain a PENDING lock after it has obtained a
** SHARED lock. A PENDING lock is implemented by obtaining a write-lock
** implemented by obtaining a write-lock on the entire 'shared byte
** range'. Since all other locks require a read-lock on one of the bytes
** within this range, this ensures that no other locks are held on the
- ** database.
+ ** database.
**
** The reason a single byte cannot be used instead of the 'shared byte
** range' is that some versions of windows do not support read-locks. By
/* If some thread using this PID has a lock via a different unixFile*
** handle that precludes the requested lock, return BUSY.
*/
- if( (pFile->eFileLock!=pInode->eFileLock &&
+ if( (pFile->eFileLock!=pInode->eFileLock &&
(pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
){
rc = SQLITE_BUSY;
** has a SHARED or RESERVED lock, then increment reference counts and
** return SQLITE_OK.
*/
- if( eFileLock==SHARED_LOCK &&
+ if( eFileLock==SHARED_LOCK &&
(pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
assert( eFileLock==SHARED_LOCK );
assert( pFile->eFileLock==0 );
*/
lock.l_len = 1L;
lock.l_whence = SEEK_SET;
- if( eFileLock==SHARED_LOCK
+ if( eFileLock==SHARED_LOCK
|| (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
){
lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
/* This could happen with a network mount */
tErrno = errno;
- rc = SQLITE_IOERR_UNLOCK;
+ rc = SQLITE_IOERR_UNLOCK;
}
if( rc ){
}
}
}
-
+
#ifdef SQLITE_DEBUG
/* Set up the transaction-counter change checking flags when
end_lock:
unixLeaveMutex();
- OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
+ OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
rc==SQLITE_OK ? "ok" : "failed"));
return rc;
}
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
-**
+**
** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
** the byte range is divided into 2 parts and the first part is unlocked then
-** set to a read lock, then the other part is simply unlocked. This works
-** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to
+** set to a read lock, then the other part is simply unlocked. This works
+** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to
** remove the write lock on a region when a read lock is set.
*/
static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
/* downgrading to a shared lock on NFS involves clearing the write lock
** before establishing the readlock - to avoid a race condition we downgrade
- ** the lock in 2 blocks, so that part of the range will be covered by a
+ ** the lock in 2 blocks, so that part of the range will be covered by a
** write lock until the rest is covered by a read lock:
** 1: [WWWWW]
** 2: [....W]
if( handleNFSUnlock ){
int tErrno; /* Error code from system call errors */
off_t divSize = SHARED_SIZE - 1;
-
+
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
if( unixFileLock(pFile, &lock) ){
/* In theory, the call to unixFileLock() cannot fail because another
- ** process is holding an incompatible lock. If it does, this
+ ** process is holding an incompatible lock. If it does, this
** indicates that the other process is not following the locking
** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
- ** SQLITE_BUSY would confuse the upper layer (in practice it causes
- ** an assert to fail). */
+ ** SQLITE_BUSY would confuse the upper layer (in practice it causes
+ ** an assert to fail). */
rc = SQLITE_IOERR_RDLOCK;
pFile->lastErrno = errno;
goto end_unlock;
static void unixUnmapfile(unixFile *pFd);
/*
-** This function performs the parts of the "close file" operation
+** This function performs the parts of the "close file" operation
** common to all locking schemes. It closes the directory and file
** handles, if they are valid, and sets all fields of the unixFile
** structure to 0.
if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
/* If there are outstanding locks, do not actually close the file just
** yet because that would clear those locks. Instead, add the file
- ** descriptor to pInode->pUnused list. It will be automatically closed
+ ** descriptor to pInode->pUnused list. It will be automatically closed
** when the last lock is cleared.
*/
setPendingFd(pFile);
unixFile *pFile = (unixFile*)id;
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
+
assert( pFile );
/* Check if a thread in this process holds such a lock */
#endif
return SQLITE_OK;
}
-
+
/* grab an exclusive lock */
rc = osMkdir(zLockFile, 0777);
if( rc<0 ){
}
}
return rc;
- }
-
+ }
+
/* got it, set the type and return ok */
pFile->eFileLock = eFileLock;
return rc;
OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
pFile->eFileLock, getpid()));
assert( eFileLock<=SHARED_LOCK );
-
+
/* no-op if possible */
if( pFile->eFileLock==eFileLock ){
return SQLITE_OK;
pFile->eFileLock = SHARED_LOCK;
return SQLITE_OK;
}
-
+
/* To fully unlock the database, delete the lock file */
assert( eFileLock==NO_LOCK );
rc = osRmdir(zLockFile);
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
- return rc;
+ return rc;
}
pFile->eFileLock = NO_LOCK;
return SQLITE_OK;
#else
# define robust_flock(a,b) flock(a,b)
#endif
-
+
/*
** This routine checks if there is a RESERVED lock held on the specified
int rc = SQLITE_OK;
int reserved = 0;
unixFile *pFile = (unixFile*)id;
-
+
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
+
assert( pFile );
-
+
/* Check if a thread in this process holds such a lock */
if( pFile->eFileLock>SHARED_LOCK ){
reserved = 1;
}
-
+
/* Otherwise see if some other process holds it. */
if( !reserved ){
/* attempt to get the lock */
if ( lrc ) {
int tErrno = errno;
/* unlock failed with an error */
- lrc = SQLITE_IOERR_UNLOCK;
+ lrc = SQLITE_IOERR_UNLOCK;
if( IS_LOCK_ERROR(lrc) ){
pFile->lastErrno = tErrno;
rc = lrc;
int tErrno = errno;
reserved = 1;
/* someone else might have it reserved */
- lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
if( IS_LOCK_ERROR(lrc) ){
pFile->lastErrno = tErrno;
rc = lrc;
assert( pFile );
- /* if we already have a lock, it is exclusive.
+ /* if we already have a lock, it is exclusive.
** Just adjust level and punt on outta here. */
if (pFile->eFileLock > NO_LOCK) {
pFile->eFileLock = eFileLock;
return SQLITE_OK;
}
-
+
/* grab an exclusive lock */
-
+
if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
int tErrno = errno;
/* didn't get, must be busy */
/* got it, set the type and return ok */
pFile->eFileLock = eFileLock;
}
- OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
+ OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
rc==SQLITE_OK ? "ok" : "failed"));
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
*/
static int flockUnlock(sqlite3_file *id, int eFileLock) {
unixFile *pFile = (unixFile*)id;
-
+
assert( pFile );
OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
pFile->eFileLock, getpid()));
assert( eFileLock<=SHARED_LOCK );
-
+
/* no-op if possible */
if( pFile->eFileLock==eFileLock ){
return SQLITE_OK;
}
-
+
/* shared can just be set because we always have an exclusive */
if (eFileLock==SHARED_LOCK) {
pFile->eFileLock = eFileLock;
return SQLITE_OK;
}
-
+
/* no, really, unlock. */
if( robust_flock(pFile->h, LOCK_UN) ){
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
unixFile *pFile = (unixFile*)id;
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
+
assert( pFile );
/* Check if a thread in this process holds such a lock */
if( pFile->eFileLock>SHARED_LOCK ){
reserved = 1;
}
-
+
/* Otherwise see if some other process holds it. */
if( !reserved ){
sem_t *pSem = pFile->pInode->pSem;
sem_t *pSem = pFile->pInode->pSem;
int rc = SQLITE_OK;
- /* if we already have a lock, it is exclusive.
+ /* if we already have a lock, it is exclusive.
** Just adjust level and punt on outta here. */
if (pFile->eFileLock > NO_LOCK) {
pFile->eFileLock = eFileLock;
rc = SQLITE_OK;
goto sem_end_lock;
}
-
+
/* lock semaphore now but bail out when already locked. */
if( sem_trywait(pSem)==-1 ){
rc = SQLITE_BUSY;
OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
pFile->eFileLock, getpid()));
assert( eFileLock<=SHARED_LOCK );
-
+
/* no-op if possible */
if( pFile->eFileLock==eFileLock ){
return SQLITE_OK;
}
-
+
/* shared can just be set because we always have an exclusive */
if (eFileLock==SHARED_LOCK) {
pFile->eFileLock = eFileLock;
return SQLITE_OK;
}
-
+
/* no, really unlock. */
if ( sem_post(pSem)==-1 ) {
int rc, tErrno = errno;
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
- return rc;
+ return rc;
}
pFile->eFileLock = NO_LOCK;
return SQLITE_OK;
/*
** This is a utility for setting or clearing a bit-range lock on an
** AFP filesystem.
-**
+**
** Return SQLITE_OK on success, SQLITE_BUSY on failure.
*/
static int afpSetLock(
){
struct ByteRangeLockPB2 pb;
int err;
-
+
pb.unLockFlag = setLockFlag ? 0 : 1;
pb.startEndFlag = 0;
pb.offset = offset;
- pb.length = length;
+ pb.length = length;
pb.fd = pFile->h;
-
- OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n",
+
+ OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n",
(setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
offset, length));
err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
int reserved = 0;
unixFile *pFile = (unixFile*)id;
afpLockingContext *context;
-
+
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
+
assert( pFile );
context = (afpLockingContext *) pFile->lockingContext;
if( context->reserved ){
return SQLITE_OK;
}
unixEnterMutex(); /* Because pFile->pInode is shared across threads */
-
+
/* Check if a thread in this process holds such a lock */
if( pFile->pInode->eFileLock>SHARED_LOCK ){
reserved = 1;
}
-
+
/* Otherwise see if some other process holds it.
*/
if( !reserved ){
/* lock the RESERVED byte */
- int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
+ int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
if( SQLITE_OK==lrc ){
/* if we succeeded in taking the reserved lock, unlock it to restore
** the original state */
rc=lrc;
}
}
-
+
unixLeaveMutex();
OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
-
+
*pResOut = reserved;
return rc;
}
unixFile *pFile = (unixFile*)id;
unixInodeInfo *pInode = pFile->pInode;
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
-
+
assert( pFile );
OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
azFileLock(eFileLock), azFileLock(pFile->eFileLock),
assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
assert( eFileLock!=PENDING_LOCK );
assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
-
+
/* This mutex is needed because pFile->pInode is shared across threads
*/
unixEnterMutex();
/* If some thread using this PID has a lock via a different unixFile*
** handle that precludes the requested lock, return BUSY.
*/
- if( (pFile->eFileLock!=pInode->eFileLock &&
+ if( (pFile->eFileLock!=pInode->eFileLock &&
(pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
){
rc = SQLITE_BUSY;
goto afp_end_lock;
}
-
+
/* If a SHARED lock is requested, and some thread using this PID already
** has a SHARED or RESERVED lock, then increment reference counts and
** return SQLITE_OK.
*/
- if( eFileLock==SHARED_LOCK &&
+ if( eFileLock==SHARED_LOCK &&
(pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
assert( eFileLock==SHARED_LOCK );
assert( pFile->eFileLock==0 );
pInode->nLock++;
goto afp_end_lock;
}
-
+
/* A PENDING lock is needed before acquiring a SHARED lock and before
** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
** be released.
*/
- if( eFileLock==SHARED_LOCK
+ if( eFileLock==SHARED_LOCK
|| (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
){
int failed;
goto afp_end_lock;
}
}
-
+
/* If control gets to this point, then actually go ahead and make
** operating system calls for the specified lock.
*/
if( eFileLock==SHARED_LOCK ){
int lrc1, lrc2, lrc1Errno = 0;
long lk, mask;
-
+
assert( pInode->nShared==0 );
assert( pInode->eFileLock==0 );
-
+
mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
/* Now get the read-lock SHARED_LOCK */
/* note that the quality of the randomness doesn't matter that much */
- lk = random();
+ lk = random();
pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
- lrc1 = afpSetLock(context->dbPath, pFile,
+ lrc1 = afpSetLock(context->dbPath, pFile,
SHARED_FIRST+pInode->sharedByte, 1, 1);
if( IS_LOCK_ERROR(lrc1) ){
lrc1Errno = pFile->lastErrno;
}
/* Drop the temporary PENDING lock */
lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
-
+
if( IS_LOCK_ERROR(lrc1) ) {
pFile->lastErrno = lrc1Errno;
rc = lrc1;
}
if (!failed && eFileLock == EXCLUSIVE_LOCK) {
/* Acquire an EXCLUSIVE lock */
-
- /* Remove the shared lock before trying the range. we'll need to
+
+ /* Remove the shared lock before trying the range. we'll need to
** reestablish the shared lock if we can't get the afpUnlock
*/
if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
pInode->sharedByte, 1, 0)) ){
int failed2 = SQLITE_OK;
/* now attemmpt to get the exclusive lock range */
- failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
+ failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
SHARED_SIZE, 1);
- if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
+ if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
/* Can't reestablish the shared lock. Sqlite can't deal, this is
** a critical I/O error
*/
- rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 :
+ rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 :
SQLITE_IOERR_LOCK;
goto afp_end_lock;
- }
+ }
}else{
- rc = failed;
+ rc = failed;
}
}
if( failed ){
rc = failed;
}
}
-
+
if( rc==SQLITE_OK ){
pFile->eFileLock = eFileLock;
pInode->eFileLock = eFileLock;
pFile->eFileLock = PENDING_LOCK;
pInode->eFileLock = PENDING_LOCK;
}
-
+
afp_end_lock:
unixLeaveMutex();
- OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
+ OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
rc==SQLITE_OK ? "ok" : "failed"));
return rc;
}
SimulateIOErrorBenign(1);
SimulateIOError( h=(-1) )
SimulateIOErrorBenign(0);
-
+
#ifdef SQLITE_DEBUG
/* When reducing a lock such that other processes can start
** reading the database file again, make sure that the
|| pFile->transCntrChng==1 );
pFile->inNormalWrite = 0;
#endif
-
+
if( pFile->eFileLock==EXCLUSIVE_LOCK ){
rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){
}
if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){
rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
- }
+ }
if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){
rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
- if( !rc ){
- context->reserved = 0;
+ if( !rc ){
+ context->reserved = 0;
}
}
if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){
}
}
}
-
+
unixLeaveMutex();
if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
return rc;
}
/*
-** Close a file & cleanup AFP specific locking context
+** Close a file & cleanup AFP specific locking context
*/
static int afpClose(sqlite3_file *id) {
int rc = SQLITE_OK;
/*
** The code above is the NFS lock implementation. The code is specific
** to MacOSX and does not work on other unix platforms. No alternative
-** is available.
+** is available.
**
********************* End of the NFS lock implementation **********************
******************************************************************************/
/******************************************************************************
**************** Non-locking sqlite3_file methods *****************************
**
-** The next division contains implementations for all methods of the
+** The next division contains implementations for all methods of the
** sqlite3_file object other than the locking methods. The locking
** methods were defined in divisions above (one locking method per
** division). Those methods that are common to all locking modes
*/
/*
-** Seek to the offset passed as the second argument, then read cnt
+** Seek to the offset passed as the second argument, then read cnt
** bytes into pBuf. Return the number of bytes actually read.
**
** NB: If you define USE_PREAD or USE_PREAD64, then it might also
** wrong.
*/
static int unixRead(
- sqlite3_file *id,
- void *pBuf,
+ sqlite3_file *id,
+ void *pBuf,
int amt,
sqlite3_int64 offset
){
#if 0
assert( pFile->pUnused==0
|| offset>=PENDING_BYTE+512
- || offset+amt<=PENDING_BYTE
+ || offset+amt<=PENDING_BYTE
);
#endif
/*
** Attempt to seek the file-descriptor passed as the first argument to
** absolute offset iOff, then attempt to write nBuf bytes of data from
-** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise,
+** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise,
** return the actual number of bytes written (which may be less than
** nBuf).
*/
** or some other error code on failure.
*/
static int unixWrite(
- sqlite3_file *id,
- const void *pBuf,
+ sqlite3_file *id,
+ const void *pBuf,
int amt,
- sqlite3_int64 offset
+ sqlite3_int64 offset
){
unixFile *pFile = (unixFile*)id;
int wrote = 0;
#if 0
assert( pFile->pUnused==0
|| offset>=PENDING_BYTE+512
- || offset+amt<=PENDING_BYTE
+ || offset+amt<=PENDING_BYTE
);
#endif
**
** SQLite sets the dataOnly flag if the size of the file is unchanged.
** The idea behind dataOnly is that it should only write the file content
-** to disk, not the inode. We only set dataOnly if the file size is
-** unchanged since the file size is part of the inode. However,
+** to disk, not the inode. We only set dataOnly if the file size is
+** unchanged since the file size is part of the inode. However,
** Ted Ts'o tells us that fdatasync() will also write the inode if the
** file size has changed. The only real difference between fdatasync()
** and fsync(), Ted tells us, is that fdatasync() will not flush the
int rc;
/* The following "ifdef/elif/else/" block has the same structure as
- ** the one below. It is replicated here solely to avoid cluttering
+ ** the one below. It is replicated here solely to avoid cluttering
** up the real code with the UNUSED_PARAMETER() macros.
*/
#ifdef SQLITE_NO_SYNC
UNUSED_PARAMETER(dataOnly);
#endif
- /* Record the number of times that we do a normal fsync() and
+ /* Record the number of times that we do a normal fsync() and
** FULLSYNC. This is used during testing to verify that this procedure
** gets called with the correct arguments.
*/
rc = 1;
}
/* If the FULLFSYNC failed, fall back to attempting an fsync().
- ** It shouldn't be possible for fullfsync to fail on the local
+ ** It shouldn't be possible for fullfsync to fail on the local
** file system (on OSX), so failure indicates that FULLFSYNC
- ** isn't supported for this file system. So, attempt an fsync
- ** and (for now) ignore the overhead of a superfluous fcntl call.
- ** It'd be better to detect fullfsync support once and avoid
+ ** isn't supported for this file system. So, attempt an fsync
+ ** and (for now) ignore the overhead of a superfluous fcntl call.
+ ** It'd be better to detect fullfsync support once and avoid
** the fcntl call every time sync is called.
*/
if( rc ) rc = fsync(fd);
** so currently we default to the macro that redefines fdatasync to fsync
*/
rc = fsync(fd);
-#else
+#else
rc = fdatasync(fd);
#if OS_VXWORKS
if( rc==-1 && errno==ENOTSUP ){
/* If the file was just truncated to a size smaller than the currently
** mapped region, reduce the effective mapping size as well. SQLite will
- ** use read() and write() to access data beyond this point from now on.
+ ** use read() and write() to access data beyond this point from now on.
*/
if( nByte<pFile->mmapSize ){
pFile->mmapSize = nByte;
static int proxyFileControl(sqlite3_file*,int,void*);
#endif
-/*
-** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
+/*
+** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
** file-control operation. Enlarge the database to nBytes in size
** (rounded up to the next chunk-size). If the database is already
** nBytes or larger, this routine is a no-op.
if( pFile->szChunk>0 ){
i64 nSize; /* Required file size */
struct stat buf; /* Used to hold return values of fstat() */
-
+
if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
if( nSize>(i64)buf.st_size ){
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
- /* The code below is handling the return value of osFallocate()
- ** correctly. posix_fallocate() is defined to "returns zero on success,
+ /* The code below is handling the return value of osFallocate()
+ ** correctly. posix_fallocate() is defined to "returns zero on success,
** or an error number on failure". See the manpage for details. */
int err;
do{
** a database and its journal file) that the sector size will be the
** same for both.
*/
-#ifndef __QNXNTO__
+#ifndef __QNXNTO__
static int unixSectorSize(sqlite3_file *NotUsed){
UNUSED_PARAMETER(NotUsed);
return SQLITE_DEFAULT_SECTOR_SIZE;
unixFile *pFile = (unixFile*)id;
if( pFile->sectorSize == 0 ){
struct statvfs fsInfo;
-
+
/* Set defaults for non-supported filesystems */
pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
pFile->deviceCharacteristics = 0;
/*
-** Object used to represent an shared memory buffer.
+** Object used to represent an shared memory buffer.
**
** When multiple threads all reference the same wal-index, each thread
** has its own unixShm object, but they all point to a single instance
** nRef
**
** The following fields are read-only after the object is created:
-**
+**
** fid
** zFilename
**
}
#endif
- return rc;
+ return rc;
}
}
/*
-** Open a shared-memory area associated with open database file pDbFd.
+** Open a shared-memory area associated with open database file pDbFd.
** This particular implementation uses mmapped files.
**
** The file used to implement shared-memory is in the same directory
** as the open database file and has the same name as the open database
** file with the "-shm" suffix added. For example, if the database file
** is "/home/user1/config.db" then the file that is created and mmapped
-** for shared memory will be called "/home/user1/config.db-shm".
+** for shared memory will be called "/home/user1/config.db-shm".
**
** Another approach to is to use files in /dev/shm or /dev/tmp or an
** some other tmpfs mount. But if a file in a different directory
** from the database file is used, then differing access permissions
** or a chroot() might cause two different processes on the same
-** database to end up using different files for shared memory -
+** database to end up using different files for shared memory -
** meaning that their memory would not really be shared - resulting
** in database corruption. Nevertheless, this tmpfs file usage
** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm"
memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename);
zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1];
#ifdef SQLITE_SHM_DIRECTORY
- sqlite3_snprintf(nShmFilename, zShmFilename,
+ sqlite3_snprintf(nShmFilename, zShmFilename,
SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
(u32)sStat.st_ino, (u32)sStat.st_dev);
#else
** the original owner will not be able to connect.
*/
osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
-
+
/* Check to see if another process is holding the dead-man switch.
- ** If not, truncate the file to zero length.
+ ** If not, truncate the file to zero length.
*/
rc = SQLITE_OK;
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
** the cover of the unixEnterMutex() mutex and the pointer from the
** new (struct unixShm) object to the pShmNode has been set. All that is
** left to do is to link the new object into the linked list starting
- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
+ ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
** mutex.
*/
sqlite3_mutex_enter(pShmNode->mutex);
}
/*
-** This function is called to obtain a pointer to region iRegion of the
-** shared-memory associated with the database file fd. Shared-memory regions
-** are numbered starting from zero. Each shared-memory region is szRegion
+** This function is called to obtain a pointer to region iRegion of the
+** shared-memory associated with the database file fd. Shared-memory regions
+** are numbered starting from zero. Each shared-memory region is szRegion
** bytes in size.
**
** If an error occurs, an error code is returned and *pp is set to NULL.
**
** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
** region has not been allocated (by any client, including one running in a
-** separate process), then *pp is set to NULL and SQLITE_OK returned. If
-** bExtend is non-zero and the requested shared-memory region has not yet
+** separate process), then *pp is set to NULL and SQLITE_OK returned. If
+** bExtend is non-zero and the requested shared-memory region has not yet
** been allocated, it is allocated by this function.
**
** If the shared-memory region has already been allocated or is allocated by
-** this call as described above, then it is mapped into this processes
-** address space (if it is not already), *pp is set to point to the mapped
+** this call as described above, then it is mapped into this processes
+** address space (if it is not already), *pp is set to point to the mapped
** memory and SQLITE_OK returned.
*/
static int unixShmMap(
rc = SQLITE_IOERR_SHMSIZE;
goto shmpage_out;
}
-
+
if( sStat.st_size<nByte ){
/* The requested memory region does not exist. If bExtend is set to
** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
void *pMem;
if( pShmNode->h>=0 ){
pMem = osMmap(0, szRegion,
- pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
+ pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
);
if( pMem==MAP_FAILED ){
if( rc==SQLITE_OK ){
p->exclMask &= ~mask;
p->sharedMask &= ~mask;
- }
+ }
}else if( flags & SQLITE_SHM_SHARED ){
u16 allShared = 0; /* Union of locks held by connections other than "p" */
break;
}
}
-
+
/* Get the exclusive locks at the system level. Then if successful
** also mark the local connection as being locked.
*/
}
/*
-** Implement a memory barrier or memory fence on shared memory.
+** Implement a memory barrier or memory fence on shared memory.
**
** All loads and stores begun before the barrier must complete before
** any load or store begun after the barrier.
}
/*
-** Close a connection to shared-memory. Delete the underlying
+** Close a connection to shared-memory. Delete the underlying
** storage if deleteFlag is true.
**
** If there is no shared memory associated with the connection then this
#if SQLITE_MAX_MMAP_SIZE>0
/*
-** Attempt to set the size of the memory mapping maintained by file
+** Attempt to set the size of the memory mapping maintained by file
** descriptor pFd to nNew bytes. Any existing mapping is discarded.
**
** If successful, this function sets the following variables:
/*
** Memory map or remap the file opened by file-descriptor pFd (if the file
-** is already mapped, the existing mapping is replaced by the new). Or, if
-** there already exists a mapping for this file, and there are still
+** is already mapped, the existing mapping is replaced by the new). Or, if
+** there already exists a mapping for this file, and there are still
** outstanding xFetch() references to it, this function is a no-op.
**
-** If parameter nByte is non-negative, then it is the requested size of
-** the mapping to create. Otherwise, if nByte is less than zero, then the
+** If parameter nByte is non-negative, then it is the requested size of
+** the mapping to create. Otherwise, if nByte is less than zero, then the
** requested size is the size of the file on disk. The actual size of the
-** created mapping is either the requested size or the value configured
+** created mapping is either the requested size or the value configured
** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
**
** SQLITE_OK is returned if no error occurs (even if the mapping is not
** Finally, if an error does occur, return an SQLite error code. The final
** value of *pp is undefined in this case.
**
-** If this function does return a pointer, the caller must eventually
+** If this function does return a pointer, the caller must eventually
** release the reference by calling unixUnfetch().
*/
static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
}
/*
-** If the third argument is non-NULL, then this function releases a
+** If the third argument is non-NULL, then this function releases a
** reference obtained by an earlier call to unixFetch(). The second
** argument passed to this function must be the same as the corresponding
-** argument that was passed to the unixFetch() invocation.
+** argument that was passed to the unixFetch() invocation.
**
-** Or, if the third argument is NULL, then this function is being called
-** to inform the VFS layer that, according to POSIX, any existing mapping
+** Or, if the third argument is NULL, then this function is being called
+** to inform the VFS layer that, according to POSIX, any existing mapping
** may now be invalid and should be unmapped.
*/
static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
unixFile *pFd = (unixFile *)fd; /* The underlying database file */
UNUSED_PARAMETER(iOff);
- /* If p==0 (unmap the entire file) then there must be no outstanding
+ /* If p==0 (unmap the entire file) then there must be no outstanding
** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
** then there must be at least one outstanding. */
assert( (p==0)==(pFd->nFetchOut==0) );
#endif
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-/*
-** This "finder" function attempts to determine the best locking strategy
+/*
+** This "finder" function attempts to determine the best locking strategy
** for the database file "filePath". It then returns the sqlite3_io_methods
** object that implements that strategy.
**
}
/* Default case. Handles, amongst others, "nfs".
- ** Test byte-range lock using fcntl(). If the call succeeds,
- ** assume that the file-system supports POSIX style locks.
+ ** Test byte-range lock using fcntl(). If the call succeeds,
+ ** assume that the file-system supports POSIX style locks.
*/
lockInfo.l_len = 1;
lockInfo.l_start = 0;
return &dotlockIoMethods;
}
}
-static const sqlite3_io_methods
+static const sqlite3_io_methods
*(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE
-/*
-** This "finder" function attempts to determine the best locking strategy
+/*
+** This "finder" function attempts to determine the best locking strategy
** for the database file "filePath". It then returns the sqlite3_io_methods
** object that implements that strategy.
**
return &semIoMethods;
}
}
-static const sqlite3_io_methods
+static const sqlite3_io_methods
*(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
** include the special Apple locking styles.
*/
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
- assert( zFilename==0 || zFilename[0]=='/'
+ assert( zFilename==0 || zFilename[0]=='/'
|| pVfs->pAppData==(void*)&autolockIoFinder );
#else
assert( zFilename==0 || zFilename[0]=='/' );
robust_close(pNew, h, __LINE__);
h = -1;
}
- unixLeaveMutex();
+ unixLeaveMutex();
}
}
#endif
else if( pLockingStyle == &dotlockIoMethods ){
/* Dotfile locking uses the file path so it needs to be included in
- ** the dotlockLockingContext
+ ** the dotlockLockingContext
*/
char *zLockFile;
int nFilename;
unixLeaveMutex();
}
#endif
-
+
pNew->lastErrno = 0;
#if OS_VXWORKS
if( rc!=SQLITE_OK ){
/* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this
- ** function failing.
+ ** function failing.
*/
SimulateIOError( return SQLITE_IOERR );
zDir = unixTempFileDir();
if( zDir==0 ) zDir = ".";
- /* Check that the output buffer is large enough for the temporary file
+ /* Check that the output buffer is large enough for the temporary file
** name. If it is not, return SQLITE_ERROR.
*/
if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 18) >= (size_t)nBuf ){
#endif
/*
-** Search for an unused file descriptor that was opened on the database
+** Search for an unused file descriptor that was opened on the database
** file (not a journal or master-journal file) identified by pathname
** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
** argument to this function.
** but the associated file descriptor could not be closed because some
** other file descriptor open on the same file is holding a file-lock.
** Refer to comments in the unixClose() function and the lengthy comment
-** describing "Posix Advisory Locking" at the start of this file for
+** describing "Posix Advisory Locking" at the start of this file for
** further details. Also, ticket #4018.
**
** If a suitable file descriptor is found, then it is returned. If no
/* Do not search for an unused file descriptor on vxworks. Not because
** vxworks would not benefit from the change (it might, we're not sure),
- ** but because no way to test it is currently available. It is better
- ** not to risk breaking vxworks support for the sake of such an obscure
+ ** but because no way to test it is currently available. It is better
+ ** not to risk breaking vxworks support for the sake of such an obscure
** feature. */
#if !OS_VXWORKS
struct stat sStat; /* Results of stat() call */
** This function is called by unixOpen() to determine the unix permissions
** to create new files with. If no error occurs, then SQLITE_OK is returned
** and a value suitable for passing as the third argument to open(2) is
-** written to *pMode. If an IO error occurs, an SQLite error code is
+** written to *pMode. If an IO error occurs, an SQLite error code is
** returned and the value of *pMode is not modified.
**
** In most cases cases, this routine sets *pMode to 0, which will become
** an indication to robust_open() to create the file using
** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
-** But if the file being opened is a WAL or regular journal file, then
-** this function queries the file-system for the permissions on the
-** corresponding database file and sets *pMode to this value. Whenever
-** possible, WAL and journal files are created using the same permissions
+** But if the file being opened is a WAL or regular journal file, then
+** this function queries the file-system for the permissions on the
+** corresponding database file and sets *pMode to this value. Whenever
+** possible, WAL and journal files are created using the same permissions
** as the associated database file.
**
** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
** "<path to db>-journalNN"
** "<path to db>-walNN"
**
- ** where NN is a decimal number. The NN naming schemes are
+ ** where NN is a decimal number. The NN naming schemes are
** used by the test_multiplex.c module.
*/
- nDb = sqlite3Strlen30(zPath) - 1;
+ nDb = sqlite3Strlen30(zPath) - 1;
#ifdef SQLITE_ENABLE_8_3_NAMES
while( nDb>0 && sqlite3Isalnum(zPath[nDb]) ) nDb--;
if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
/*
** Open the file zPath.
-**
+**
** Previously, the SQLite OS layer used three functions in place of this
** one:
**
** These calls correspond to the following combinations of flags:
**
** ReadWrite() -> (READWRITE | CREATE)
-** ReadOnly() -> (READONLY)
+** ReadOnly() -> (READONLY)
** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
**
** The old OpenExclusive() accepted a boolean argument - "delFlag". If
** true, the file was configured to be automatically deleted when the
-** file handle closed. To achieve the same effect using this new
-** interface, add the DELETEONCLOSE flag to those specified above for
+** file handle closed. To achieve the same effect using this new
+** interface, add the DELETEONCLOSE flag to those specified above for
** OpenExclusive().
*/
static int unixOpen(
** is called the directory file descriptor will be fsync()ed and close()d.
*/
int syncDir = (isCreate && (
- eType==SQLITE_OPEN_MASTER_JOURNAL
- || eType==SQLITE_OPEN_MAIN_JOURNAL
+ eType==SQLITE_OPEN_MASTER_JOURNAL
+ || eType==SQLITE_OPEN_MAIN_JOURNAL
|| eType==SQLITE_OPEN_WAL
));
char zTmpname[MAX_PATHNAME+2];
const char *zName = zPath;
- /* Check the following statements are true:
+ /* Check the following statements are true:
**
- ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
+ ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
** (b) if CREATE is set, then READWRITE must also be set, and
** (c) if EXCLUSIVE is set, then CREATE must also be set.
** (d) if DELETEONCLOSE is set, then CREATE must also be set.
assert(isExclusive==0 || isCreate);
assert(isDelete==0 || isCreate);
- /* The main DB, main journal, WAL file and master journal are never
+ /* The main DB, main journal, WAL file and master journal are never
** automatically deleted. Nor are they ever temporary files. */
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
/* Assert that the upper layer has set one of the "file-type" flags. */
- assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
- || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
- || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
+ assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
+ || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
+ || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
/* Determine the value of the flags parameter passed to POSIX function
** open(). These must be calculated even if open() is not called, as
- ** they may be stored as part of the file handle and used by the
+ ** they may be stored as part of the file handle and used by the
** 'conch file' locking functions later on. */
if( isReadonly ) openFlags |= O_RDONLY;
if( isReadWrite ) openFlags |= O_RDWR;
noLock = eType!=SQLITE_OPEN_MAIN_DB;
-
+
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
if( fstatfs(fd, &fsInfo) == -1 ){
((unixFile*)pFile)->lastErrno = errno;
char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
int useProxy = 0;
- /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means
+ /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means
** never use proxy, NULL means use proxy for non-local files only. */
if( envforce!=NULL ){
useProxy = atoi(envforce)>0;
if( rc==SQLITE_OK ){
rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
if( rc!=SQLITE_OK ){
- /* Use unixClose to clean up the resources added in fillInUnixFile
- ** and clear all the structure's references. Specifically,
- ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op
+ /* Use unixClose to clean up the resources added in fillInUnixFile
+ ** and clear all the structure's references. Specifically,
+ ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op
*/
unixClose(pFile);
return rc;
}
}
#endif
-
+
rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
open_finished:
/*
** Turn a relative pathname into a full pathname. The relative path
** is stored as a nul-terminated string in the buffer pointed to by
-** zPath.
+** zPath.
**
-** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
+** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
** (in this case, MAX_PATHNAME bytes). The full-path is written to
** this buffer before returning.
*/
unixLeaveMutex();
}
static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){
- /*
+ /*
** GCC with -pedantic-errors says that C90 does not allow a void* to be
** cast into a pointer to a function. And yet the library dlsym() routine
** returns a void* which is really a pointer to a function. So how do we
** parameters void* and const char* and returning a pointer to a function.
** We initialize x by assigning it a pointer to the dlsym() function.
** (That assignment requires a cast.) Then we call the function that
- ** x points to.
+ ** x points to.
**
** This work-around is unlikely to work correctly on any system where
** you really cannot cast a function pointer into void*. But then, on the
** epoch of noon in Greenwich on November 24, 4714 B.C according to the
** proleptic Gregorian calendar.
**
-** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
+** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
** cannot be found.
*/
static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
** To address the performance and cache coherency issues, proxy file locking
** changes the way database access is controlled by limiting access to a
** single host at a time and moving file locks off of the database file
-** and onto a proxy file on the local file system.
+** and onto a proxy file on the local file system.
**
**
** Using proxy locks
** actual proxy file name is generated from the name and path of the
** database file. For example:
**
-** For database path "/Users/me/foo.db"
+** For database path "/Users/me/foo.db"
** The lock path will be "<tmpdir>/sqliteplocks/_Users_me_foo.db:auto:")
**
** Once a lock proxy is configured for a database connection, it can not
** be removed, however it may be switched to a different proxy path via
** the above APIs (assuming the conch file is not being held by another
-** connection or process).
+** connection or process).
**
**
** How proxy locking works
** -----------------------
**
-** Proxy file locking relies primarily on two new supporting files:
+** Proxy file locking relies primarily on two new supporting files:
**
** * conch file to limit access to the database file to a single host
** at a time
** host (the conch ensures that they all use the same local lock file).
**
** Requesting the lock proxy does not immediately take the conch, it is
-** only taken when the first request to lock database file is made.
+** only taken when the first request to lock database file is made.
** This matches the semantics of the traditional locking behavior, where
** opening a connection to a database file does not take a lock on it.
-** The shared lock and an open file descriptor are maintained until
-** the connection to the database is closed.
+** The shared lock and an open file descriptor are maintained until
+** the connection to the database is closed.
**
** The proxy file and the lock file are never deleted so they only need
** to be created the first time they are used.
** automatically configured for proxy locking, lock files are
** named automatically using the same logic as
** PRAGMA lock_proxy_file=":auto:"
-**
+**
** SQLITE_PROXY_DEBUG
**
** Enables the logging of error messages during host id file
**
** Permissions to use when creating a directory for storing the
** lock proxy files, only used when LOCKPROXYDIR is not set.
-**
-**
+**
+**
** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING,
** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
** force proxy locking to be used for every database file opened, and 0
*/
/*
-** Proxy locking is only available on MacOSX
+** Proxy locking is only available on MacOSX
*/
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
/*
-** The proxyLockingContext has the path and file structures for the remote
+** The proxyLockingContext has the path and file structures for the remote
** and local proxy files in it
*/
typedef struct proxyLockingContext proxyLockingContext;
sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */
};
-/*
-** The proxy lock file path for the database at dbPath is written into lPath,
+/*
+** The proxy lock file path for the database at dbPath is written into lPath,
** which must point to valid, writable memory large enough for a maxLen length
-** file path.
+** file path.
*/
static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
int len;
lPath, errno, getpid()));
return SQLITE_IOERR_LOCK;
}
- len = strlcat(lPath, "sqliteplocks", maxLen);
+ len = strlcat(lPath, "sqliteplocks", maxLen);
}
# else
len = strlcpy(lPath, "/tmp/", maxLen);
if( lPath[len-1]!='/' ){
len = strlcat(lPath, "/", maxLen);
}
-
+
/* transform the db path to a unique cache name */
dbLen = (int)strlen(dbPath);
for( i=0; i<dbLen && (i+len+7)<(int)maxLen; i++){
return SQLITE_OK;
}
-/*
+/*
** Creates the lock file and any missing directories in lockPath
*/
static int proxyCreateLockPath(const char *lockPath){
int i, len;
char buf[MAXPATHLEN];
int start = 0;
-
+
assert(lockPath!=NULL);
/* try to create all the intermediate directories */
len = (int)strlen(lockPath);
for( i=1; i<len; i++ ){
if( lockPath[i] == '/' && (i - start > 0) ){
/* only mkdir if leaf dir != "." or "/" or ".." */
- if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/')
+ if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/')
|| (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
buf[i]='\0';
if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
switch (terrno) {
case EACCES:
return SQLITE_PERM;
- case EIO:
+ case EIO:
return SQLITE_IOERR_LOCK; /* even though it is the conch */
default:
return SQLITE_CANTOPEN_BKPT;
}
}
-
+
pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
if( pNew==NULL ){
rc = SQLITE_NOMEM;
pUnused->fd = fd;
pUnused->flags = openFlags;
pNew->pUnused = pUnused;
-
+
rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
if( rc==SQLITE_OK ){
*ppFile = pNew;
return SQLITE_OK;
}
-end_create_proxy:
+end_create_proxy:
robust_close(pNew, fd, __LINE__);
sqlite3_free(pNew);
sqlite3_free(pUnused);
/* Not always defined in the headers as it ought to be */
extern int gethostuuid(uuid_t id, const struct timespec *wait);
-/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
+/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
** bytes of writable memory.
*/
static int proxyGetHostID(unsigned char *pHostID, int *pError){
pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
}
#endif
-
+
return SQLITE_OK;
}
#define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN)
#define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN)
-/*
-** Takes an open conch file, copies the contents to a new path and then moves
+/*
+** Takes an open conch file, copies the contents to a new path and then moves
** it back. The newly created file's file descriptor is assigned to the
-** conch file structure and finally the original conch file descriptor is
+** conch file structure and finally the original conch file descriptor is
** closed. Returns zero if successful.
*/
static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
unixFile *conchFile = pCtx->conchFile;
char tPath[MAXPATHLEN];
char buf[PROXY_MAXCONCHLEN];
/* create a new path by replace the trailing '-conch' with '-break' */
pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
- if( pathLen>MAXPATHLEN || pathLen<6 ||
+ if( pathLen>MAXPATHLEN || pathLen<6 ||
(strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){
sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen);
goto end_breaklock;
return rc;
}
-/* Take the requested lock on the conch file and break a stale lock if the
+/* Take the requested lock on the conch file and break a stale lock if the
** host id matches.
*/
static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
unixFile *conchFile = pCtx->conchFile;
int rc = SQLITE_OK;
int nTries = 0;
struct timespec conchModTime;
-
+
memset(&conchModTime, 0, sizeof(conchModTime));
do {
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
nTries ++;
if( rc==SQLITE_BUSY ){
/* If the lock failed (busy):
- * 1st try: get the mod time of the conch, wait 0.5s and try again.
- * 2nd try: fail if the mod time changed or host id is different, wait
+ * 1st try: get the mod time of the conch, wait 0.5s and try again.
+ * 2nd try: fail if the mod time changed or host id is different, wait
* 10 sec and try again
* 3rd try: break the lock unless the mod time has changed.
*/
pFile->lastErrno = errno;
return SQLITE_IOERR_LOCK;
}
-
+
if( nTries==1 ){
conchModTime = buf.st_mtimespec;
usleep(500000); /* wait 0.5 sec and try the lock again*/
- continue;
+ continue;
}
assert( nTries>1 );
- if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec ||
+ if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec ||
conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
return SQLITE_BUSY;
}
-
- if( nTries==2 ){
+
+ if( nTries==2 ){
char tBuf[PROXY_MAXCONCHLEN];
int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
if( len<0 ){
return SQLITE_BUSY;
}
usleep(10000000); /* wait 10 sec and try the lock again */
- continue;
+ continue;
}
-
+
assert( nTries==3 );
if( 0==proxyBreakConchLock(pFile, myHostID) ){
rc = SQLITE_OK;
if( lockType==EXCLUSIVE_LOCK ){
- rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
}
if( !rc ){
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
}
}
} while( rc==SQLITE_BUSY && nTries<3 );
-
+
return rc;
}
-/* Takes the conch by taking a shared lock and read the contents conch, if
-** lockPath is non-NULL, the host ID and lock file path must match. A NULL
-** lockPath means that the lockPath in the conch file will be used if the
-** host IDs match, or a new lock path will be generated automatically
+/* Takes the conch by taking a shared lock and read the contents conch, if
+** lockPath is non-NULL, the host ID and lock file path must match. A NULL
+** lockPath means that the lockPath in the conch file will be used if the
+** host IDs match, or a new lock path will be generated automatically
** and written to the conch file.
*/
static int proxyTakeConch(unixFile *pFile){
- proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
-
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+
if( pCtx->conchHeld!=0 ){
return SQLITE_OK;
}else{
int readLen = 0;
int tryOldLockPath = 0;
int forceNewLockPath = 0;
-
+
OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()));
pFile->lastErrno = conchFile->lastErrno;
rc = SQLITE_IOERR_READ;
goto end_takeconch;
- }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) ||
+ }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) ||
readBuf[0]!=(char)PROXY_CONCHVERSION ){
- /* a short read or version format mismatch means we need to create a new
- ** conch file.
+ /* a short read or version format mismatch means we need to create a new
+ ** conch file.
*/
createConch = 1;
}
/* if the host id matches and the lock path already exists in the conch
- ** we'll try to use the path there, if we can't open that path, we'll
- ** retry with a new auto-generated path
+ ** we'll try to use the path there, if we can't open that path, we'll
+ ** retry with a new auto-generated path
*/
do { /* in case we need to try again for an :auto: named lock file */
if( !createConch && !forceNewLockPath ){
- hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID,
+ hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID,
PROXY_HOSTIDLEN);
/* if the conch has data compare the contents */
if( !pCtx->lockProxyPath ){
*/
if( hostIdMatch ){
size_t pathLen = (readLen - PROXY_PATHINDEX);
-
+
if( pathLen>=MAXPATHLEN ){
pathLen=MAXPATHLEN-1;
}
readLen-PROXY_PATHINDEX)
){
/* conch host and lock path match */
- goto end_takeconch;
+ goto end_takeconch;
}
}
-
+
/* if the conch isn't writable and doesn't match, we can't take it */
if( (conchFile->openFlags&O_RDWR) == 0 ){
rc = SQLITE_BUSY;
goto end_takeconch;
}
-
+
/* either the conch didn't match or we need to create a new one */
if( !pCtx->lockProxyPath ){
proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
tempLockPath = lockPath;
/* create a copy of the lock path _only_ if the conch is taken */
}
-
+
/* update conch with host and path (this will fail if other process
** has a shared lock already), if the host id matches, use the big
** stick.
/* We are trying for an exclusive lock but another thread in this
** same process is still holding a shared lock. */
rc = SQLITE_BUSY;
- } else {
+ } else {
rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
}
}else{
if( rc==SQLITE_OK ){
char writeBuffer[PROXY_MAXCONCHLEN];
int writeSize = 0;
-
+
writeBuffer[0] = (char)PROXY_CONCHVERSION;
memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
if( pCtx->lockProxyPath!=NULL ){
robust_ftruncate(conchFile->h, writeSize);
rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
fsync(conchFile->h);
- /* If we created a new conch file (not just updated the contents of a
- ** valid conch file), try to match the permissions of the database
+ /* If we created a new conch file (not just updated the contents of a
+ ** valid conch file), try to match the permissions of the database
*/
if( rc==SQLITE_OK && createConch ){
struct stat buf;
}
}else{
int code = errno;
- fprintf(stderr, "STAT FAILED[%d] with %d %s\n",
+ fprintf(stderr, "STAT FAILED[%d] with %d %s\n",
err, code, strerror(code));
#endif
}
}
}
conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
-
+
end_takeconch:
OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h));
if( rc==SQLITE_OK && pFile->openFlags ){
rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1);
if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){
/* we couldn't create the proxy lock file with the old lock file path
- ** so try again via auto-naming
+ ** so try again via auto-naming
*/
forceNewLockPath = 1;
tryOldLockPath = 0;
}
if( rc==SQLITE_OK ){
pCtx->conchHeld = 1;
-
+
if( pCtx->lockProxy->pMethod == &afpIoMethods ){
afpLockingContext *afpCtx;
afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
OSTRACE(("TAKECONCH %d %s\n", conchFile->h,
rc==SQLITE_OK?"ok":"failed"));
return rc;
- } while (1); /* in case we need to retry the :auto: lock file -
+ } while (1); /* in case we need to retry the :auto: lock file -
** we should never get here except via the 'continue' call. */
}
}
pCtx = (proxyLockingContext *)pFile->lockingContext;
conchFile = pCtx->conchFile;
OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
- (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
+ (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
getpid()));
if( pCtx->conchHeld>0 ){
rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
char *conchPath; /* buffer in which to construct conch name */
/* Allocate space for the conch filename and initialize the name to
- ** the name of the original database file. */
+ ** the name of the original database file. */
*pConchPath = conchPath = (char *)sqlite3_malloc(len + 8);
if( conchPath==0 ){
return SQLITE_NOMEM;
}
memcpy(conchPath, dbPath, len+1);
-
+
/* now insert a "." before the last / character */
for( i=(len-1); i>=0; i-- ){
if( conchPath[i]=='/' ){
/* Takes a fully configured proxy locking-style unix file and switches
-** the local lock file path
+** the local lock file path
*/
static int switchLockProxyPath(unixFile *pFile, const char *path) {
proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
if( pFile->eFileLock!=NO_LOCK ){
return SQLITE_BUSY;
- }
+ }
/* nothing to do if the path is NULL, :auto: or matches the existing path */
if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ||
sqlite3_free(oldPath);
pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
}
-
+
return rc;
}
static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
#if defined(__APPLE__)
if( pFile->pMethod == &afpIoMethods ){
- /* afp style keeps a reference to the db path in the filePath field
+ /* afp style keeps a reference to the db path in the filePath field
** of the struct */
assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN);
}
/*
-** Takes an already filled in unix file and alters it so all file locking
+** Takes an already filled in unix file and alters it so all file locking
** will be performed on the local proxy lock file. The following fields
-** are preserved in the locking context so that they can be restored and
+** are preserved in the locking context so that they can be restored and
** the unix structure properly cleaned up at close time:
** ->lockingContext
** ->pMethod
char dbPath[MAXPATHLEN+1]; /* Name of the database file */
char *lockPath=NULL;
int rc = SQLITE_OK;
-
+
if( pFile->eFileLock!=NO_LOCK ){
return SQLITE_BUSY;
}
}else{
lockPath=(char *)path;
}
-
+
OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
(lockPath ? lockPath : ":auto:"), getpid()));
rc = SQLITE_OK;
}
}
- }
+ }
if( rc==SQLITE_OK && lockPath ){
pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
}
}
}
if( rc==SQLITE_OK ){
- /* all memory is allocated, proxys are created and assigned,
+ /* all memory is allocated, proxys are created and assigned,
** switch the locking context and pMethod then return.
*/
pCtx->oldLockingContext = pFile->lockingContext;
pCtx->pOldMethod = pFile->pMethod;
pFile->pMethod = &proxyIoMethods;
}else{
- if( pCtx->conchFile ){
+ if( pCtx->conchFile ){
pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
sqlite3_free(pCtx->conchFile);
}
sqlite3DbFree(0, pCtx->lockProxyPath);
- sqlite3_free(pCtx->conchFilePath);
+ sqlite3_free(pCtx->conchFilePath);
sqlite3_free(pCtx);
}
OSTRACE(("TRANSPROXY %d %s\n", pFile->h,
}else{
const char *proxyPath = (const char *)pArg;
if( isProxyStyle ){
- proxyLockingContext *pCtx =
+ proxyLockingContext *pCtx =
(proxyLockingContext*)pFile->lockingContext;
- if( !strcmp(pArg, ":auto:")
+ if( !strcmp(pArg, ":auto:")
|| (pCtx->lockProxyPath &&
!strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
){
unixFile *lockProxy = pCtx->lockProxy;
unixFile *conchFile = pCtx->conchFile;
int rc = SQLITE_OK;
-
+
if( lockProxy ){
rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK);
if( rc ) return rc;
** The proxy locking style is intended for use with AFP filesystems.
** And since AFP is only supported on MacOSX, the proxy locking is also
** restricted to MacOSX.
-**
+**
**
******************* End of the proxy lock implementation **********************
******************************************************************************/
** necessarily been initialized when this routine is called, and so they
** should not be used.
*/
-SQLITE_API int sqlite3_os_init(void){
- /*
+SQLITE_API int sqlite3_os_init(void){
+ /*
** The following macro defines an initializer for an sqlite3_vfs object.
** The name of the VFS is NAME. The pAppData is a pointer to a pointer
** to the "finder" function. (pAppData is a pointer to a pointer because
**
** Most finders simply return a pointer to a fixed sqlite3_io_methods
** object. But the "autolockIoFinder" available on MacOSX does a little
- ** more than that; it looks at the filesystem type that hosts the
+ ** more than that; it looks at the filesystem type that hosts the
** database file and tries to choose an locking method appropriate for
** that filesystem time.
*/
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
sqlite3_vfs_register(&aVfs[i], i==0);
}
- return SQLITE_OK;
+ return SQLITE_OK;
}
/*
** to release dynamically allocated objects. But not on unix.
** This routine is a no-op for unix.
*/
-SQLITE_API int sqlite3_os_end(void){
- return SQLITE_OK;
+SQLITE_API int sqlite3_os_end(void){
+ return SQLITE_OK;
}
-
+
#endif /* SQLITE_OS_UNIX */
/************** End of os_unix.c *********************************************/
*/
#ifdef SQLITE_PERFORMANCE_TRACE
-/*
-** hwtime.h contains inline assembler code for implementing
+/*
+** hwtime.h contains inline assembler code for implementing
** high-performance timing routines.
*/
/************** Include hwtime.h in the middle of os_common.h ****************/
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
}
-
+
#elif (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
** Some Microsoft compilers lack this definition.
*/
#ifndef INVALID_FILE_ATTRIBUTES
-# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
#ifndef FILE_FLAG_MASK
int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
#if SQLITE_OS_WINCE
LPWSTR zDeleteOnClose; /* Name of file to delete when closing */
- HANDLE hMutex; /* Mutex used to control access to shared lock */
+ HANDLE hMutex; /* Mutex used to control access to shared lock */
HANDLE hShared; /* Shared memory segment used for locking */
winceLock local; /* Locks obtained by this instance of winFile */
winceLock *shared; /* Global shared lock memory for the file */
#endif /* SQLITE_WIN32_MALLOC */
/*
-** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
+** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
**
** Space to hold the returned string is obtained from malloc.
*/
/*
** Convert an ANSI string to Microsoft Unicode, based on the
** current codepage settings for file apis.
-**
+**
** Space to hold the returned string is obtained
** from sqlite3_malloc.
*/
}
/*
-** Convert UTF-8 to multibyte character string. Space to hold the
+** Convert UTF-8 to multibyte character string. Space to hold the
** returned string is obtained from sqlite3_malloc().
*/
SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
**
** This routine is invoked after an error occurs in an OS function.
** It logs a message using sqlite3_log() containing the current value of
-** error code and, if possible, the human-readable equivalent from
+** error code and, if possible, the human-readable equivalent from
** FormatMessage.
**
** The first argument passed to the macro should be the error code that
-** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
+** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
** The two subsequent arguments should be the name of the OS function that
** failed and the associated file-system path, if any.
*/
/*
** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
-** will be retried following a locking error - probably caused by
+** will be retried following a locking error - probably caused by
** antivirus software. Also the initial delay before the first retry.
** The delay increases linearly with each retry.
*/
*/
static void logIoerr(int nRetry){
if( nRetry ){
- sqlite3_log(SQLITE_IOERR,
+ sqlite3_log(SQLITE_IOERR,
"delayed %dms for lock/sharing conflict",
win32IoerrRetryDelay*nRetry*(nRetry+1)/2
);
/* Acquire the mutex before continuing */
winceMutexAcquire(pFile->hMutex);
-
- /* Since the names of named mutexes, semaphores, file mappings etc are
+
+ /* Since the names of named mutexes, semaphores, file mappings etc are
** case-sensitive, take advantage of that by uppercasing the mutex name
** and using that as the shared filemapping name.
*/
osCharUpperW(zName);
pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, sizeof(winceLock),
- zName);
+ zName);
- /* Set a flag that indicates we're the first to create the memory so it
+ /* Set a flag that indicates we're the first to create the memory so it
** must be zero-initialized */
lastErrno = osGetLastError();
if (lastErrno == ERROR_ALREADY_EXISTS){
/* If we succeeded in making the shared memory handle, map it. */
if( pFile->hShared ){
- pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
+ pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
/* If mapping failed, close the shared memory handle and erase it */
if( !pFile->shared ){
pFile->hMutex = NULL;
return SQLITE_IOERR;
}
-
+
/* Initialize the shared memory if we're supposed to */
if( bInit ){
memset(pFile->shared, 0, sizeof(winceLock));
osCloseHandle(pFile->hShared);
/* Done with the mutex */
- winceMutexRelease(pFile->hMutex);
+ winceMutexRelease(pFile->hMutex);
osCloseHandle(pFile->hMutex);
pFile->hMutex = NULL;
}
}
-/*
+/*
** An implementation of the LockFile() API of Windows for CE
*/
static BOOL winceLockFile(
#endif
/*
-** Move the current position of the file handle passed as the first
-** argument to offset iOffset within the file. If successful, return 0.
+** Move the current position of the file handle passed as the first
+** argument to offset iOffset within the file. If successful, return 0.
** Otherwise, set pFile->lastErrno and return non-zero.
*/
static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
lowerBits = (LONG)(iOffset & 0xffffffff);
- /* API oddity: If successful, SetFilePointer() returns a dword
+ /* API oddity: If successful, SetFilePointer() returns a dword
** containing the lower 32-bits of the new file-offset. Or, if it fails,
- ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
- ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
- ** whether an error has actually occurred, it is also necessary to call
+ ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
+ ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
+ ** whether an error has actually occurred, it is also necessary to call
** GetLastError().
*/
dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
int cnt = 0;
while(
osDeleteFileW(pFile->zDeleteOnClose)==0
- && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
+ && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
&& cnt++ < WINCE_DELETION_ATTEMPTS
){
sqlite3_win32_sleep(100); /* Wait a little before trying again */
((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
}
-/*
+/*
** Windows will only let you create file view mappings
** on allocation size granularity boundaries.
** During sqlite3_os_init() we do a GetSystemInfo()
/*
** Helper functions to obtain and relinquish the global mutex. The
-** global mutex is used to protect the winLockInfo objects used by
+** global mutex is used to protect the winLockInfo objects used by
** this file, all of which may be shared by multiple threads.
**
-** Function winShmMutexHeld() is used to assert() that the global mutex
-** is held when required. This function is only used as part of assert()
+** Function winShmMutexHeld() is used to assert() that the global mutex
+** is held when required. This function is only used as part of assert()
** statements. e.g.
**
** winShmEnterMutex()
** this object or while reading or writing the following fields:
**
** nRef
-** pNext
+** pNext
**
** The following fields are read-only after the object is created:
-**
+**
** fid
** zFilename
**
if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
}
-
+
if( rc!= 0 ){
rc = SQLITE_OK;
}else{
}
pNew->zFilename = (char*)&pNew[1];
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
- sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
+ sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
/* Look to see if there is an existing winShmNode that can be used.
** If no matching winShmNode currently exists, create a new one.
}
/* Check to see if another process is holding the dead-man switch.
- ** If not, truncate the file to zero length.
+ ** If not, truncate the file to zero length.
*/
if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
** the cover of the winShmEnterMutex() mutex and the pointer from the
** new (struct winShm) object to the pShmNode has been set. All that is
** left to do is to link the new object into the linked list starting
- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
+ ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
** mutex.
*/
sqlite3_mutex_enter(pShmNode->mutex);
}
/*
-** Close a connection to shared-memory. Delete the underlying
+** Close a connection to shared-memory. Delete the underlying
** storage if deleteFlag is true.
*/
static int winShmUnmap(
if( rc==SQLITE_OK ){
p->exclMask &= ~mask;
p->sharedMask &= ~mask;
- }
+ }
}else if( flags & SQLITE_SHM_SHARED ){
u16 allShared = 0; /* Union of locks held by connections other than "p" */
break;
}
}
-
+
/* Get the exclusive locks at the system level. Then if successful
** also mark the local connection as being locked.
*/
}
/*
-** Implement a memory barrier or memory fence on shared memory.
+** Implement a memory barrier or memory fence on shared memory.
**
** All loads and stores begun before the barrier must complete before
** any load or store begun after the barrier.
}
/*
-** This function is called to obtain a pointer to region iRegion of the
-** shared-memory associated with the database file fd. Shared-memory regions
-** are numbered starting from zero. Each shared-memory region is szRegion
+** This function is called to obtain a pointer to region iRegion of the
+** shared-memory associated with the database file fd. Shared-memory regions
+** are numbered starting from zero. Each shared-memory region is szRegion
** bytes in size.
**
** If an error occurs, an error code is returned and *pp is set to NULL.
**
** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
** region has not been allocated (by any client, including one running in a
-** separate process), then *pp is set to NULL and SQLITE_OK returned. If
-** isWrite is non-zero and the requested shared-memory region has not yet
+** separate process), then *pp is set to NULL and SQLITE_OK returned. If
+** isWrite is non-zero and the requested shared-memory region has not yet
** been allocated, it is allocated by this function.
**
** If the shared-memory region has already been allocated or is allocated by
-** this call as described above, then it is mapped into this processes
-** address space (if it is not already), *pp is set to point to the mapped
+** this call as described above, then it is mapped into this processes
+** address space (if it is not already), *pp is set to point to the mapped
** memory and SQLITE_OK returned.
*/
static int winShmMap(
while( pShmNode->nRegion<=iRegion ){
HANDLE hMap = NULL; /* file-mapping handle */
void *pMap = 0; /* Mapped memory region */
-
+
#if SQLITE_OS_WINRT
hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
NULL, PAGE_READWRITE, nByte, NULL
);
#elif defined(SQLITE_WIN32_HAS_WIDE)
- hMap = osCreateFileMappingW(pShmNode->hFile.h,
+ hMap = osCreateFileMappingW(pShmNode->hFile.h,
NULL, PAGE_READWRITE, 0, nByte, NULL
);
#elif defined(SQLITE_WIN32_HAS_ANSI)
- hMap = osCreateFileMappingA(pShmNode->hFile.h,
+ hMap = osCreateFileMappingA(pShmNode->hFile.h,
NULL, PAGE_READWRITE, 0, nByte, NULL
);
#endif
/*
** Memory map or remap the file opened by file-descriptor pFd (if the file
-** is already mapped, the existing mapping is replaced by the new). Or, if
-** there already exists a mapping for this file, and there are still
+** is already mapped, the existing mapping is replaced by the new). Or, if
+** there already exists a mapping for this file, and there are still
** outstanding xFetch() references to it, this function is a no-op.
**
-** If parameter nByte is non-negative, then it is the requested size of
-** the mapping to create. Otherwise, if nByte is less than zero, then the
+** If parameter nByte is non-negative, then it is the requested size of
+** the mapping to create. Otherwise, if nByte is less than zero, then the
** requested size is the size of the file on disk. The actual size of the
-** created mapping is either the requested size or the value configured
+** created mapping is either the requested size or the value configured
** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
**
** SQLITE_OK is returned if no error occurs (even if the mapping is not
nMap = pFd->mmapSizeMax;
}
nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
-
+
if( nMap==0 && pFd->mmapSize>0 ){
winUnmapfile(pFd);
}
** Finally, if an error does occur, return an SQLite error code. The final
** value of *pp is undefined in this case.
**
-** If this function does return a pointer, the caller must eventually
+** If this function does return a pointer, the caller must eventually
** release the reference by calling winUnfetch().
*/
static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
}
/*
-** If the third argument is non-NULL, then this function releases a
+** If the third argument is non-NULL, then this function releases a
** reference obtained by an earlier call to winFetch(). The second
** argument passed to this function must be the same as the corresponding
-** argument that was passed to the winFetch() invocation.
+** argument that was passed to the winFetch() invocation.
**
-** Or, if the third argument is NULL, then this function is being called
-** to inform the VFS layer that, according to POSIX, any existing mapping
+** Or, if the third argument is NULL, then this function is being called
+** to inform the VFS layer that, according to POSIX, any existing mapping
** may now be invalid and should be unmapped.
*/
static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
#if SQLITE_MAX_MMAP_SIZE>0
winFile *pFd = (winFile*)fd; /* The underlying database file */
- /* If p==0 (unmap the entire file) then there must be no outstanding
+ /* If p==0 (unmap the entire file) then there must be no outstanding
** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
** then there must be at least one outstanding. */
assert( (p==0)==(pFd->nFetchOut==0) );
/* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this
- ** function failing.
+ ** function failing.
*/
SimulateIOError( return SQLITE_IOERR );
#endif
#endif
- /* Check that the output buffer is large enough for the temporary file
+ /* Check that the output buffer is large enough for the temporary file
** name. If it is not, return SQLITE_ERROR.
*/
nTempPath = sqlite3Strlen30(zTempPath);
#ifndef NDEBUG
int isOpenJournal = (isCreate && (
- eType==SQLITE_OPEN_MASTER_JOURNAL
- || eType==SQLITE_OPEN_MAIN_JOURNAL
+ eType==SQLITE_OPEN_MASTER_JOURNAL
+ || eType==SQLITE_OPEN_MAIN_JOURNAL
|| eType==SQLITE_OPEN_WAL
));
#endif
OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
zUtf8Name, id, flags, pOutFlags));
- /* Check the following statements are true:
+ /* Check the following statements are true:
**
- ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
+ ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
** (b) if CREATE is set, then READWRITE must also be set, and
** (c) if EXCLUSIVE is set, then CREATE must also be set.
** (d) if DELETEONCLOSE is set, then CREATE must also be set.
assert(isExclusive==0 || isCreate);
assert(isDelete==0 || isCreate);
- /* The main DB, main journal, WAL file and master journal are never
+ /* The main DB, main journal, WAL file and master journal are never
** automatically deleted. Nor are they ever temporary files. */
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
/* Assert that the upper layer has set one of the "file-type" flags. */
- assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
- || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
- || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
+ assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
+ || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
+ || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
}
#endif
- /* If the second argument to this function is NULL, generate a
- ** temporary file name to use
+ /* If the second argument to this function is NULL, generate a
+ ** temporary file name to use
*/
if( !zUtf8Name ){
assert(isDelete && !isOpenJournal);
dwDesiredAccess = GENERIC_READ;
}
- /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
- ** created. SQLite doesn't use it to indicate "exclusive access"
+ /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
+ ** created. SQLite doesn't use it to indicate "exclusive access"
** as it is usually understood.
*/
if( isExclusive ){
winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
sqlite3_free(zConverted);
if( isReadWrite && !isExclusive ){
- return winOpen(pVfs, zName, id,
+ return winOpen(pVfs, zName, id,
((flags|SQLITE_OPEN_READONLY) &
~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
pOutFlags);
WIN32_FILE_ATTRIBUTE_DATA sAttrData;
memset(&sAttrData, 0, sizeof(sAttrData));
while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
- GetFileExInfoStandard,
+ GetFileExInfoStandard,
&sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
if( rc ){
/* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
** as if it does not exist.
*/
if( flags==SQLITE_ACCESS_EXISTS
- && sAttrData.nFileSizeHigh==0
+ && sAttrData.nFileSizeHigh==0
&& sAttrData.nFileSizeLow==0 ){
attr = INVALID_FILE_ATTRIBUTES;
}else{
int nFull, /* Size of output buffer in bytes */
char *zFull /* Output buffer */
){
-
+
#if defined(__CYGWIN__)
SimulateIOError( return SQLITE_ERROR );
UNUSED_PARAMETER(nFull);
** epoch of noon in Greenwich on November 24, 4714 B.C according to the
** proleptic Gregorian calendar.
**
-** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
+** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
** cannot be found.
*/
static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
- /* FILETIME structure is a 64-bit value representing the number of
- 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
+ /* FILETIME structure is a 64-bit value representing the number of
+ 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
*/
FILETIME ft;
static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
#endif
/* 2^32 - to avoid use of LL and warnings in gcc */
- static const sqlite3_int64 max32BitValue =
+ static const sqlite3_int64 max32BitValue =
(sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
(sqlite3_int64)294967296;
#endif
*piNow = winFiletimeEpoch +
- ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
+ ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
(sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
#ifdef SQLITE_TEST
assert( winSysInfo.dwPageSize>0 );
sqlite3_vfs_register(&winVfs, 1);
- return SQLITE_OK;
+ return SQLITE_OK;
}
-SQLITE_API int sqlite3_os_end(void){
+SQLITE_API int sqlite3_os_end(void){
#if SQLITE_OS_WINRT
if( sleepObj!=NULL ){
osCloseHandle(sleepObj);
** property. Usually only a few pages are meet either condition.
** So the bitmap is usually sparse and has low cardinality.
** But sometimes (for example when during a DROP of a large table) most
-** or all of the pages in a database can get journalled. In those cases,
-** the bitmap becomes dense with high cardinality. The algorithm needs
+** or all of the pages in a database can get journalled. In those cases,
+** the bitmap becomes dense with high cardinality. The algorithm needs
** to handle both cases well.
**
** The size of the bitmap is fixed when the object is created.
/* Size of the Bitvec structure in bytes. */
#define BITVEC_SZ 512
-/* Round the union size down to the nearest pointer boundary, since that's how
+/* Round the union size down to the nearest pointer boundary, since that's how
** it will be aligned within the Bitvec struct. */
#define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*))
-/* Type of the array "element" for the bitmap representation.
-** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE.
+/* Type of the array "element" for the bitmap representation.
+** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE.
** Setting this to the "natural word" size of your CPU may improve
** performance. */
#define BITVEC_TELEM u8
/* Number of u32 values in hash table. */
#define BITVEC_NINT (BITVEC_USIZE/sizeof(u32))
-/* Maximum number of entries in hash table before
+/* Maximum number of entries in hash table before
** sub-dividing and re-hashing. */
#define BITVEC_MXHASH (BITVEC_NINT/2)
/* Hashing function for the aHash representation.
-** Empirical testing showed that the *37 multiplier
-** (an arbitrary prime)in the hash function provided
+** Empirical testing showed that the *37 multiplier
+** (an arbitrary prime)in the hash function provided
** no fewer collisions than the no-op *1. */
#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT)
/*
** Create a new bitmap object able to handle bits between 0 and iSize,
-** inclusive. Return a pointer to the new object. Return NULL if
+** inclusive. Return a pointer to the new object. Return NULL if
** malloc fails.
*/
SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){
break;
}
case 3:
- case 4:
+ case 4:
default: {
nx = 2;
sqlite3_randomness(sizeof(i), &i);
/*************************************************** General Interfaces ******
**
-** Initialize and shutdown the page cache subsystem. Neither of these
+** Initialize and shutdown the page cache subsystem. Neither of these
** functions are threadsafe.
*/
SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
/*
** Create a new PCache object. Storage space to hold the object
-** has already been allocated and is passed in as the p pointer.
-** The caller discovers how much space needs to be allocated by
+** has already been allocated and is passed in as the p pointer.
+** The caller discovers how much space needs to be allocated by
** calling sqlite3PcacheSize().
*/
SQLITE_PRIVATE void sqlite3PcacheOpen(
if( !pPage && eCreate==1 ){
PgHdr *pPg;
- /* Find a dirty page to write-out and recycle. First try to find a
+ /* Find a dirty page to write-out and recycle. First try to find a
** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
- ** cleared), but if that is not possible settle for any other
+ ** cleared), but if that is not possible settle for any other
** unreferenced dirty page.
*/
expensive_assert( pcacheCheckSynced(pCache) );
- for(pPg=pCache->pSynced;
- pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
+ for(pPg=pCache->pSynced;
+ pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
pPg=pPg->pDirtyPrev
);
pCache->pSynced = pPg;
if( pPg ){
int rc;
#ifdef SQLITE_LOG_CACHE_SPILL
- sqlite3_log(SQLITE_FULL,
+ sqlite3_log(SQLITE_FULL,
"spill page %d making room for %d - cache used: %d/%d",
pPg->pgno, pgno,
sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache),
}
/*
-** Change the page number of page p to newPgno.
+** Change the page number of page p to newPgno.
*/
SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
PCache *pCache = p->pCache;
}
}
-/*
+/*
** Discard the contents of the cache.
*/
SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){
return pcacheSortDirtyList(pCache->pDirty);
}
-/*
+/*
** Return the total number of referenced pages held by the cache.
*/
SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){
return p->nRef;
}
-/*
+/*
** Return the total number of pages in the cache.
*/
SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){
typedef struct PgFreeslot PgFreeslot;
typedef struct PGroup PGroup;
-/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
+/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
** of one or more PCaches that are able to recycle each others unpinned
** pages when they are under memory pressure. A PGroup is an instance of
** the following object.
** temporary or transient database) has a single page cache which
** is an instance of this object.
**
-** Pointers to structures of this type are cast and returned as
+** Pointers to structures of this type are cast and returned as
** opaque sqlite3_pcache* handles.
*/
struct PCache1 {
/* Cache configuration parameters. Page size (szPage) and the purgeable
- ** flag (bPurgeable) are set when the cache is created. nMax may be
+ ** flag (bPurgeable) are set when the cache is created. nMax may be
** modified at any time by a call to the pcache1Cachesize() method.
** The PGroup mutex must be held when accessing nMax.
*/
};
/*
-** Each cache entry is represented by an instance of the following
+** Each cache entry is represented by an instance of the following
** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
-** PgHdr1.pCache->szPage bytes is allocated directly before this structure
+** PgHdr1.pCache->szPage bytes is allocated directly before this structure
** in memory.
*/
struct PgHdr1 {
/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
/*
-** This function is called during initialization if a static buffer is
+** This function is called during initialization if a static buffer is
** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
** verb to sqlite3_config(). Parameter pBuf points to an allocation large
** enough to contain 'n' buffers of 'sz' bytes each.
/*
** Malloc function used within this file to allocate space from the buffer
-** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no
-** such buffer exists or there is no space left in it, this function falls
+** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no
+** such buffer exists or there is no space left in it, this function falls
** back to sqlite3Malloc().
**
** Multiple threads can run this routine at the same time. Global variables
void *pPg;
/* The group mutex must be released before pcache1Alloc() is called. This
- ** is because it may call sqlite3_release_memory(), which assumes that
+ ** is because it may call sqlite3_release_memory(), which assumes that
** this mutex is not held. */
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
pcache1LeaveMutex(pCache->pGroup);
}
/*
-** This function is used internally to remove the page pPage from the
+** This function is used internally to remove the page pPage from the
** PGroup LRU list, if is part of it. If pPage is not part of the PGroup
** LRU list, then this function is a no-op.
**
/*
-** Remove the page supplied as an argument from the hash table
+** Remove the page supplied as an argument from the hash table
** (PCache1.apHash structure) that it is currently stored in.
**
** The PGroup mutex must be held when this function is called.
}
/*
-** Discard all pages from cache pCache with a page number (key value)
-** greater than or equal to iLimit. Any pinned pages that meet this
+** Discard all pages from cache pCache with a page number (key value)
+** greater than or equal to iLimit. Any pinned pages that meet this
** criteria are unpinned before they are discarded.
**
** The PCache mutex must be held when this function is called.
unsigned int h;
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
for(h=0; h<pCache->nHash; h++){
- PgHdr1 **pp = &pCache->apHash[h];
+ PgHdr1 **pp = &pCache->apHash[h];
PgHdr1 *pPage;
while( (pPage = *pp)!=0 ){
if( pPage->iKey>=iLimit ){
/*
** Implementation of the sqlite3_pcache.xShutdown method.
-** Note that the static mutex allocated in xInit does
+** Note that the static mutex allocated in xInit does
** not need to be freed.
*/
static void pcache1Shutdown(void *NotUsed){
}
/*
-** Implementation of the sqlite3_pcache.xCachesize method.
+** Implementation of the sqlite3_pcache.xCachesize method.
**
** Configure the cache_size limit for a cache.
*/
}
/*
-** Implementation of the sqlite3_pcache.xShrink method.
+** Implementation of the sqlite3_pcache.xShrink method.
**
** Free up as much memory as possible.
*/
}
/*
-** Implementation of the sqlite3_pcache.xPagecount method.
+** Implementation of the sqlite3_pcache.xPagecount method.
*/
static int pcache1Pagecount(sqlite3_pcache *p){
int n;
}
/*
-** Implementation of the sqlite3_pcache.xFetch method.
+** Implementation of the sqlite3_pcache.xFetch method.
**
** Fetch a page by key value.
**
** Whether or not a new page may be allocated by this function depends on
** the value of the createFlag argument. 0 means do not allocate a new
-** page. 1 means allocate a new page if space is easily available. 2
+** page. 1 means allocate a new page if space is easily available. 2
** means to try really hard to allocate a new page.
**
** For a non-purgeable cache (a cache used as the storage for an in-memory
** There are three different approaches to obtaining space for a page,
** depending on the value of parameter createFlag (which may be 0, 1 or 2).
**
-** 1. Regardless of the value of createFlag, the cache is searched for a
+** 1. Regardless of the value of createFlag, the cache is searched for a
** copy of the requested page. If one is found, it is returned.
**
** 2. If createFlag==0 and the page is not already in the cache, NULL is
** PCache1.nMax, or
**
** (b) the number of pages pinned by the cache is greater than
-** the sum of nMax for all purgeable caches, less the sum of
+** the sum of nMax for all purgeable caches, less the sum of
** nMin for all other purgeable caches, or
**
** 4. If none of the first three conditions apply and the cache is marked
** as purgeable, and if one of the following is true:
**
-** (a) The number of pages allocated for the cache is already
+** (a) The number of pages allocated for the cache is already
** PCache1.nMax, or
**
** (b) The number of pages allocated for all purgeable caches is
**
** then attempt to recycle a page from the LRU list. If it is the right
** size, return the recycled buffer. Otherwise, free the buffer and
-** proceed to step 5.
+** proceed to step 5.
**
** 5. Otherwise, allocate and return a new page buffer.
*/
static sqlite3_pcache_page *pcache1Fetch(
- sqlite3_pcache *p,
- unsigned int iKey,
+ sqlite3_pcache *p,
+ unsigned int iKey,
int createFlag
){
unsigned int nPinned;
}
}
- /* Step 5. If a usable page buffer has still not been found,
- ** attempt to allocate a new one.
+ /* Step 5. If a usable page buffer has still not been found,
+ ** attempt to allocate a new one.
*/
if( !pPage ){
if( createFlag==1 ) sqlite3BeginBenignMalloc();
** Mark a page as unpinned (eligible for asynchronous recycling).
*/
static void pcache1Unpin(
- sqlite3_pcache *p,
- sqlite3_pcache_page *pPg,
+ sqlite3_pcache *p,
+ sqlite3_pcache_page *pPg,
int reuseUnlikely
){
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = (PgHdr1 *)pPg;
PGroup *pGroup = pCache->pGroup;
-
+
assert( pPage->pCache==pCache );
pcache1EnterMutex(pGroup);
- /* It is an error to call this function if the page is already
+ /* It is an error to call this function if the page is already
** part of the PGroup LRU list.
*/
assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
}
/*
-** Implementation of the sqlite3_pcache.xRekey method.
+** Implementation of the sqlite3_pcache.xRekey method.
*/
static void pcache1Rekey(
sqlite3_pcache *p,
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = (PgHdr1 *)pPg;
PgHdr1 **pp;
- unsigned int h;
+ unsigned int h;
assert( pPage->iKey==iOld );
assert( pPage->pCache==pCache );
}
/*
-** Implementation of the sqlite3_pcache.xTruncate method.
+** Implementation of the sqlite3_pcache.xTruncate method.
**
** Discard all unpinned pages in the cache with a page number equal to
** or greater than parameter iLimit. Any pinned pages with a page number
}
/*
-** Implementation of the sqlite3_pcache.xDestroy method.
+** Implementation of the sqlite3_pcache.xDestroy method.
**
** Destroy a cache allocated using pcache1Create().
*/
** by the current thread may be sqlite3_free()ed.
**
** nReq is the number of bytes of memory required. Once this much has
-** been released, the function returns. The return value is the total number
+** been released, the function returns. The return value is the total number
** of bytes of memory released.
*/
SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
** extracts the least value from the RowSet.
**
** The INSERT primitive might allocate additional memory. Memory is
-** allocated in chunks so most INSERTs do no allocation. There is an
+** allocated in chunks so most INSERTs do no allocation. There is an
** upper bound on the size of allocated memory. No memory is freed
** until DESTROY.
**
** in the list, pLeft points to the tree, and v is unused. The
** RowSet.pForest value points to the head of this forest list.
*/
-struct RowSetEntry {
+struct RowSetEntry {
i64 v; /* ROWID value for this entry */
struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */
struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */
**
** It must be the case that N is sufficient to make a Rowset. If not
** an assertion fault occurs.
-**
+**
** If N is larger than the minimum, use the surplus as an initial
** allocation of entries available to be filled.
*/
/*
** Merge two lists of RowSetEntry objects. Remove duplicates.
**
-** The input lists are connected via pRight pointers and are
+** The input lists are connected via pRight pointers and are
** assumed to each already be in sorted order.
*/
static struct RowSetEntry *rowSetEntryMerge(
/*
** Sort all elements on the list of RowSetEntry objects into order of
** increasing v.
-*/
+*/
static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){
unsigned int i;
struct RowSetEntry *pNext, *aBucket[40];
** 0 if the RowSet is already empty.
**
** After this routine has been called, the sqlite3RowSetInsert()
-** routine may not be called again.
+** routine may not be called again.
*/
SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
assert( p!=0 );
/* This routine is never called after sqlite3RowSetNext() */
assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );
- /* Sort entries into the forest on the first test of a new batch
+ /* Sort entries into the forest on the first test of a new batch
*/
if( iBatch!=pRowSet->iBatch ){
p = pRowSet->pEntry;
**
*************************************************************************
** This is the implementation of the page cache subsystem or "pager".
-**
+**
** The pager is used to access a database disk file. It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file. The pager also implements file
** May you share freely, never taking more than you give.
**
*************************************************************************
-** This header file defines the interface to the write-ahead logging
-** system. Refer to the comments below and the header comment attached to
+** This header file defines the interface to the write-ahead logging
+** system. Refer to the comments below and the header comment attached to
** the implementation of each function in log.c for further details.
*/
#define WAL_SAVEPOINT_NDATA 4
-/* Connection to a write-ahead log (WAL) file.
-** There is one object of this type for each pager.
+/* Connection to a write-ahead log (WAL) file.
+** There is one object of this type for each pager.
*/
typedef struct Wal Wal;
/* Set the limiting size of a WAL file. */
SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
-/* Used by readers to open (lock) and close (unlock) a snapshot. A
+/* Used by readers to open (lock) and close (unlock) a snapshot. A
** snapshot is like a read-transaction. It is the state of the database
** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and
** preserves the current state even if the other threads or processes
/* Write a frame or frames to the log. */
SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
-/* Copy pages from the log to the database file */
+/* Copy pages from the log to the database file */
SQLITE_PRIVATE int sqlite3WalCheckpoint(
Wal *pWal, /* Write-ahead log connection */
int eMode, /* One of PASSIVE, FULL and RESTART */
/* Return true if the argument is non-NULL and the WAL module is using
** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
-** WAL module is using shared-memory, return false.
+** WAL module is using shared-memory, return false.
*/
SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
**
** Definition: A page of the database file is said to be "overwriteable" if
** one or more of the following are true about the page:
-**
+**
** (a) The original content of the page as it was at the beginning of
** the transaction has been written into the rollback journal and
** synced.
-**
+**
** (b) The page was a freelist leaf page at the start of the transaction.
-**
+**
** (c) The page number is greater than the largest page that existed in
** the database file at the start of the transaction.
-**
+**
** (1) A page of the database file is never overwritten unless one of the
** following are true:
-**
+**
** (a) The page and all other pages on the same sector are overwriteable.
-**
+**
** (b) The atomic page write optimization is enabled, and the entire
** transaction other than the update of the transaction sequence
** number consists of a single page change.
-**
+**
** (2) The content of a page written into the rollback journal exactly matches
** both the content in the database when the rollback journal was written
** and the content in the database at the beginning of the current
** transaction.
-**
+**
** (3) Writes to the database file are an integer multiple of the page size
** in length and are aligned on a page boundary.
-**
+**
** (4) Reads from the database file are either aligned on a page boundary and
** an integer multiple of the page size in length or are taken from the
** first 100 bytes of the database file.
-**
+**
** (5) All writes to the database file are synced prior to the rollback journal
** being deleted, truncated, or zeroed.
-**
+**
** (6) If a master journal file is used, then all writes to the database file
** are synced prior to the master journal being deleted.
-**
+**
** Definition: Two databases (or the same database at two points it time)
** are said to be "logically equivalent" if they give the same answer to
** all queries. Note in particular the content of freelist leaf
** pages can be changed arbitarily without effecting the logical equivalence
** of the database.
-**
+**
** (7) At any time, if any subset, including the empty set and the total set,
-** of the unsynced changes to a rollback journal are removed and the
+** of the unsynced changes to a rollback journal are removed and the
** journal is rolled back, the resulting database file will be logical
** equivalent to the database file at the beginning of the transaction.
-**
+**
** (8) When a transaction is rolled back, the xTruncate method of the VFS
** is called to restore the database file to the same size it was at
** the beginning of the transaction. (In some VFSes, the xTruncate
** method is a no-op, but that does not change the fact the SQLite will
** invoke it.)
-**
+**
** (9) Whenever the database file is modified, at least one bit in the range
** of bytes from 24 through 39 inclusive will be changed prior to releasing
** the EXCLUSIVE lock, thus signaling other connections on the same
/*
** The following two macros are used within the PAGERTRACE() macros above
-** to print out file-descriptors.
+** to print out file-descriptors.
**
** PAGERID() takes a pointer to a Pager struct as its argument. The
** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
** | | |
** | V |
** |<-------WRITER_LOCKED------> ERROR
-** | | ^
+** | | ^
** | V |
** |<------WRITER_CACHEMOD-------->|
** | | |
**
**
** List of state transitions and the C [function] that performs each:
-**
+**
** OPEN -> READER [sqlite3PagerSharedLock]
** READER -> OPEN [pager_unlock]
**
**
** WRITER_*** -> ERROR [pager_error]
** ERROR -> OPEN [pager_unlock]
-**
+**
**
** OPEN:
**
**
** READER:
**
-** In this state all the requirements for reading the database in
+** In this state all the requirements for reading the database in
** rollback (non-WAL) mode are met. Unless the pager is (or recently
-** was) in exclusive-locking mode, a user-level read transaction is
+** was) in exclusive-locking mode, a user-level read transaction is
** open. The database size is known in this state.
**
** A connection running with locking_mode=normal enters this state when
** this state even after the read-transaction is closed. The only way
** a locking_mode=exclusive connection can transition from READER to OPEN
** is via the ERROR state (see below).
-**
+**
** * A read transaction may be active (but a write-transaction cannot).
** * A SHARED or greater lock is held on the database file.
-** * The dbSize variable may be trusted (even if a user-level read
+** * The dbSize variable may be trusted (even if a user-level read
** transaction is not active). The dbOrigSize and dbFileSize variables
** may not be trusted at this point.
** * If the database is a WAL database, then the WAL connection is open.
-** * Even if a read-transaction is not open, it is guaranteed that
+** * Even if a read-transaction is not open, it is guaranteed that
** there is no hot-journal in the file-system.
**
** WRITER_LOCKED:
**
** The pager moves to this state from READER when a write-transaction
-** is first opened on the database. In WRITER_LOCKED state, all locks
-** required to start a write-transaction are held, but no actual
+** is first opened on the database. In WRITER_LOCKED state, all locks
+** required to start a write-transaction are held, but no actual
** modifications to the cache or database have taken place.
**
-** In rollback mode, a RESERVED or (if the transaction was opened with
+** In rollback mode, a RESERVED or (if the transaction was opened with
** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when
-** moving to this state, but the journal file is not written to or opened
-** to in this state. If the transaction is committed or rolled back while
-** in WRITER_LOCKED state, all that is required is to unlock the database
+** moving to this state, but the journal file is not written to or opened
+** to in this state. If the transaction is committed or rolled back while
+** in WRITER_LOCKED state, all that is required is to unlock the database
** file.
**
** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file.
** is made to obtain an EXCLUSIVE lock on the database file.
**
** * A write transaction is active.
-** * If the connection is open in rollback-mode, a RESERVED or greater
+** * If the connection is open in rollback-mode, a RESERVED or greater
** lock is held on the database file.
** * If the connection is open in WAL-mode, a WAL write transaction
** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully
**
** * A write transaction is active.
** * A RESERVED or greater lock is held on the database file.
-** * The journal file is open and the first header has been written
+** * The journal file is open and the first header has been written
** to it, but the header has not been synced to disk.
** * The contents of the page cache have been modified.
**
**
** * A write transaction is active.
** * An EXCLUSIVE or greater lock is held on the database file.
-** * The journal file is open and the first header has been written
+** * The journal file is open and the first header has been written
** and synced to disk.
** * The contents of the page cache have been modified (and possibly
** written to disk).
** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD
** state after the entire transaction has been successfully written into the
** database file. In this state the transaction may be committed simply
-** by finalizing the journal file. Once in WRITER_FINISHED state, it is
-** not possible to modify the database further. At this point, the upper
+** by finalizing the journal file. Once in WRITER_FINISHED state, it is
+** not possible to modify the database further. At this point, the upper
** layer must either commit or rollback the transaction.
**
** * A write transaction is active.
** * All writing and syncing of journal and database data has finished.
** If no error occurred, all that remains is to finalize the journal to
** commit the transaction. If an error did occur, the caller will need
-** to rollback the transaction.
+** to rollback the transaction.
**
** ERROR:
**
** The ERROR state is entered when an IO or disk-full error (including
-** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it
-** difficult to be sure that the in-memory pager state (cache contents,
+** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it
+** difficult to be sure that the in-memory pager state (cache contents,
** db size etc.) are consistent with the contents of the file-system.
**
** Temporary pager files may enter the ERROR state, but in-memory pagers
** cannot.
**
-** For example, if an IO error occurs while performing a rollback,
+** For example, if an IO error occurs while performing a rollback,
** the contents of the page-cache may be left in an inconsistent state.
** At this point it would be dangerous to change back to READER state
** (as usually happens after a rollback). Any subsequent readers might
** instead of READER following such an error.
**
** Once it has entered the ERROR state, any attempt to use the pager
-** to read or write data returns an error. Eventually, once all
+** to read or write data returns an error. Eventually, once all
** outstanding transactions have been abandoned, the pager is able to
-** transition back to OPEN state, discarding the contents of the
+** transition back to OPEN state, discarding the contents of the
** page-cache and any other in-memory state at the same time. Everything
** is reloaded from disk (and, if necessary, hot-journal rollback peformed)
** when a read-transaction is next opened on the pager (transitioning
-** the pager into READER state). At that point the system has recovered
+** the pager into READER state). At that point the system has recovered
** from the error.
**
** Specifically, the pager jumps into the ERROR state if:
** memory.
**
** In other cases, the error is returned to the b-tree layer. The b-tree
-** layer then attempts a rollback operation. If the error condition
+** layer then attempts a rollback operation. If the error condition
** persists, the pager enters the ERROR state via condition (1) above.
**
** Condition (3) is necessary because it can be triggered by a read-only
** statement executed within a transaction. In this case, if the error
** code were simply returned to the user, the b-tree layer would not
** automatically attempt a rollback, as it assumes that an error in a
-** read-only statement cannot leave the pager in an internally inconsistent
+** read-only statement cannot leave the pager in an internally inconsistent
** state.
**
** * The Pager.errCode variable is set to something other than SQLITE_OK.
** * There are one or more outstanding references to pages (after the
** last reference is dropped the pager should move back to OPEN state).
** * The pager is not an in-memory pager.
-**
+**
**
** Notes:
**
**
** * Normally, a connection open in exclusive mode is never in PAGER_OPEN
** state. There are two exceptions: immediately after exclusive-mode has
-** been turned on (and before any read or write transactions are
+** been turned on (and before any read or write transactions are
** executed), and when the pager is leaving the "error state".
**
** * See also: assert_pager_state().
#define PAGER_ERROR 6
/*
-** The Pager.eLock variable is almost always set to one of the
+** The Pager.eLock variable is almost always set to one of the
** following locking-states, according to the lock currently held on
** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
** This variable is kept up to date as locks are taken and released by
** to a less exclusive (lower) value than the lock that is actually held
** at the system level, but it is never set to a more exclusive value.
**
-** This is usually safe. If an xUnlock fails or appears to fail, there may
+** This is usually safe. If an xUnlock fails or appears to fail, there may
** be a few redundant xLock() calls or a lock may be held for longer than
** required, but nothing really goes wrong.
**
** The exception is when the database file is unlocked as the pager moves
-** from ERROR to OPEN state. At this point there may be a hot-journal file
+** from ERROR to OPEN state. At this point there may be a hot-journal file
** in the file-system that needs to be rolled back (as part of a OPEN->SHARED
** transition, by the same pager or any other). If the call to xUnlock()
** fails at this point and the pager is left holding an EXCLUSIVE lock, this
** can confuse the call to xCheckReservedLock() call made later as part
** of hot-journal detection.
**
-** xCheckReservedLock() is defined as returning true "if there is a RESERVED
-** lock held by this process or any others". So xCheckReservedLock may
+** xCheckReservedLock() is defined as returning true "if there is a RESERVED
+** lock held by this process or any others". So xCheckReservedLock may
** return true because the caller itself is holding an EXCLUSIVE lock (but
** doesn't know it because of a previous error in xUnlock). If this happens
** a hot-journal may be mistaken for a journal being created by an active
** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It
** is only changed back to a real locking state after a successful call
** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition
-** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK
+** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK
** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE
** lock on the database file before attempting to roll it back. See function
** PagerSharedLock() for more detail.
**
-** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in
+** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in
** PAGER_OPEN state.
*/
#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1)
#endif
/*
-** The maximum allowed sector size. 64KiB. If the xSectorsize() method
+** The maximum allowed sector size. 64KiB. If the xSectorsize() method
** returns a value larger than this, then MAX_SECTOR_SIZE is used instead.
** This could conceivably cause corruption following a power failure on
** such a system. This is currently an undocumented limit.
**
** When a savepoint is created, the PagerSavepoint.iHdrOffset field is
** set to 0. If a journal-header is written into the main journal while
-** the savepoint is active, then iHdrOffset is set to the byte offset
+** the savepoint is active, then iHdrOffset is set to the byte offset
** immediately following the last journal record written into the main
** journal before the journal-header. This is required during savepoint
** rollback (see pagerPlaybackSavepoint()).
**
** changeCountDone
**
-** This boolean variable is used to make sure that the change-counter
-** (the 4-byte header field at byte offset 24 of the database file) is
-** not updated more often than necessary.
+** This boolean variable is used to make sure that the change-counter
+** (the 4-byte header field at byte offset 24 of the database file) is
+** not updated more often than necessary.
**
-** It is set to true when the change-counter field is updated, which
+** It is set to true when the change-counter field is updated, which
** can only happen if an exclusive lock is held on the database file.
-** It is cleared (set to false) whenever an exclusive lock is
+** It is cleared (set to false) whenever an exclusive lock is
** relinquished on the database file. Each time a transaction is committed,
** The changeCountDone flag is inspected. If it is true, the work of
** updating the change-counter is omitted for the current transaction.
**
-** This mechanism means that when running in exclusive mode, a connection
+** This mechanism means that when running in exclusive mode, a connection
** need only update the change-counter once, for the first transaction
** committed.
**
** setMaster
**
** When PagerCommitPhaseOne() is called to commit a transaction, it may
-** (or may not) specify a master-journal name to be written into the
+** (or may not) specify a master-journal name to be written into the
** journal file before it is synced to disk.
**
-** Whether or not a journal file contains a master-journal pointer affects
-** the way in which the journal file is finalized after the transaction is
+** Whether or not a journal file contains a master-journal pointer affects
+** the way in which the journal file is finalized after the transaction is
** committed or rolled back when running in "journal_mode=PERSIST" mode.
** If a journal file does not contain a master-journal pointer, it is
** finalized by overwriting the first journal header with zeroes. If
-** it does contain a master-journal pointer the journal file is finalized
-** by truncating it to zero bytes, just as if the connection were
+** it does contain a master-journal pointer the journal file is finalized
+** by truncating it to zero bytes, just as if the connection were
** running in "journal_mode=truncate" mode.
**
** Journal files that contain master journal pointers cannot be finalized
** comes up during savepoint rollback that requires the pcache module
** to allocate a new page to prevent the journal file from being written
** while it is being traversed by code in pager_playback().
-**
+**
** If doNotSyncSpill is non-zero, writing to the database from pagerStress()
** is permitted, but syncing the journal file is not. This flag is set
** by sqlite3PagerWrite() when the file-system sector-size is larger than
-** the database page-size in order to prevent a journal sync from happening
-** in between the journalling of two pages on the same sector.
+** the database page-size in order to prevent a journal sync from happening
+** in between the journalling of two pages on the same sector.
**
** subjInMemory
**
** is opened as an in-memory journal file. If false, then in-memory
** sub-journals are only used for in-memory pager files.
**
-** This variable is updated by the upper layer each time a new
+** This variable is updated by the upper layer each time a new
** write-transaction is opened.
**
** dbSize, dbOrigSize, dbFileSize
**
** Variable dbSize is set to the number of pages in the database file.
** It is valid in PAGER_READER and higher states (all states except for
-** OPEN and ERROR).
+** OPEN and ERROR).
**
-** dbSize is set based on the size of the database file, which may be
+** dbSize is set based on the size of the database file, which may be
** larger than the size of the database (the value stored at offset
** 28 of the database header by the btree). If the size of the file
** is not an integer multiple of the page-size, the value stored in
**
** During a write-transaction, if pages with page-numbers greater than
** dbSize are modified in the cache, dbSize is updated accordingly.
-** Similarly, if the database is truncated using PagerTruncateImage(),
+** Similarly, if the database is truncated using PagerTruncateImage(),
** dbSize is updated.
**
-** Variables dbOrigSize and dbFileSize are valid in states
+** Variables dbOrigSize and dbFileSize are valid in states
** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize
** variable at the start of the transaction. It is used during rollback,
** and to determine whether or not pages need to be journalled before
** Throughout a write-transaction, dbFileSize contains the size of
** the file on disk in pages. It is set to a copy of dbSize when the
** write-transaction is first opened, and updated when VFS calls are made
-** to write or truncate the database file on disk.
+** to write or truncate the database file on disk.
**
-** The only reason the dbFileSize variable is required is to suppress
-** unnecessary calls to xTruncate() after committing a transaction. If,
-** when a transaction is committed, the dbFileSize variable indicates
-** that the database file is larger than the database image (Pager.dbSize),
+** The only reason the dbFileSize variable is required is to suppress
+** unnecessary calls to xTruncate() after committing a transaction. If,
+** when a transaction is committed, the dbFileSize variable indicates
+** that the database file is larger than the database image (Pager.dbSize),
** pager_truncate() is called. The pager_truncate() call uses xFilesize()
** to measure the database file on disk, and then truncates it if required.
** dbFileSize is not used when rolling back a transaction. In this case
** dbHintSize
**
** The dbHintSize variable is used to limit the number of calls made to
-** the VFS xFileControl(FCNTL_SIZE_HINT) method.
+** the VFS xFileControl(FCNTL_SIZE_HINT) method.
**
** dbHintSize is set to a copy of the dbSize variable when a
** write-transaction is opened (at the same time as dbFileSize and
** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called,
** dbHintSize is increased to the number of pages that correspond to the
-** size-hint passed to the method call. See pager_write_pagelist() for
+** size-hint passed to the method call. See pager_write_pagelist() for
** details.
**
** errCode
**
** The Pager.errCode variable is only ever used in PAGER_ERROR state. It
-** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode
-** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX
+** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode
+** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX
** sub-codes.
*/
struct Pager {
/*
** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
-** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
+** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
** or CACHE_WRITE to sqlite3_db_status().
*/
#define PAGER_STAT_HIT 0
#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8)
/*
-** The journal header size for this pager. This is usually the same
+** The journal header size for this pager. This is usually the same
** size as a single disk sector. See also setSectorSize().
*/
#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize)
# define pagerBeginReadTransaction(z) SQLITE_OK
#endif
-#ifndef NDEBUG
+#ifndef NDEBUG
/*
** Usage:
**
assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK );
assert( p->tempFile==0 || pPager->changeCountDone );
- /* If the useJournal flag is clear, the journal-mode must be "OFF".
+ /* If the useJournal flag is clear, the journal-mode must be "OFF".
** And if the journal-mode is "OFF", the journal file must not be open.
*/
assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal );
assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) );
- /* Check that MEMDB implies noSync. And an in-memory journal. Since
- ** this means an in-memory pager performs no IO at all, it cannot encounter
- ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing
- ** a journal file. (although the in-memory journal implementation may
- ** return SQLITE_IOERR_NOMEM while the journal file is being written). It
- ** is therefore not possible for an in-memory pager to enter the ERROR
+ /* Check that MEMDB implies noSync. And an in-memory journal. Since
+ ** this means an in-memory pager performs no IO at all, it cannot encounter
+ ** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing
+ ** a journal file. (although the in-memory journal implementation may
+ ** return SQLITE_IOERR_NOMEM while the journal file is being written). It
+ ** is therefore not possible for an in-memory pager to enter the ERROR
** state.
*/
if( MEMDB ){
assert( p->noSync );
- assert( p->journalMode==PAGER_JOURNALMODE_OFF
- || p->journalMode==PAGER_JOURNALMODE_MEMORY
+ assert( p->journalMode==PAGER_JOURNALMODE_OFF
+ || p->journalMode==PAGER_JOURNALMODE_MEMORY
);
assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
assert( pagerUseWal(p)==0 );
** to journal_mode=wal.
*/
assert( p->eLock>=RESERVED_LOCK );
- assert( isOpen(p->jfd)
- || p->journalMode==PAGER_JOURNALMODE_OFF
- || p->journalMode==PAGER_JOURNALMODE_WAL
+ assert( isOpen(p->jfd)
+ || p->journalMode==PAGER_JOURNALMODE_OFF
+ || p->journalMode==PAGER_JOURNALMODE_WAL
);
}
assert( pPager->dbOrigSize==pPager->dbFileSize );
assert( pPager->errCode==SQLITE_OK );
assert( !pagerUseWal(pPager) );
assert( p->eLock>=EXCLUSIVE_LOCK );
- assert( isOpen(p->jfd)
- || p->journalMode==PAGER_JOURNALMODE_OFF
- || p->journalMode==PAGER_JOURNALMODE_WAL
+ assert( isOpen(p->jfd)
+ || p->journalMode==PAGER_JOURNALMODE_OFF
+ || p->journalMode==PAGER_JOURNALMODE_WAL
);
assert( pPager->dbOrigSize<=pPager->dbHintSize );
break;
assert( p->eLock==EXCLUSIVE_LOCK );
assert( pPager->errCode==SQLITE_OK );
assert( !pagerUseWal(pPager) );
- assert( isOpen(p->jfd)
- || p->journalMode==PAGER_JOURNALMODE_OFF
- || p->journalMode==PAGER_JOURNALMODE_WAL
+ assert( isOpen(p->jfd)
+ || p->journalMode==PAGER_JOURNALMODE_OFF
+ || p->journalMode==PAGER_JOURNALMODE_WAL
);
break;
}
#endif /* ifndef NDEBUG */
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
/*
** Return a pointer to a human readable string in a static buffer
** containing the state of the Pager object passed as an argument. This
** succeeds, set the Pager.eLock variable to match the (attempted) new lock.
**
** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
-** called, do not modify it. See the comment above the #define of
+** called, do not modify it. See the comment above the #define of
** UNKNOWN_LOCK for an explanation of this.
*/
static int pagerUnlockDb(Pager *pPager, int eLock){
/*
** Lock the database file to level eLock, which must be either SHARED_LOCK,
** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
-** Pager.eLock variable to the new locking state.
+** Pager.eLock variable to the new locking state.
**
-** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
-** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK.
-** See the comment above the #define of UNKNOWN_LOCK for an explanation
+** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
+** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK.
+** See the comment above the #define of UNKNOWN_LOCK for an explanation
** of this.
*/
static int pagerLockDb(Pager *pPager, int eLock){
/*
** When this is called the journal file for pager pPager must be open.
-** This function attempts to read a master journal file name from the
-** end of the file and, if successful, copies it into memory supplied
+** This function attempts to read a master journal file name from the
+** end of the file and, if successful, copies it into memory supplied
** by the caller. See comments above writeMasterJournal() for the format
** used to store a master journal file name at the end of a journal file.
**
** nul-terminator byte is appended to the buffer following the master
** journal file name.
**
-** If it is determined that no master journal file name is present
+** If it is determined that no master journal file name is present
** zMaster[0] is set to 0 and SQLITE_OK returned.
**
** If an error occurs while reading from the journal file, an SQLite
if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
|| szJ<16
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
- || len>=nMaster
+ || len>=nMaster
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|| memcmp(aMagic, aJournalMagic, 8)
len = 0;
}
zMaster[len] = '\0';
-
+
return SQLITE_OK;
}
/*
-** Return the offset of the sector boundary at or immediately
-** following the value in pPager->journalOff, assuming a sector
+** Return the offset of the sector boundary at or immediately
+** following the value in pPager->journalOff, assuming a sector
** size of pPager->sectorSize bytes.
**
** i.e for a sector size of 512:
** 512 512
** 100 512
** 2000 2048
-**
+**
*/
static i64 journalHdrOffset(Pager *pPager){
i64 offset = 0;
**
** If doTruncate is non-zero or the Pager.journalSizeLimit variable is
** set to 0, then truncate the journal file to zero bytes in size. Otherwise,
-** zero the 28-byte header at the start of the journal file. In either case,
-** if the pager is not in no-sync mode, sync the journal file immediately
+** zero the 28-byte header at the start of the journal file. In either case,
+** if the pager is not in no-sync mode, sync the journal file immediately
** after writing or truncating it.
**
** If Pager.journalSizeLimit is set to a positive, non-zero value, and
-** following the truncation or zeroing described above the size of the
+** following the truncation or zeroing described above the size of the
** journal file in bytes is larger than this value, then truncate the
** journal file to Pager.journalSizeLimit bytes. The journal file does
** not need to be synced following this operation.
rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags);
}
- /* At this point the transaction is committed but the write lock
- ** is still held on the file. If there is a size limit configured for
+ /* At this point the transaction is committed but the write lock
+ ** is still held on the file. If there is a size limit configured for
** the persistent journal and the journal file currently consumes more
** space than that limit allows for, truncate it now. There is no need
** to sync the file following this operation.
** - 4 bytes: Initial database page count.
** - 4 bytes: Sector size used by the process that wrote this journal.
** - 4 bytes: Database page size.
-**
+**
** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
*/
static int writeJournalHdr(Pager *pPager){
nHeader = JOURNAL_HDR_SZ(pPager);
}
- /* If there are active savepoints and any of them were created
- ** since the most recent journal header was written, update the
+ /* If there are active savepoints and any of them were created
+ ** since the most recent journal header was written, update the
** PagerSavepoint.iHdrOffset fields now.
*/
for(ii=0; ii<pPager->nSavepoint; ii++){
pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager);
- /*
+ /*
** Write the nRec Field - the number of page records that follow this
** journal header. Normally, zero is written to this value at this time.
- ** After the records are added to the journal (and the journal synced,
+ ** After the records are added to the journal (and the journal synced,
** if in full-sync mode), the zero is overwritten with the true number
** of records (see syncJournal()).
**
*/
assert( isOpen(pPager->fd) || pPager->noSync );
if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
- || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
+ || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
){
memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
memset(zHeader, 0, sizeof(aJournalMagic)+4);
}
- /* The random check-hash initializer */
+ /* The random check-hash initializer */
sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
/* The initial database size */
memset(&zHeader[sizeof(aJournalMagic)+20], 0,
nHeader-(sizeof(aJournalMagic)+20));
- /* In theory, it is only necessary to write the 28 bytes that the
- ** journal header consumes to the journal file here. Then increment the
- ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next
+ /* In theory, it is only necessary to write the 28 bytes that the
+ ** journal header consumes to the journal file here. Then increment the
+ ** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next
** record is written to the following sector (leaving a gap in the file
** that will be implicitly filled in by the OS).
**
- ** However it has been discovered that on some systems this pattern can
+ ** However it has been discovered that on some systems this pattern can
** be significantly slower than contiguously writing data to the file,
- ** even if that means explicitly writing data to the block of
+ ** even if that means explicitly writing data to the block of
** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what
- ** is done.
+ ** is done.
**
- ** The loop is required here in case the sector-size is larger than the
+ ** The loop is required here in case the sector-size is larger than the
** database page size. Since the zHeader buffer is only Pager.pageSize
** bytes in size, more than one call to sqlite3OsWrite() may be required
** to populate the entire journal header sector.
- */
+ */
for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){
IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))
rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
/* Check that the values read from the page-size and sector-size fields
** are within range. To be 'in range', both values need to be a power
- ** of two greater than or equal to 512 or 32, and not greater than their
+ ** of two greater than or equal to 512 or 32, and not greater than their
** respective compile time maximum limits.
*/
if( iPageSize<512 || iSectorSize<32
|| iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE
- || ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0
+ || ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0
){
- /* If the either the page-size or sector-size in the journal-header is
- ** invalid, then the process that wrote the journal-header must have
- ** crashed before the header was synced. In this case stop reading
+ /* If the either the page-size or sector-size in the journal-header is
+ ** invalid, then the process that wrote the journal-header must have
+ ** crashed before the header was synced. In this case stop reading
** the journal file here.
*/
return SQLITE_DONE;
}
- /* Update the page-size to match the value read from the journal.
- ** Use a testcase() macro to make sure that malloc failure within
+ /* Update the page-size to match the value read from the journal.
+ ** Use a testcase() macro to make sure that malloc failure within
** PagerSetPagesize() is tested.
*/
rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1);
testcase( rc!=SQLITE_OK );
- /* Update the assumed sector-size to match the value used by
+ /* Update the assumed sector-size to match the value used by
** the process that created this journal. If this journal was
** created by a process other than this one, then this routine
** is being called from within pager_playback(). The local value
** The master journal page checksum is the sum of the bytes in the master
** journal name, where each byte is interpreted as a signed 8-bit integer.
**
-** If zMaster is a NULL pointer (occurs for a single database transaction),
+** If zMaster is a NULL pointer (occurs for a single database transaction),
** this call is a no-op.
*/
static int writeMasterJournal(Pager *pPager, const char *zMaster){
assert( pPager->setMaster==0 );
assert( !pagerUseWal(pPager) );
- if( !zMaster
- || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
- || pPager->journalMode==PAGER_JOURNALMODE_OFF
+ if( !zMaster
+ || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
+ || pPager->journalMode==PAGER_JOURNALMODE_OFF
){
return SQLITE_OK;
}
}
pPager->journalOff += (nMaster+20);
- /* If the pager is in peristent-journal mode, then the physical
+ /* If the pager is in peristent-journal mode, then the physical
** journal-file may extend past the end of the master-journal name
- ** and 8 bytes of magic data just written to the file. This is
+ ** and 8 bytes of magic data just written to the file. This is
** dangerous because the code to rollback a hot-journal file
- ** will not be able to find the master-journal name to determine
- ** whether or not the journal is hot.
+ ** will not be able to find the master-journal name to determine
+ ** whether or not the journal is hot.
**
- ** Easiest thing to do in this scenario is to truncate the journal
+ ** Easiest thing to do in this scenario is to truncate the journal
** file to the required size.
- */
+ */
if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))
&& jrnlSize>pPager->journalOff
){
/*
** Find a page in the hash table given its page number. Return
-** a pointer to the page or NULL if the requested page is not
+** a pointer to the page or NULL if the requested page is not
** already in memory.
*/
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
}
/*
-** Set the bit number pgno in the PagerSavepoint.pInSavepoint
+** Set the bit number pgno in the PagerSavepoint.pInSavepoint
** bitvecs of all open savepoints. Return SQLITE_OK if successful
** or SQLITE_NOMEM if a malloc failure occurs.
*/
** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is
** closed (if it is open).
**
-** If the pager is in ERROR state when this function is called, the
-** contents of the pager cache are discarded before switching back to
+** If the pager is in ERROR state when this function is called, the
+** contents of the pager cache are discarded before switching back to
** the OPEN state. Regardless of whether the pager is in exclusive-mode
** or not, any journal file left in the file-system will be treated
** as a hot-journal and rolled back the next time a read-transaction
*/
static void pager_unlock(Pager *pPager){
- assert( pPager->eState==PAGER_READER
- || pPager->eState==PAGER_OPEN
- || pPager->eState==PAGER_ERROR
+ assert( pPager->eState==PAGER_READER
+ || pPager->eState==PAGER_OPEN
+ || pPager->eState==PAGER_ERROR
);
sqlite3BitvecDestroy(pPager->pInJournal);
/*
** This function is called whenever an IOERR or FULL error that requires
** the pager to transition into the ERROR state may ahve occurred.
-** The first argument is a pointer to the pager structure, the second
-** the error-code about to be returned by a pager API function. The
-** value returned is a copy of the second argument to this function.
+** The first argument is a pointer to the pager structure, the second
+** the error-code about to be returned by a pager API function. The
+** value returned is a copy of the second argument to this function.
**
** If the second argument is SQLITE_FULL, SQLITE_IOERR or one of the
** IOERR sub-codes, the pager enters the ERROR state and the error code
** is stored in Pager.errCode. While the pager remains in the ERROR state,
** all major API calls on the Pager will immediately return Pager.errCode.
**
-** The ERROR state indicates that the contents of the pager-cache
-** cannot be trusted. This state can be cleared by completely discarding
+** The ERROR state indicates that the contents of the pager-cache
+** cannot be trusted. This state can be cleared by completely discarding
** the contents of the pager-cache. If a transaction was active when
** the persistent error occurred, then the rollback journal may need
** to be replayed to restore the contents of the database file (as if
static int pager_truncate(Pager *pPager, Pgno nPage);
/*
-** This routine ends a transaction. A transaction is usually ended by
-** either a COMMIT or a ROLLBACK operation. This routine may be called
+** This routine ends a transaction. A transaction is usually ended by
+** either a COMMIT or a ROLLBACK operation. This routine may be called
** after rollback of a hot-journal, or if an error occurs while opening
** the journal file or writing the very first journal-header of a
** database transaction.
-**
+**
** This routine is never called in PAGER_ERROR state. If it is called
** in PAGER_NONE or PAGER_SHARED state and the lock held is less
** exclusive than a RESERVED lock, it is a no-op.
**
** Otherwise, any active savepoints are released.
**
-** If the journal file is open, then it is "finalized". Once a journal
-** file has been finalized it is not possible to use it to roll back a
+** If the journal file is open, then it is "finalized". Once a journal
+** file has been finalized it is not possible to use it to roll back a
** transaction. Nor will it be considered to be a hot-journal by this
** or any other database connection. Exactly how a journal is finalized
** depends on whether or not the pager is running in exclusive mode and
** the current journal-mode (Pager.journalMode value), as follows:
**
** journalMode==MEMORY
-** Journal file descriptor is simply closed. This destroys an
+** Journal file descriptor is simply closed. This destroys an
** in-memory journal.
**
** journalMode==TRUNCATE
** journalMode==PERSIST is used instead.
**
** After the journal is finalized, the pager moves to PAGER_READER state.
-** If running in non-exclusive rollback mode, the lock on the file is
+** If running in non-exclusive rollback mode, the lock on the file is
** downgraded to a SHARED_LOCK.
**
** SQLITE_OK is returned if no error occurs. If an error occurs during
** any of the IO operations to finalize the journal file or unlock the
-** database then the IO error code is returned to the user. If the
+** database then the IO error code is returned to the user. If the
** operation to finalize the journal file fails, then the code still
** tries to unlock the database file if not in exclusive mode. If the
** unlock operation fails as well, then the first error code related
** 1. After a successful hot-journal rollback, it is called with
** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK.
**
- ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE
+ ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE
** lock switches back to locking_mode=normal and then executes a
- ** read-transaction, this function is called with eState==PAGER_READER
+ ** read-transaction, this function is called with eState==PAGER_READER
** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed.
*/
assert( assert_pager_state(pPager) );
/* This branch may be executed with Pager.journalMode==MEMORY if
** a hot-journal was just rolled back. In this case the journal
** file should be closed and deleted. If this connection writes to
- ** the database file, it will do so using an in-memory journal.
+ ** the database file, it will do so using an in-memory journal.
*/
int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd));
- assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
- || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
- || pPager->journalMode==PAGER_JOURNALMODE_WAL
+ assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
+ || pPager->journalMode==PAGER_JOURNALMODE_MEMORY
+ || pPager->journalMode==PAGER_JOURNALMODE_WAL
);
sqlite3OsClose(pPager->jfd);
if( bDelete ){
sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
if( pagerUseWal(pPager) ){
- /* Drop the WAL write-lock, if any. Also, if the connection was in
- ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE
+ /* Drop the WAL write-lock, if any. Also, if the connection was in
+ ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE
** lock held on the database file.
*/
rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
}else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
/* This branch is taken when committing a transaction in rollback-journal
** mode if the database file on disk is larger than the database image.
- ** At this point the journal has been finalized and the transaction
+ ** At this point the journal has been finalized and the transaction
** successfully committed, but the EXCLUSIVE lock is still held on the
** file. So it is safe to truncate the database file to its minimum
** required size. */
rc = pager_truncate(pPager, pPager->dbSize);
}
- if( !pPager->exclusiveMode
+ if( !pPager->exclusiveMode
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
){
rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
}
/*
-** Execute a rollback if a transaction is active and unlock the
-** database file.
+** Execute a rollback if a transaction is active and unlock the
+** database file.
**
-** If the pager has already entered the ERROR state, do not attempt
+** If the pager has already entered the ERROR state, do not attempt
** the rollback at this time. Instead, pager_unlock() is called. The
** call to pager_unlock() will discard all in-memory pages, unlock
-** the database file and move the pager back to OPEN state. If this
-** means that there is a hot-journal left in the file-system, the next
-** connection to obtain a shared lock on the pager (which may be this one)
+** the database file and move the pager back to OPEN state. If this
+** means that there is a hot-journal left in the file-system, the next
+** connection to obtain a shared lock on the pager (which may be this one)
** will roll it back.
**
** If the pager has not already entered the ERROR state, but an IO or
-** malloc error occurs during a rollback, then this will itself cause
+** malloc error occurs during a rollback, then this will itself cause
** the pager to enter the ERROR state. Which will be cleared by the
** call to pager_unlock(), as described above.
*/
/*
** Parameter aData must point to a buffer of pPager->pageSize bytes
-** of data. Compute and return a checksum based ont the contents of the
+** of data. Compute and return a checksum based ont the contents of the
** page of data and the current value of pPager->cksumInit.
**
-** This is not a real checksum. It is really just the sum of the
+** This is not a real checksum. It is really just the sum of the
** random initial value (pPager->cksumInit) and every 200th byte
** of the page data, starting with byte offset (pPager->pageSize%200).
** Each byte is interpreted as an 8-bit unsigned integer.
** Changing the formula used to compute this checksum results in an
** incompatible journal file format.
**
-** If journal corruption occurs due to a power failure, the most likely
-** scenario is that one end or the other of the record will be changed.
+** If journal corruption occurs due to a power failure, the most likely
+** scenario is that one end or the other of the record will be changed.
** It is much less likely that the two ends of the journal record will be
** correct and the middle be corrupt. Thus, this "checksum" scheme,
** though fast and simple, catches the mostly likely kind of corruption.
** The page begins at offset *pOffset into the file. The *pOffset
** value is increased to the start of the next page in the journal.
**
-** The main rollback journal uses checksums - the statement journal does
+** The main rollback journal uses checksums - the statement journal does
** not.
**
** If the page number of the page record read from the (sub-)journal file
** is successfully read from the (sub-)journal file but appears to be
** corrupted, SQLITE_DONE is returned. Data is considered corrupted in
** two circumstances:
-**
+**
** * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or
** * If the record is being rolled back from the main journal file
** and the checksum field does not match the record content.
assert( aData ); /* Temp storage must have already been allocated */
assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) );
- /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction
+ /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction
** or savepoint rollback done at the request of the caller) or this is
** a hot-journal rollback. If it is a hot-journal rollback, the pager
** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback
** assert()able.
**
** If in WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the
- ** pager cache if it exists and the main file. The page is then marked
+ ** pager cache if it exists and the main file. The page is then marked
** not dirty. Since this code is only executed in PAGER_OPEN state for
** a hot-journal rollback, it is guaranteed that the page-cache is empty
** if the pager is in OPEN state.
}else if( !isMainJrnl && pPg==0 ){
/* If this is a rollback of a savepoint and data was not written to
** the database and the page is not in-memory, there is a potential
- ** problem. When the page is next fetched by the b-tree layer, it
- ** will be read from the database file, which may or may not be
- ** current.
+ ** problem. When the page is next fetched by the b-tree layer, it
+ ** will be read from the database file, which may or may not be
+ ** current.
**
** There are a couple of different ways this can happen. All are quite
- ** obscure. When running in synchronous mode, this can only happen
+ ** obscure. When running in synchronous mode, this can only happen
** if the page is on the free-list at the start of the transaction, then
** populated, then moved using sqlite3PagerMovepage().
**
** The solution is to add an in-memory page to the cache containing
- ** the data just read from the sub-journal. Mark the page as dirty
- ** and if the pager requires a journal-sync, then mark the page as
+ ** the data just read from the sub-journal. Mark the page as dirty
+ ** and if the pager requires a journal-sync, then mark the page as
** requiring a journal-sync before it is written.
*/
assert( isSavepnt );
memcpy(pData, (u8*)aData, pPager->pageSize);
pPager->xReiniter(pPg);
if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){
- /* If the contents of this page were just restored from the main
- ** journal file, then its content must be as they were when the
+ /* If the contents of this page were just restored from the main
+ ** journal file, then its content must be as they were when the
** transaction was first opened. In this case we can mark the page
** as clean, since there will be no need to write it out to the
** database.
**
** There is one exception to this rule. If the page is being rolled
- ** back as part of a savepoint (or statement) rollback from an
+ ** back as part of a savepoint (or statement) rollback from an
** unsynced portion of the main journal file, then it is not safe
** to mark the page as clean. This is because marking the page as
** clean will clear the PGHDR_NEED_SYNC flag. Since the page is
** This routine checks if it is possible to delete the master journal file,
** and does so if it is.
**
-** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not
+** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not
** available for use within this function.
**
-** When a master journal file is created, it is populated with the names
-** of all of its child journals, one after another, formatted as utf-8
-** encoded text. The end of each child journal file is marked with a
+** When a master journal file is created, it is populated with the names
+** of all of its child journals, one after another, formatted as utf-8
+** encoded text. The end of each child journal file is marked with a
** nul-terminator byte (0x00). i.e. the entire contents of a master journal
** file for a transaction involving two databases might be:
**
** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
**
-** A master journal file may only be deleted once all of its child
+** A master journal file may only be deleted once all of its child
** journals have been rolled back.
**
-** This function reads the contents of the master-journal file into
+** This function reads the contents of the master-journal file into
** memory and loops through each of the child journal names. For
** each child journal, it checks if:
**
** * if the child journal exists, and if so
-** * if the child journal contains a reference to master journal
+** * if the child journal contains a reference to master journal
** file zMaster
**
** If a child journal can be found that matches both of the criteria
**
** If an IO error within this function, an error code is returned. This
** function allocates memory by calling sqlite3Malloc(). If an allocation
-** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors
+** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors
** occur, SQLITE_OK is returned.
**
** TODO: This function allocates a single block of memory to load
** the entire contents of the master journal file. This could be
-** a couple of kilobytes or so - potentially larger than the page
+** a couple of kilobytes or so - potentially larger than the page
** size.
*/
static int pager_delmaster(Pager *pPager, const char *zMaster){
}
zJournal += (sqlite3Strlen30(zJournal)+1);
}
-
+
sqlite3OsClose(pMaster);
rc = sqlite3OsDelete(pVfs, zMaster, 0);
/*
-** This function is used to change the actual size of the database
+** This function is used to change the actual size of the database
** file in the file-system. This only happens when committing a transaction,
** or rolling back a transaction (including rolling back a hot-journal).
**
** If the main database file is not open, or the pager is not in either
-** DBMOD or OPEN state, this function is a no-op. Otherwise, the size
-** of the file is changed to nPage pages (nPage*pPager->pageSize bytes).
+** DBMOD or OPEN state, this function is a no-op. Otherwise, the size
+** of the file is changed to nPage pages (nPage*pPager->pageSize bytes).
** If the file on disk is currently larger than nPage pages, then use the VFS
** xTruncate() method to truncate it.
**
-** Or, it might might be the case that the file on disk is smaller than
-** nPage pages. Some operating system implementations can get confused if
-** you try to truncate a file to some size that is larger than it
-** currently is, so detect this case and write a single zero byte to
+** Or, it might might be the case that the file on disk is smaller than
+** nPage pages. Some operating system implementations can get confused if
+** you try to truncate a file to some size that is larger than it
+** currently is, so detect this case and write a single zero byte to
** the end of the new file instead.
**
** If successful, return SQLITE_OK. If an IO error occurs while modifying
int rc = SQLITE_OK;
assert( pPager->eState!=PAGER_ERROR );
assert( pPager->eState!=PAGER_READER );
-
- if( isOpen(pPager->fd)
- && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
+
+ if( isOpen(pPager->fd)
+ && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
){
i64 currentSize, newSize;
int szPage = pPager->pageSize;
/*
** Set the value of the Pager.sectorSize variable for the given
** pager based on the value returned by the xSectorSize method
-** of the open database file. The sector size will be used used
-** to determine the size and alignment of journal header and
+** of the open database file. The sector size will be used used
+** to determine the size and alignment of journal header and
** master journal pointers within created journal files.
**
** For temporary files the effective sector size is always 512 bytes.
assert( isOpen(pPager->fd) || pPager->tempFile );
if( pPager->tempFile
- || (sqlite3OsDeviceCharacteristics(pPager->fd) &
+ || (sqlite3OsDeviceCharacteristics(pPager->fd) &
SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0
){
/* Sector size doesn't matter for temporary files. Also, the file
/*
** Playback the journal and thus restore the database file to
-** the state it was in before we started making changes.
+** the state it was in before we started making changes.
**
-** The journal file format is as follows:
+** The journal file format is as follows:
**
** (1) 8 byte prefix. A copy of aJournalMagic[].
** (2) 4 byte big-endian integer which is the number of valid page records
** in the journal. If this value is 0xffffffff, then compute the
** number of page records from the journal size.
-** (3) 4 byte big-endian integer which is the initial value for the
+** (3) 4 byte big-endian integer which is the initial value for the
** sanity checksum.
** (4) 4 byte integer which is the number of pages to truncate the
** database to during a rollback.
** from the file size. This value is used when the user selects the
** no-sync option for the journal. A power failure could lead to corruption
** in this case. But for things like temporary table (which will be
-** deleted when the power is restored) we don't care.
+** deleted when the power is restored) we don't care.
**
** If the file opened as the journal file is not a well-formed
** journal file then all pages up to the first corrupted page are rolled
** and an error code is returned.
**
** The isHot parameter indicates that we are trying to rollback a journal
-** that might be a hot journal. Or, it could be that the journal is
+** that might be a hot journal. Or, it could be that the journal is
** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE.
** If the journal really is hot, reset the pager cache prior rolling
** back any content. If the journal is merely persistent, no reset is
pPager->journalOff = 0;
needPagerReset = isHot;
- /* This loop terminates either when a readJournalHdr() or
- ** pager_playback_one_page() call returns SQLITE_DONE or an IO error
- ** occurs.
+ /* This loop terminates either when a readJournalHdr() or
+ ** pager_playback_one_page() call returns SQLITE_DONE or an IO error
+ ** occurs.
*/
while( 1 ){
/* Read the next journal header from the journal file. If there are
** This indicates nothing more needs to be rolled back.
*/
rc = readJournalHdr(pPager, isHot, szJ, &nRec, &mxPg);
- if( rc!=SQLITE_OK ){
+ if( rc!=SQLITE_OK ){
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
}
** chunk of the journal contains zero pages to be rolled back. But
** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in
** the journal, it means that the journal might contain additional
- ** pages that need to be rolled back and that the number of pages
+ ** pages that need to be rolled back and that the number of pages
** should be computed based on the journal file size.
*/
if( nRec==0 && !isHot &&
pPager->dbSize = mxPg;
}
- /* Copy original pages out of the journal and back into the
+ /* Copy original pages out of the journal and back into the
** database file and/or page cache.
*/
for(u=0; u<nRec; u++){
}
#endif
- /* If this playback is happening automatically as a result of an IO or
- ** malloc error that occurred after the change-counter was updated but
- ** before the transaction was committed, then the change-counter
- ** modification may just have been reverted. If this happens in exclusive
+ /* If this playback is happening automatically as a result of an IO or
+ ** malloc error that occurred after the change-counter was updated but
+ ** before the transaction was committed, then the change-counter
+ ** modification may just have been reverted. If this happens in exclusive
** mode, then subsequent transactions performed by the connection will not
** update the change-counter at all. This may lead to cache inconsistency
** problems for other processes at some point in the future. So, just
/*
-** Read the content for page pPg out of the database file and into
+** Read the content for page pPg out of the database file and into
** pPg->pData. A shared lock or greater must be held on the database
** file before this function is called.
**
#ifndef SQLITE_OMIT_WAL
/*
-** This function is invoked once for each page that has already been
+** This function is invoked once for each page that has already been
** written into the log file when a WAL transaction is rolled back.
-** Parameter iPg is the page number of said page. The pCtx argument
+** Parameter iPg is the page number of said page. The pCtx argument
** is actually a pointer to the Pager structure.
**
** If page iPg is present in the cache, and has no outstanding references,
** it is discarded. Otherwise, if there are one or more outstanding
** references, the page content is reloaded from the database. If the
-** attempt to reload content from the database is required and fails,
+** attempt to reload content from the database is required and fails,
** return an SQLite error code. Otherwise, SQLITE_OK.
*/
static int pagerUndoCallback(void *pCtx, Pgno iPg){
** updated as data is copied out of the rollback journal and into the
** database. This is not generally possible with a WAL database, as
** rollback involves simply truncating the log file. Therefore, if one
- ** or more frames have already been written to the log (and therefore
+ ** or more frames have already been written to the log (and therefore
** also copied into the backup databases) as part of this transaction,
** the backups must be restarted.
*/
PgHdr *pList; /* List of dirty pages to revert */
/* For all pages in the cache that are currently dirty or have already
- ** been written (but not committed) to the log file, do one of the
+ ** been written (but not committed) to the log file, do one of the
** following:
**
** + Discard the cached page (if refcount==0), or
** This function is a wrapper around sqlite3WalFrames(). As well as logging
** the contents of the list of pages headed by pList (connected by pDirty),
** this function notifies any active backup processes that the pages have
-** changed.
+** changed.
**
** The list of pages passed into this routine is always sorted by page number.
** Hence, if page 1 appears anywhere on the list, it will be the first page.
-*/
+*/
static int pagerWalFrames(
Pager *pPager, /* Pager object */
PgHdr *pList, /* List of frames to log */
pPager->aStat[PAGER_STAT_WRITE] += nList;
if( pList->pgno==1 ) pager_write_changecounter(pList);
- rc = sqlite3WalFrames(pPager->pWal,
+ rc = sqlite3WalFrames(pPager->pWal,
pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
);
if( rc==SQLITE_OK && pPager->pBackup ){
** Return SQLITE_OK or an error code.
**
** The caller must hold a SHARED lock on the database file to call this
-** function. Because an EXCLUSIVE lock on the db file is required to delete
-** a WAL on a none-empty database, this ensures there is no race condition
-** between the xAccess() below and an xDelete() being executed by some
+** function. Because an EXCLUSIVE lock on the db file is required to delete
+** a WAL on a none-empty database, this ensures there is no race condition
+** between the xAccess() below and an xDelete() being executed by some
** other connection.
*/
static int pagerOpenWalIfPresent(Pager *pPager){
/*
** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
-** the entire master journal file. The case pSavepoint==NULL occurs when
-** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction
+** the entire master journal file. The case pSavepoint==NULL occurs when
+** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction
** savepoint.
**
-** When pSavepoint is not NULL (meaning a non-transaction savepoint is
+** When pSavepoint is not NULL (meaning a non-transaction savepoint is
** being rolled back), then the rollback consists of up to three stages,
** performed in the order specified:
**
** * Pages are played back from the main journal starting at byte
-** offset PagerSavepoint.iOffset and continuing to
+** offset PagerSavepoint.iOffset and continuing to
** PagerSavepoint.iHdrOffset, or to the end of the main journal
** file if PagerSavepoint.iHdrOffset is zero.
**
** * If PagerSavepoint.iHdrOffset is not zero, then pages are played
-** back starting from the journal header immediately following
+** back starting from the journal header immediately following
** PagerSavepoint.iHdrOffset to the end of the main journal file.
**
** * Pages are then played back from the sub-journal file, starting
** journal file. There is no need for a bitvec in this case.
**
** In either case, before playback commences the Pager.dbSize variable
-** is reset to the value that it held at the start of the savepoint
+** is reset to the value that it held at the start of the savepoint
** (or transaction). No page with a page-number greater than this value
** is played back. If one is encountered it is simply skipped.
*/
}
}
- /* Set the database size back to the value it was before the savepoint
+ /* Set the database size back to the value it was before the savepoint
** being reverted was opened.
*/
pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize;
** test is related to ticket #2565. See the discussion in the
** pager_playback() function for additional information.
*/
- if( nJRec==0
+ if( nJRec==0
&& pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff
){
nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager));
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
Pager *pPager, /* The pager to set safety level for */
- int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */
+ int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */
int bFullFsync, /* PRAGMA fullfsync */
int bCkptFullFsync /* PRAGMA checkpoint_fullfsync */
){
/*
** The following global variable is incremented whenever the library
** attempts to open a temporary file. This information is used for
-** testing and analysis only.
+** testing and analysis only.
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_opentemp_count = 0;
/*
** Open a temporary file.
**
-** Write the file descriptor into *pFile. Return SQLITE_OK on success
-** or some other error code if we fail. The OS will automatically
+** Write the file descriptor into *pFile. Return SQLITE_OK on success
+** or some other error code if we fail. The OS will automatically
** delete the temporary file when it is closed.
**
** The flags passed to the VFS layer xOpen() call are those specified
/*
** Set the busy handler function.
**
-** The pager invokes the busy-handler if sqlite3OsLock() returns
+** The pager invokes the busy-handler if sqlite3OsLock() returns
** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock,
-** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE
+** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE
** lock. It does *not* invoke the busy handler when upgrading from
** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE
** (which occurs during hot-journal rollback). Summary:
** SHARED_LOCK -> EXCLUSIVE_LOCK | No
** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes
**
-** If the busy-handler callback returns non-zero, the lock is
+** If the busy-handler callback returns non-zero, the lock is
** retried. If it returns zero, then the SQLITE_BUSY error is
** returned to the caller of the pager API function.
*/
}
/*
-** Change the page size used by the Pager object. The new page size
+** Change the page size used by the Pager object. The new page size
** is passed in *pPageSize.
**
** If the pager is in the error state when this function is called, it
-** is a no-op. The value returned is the error state error code (i.e.
+** is a no-op. The value returned is the error state error code (i.e.
** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL).
**
** Otherwise, if all of the following are true:
**
-** * the new page size (value of *pPageSize) is valid (a power
+** * the new page size (value of *pPageSize) is valid (a power
** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and
**
** * there are no outstanding page references, and
**
** then the pager object page size is set to *pPageSize.
**
-** If the page size is changed, then this function uses sqlite3PagerMalloc()
-** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
-** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
+** If the page size is changed, then this function uses sqlite3PagerMalloc()
+** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
+** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
** In all other cases, SQLITE_OK is returned.
**
** If the page size is not changed, either because one of the enumerated
** conditions above is not true, the pager was in error state when this
-** function was called, or because the memory allocation attempt failed,
+** function was called, or because the memory allocation attempt failed,
** then *pPageSize is set to the old, retained page size before returning.
*/
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
** function may be called from within PagerOpen(), before the state
** of the Pager object is internally consistent.
**
- ** At one point this function returned an error if the pager was in
+ ** At one point this function returned an error if the pager was in
** PAGER_ERROR state. But since PAGER_ERROR state guarantees that
** there is at least one outstanding page reference, this function
** is a no-op for that case anyhow.
u32 pageSize = *pPageSize;
assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
if( (pPager->memDb==0 || pPager->dbSize==0)
- && sqlite3PcacheRefCount(pPager->pPCache)==0
- && pageSize && pageSize!=(u32)pPager->pageSize
+ && sqlite3PcacheRefCount(pPager->pPCache)==0
+ && pageSize && pageSize!=(u32)pPager->pageSize
){
char *pNew = NULL; /* New temp space */
i64 nByte = 0;
}
/*
-** Attempt to set the maximum database page count if mxPage is positive.
+** Attempt to set the maximum database page count if mxPage is positive.
** Make no changes if mxPage is zero or negative. And never reduce the
** maximum page count below the current size of the database.
**
/*
** Read the first N bytes from the beginning of the file into memory
-** that pDest points to.
+** that pDest points to.
**
** If the pager was opened on a transient file (zFilename==""), or
** opened on a file less than N bytes in size, the output buffer is
-** zeroed and SQLITE_OK returned. The rationale for this is that this
+** zeroed and SQLITE_OK returned. The rationale for this is that this
** function is used to read database headers, and a new transient or
** zero sized database has a header than consists entirely of zeroes.
**
** This function may only be called when a read-transaction is open on
** the pager. It returns the total number of pages in the database.
**
-** However, if the file is between 1 and <page-size> bytes in size, then
+** However, if the file is between 1 and <page-size> bytes in size, then
** this is considered a 1 page file.
*/
SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){
** a similar or greater lock is already held, this function is a no-op
** (returning SQLITE_OK immediately).
**
-** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke
-** the busy callback if the lock is currently not available. Repeat
-** until the busy callback returns false or until the attempt to
+** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke
+** the busy callback if the lock is currently not available. Repeat
+** until the busy callback returns false or until the attempt to
** obtain the lock succeeds.
**
** Return SQLITE_OK on success and an error code if we cannot obtain
-** the lock. If the lock is obtained successfully, set the Pager.state
+** the lock. If the lock is obtained successfully, set the Pager.state
** variable to locktype before returning.
*/
static int pager_wait_on_lock(Pager *pPager, int locktype){
int rc; /* Return code */
- /* Check that this is either a no-op (because the requested lock is
+ /* Check that this is either a no-op (because the requested lock is
** already held, or one of the transistions that the busy-handler
** may be invoked during, according to the comment above
** sqlite3PagerSetBusyhandler().
}
/*
-** Function assertTruncateConstraint(pPager) checks that one of the
+** Function assertTruncateConstraint(pPager) checks that one of the
** following is true for all dirty pages currently in the page-cache:
**
-** a) The page number is less than or equal to the size of the
+** a) The page number is less than or equal to the size of the
** current database image, in pages, OR
**
** b) if the page content were written at this time, it would not
** the database file. If a savepoint transaction were rolled back after
** this happened, the correct behavior would be to restore the current
** content of the page. However, since this content is not present in either
-** the database file or the portion of the rollback journal and
+** the database file or the portion of the rollback journal and
** sub-journal rolled back the content could not be restored and the
-** database image would become corrupt. It is therefore fortunate that
+** database image would become corrupt. It is therefore fortunate that
** this circumstance cannot arise.
*/
#if defined(SQLITE_DEBUG)
#endif
/*
-** Truncate the in-memory database file image to nPage pages. This
-** function does not actually modify the database file on disk. It
-** just sets the internal state of the pager object so that the
+** Truncate the in-memory database file image to nPage pages. This
+** function does not actually modify the database file on disk. It
+** just sets the internal state of the pager object so that the
** truncation will be done when the current transaction is committed.
**
** This function is only called right before committing a transaction.
/* At one point the code here called assertTruncateConstraint() to
** ensure that all pages being truncated away by this operation are,
- ** if one or more savepoints are open, present in the savepoint
+ ** if one or more savepoints are open, present in the savepoint
** journal so that they can be restored if the savepoint is rolled
** back. This is no longer necessary as this function is now only
- ** called right before committing a transaction. So although the
- ** Pager object may still have open savepoints (Pager.nSavepoint!=0),
+ ** called right before committing a transaction. So although the
+ ** Pager object may still have open savepoints (Pager.nSavepoint!=0),
** they cannot be rolled back. So the assertTruncateConstraint() call
** is no longer correct. */
}
** size of the journal file so that the pager_playback() routine knows
** that the entire journal file has been synced.
**
-** Syncing a hot-journal to disk before attempting to roll it back ensures
+** Syncing a hot-journal to disk before attempting to roll it back ensures
** that if a power-failure occurs during the rollback, the process that
** attempts rollback following system recovery sees the same journal
** content as this process.
**
-** If everything goes as planned, SQLITE_OK is returned. Otherwise,
+** If everything goes as planned, SQLITE_OK is returned. Otherwise,
** an SQLite error code.
*/
static int pagerSyncHotJournal(Pager *pPager){
}
/*
-** Obtain a reference to a memory mapped page object for page number pgno.
+** Obtain a reference to a memory mapped page object for page number pgno.
** The new object will use the pointer pData, obtained from xFetch().
** If successful, set *ppPage to point to the new page reference
** and return SQLITE_OK. Otherwise, return an SQLite error code and set
}
/*
-** Release a reference to page pPg. pPg must have been returned by an
+** Release a reference to page pPg. pPg must have been returned by an
** earlier call to pagerAcquireMapPage().
*/
static void pagerReleaseMapPage(PgHdr *pPg){
** result in a coredump.
**
** This function always succeeds. If a transaction is active an attempt
-** is made to roll it back. If an error occurs during the rollback
+** is made to roll it back. If an error occurs during the rollback
** a hot journal may be left in the filesystem but no error is returned
** to the caller.
*/
pager_unlock(pPager);
}else{
/* If it is open, sync the journal file before calling UnlockAndRollback.
- ** If this is not done, then an unsynced portion of the open journal
- ** file may be played back into the database. If a power failure occurs
+ ** If this is not done, then an unsynced portion of the open journal
+ ** file may be played back into the database. If a power failure occurs
** while this is happening, the database could become corrupt.
**
** If an error occurs while trying to sync the journal, shift the pager
** disk and can be restored in the event of a hot-journal rollback.
**
** If the Pager.noSync flag is set, then this function is a no-op.
-** Otherwise, the actions required depend on the journal-mode and the
+** Otherwise, the actions required depend on the journal-mode and the
** device characteristics of the file-system, as follows:
**
** * If the journal file is an in-memory journal file, no action need
** been written following it. If the pager is operating in full-sync
** mode, then the journal file is synced before this field is updated.
**
-** * If the device does not support the SEQUENTIAL property, then
+** * If the device does not support the SEQUENTIAL property, then
** journal file is synced.
**
** Or, in pseudo-code:
** if( NOT SAFE_APPEND ){
** if( <full-sync mode> ) xSync(<journal file>);
** <update nRec field>
-** }
+** }
** if( NOT SEQUENTIAL ) xSync(<journal file>);
** }
**
-** If successful, this routine clears the PGHDR_NEED_SYNC flag of every
+** If successful, this routine clears the PGHDR_NEED_SYNC flag of every
** page currently held in memory before returning SQLITE_OK. If an IO
** error is encountered, then the IO error code is returned to the caller.
*/
** mode, then the journal file may at this point actually be larger
** than Pager.journalOff bytes. If the next thing in the journal
** file happens to be a journal-header (written as part of the
- ** previous connection's transaction), and a crash or power-failure
- ** occurs after nRec is updated but before this connection writes
- ** anything else to the journal file (or commits/rolls back its
- ** transaction), then SQLite may become confused when doing the
+ ** previous connection's transaction), and a crash or power-failure
+ ** occurs after nRec is updated but before this connection writes
+ ** anything else to the journal file (or commits/rolls back its
+ ** transaction), then SQLite may become confused when doing the
** hot-journal rollback following recovery. It may roll back all
** of this connections data, then proceed to rolling back the old,
** out-of-date data that follows it. Database corruption.
** byte to the start of it to prevent it from being recognized.
**
** Variable iNextHdrOffset is set to the offset at which this
- ** problematic header will occur, if it exists. aMagic is used
+ ** problematic header will occur, if it exists. aMagic is used
** as a temporary buffer to inspect the first couple of bytes of
** the potential journal header.
*/
** it as a candidate for rollback.
**
** This is not required if the persistent media supports the
- ** SAFE_APPEND property. Because in this case it is not possible
+ ** SAFE_APPEND property. Because in this case it is not possible
** for garbage data to be appended to the file, the nRec field
** is populated with 0xFFFFFFFF when the journal header is written
** and never needs to be updated.
if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){
PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager)));
IOTRACE(("JSYNC %p\n", pPager))
- rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags|
+ rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags|
(pPager->syncFlags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0)
);
if( rc!=SQLITE_OK ) return rc;
}
}
- /* Unless the pager is in noSync mode, the journal file was just
- ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on
+ /* Unless the pager is in noSync mode, the journal file was just
+ ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on
** all pages.
*/
sqlite3PcacheClearSyncFlags(pPager->pPCache);
** is called. Before writing anything to the database file, this lock
** is upgraded to an EXCLUSIVE lock. If the lock cannot be obtained,
** SQLITE_BUSY is returned and no data is written to the database file.
-**
+**
** If the pager is a temp-file pager and the actual file-system file
-** is not yet open, it is created and opened before any data is
+** is not yet open, it is created and opened before any data is
** written out.
**
** Once the lock has been upgraded and, if necessary, the file opened,
** in Pager.dbFileVers[] is updated to match the new value stored in
** the database file.
**
-** If everything is successful, SQLITE_OK is returned. If an IO error
+** If everything is successful, SQLITE_OK is returned. If an IO error
** occurs, an IO error code is returned. Or, if the EXCLUSIVE lock cannot
** be obtained, SQLITE_BUSY is returned.
*/
** file size will be.
*/
assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
- if( rc==SQLITE_OK
- && (pList->pDirty ? pPager->dbSize : pList->pgno+1)>pPager->dbHintSize
+ if( rc==SQLITE_OK
+ && (pList->pDirty ? pPager->dbSize : pList->pgno+1)>pPager->dbHintSize
){
sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
*/
if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */
- char *pData; /* Data to write */
+ char *pData; /* Data to write */
assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
if( pList->pgno==1 ) pager_write_changecounter(pList);
rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
/* If page 1 was just written, update Pager.dbFileVers to match
- ** the value now stored in the database file. If writing this
- ** page caused the database file to grow, update dbFileSize.
+ ** the value now stored in the database file. If writing this
+ ** page caused the database file to grow, update dbFileSize.
*/
if( pgno==1 ){
memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers));
}
/*
-** Ensure that the sub-journal file is open. If it is already open, this
+** Ensure that the sub-journal file is open. If it is already open, this
** function is a no-op.
**
-** SQLITE_OK is returned if everything goes according to plan. An
-** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen()
+** SQLITE_OK is returned if everything goes according to plan. An
+** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen()
** fails.
*/
static int openSubJournal(Pager *pPager){
}
/*
-** Append a record of the current state of page pPg to the sub-journal.
-** It is the callers responsibility to use subjRequiresPage() to check
+** Append a record of the current state of page pPg to the sub-journal.
+** It is the callers responsibility to use subjRequiresPage() to check
** that it is really required before calling this function.
**
** If successful, set the bit corresponding to pPg->pgno in the bitvecs
** for all open savepoints before returning.
**
** This function returns SQLITE_OK if everything is successful, an IO
-** error code if the attempt to write to the sub-journal fails, or
+** error code if the attempt to write to the sub-journal fails, or
** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint
** bitvec.
*/
assert( pPager->useJournal );
assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
- assert( pagerUseWal(pPager)
- || pageInJournal(pPg)
- || pPg->pgno>pPager->dbOrigSize
+ assert( pagerUseWal(pPager)
+ || pageInJournal(pPg)
+ || pPg->pgno>pPager->dbOrigSize
);
rc = openSubJournal(pPager);
void *pData = pPg->pData;
i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
char *pData2;
-
+
CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
rc = write32bits(pPager->sjfd, offset, pPg->pgno);
** This function is called by the pcache layer when it has reached some
** soft memory limit. The first argument is a pointer to a Pager object
** (cast as a void*). The pager is always 'purgeable' (not an in-memory
-** database). The second argument is a reference to a page that is
+** database). The second argument is a reference to a page that is
** currently dirty but has no outstanding references. The page
-** is always associated with the Pager object passed as the first
+** is always associated with the Pager object passed as the first
** argument.
**
** The job of this function is to make pPg clean by writing its contents
** out to the database file, if possible. This may involve syncing the
-** journal file.
+** journal file.
**
** If successful, sqlite3PcacheMakeClean() is called on the page and
** SQLITE_OK returned. If an IO error occurs while trying to make the
** or not a sync is required. This is set during a rollback.
**
** Spilling is also prohibited when in an error state since that could
- ** lead to database corruption. In the current implementaton it
+ ** lead to database corruption. In the current implementaton it
** is impossible for sqlite3PcacheFetch() to be called with createFlag==1
** while in the error state, hence it is impossible for this routine to
** be called in the error state. Nevertheless, we include a NEVER()
pPg->pDirty = 0;
if( pagerUseWal(pPager) ){
/* Write a single frame for this page to the log. */
- if( subjRequiresPage(pPg) ){
- rc = subjournalPage(pPg);
+ if( subjRequiresPage(pPg) ){
+ rc = subjournalPage(pPg);
}
if( rc==SQLITE_OK ){
rc = pagerWalFrames(pPager, pPg, 0, 0);
}
}else{
-
+
/* Sync the journal file if required. */
- if( pPg->flags&PGHDR_NEED_SYNC
+ if( pPg->flags&PGHDR_NEED_SYNC
|| pPager->eState==PAGER_WRITER_CACHEMOD
){
rc = syncJournal(pPager, 1);
}
-
+
/* If the page number of this page is larger than the current size of
** the database image, it may need to be written to the sub-journal.
** This is because the call to pager_write_pagelist() below will not
** was when the transaction started, not as it was when "SAVEPOINT sp"
** was executed.
**
- ** The solution is to write the current data for page X into the
+ ** The solution is to write the current data for page X into the
** sub-journal file now (if it is not already there), so that it will
- ** be restored to its current value when the "ROLLBACK TO sp" is
+ ** be restored to its current value when the "ROLLBACK TO sp" is
** executed.
*/
if( NEVER(
) ){
rc = subjournalPage(pPg);
}
-
+
/* Write the contents of the page out to the database file. */
if( rc==SQLITE_OK ){
assert( (pPg->flags&PGHDR_NEED_SYNC)==0 );
sqlite3PcacheMakeClean(pPg);
}
- return pager_error(pPager, rc);
+ return pager_error(pPager, rc);
}
** The zFilename argument is the path to the database file to open.
** If zFilename is NULL then a randomly-named temporary file is created
** and used as the file to be cached. Temporary files are be deleted
-** automatically when they are closed. If zFilename is ":memory:" then
-** all information is held in cache. It is never written to disk.
+** automatically when they are closed. If zFilename is ":memory:" then
+** all information is held in cache. It is never written to disk.
** This can be used to implement an in-memory database.
**
** The nExtra parameter specifies the number of bytes of space allocated
** of the PAGER_* flags.
**
** The vfsFlags parameter is a bitmask to pass to the flags parameter
-** of the xOpen() method of the supplied VFS when opening files.
+** of the xOpen() method of the supplied VFS when opening files.
**
-** If the pager object is allocated and the specified file opened
+** If the pager object is allocated and the specified file opened
** successfully, SQLITE_OK is returned and *ppPager set to point to
** the new pager object. If an error occurs, *ppPager is set to NULL
** and error code returned. This function may return SQLITE_NOMEM
-** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or
+** (sqlite3Malloc() is used to allocate memory), SQLITE_CANTOPEN or
** various SQLITE_IO_XXX errors.
*/
SQLITE_PRIVATE int sqlite3PagerOpen(
/* Figure out how much space is required for each journal file-handle
** (there are two of them, the main journal and the sub-journal). This
- ** is the maximum space required for an in-memory journal file handle
+ ** is the maximum space required for an in-memory journal file handle
** and a regular journal file-handle. Note that a "regular journal-handle"
** may be a wrapper capable of caching the first portion of the journal
- ** file in memory to implement the atomic-write optimization (see
+ ** file in memory to implement the atomic-write optimization (see
** source file journal.c).
*/
if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){
}
/* Allocate memory for the Pager structure, PCache object, the
- ** three file descriptors, the database file name and the journal
+ ** three file descriptors, the database file name and the journal
** file name. The layout in memory is as follows:
**
** Pager object (sizeof(Pager) bytes)
ROUND8(sizeof(*pPager)) + /* Pager structure */
ROUND8(pcacheSize) + /* PCache object */
ROUND8(pVfs->szOsFile) + /* The main db file */
- journalFileSize * 2 + /* The two journal files */
+ journalFileSize * 2 + /* The two journal files */
nPathname + 1 + nUri + /* zFilename */
nPathname + 8 + 2 /* zJournal */
#ifndef SQLITE_OMIT_WAL
** This branch is also run for an in-memory database. An in-memory
** database is the same as a temp-file that is never written out to
** disk and uses an in-memory rollback journal.
- */
+ */
tempFile = 1;
pPager->eState = PAGER_READER;
pPager->eLock = EXCLUSIVE_LOCK;
readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
}
- /* The following call to PagerSetPagesize() serves to set the value of
+ /* The following call to PagerSetPagesize() serves to set the value of
** Pager.pageSize and to allocate the Pager.pTmpSpace buffer.
*/
if( rc==SQLITE_OK ){
testcase( rc!=SQLITE_OK );
}
- /* If an error occurred in either of the blocks above, free the
+ /* If an error occurred in either of the blocks above, free the
** Pager structure and close the file.
*/
if( rc!=SQLITE_OK ){
#endif
/* pPager->errMask = 0; */
pPager->tempFile = (u8)tempFile;
- assert( tempFile==PAGER_LOCKINGMODE_NORMAL
+ assert( tempFile==PAGER_LOCKINGMODE_NORMAL
|| tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
- pPager->exclusiveMode = (u8)tempFile;
+ pPager->exclusiveMode = (u8)tempFile;
pPager->changeCountDone = pPager->tempFile;
pPager->memDb = (u8)memDb;
pPager->readOnly = (u8)readOnly;
/*
** This function is called after transitioning from PAGER_UNLOCK to
** PAGER_SHARED state. It tests if there is a hot journal present in
-** the file-system for the given pager. A hot journal is one that
+** the file-system for the given pager. A hot journal is one that
** needs to be played back. According to this function, a hot-journal
** file exists if the following criteria are met:
**
** at the end of the file. If there is, and that master journal file
** does not exist, then the journal file is not really hot. In this
** case this routine will return a false-positive. The pager_playback()
-** routine will discover that the journal file is not really hot and
-** will not roll it back.
+** routine will discover that the journal file is not really hot and
+** will not roll it back.
**
-** If a hot-journal file is found to exist, *pExists is set to 1 and
+** If a hot-journal file is found to exist, *pExists is set to 1 and
** SQLITE_OK returned. If no hot-journal file is present, *pExists is
** set to 0 and SQLITE_OK returned. If an IO error occurs while trying
** to determine whether or not a hot-journal file exists, the IO error
int locked = 0; /* True if some process holds a RESERVED lock */
/* Race condition here: Another process might have been holding the
- ** the RESERVED lock and have a journal open at the sqlite3OsAccess()
+ ** the RESERVED lock and have a journal open at the sqlite3OsAccess()
** call above, but then delete the journal and drop the lock before
** we get to the following sqlite3OsCheckReservedLock() call. If that
** is the case, this routine might think there is a hot journal when
Pgno nPage; /* Number of pages in database file */
/* Check the size of the database file. If it consists of 0 pages,
- ** then delete the journal file. See the header comment above for
+ ** then delete the journal file. See the header comment above for
** the reasoning here. Delete the obsolete journal file under
** a RESERVED lock to avoid race conditions and to avoid violating
** [H33020].
/* The journal file exists and no other connection has a reserved
** or greater lock on the database file. Now check that there is
** at least one non-zero bytes at the start of the journal file.
- ** If there is, then we consider this journal to be hot. If not,
+ ** If there is, then we consider this journal to be hot. If not,
** it can be ignored.
*/
if( !jrnlOpen ){
** on the database file), then an attempt is made to obtain a
** SHARED lock on the database file. Immediately after obtaining
** the SHARED lock, the file-system is checked for a hot-journal,
-** which is played back if present. Following any hot-journal
+** which is played back if present. Following any hot-journal
** rollback, the contents of the cache are validated by checking
** the 'change-counter' field of the database file header and
** discarded if they are found to be invalid.
** the contents of the page cache and rolling back any open journal
** file.
**
-** If everything is successful, SQLITE_OK is returned. If an IO error
-** occurs while locking the database, checking for a hot-journal file or
+** If everything is successful, SQLITE_OK is returned. If an IO error
+** occurs while locking the database, checking for a hot-journal file or
** rolling back a journal file, the IO error code is returned.
*/
SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
/* This routine is only called from b-tree and only when there are no
** outstanding pages. This implies that the pager state should either
- ** be OPEN or READER. READER is only possible if the pager is or was in
+ ** be OPEN or READER. READER is only possible if the pager is or was in
** exclusive access mode.
*/
assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
** important that a RESERVED lock is not obtained on the way to the
** EXCLUSIVE lock. If it were, another process might open the
** database file, detect the RESERVED lock, and conclude that the
- ** database is safe to read while this process is still rolling the
+ ** database is safe to read while this process is still rolling the
** hot-journal back.
- **
+ **
** Because the intermediate RESERVED lock is not requested, any
- ** other process attempting to access the database file will get to
- ** this point in the code and fail to obtain its own EXCLUSIVE lock
+ ** other process attempting to access the database file will get to
+ ** this point in the code and fail to obtain its own EXCLUSIVE lock
** on the database file.
**
** Unless the pager is in locking_mode=exclusive mode, the lock is
if( rc!=SQLITE_OK ){
goto failed;
}
-
- /* If it is not already open and the file exists on disk, open the
- ** journal for read/write access. Write access is required because
- ** in exclusive-access mode the file descriptor will be kept open
- ** and possibly used for a transaction later on. Also, write-access
- ** is usually required to finalize the journal in journal_mode=persist
+
+ /* If it is not already open and the file exists on disk, open the
+ ** journal for read/write access. Write access is required because
+ ** in exclusive-access mode the file descriptor will be kept open
+ ** and possibly used for a transaction later on. Also, write-access
+ ** is usually required to finalize the journal in journal_mode=persist
** mode (and also for journal_mode=truncate on some systems).
**
- ** If the journal does not exist, it usually means that some
- ** other connection managed to get in and roll it back before
- ** this connection obtained the exclusive lock above. Or, it
+ ** If the journal does not exist, it usually means that some
+ ** other connection managed to get in and roll it back before
+ ** this connection obtained the exclusive lock above. Or, it
** may mean that the pager was in the error-state when this
** function was called and the journal file does not exist.
*/
}
}
}
-
+
/* Playback and delete the journal. Drop the database write
** lock and reacquire the read lock. Purge the cache before
** playing back the hot-journal so that we don't end up with
** or roll back a hot-journal while holding an EXCLUSIVE lock. The
** pager_unlock() routine will be called before returning to unlock
** the file. If the unlock attempt fails, then Pager.eLock must be
- ** set to UNKNOWN_LOCK (see the comment above the #define for
- ** UNKNOWN_LOCK above for an explanation).
+ ** set to UNKNOWN_LOCK (see the comment above the #define for
+ ** UNKNOWN_LOCK above for an explanation).
**
** In order to get pager_unlock() to do this, set Pager.eState to
** PAGER_ERROR now. This is not actually counted as a transition
** since we know that the same call to pager_unlock() will very
** shortly transition the pager object to the OPEN state. Calling
** assert_pager_state() would fail now, as it should not be possible
- ** to be in ERROR state when there are zero outstanding page
+ ** to be in ERROR state when there are zero outstanding page
** references.
*/
pager_error(pPager, rc);
}
if( !pPager->tempFile && (
- pPager->pBackup
- || sqlite3PcachePagecount(pPager->pPCache)>0
+ pPager->pBackup
+ || sqlite3PcachePagecount(pPager->pPCache)>0
|| USEFETCH(pPager)
)){
/* The shared-lock has just been acquired on the database file
** a 32-bit counter that is incremented with each change. The
** other bytes change randomly with each file change when
** a codec is in use.
- **
- ** There is a vanishingly small chance that a change will not be
+ **
+ ** There is a vanishingly small chance that a change will not be
** detected. The chance of an undetected change is so small that
** it can be neglected.
*/
** Except, in locking_mode=EXCLUSIVE when there is nothing to in
** the rollback journal, the unlock is not performed and there is
** nothing to rollback, so this routine is a no-op.
-*/
+*/
static void pagerUnlockIfUnused(Pager *pPager){
if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
pagerUnlockAndRollback(pPager);
/*
** Acquire a reference to page number pgno in pager pPager (a page
-** reference has type DbPage*). If the requested reference is
+** reference has type DbPage*). If the requested reference is
** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
**
-** If the requested page is already in the cache, it is returned.
+** If the requested page is already in the cache, it is returned.
** Otherwise, a new page object is allocated and populated with data
** read from the database file. In some cases, the pcache module may
** choose not to allocate a new page object and may reuse an existing
** object with no outstanding references.
**
-** The extra data appended to a page is always initialized to zeros the
-** first time a page is loaded into memory. If the page requested is
+** The extra data appended to a page is always initialized to zeros the
+** first time a page is loaded into memory. If the page requested is
** already in the cache when this function is called, then the extra
** data is left as it was when the page object was last used.
**
-** If the database image is smaller than the requested page or if a
-** non-zero value is passed as the noContent parameter and the
-** requested page is not already stored in the cache, then no
-** actual disk read occurs. In this case the memory image of the
-** page is initialized to all zeros.
+** If the database image is smaller than the requested page or if a
+** non-zero value is passed as the noContent parameter and the
+** requested page is not already stored in the cache, then no
+** actual disk read occurs. In this case the memory image of the
+** page is initialized to all zeros.
**
** If noContent is true, it means that we do not care about the contents
** of the page. This occurs in two seperate scenarios:
/* It is acceptable to use a read-only (mmap) page for any page except
** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
- ** flag was specified by the caller. And so long as the db is not a
+ ** flag was specified by the caller. And so long as the db is not a
** temporary or in-memory database. */
const int bMmapOk = (pgno!=1 && USEFETCH(pPager)
&& (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
return SQLITE_CORRUPT_BKPT;
}
- /* If the pager is in the error state, return an error immediately.
+ /* If the pager is in the error state, return an error immediately.
** Otherwise, request the page from the PCache layer. */
if( pPager->errCode!=SQLITE_OK ){
rc = pPager->errCode;
if( iFrame==0 && bMmapOk ){
void *pData = 0;
- rc = sqlite3OsFetch(pPager->fd,
+ rc = sqlite3OsFetch(pPager->fd,
(i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
);
return SQLITE_OK;
}else{
- /* The pager cache has created a new page. Its content needs to
+ /* The pager cache has created a new page. Its content needs to
** be initialized. */
pPg = *ppPage;
}
if( noContent ){
/* Failure to set the bits in the InJournal bit-vectors is benign.
- ** It merely means that we might do some extra work to journal a
- ** page that does not need to be journaled. Nevertheless, be sure
- ** to test the case where a malloc error occurs while trying to set
+ ** It merely means that we might do some extra work to journal a
+ ** page that does not need to be journaled. Nevertheless, be sure
+ ** to test the case where a malloc error occurs while trying to set
** a bit in a bit vector.
*/
sqlite3BeginBenignMalloc();
/*
** Acquire a page if it is already in the in-memory cache. Do
** not read the page from disk. Return a pointer to the page,
-** or 0 if the page is not in cache.
+** or 0 if the page is not in cache.
**
** See also sqlite3PagerGet(). The difference between this routine
** and sqlite3PagerGet() is that _get() will go to the disk and read
** in the page if the page is not already in cache. This routine
-** returns NULL if the page is not in cache or if a disk I/O error
+** returns NULL if the page is not in cache or if a disk I/O error
** has ever happened.
*/
SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
/*
** This function is called at the start of every write transaction.
-** There must already be a RESERVED or EXCLUSIVE lock on the database
+** There must already be a RESERVED or EXCLUSIVE lock on the database
** file when this routine is called.
**
** Open the journal file for pager pPager and write a journal header
** to the start of it. If there are active savepoints, open the sub-journal
-** as well. This function is only used when the journal file is being
-** opened to write a rollback log for a transaction. It is not used
+** as well. This function is only used when the journal file is being
+** opened to write a rollback log for a transaction. It is not used
** when opening a hot journal file to roll it back.
**
** If the journal file is already open (as it may be in exclusive mode),
** then this function just writes a journal header to the start of the
-** already open file.
+** already open file.
**
** Whether or not the journal file is opened by this function, the
** Pager.pInJournal bitvec structure is allocated.
**
-** Return SQLITE_OK if everything is successful. Otherwise, return
-** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or
+** Return SQLITE_OK if everything is successful. Otherwise, return
+** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or
** an IO error code if opening or writing the journal file fails.
*/
static int pager_open_journal(Pager *pPager){
assert( pPager->eState==PAGER_WRITER_LOCKED );
assert( assert_pager_state(pPager) );
assert( pPager->pInJournal==0 );
-
+
/* If already in the error state, this function is a no-op. But on
** the other hand, this routine is never called if we are already in
** an error state. */
if( pPager->pInJournal==0 ){
return SQLITE_NOMEM;
}
-
+
/* Open the journal file if it is not already open. */
if( !isOpen(pPager->jfd) ){
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
}else{
const int flags = /* VFS flags to open journal file */
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
- (pPager->tempFile ?
+ (pPager->tempFile ?
(SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
(SQLITE_OPEN_MAIN_JOURNAL)
);
}
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
}
-
-
- /* Write the first journal header to the journal file and open
+
+
+ /* Write the first journal header to the journal file and open
** the sub-journal if necessary.
*/
if( rc==SQLITE_OK ){
}
/*
-** Begin a write-transaction on the specified pager object. If a
+** Begin a write-transaction on the specified pager object. If a
** write-transaction has already been opened, this function is a no-op.
**
** If the exFlag argument is false, then acquire at least a RESERVED
** lock on the database file. If exFlag is true, then acquire at least
-** an EXCLUSIVE lock. If such a lock is already held, no locking
+** an EXCLUSIVE lock. If such a lock is already held, no locking
** functions need be called.
**
** If the subjInMemory argument is non-zero, then any sub-journal opened
** has no effect if the sub-journal is already opened (as it may be when
** running in exclusive mode) or if the transaction does not require a
** sub-journal. If the subjInMemory argument is zero, then any required
-** sub-journal is implemented in-memory if pPager is an in-memory database,
+** sub-journal is implemented in-memory if pPager is an in-memory database,
** or using a temporary file otherwise.
*/
SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
**
** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD
** when it has an open transaction, but never to DBMOD or FINISHED.
- ** This is because in those states the code to roll back savepoint
- ** transactions may copy data from the sub-journal into the database
- ** file as well as into the page cache. Which would be incorrect in
+ ** This is because in those states the code to roll back savepoint
+ ** transactions may copy data from the sub-journal into the database
+ ** file as well as into the page cache. Which would be incorrect in
** WAL mode.
*/
pPager->eState = PAGER_WRITER_LOCKED;
}
/*
-** Mark a single data page as writeable. The page is written into the
+** Mark a single data page as writeable. The page is written into the
** main journal or sub-journal as required. If the page is written into
-** one of the journals, the corresponding bit is set in the
+** one of the journals, the corresponding bit is set in the
** Pager.pInJournal bitvec and the PagerSavepoint.pInSavepoint bitvecs
** of any open savepoints as appropriate.
*/
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
- /* This routine is not called unless a write-transaction has already
+ /* This routine is not called unless a write-transaction has already
** been started. The journal file may or may not be open at this point.
** It is never called in the ERROR state.
*/
** obtained the necessary locks to begin the write-transaction, but the
** rollback journal might not yet be open. Open it now if this is the case.
**
- ** This is done before calling sqlite3PcacheMakeDirty() on the page.
+ ** This is done before calling sqlite3PcacheMakeDirty() on the page.
** Otherwise, if it were done after calling sqlite3PcacheMakeDirty(), then
** an error might occur and the pager would end up in WRITER_LOCKED state
** with pages marked as dirty in the cache.
if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){
assert( !pagerUseWal(pPager) );
}else{
-
+
/* The transaction journal now exists and we have a RESERVED or an
** EXCLUSIVE lock on the main database file. Write the current page to
** the transaction journal if it is not there already.
rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum);
if( rc!=SQLITE_OK ) return rc;
- IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
+ IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
pPager->journalOff, pPager->pageSize));
PAGER_INCR(sqlite3_pager_writej_count);
PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n",
- PAGERID(pPager), pPg->pgno,
+ PAGERID(pPager), pPg->pgno,
((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)));
pPager->journalOff += 8 + pPager->pageSize;
((pPg->flags&PGHDR_NEED_SYNC)?1:0)));
}
}
-
+
/* If the statement journal is open and the page is not in it,
** then write the current page to the statement journal. Note that
** the statement journal format differs from the standard journal format
}
/*
-** Mark a data page as writeable. This routine must be called before
-** making changes to a page. The caller must check the return value
-** of this function and be careful not to change any page data unless
+** Mark a data page as writeable. This routine must be called before
+** making changes to a page. The caller must check the return value
+** of this function and be careful not to change any page data unless
** this routine returns SQLITE_OK.
**
** The difference between this function and pager_write() is that this
}
}
- /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages
+ /* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages
** starting at pg1, then it needs to be set for all of them. Because
** writing to any of these nPage pages may damage the others, the
** journal file must contain sync()ed copies of all of them
** on the given page is unused. The pager marks the page as clean so
** that it does not get written to disk.
**
-** Tests show that this optimization can quadruple the speed of large
+** Tests show that this optimization can quadruple the speed of large
** DELETE operations.
*/
SQLITE_PRIVATE void sqlite3PagerDontWrite(PgHdr *pPg){
}
/*
-** This routine is called to increment the value of the database file
-** change-counter, stored as a 4-byte big-endian integer starting at
+** This routine is called to increment the value of the database file
+** change-counter, stored as a 4-byte big-endian integer starting at
** byte offset 24 of the pager file. The secondary change counter at
** 92 is also updated, as is the SQLite version number at offset 96.
**
** But this only happens if the pPager->changeCountDone flag is false.
** To avoid excess churning of page 1, the update only happens once.
-** See also the pager_write_changecounter() routine that does an
+** See also the pager_write_changecounter() routine that does an
** unconditional update of the change counters.
**
-** If the isDirectMode flag is zero, then this is done by calling
+** If the isDirectMode flag is zero, then this is done by calling
** sqlite3PagerWrite() on page 1, then modifying the contents of the
** page data. In this case the file will be updated when the current
** transaction is committed.
** The isDirectMode flag may only be non-zero if the library was compiled
** with the SQLITE_ENABLE_ATOMIC_WRITE macro defined. In this case,
** if isDirect is non-zero, then the database file is updated directly
-** by writing an updated version of page 1 using a call to the
+** by writing an updated version of page 1 using a call to the
** sqlite3OsWrite() function.
*/
static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
assert( pPgHdr==0 || rc==SQLITE_OK );
/* If page one was fetched successfully, and this function is not
- ** operating in direct-mode, make page 1 writable. When not in
+ ** operating in direct-mode, make page 1 writable. When not in
** direct mode, page 1 is always held in cache and hence the PagerGet()
** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
*/
/*
** This function may only be called while a write-transaction is active in
-** rollback. If the connection is in WAL mode, this call is a no-op.
-** Otherwise, if the connection does not already have an EXCLUSIVE lock on
+** rollback. If the connection is in WAL mode, this call is a no-op.
+** Otherwise, if the connection does not already have an EXCLUSIVE lock on
** the database file, an attempt is made to obtain one.
**
** If the EXCLUSIVE lock is already held or the attempt to obtain it is
** successful, or the connection is in WAL mode, SQLITE_OK is returned.
-** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is
+** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is
** returned.
*/
SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager *pPager){
int rc = SQLITE_OK;
- assert( pPager->eState==PAGER_WRITER_CACHEMOD
- || pPager->eState==PAGER_WRITER_DBMOD
- || pPager->eState==PAGER_WRITER_LOCKED
+ assert( pPager->eState==PAGER_WRITER_CACHEMOD
+ || pPager->eState==PAGER_WRITER_DBMOD
+ || pPager->eState==PAGER_WRITER_LOCKED
);
assert( assert_pager_state(pPager) );
if( 0==pagerUseWal(pPager) ){
**
** * The database file change-counter is updated,
** * the journal is synced (unless the atomic-write optimization is used),
-** * all dirty pages are written to the database file,
+** * all dirty pages are written to the database file,
** * the database file is truncated (if required), and
-** * the database file synced.
+** * the database file synced.
**
-** The only thing that remains to commit the transaction is to finalize
-** (delete, truncate or zero the first part of) the journal file (or
+** The only thing that remains to commit the transaction is to finalize
+** (delete, truncate or zero the first part of) the journal file (or
** delete the master journal file if specified).
**
** Note that if zMaster==NULL, this does not overwrite a previous value
/* If a prior error occurred, report that error again. */
if( NEVER(pPager->errCode) ) return pPager->errCode;
- PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
+ PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
pPager->zFilename, zMaster, pPager->dbSize));
/* If no database changes have been made, return early. */
}else{
/* The following block updates the change-counter. Exactly how it
** does this depends on whether or not the atomic-update optimization
- ** was enabled at compile time, and if this transaction meets the
- ** runtime criteria to use the operation:
+ ** was enabled at compile time, and if this transaction meets the
+ ** runtime criteria to use the operation:
**
** * The file-system supports the atomic-write property for
- ** blocks of size page-size, and
+ ** blocks of size page-size, and
** * This commit is not part of a multi-file transaction, and
** * Exactly one page has been modified and store in the journal file.
**
** is not applicable to this transaction, call sqlite3JournalCreate()
** to make sure the journal file has actually been created, then call
** pager_incr_changecounter() to update the change-counter in indirect
- ** mode.
+ ** mode.
**
** Otherwise, if the optimization is both enabled and applicable,
** then call pager_incr_changecounter() to update the change-counter
*/
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
PgHdr *pPg;
- assert( isOpen(pPager->jfd)
- || pPager->journalMode==PAGER_JOURNALMODE_OFF
- || pPager->journalMode==PAGER_JOURNALMODE_WAL
+ assert( isOpen(pPager->jfd)
+ || pPager->journalMode==PAGER_JOURNALMODE_OFF
+ || pPager->journalMode==PAGER_JOURNALMODE_WAL
);
- if( !zMaster && isOpen(pPager->jfd)
- && pPager->journalOff==jrnlBufferSize(pPager)
+ if( !zMaster && isOpen(pPager->jfd)
+ && pPager->journalOff==jrnlBufferSize(pPager)
&& pPager->dbSize>=pPager->dbOrigSize
&& (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
){
- /* Update the db file change counter via the direct-write method. The
- ** following call will modify the in-memory representation of page 1
- ** to include the updated change counter and then write page 1
- ** directly to the database file. Because of the atomic-write
+ /* Update the db file change counter via the direct-write method. The
+ ** following call will modify the in-memory representation of page 1
+ ** to include the updated change counter and then write page 1
+ ** directly to the database file. Because of the atomic-write
** property of the host file-system, this is safe.
*/
rc = pager_incr_changecounter(pPager, 1);
rc = pager_incr_changecounter(pPager, 0);
#endif
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-
- /* Write the master journal name into the journal file. If a master
- ** journal file name has already been written to the journal file,
+
+ /* Write the master journal name into the journal file. If a master
+ ** journal file name has already been written to the journal file,
** or if zMaster is NULL (no master journal), then this call is a no-op.
*/
rc = writeMasterJournal(pPager, zMaster);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-
+
/* Sync the journal file and write all dirty pages to the database.
- ** If the atomic-update optimization is being used, this sync will not
+ ** If the atomic-update optimization is being used, this sync will not
** create the journal file or perform any real IO.
**
** Because the change-counter page was just modified, unless the
** atomic-update optimization is used it is almost certain that the
** journal requires a sync here. However, in locking_mode=exclusive
- ** on a system under memory pressure it is just possible that this is
+ ** on a system under memory pressure it is just possible that this is
** not the case. In this case it is likely enough that the redundant
- ** xSync() call will be changed to a no-op by the OS anyhow.
+ ** xSync() call will be changed to a no-op by the OS anyhow.
*/
rc = syncJournal(pPager, 0);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-
+
rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
if( rc!=SQLITE_OK ){
assert( rc!=SQLITE_IOERR_BLOCKED );
}
sqlite3PcacheCleanAll(pPager->pPCache);
- /* If the file on disk is smaller than the database image, use
+ /* If the file on disk is smaller than the database image, use
** pager_truncate to grow the file here. This can happen if the database
** image was extended as part of the current transaction and then the
** last page in the db image moved to the free-list. In this case the
rc = pager_truncate(pPager, nNew);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
}
-
+
/* Finally, sync the database file. */
if( !noSync ){
rc = sqlite3PagerSync(pPager);
/*
** When this function is called, the database file has been completely
** updated to reflect the changes made by the current transaction and
-** synced to disk. The journal file still exists in the file-system
+** synced to disk. The journal file still exists in the file-system
** though, and if a failure occurs at this point it will eventually
** be used as a hot-journal and the current transaction rolled back.
**
-** This function finalizes the journal file, either by deleting,
-** truncating or partially zeroing it, so that it cannot be used
+** This function finalizes the journal file, either by deleting,
+** truncating or partially zeroing it, so that it cannot be used
** for hot-journal rollback. Once this is done the transaction is
** irrevocably committed.
**
** this transaction, the pager is running in exclusive-mode and is
** using persistent journals, then this function is a no-op.
**
- ** The start of the journal file currently contains a single journal
+ ** The start of the journal file currently contains a single journal
** header with the nRec field set to 0. If such a journal is used as
** a hot-journal during hot-journal rollback, 0 changes will be made
- ** to the database file. So there is no need to zero the journal
+ ** to the database file. So there is no need to zero the journal
** header. Since the pager is in exclusive mode, there is no need
** to drop any locks either.
*/
- if( pPager->eState==PAGER_WRITER_LOCKED
- && pPager->exclusiveMode
+ if( pPager->eState==PAGER_WRITER_LOCKED
+ && pPager->exclusiveMode
&& pPager->journalMode==PAGER_JOURNALMODE_PERSIST
){
assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff );
}
/*
-** If a write transaction is open, then all changes made within the
+** If a write transaction is open, then all changes made within the
** transaction are reverted and the current write-transaction is closed.
** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR
** state if an error occurs.
**
** Otherwise, in rollback mode, this function performs two functions:
**
-** 1) It rolls back the journal file, restoring all database file and
+** 1) It rolls back the journal file, restoring all database file and
** in-memory cache pages to the state they were in when the transaction
** was opened, and
**
** 2) It finalizes the journal file, so that it is not used for hot
** rollback at any point in the future.
**
-** Finalization of the journal file (task 2) is only performed if the
+** Finalization of the journal file (task 2) is only performed if the
** rollback is successful.
**
** In WAL mode, all cache-entries containing data modified within the
PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager)));
/* PagerRollback() is a no-op if called in READER or OPEN state. If
- ** the pager is already in the ERROR state, the rollback is not
+ ** the pager is already in the ERROR state, the rollback is not
** attempted here. Instead, the error code is returned to the caller.
*/
assert( assert_pager_state(pPager) );
int eState = pPager->eState;
rc = pager_end_transaction(pPager, 0, 0);
if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
- /* This can happen using journal_mode=off. Move the pager to the error
+ /* This can happen using journal_mode=off. Move the pager to the error
** state to indicate that the contents of the cache may not be trusted.
** Any active readers will get SQLITE_ABORT.
*/
/*
** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or
** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the
-** current cache hit or miss count, according to the value of eStat. If the
-** reset parameter is non-zero, the cache hit or miss count is zeroed before
+** current cache hit or miss count, according to the value of eStat. If the
+** reset parameter is non-zero, the cache hit or miss count is zeroed before
** returning.
*/
SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){
** to make up the difference. If the number of savepoints is already
** equal to nSavepoint, then this function is a no-op.
**
-** If a memory allocation fails, SQLITE_NOMEM is returned. If an error
+** If a memory allocation fails, SQLITE_NOMEM is returned. If an error
** occurs while opening the sub-journal file, then an IO error code is
** returned. Otherwise, SQLITE_OK.
*/
PagerSavepoint *aNew; /* New Pager.aSavepoint array */
/* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM
- ** if the allocation fails. Otherwise, zero the new portion in case a
+ ** if the allocation fails. Otherwise, zero the new portion in case a
** malloc failure occurs while populating it in the for(...) loop below.
*/
aNew = (PagerSavepoint *)sqlite3Realloc(
/*
** This function is called to rollback or release (commit) a savepoint.
-** The savepoint to release or rollback need not be the most recently
+** The savepoint to release or rollback need not be the most recently
** created savepoint.
**
** Parameter op is always either SAVEPOINT_ROLLBACK or SAVEPOINT_RELEASE.
** index iSavepoint. If it is SAVEPOINT_ROLLBACK, then rollback all changes
** that have occurred since the specified savepoint was created.
**
-** The savepoint to rollback or release is identified by parameter
+** The savepoint to rollback or release is identified by parameter
** iSavepoint. A value of 0 means to operate on the outermost savepoint
** (the first created). A value of (Pager.nSavepoint-1) means operate
** on the most recently created savepoint. If iSavepoint is greater than
** (Pager.nSavepoint-1), then this function is a no-op.
**
** If a negative value is passed to this function, then the current
-** transaction is rolled back. This is different to calling
+** transaction is rolled back. This is different to calling
** sqlite3PagerRollback() because this function does not terminate
-** the transaction or unlock the database, it just restores the
-** contents of the database to its original state.
+** the transaction or unlock the database, it just restores the
+** contents of the database to its original state.
**
-** In any case, all savepoints with an index greater than iSavepoint
+** In any case, all savepoints with an index greater than iSavepoint
** are destroyed. If this is a release operation (op==SAVEPOINT_RELEASE),
** then savepoint iSavepoint is also destroyed.
**
** This function may return SQLITE_NOMEM if a memory allocation fails,
-** or an IO error code if an IO error occurs while rolling back a
+** or an IO error code if an IO error occurs while rolling back a
** savepoint. If no errors occur, SQLITE_OK is returned.
-*/
+*/
SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
int rc = pPager->errCode; /* Return code */
int nNew; /* Number of remaining savepoints after this op. */
/* Figure out how many savepoints will still be active after this
- ** operation. Store this value in nNew. Then free resources associated
+ ** operation. Store this value in nNew. Then free resources associated
** with any savepoints that are destroyed by this operation.
*/
nNew = iSavepoint + (( op==SAVEPOINT_RELEASE ) ? 0 : 1);
}
pPager->nSavepoint = nNew;
- /* If this is a release of the outermost savepoint, truncate
+ /* If this is a release of the outermost savepoint, truncate
** the sub-journal to zero bytes in size. */
if( op==SAVEPOINT_RELEASE ){
if( nNew==0 && isOpen(pPager->sjfd) ){
** transaction is active).
**
** If the fourth argument, isCommit, is non-zero, then this page is being
-** moved as part of a database reorganization just before the transaction
-** is being committed. In this case, it is guaranteed that the database page
+** moved as part of a database reorganization just before the transaction
+** is being committed. In this case, it is guaranteed that the database page
** pPg refers to will not be written to again within this transaction.
**
** This function may return SQLITE_NOMEM or an IO error code if an error
}
/* If the page being moved is dirty and has not been saved by the latest
- ** savepoint, then save the current contents of the page into the
+ ** savepoint, then save the current contents of the page into the
** sub-journal now. This is required to handle the following scenario:
**
** BEGIN;
return rc;
}
- PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n",
+ PAGERTRACE(("MOVE %d page %d (needSync=%d) moves to %d\n",
PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno));
IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))
** be written to, store pPg->pgno in local variable needSyncPgno.
**
** If the isCommit flag is set, there is no need to remember that
- ** the journal needs to be sync()ed before database page pPg->pgno
+ ** the journal needs to be sync()ed before database page pPg->pgno
** can be written to. The caller has already promised not to write to it.
*/
if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
}
/* If the cache contains a page with page-number pgno, remove it
- ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for
- ** page pgno before the 'move' operation, it needs to be retained
+ ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for
+ ** page pgno before the 'move' operation, it needs to be retained
** for the page moved there.
*/
pPg->flags &= ~PGHDR_NEED_SYNC;
}
if( needSyncPgno ){
- /* If needSyncPgno is non-zero, then the journal file needs to be
+ /* If needSyncPgno is non-zero, then the journal file needs to be
** sync()ed before any data is written to database file page needSyncPgno.
- ** Currently, no such page exists in the page-cache and the
+ ** Currently, no such page exists in the page-cache and the
** "is journaled" bitvec flag has been set. This needs to be remedied by
** loading the page into the pager-cache and setting the PGHDR_NEED_SYNC
** flag.
}
/*
-** Return a pointer to the Pager.nExtra bytes of "extra" space
+** Return a pointer to the Pager.nExtra bytes of "extra" space
** allocated along with the specified page.
*/
SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){
/*
** Get/set the locking-mode for this pager. Parameter eMode must be one
-** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or
+** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or
** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then
** the locking-mode is set to the value specified.
**
assert( eMode==PAGER_JOURNALMODE_DELETE
|| eMode==PAGER_JOURNALMODE_TRUNCATE
|| eMode==PAGER_JOURNALMODE_PERSIST
- || eMode==PAGER_JOURNALMODE_OFF
- || eMode==PAGER_JOURNALMODE_WAL
+ || eMode==PAGER_JOURNALMODE_OFF
+ || eMode==PAGER_JOURNALMODE_WAL
|| eMode==PAGER_JOURNALMODE_MEMORY );
/* This routine is only called from the OP_JournalMode opcode, and
assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
if( rc!=SQLITE_OK ){
- /* If the attempt to grab the exclusive lock failed, release the
+ /* If the attempt to grab the exclusive lock failed, release the
** pending lock that may have been obtained instead. */
pagerUnlockDb(pPager, SHARED_LOCK);
}
}
/*
-** Call sqlite3WalOpen() to open the WAL handle. If the pager is in
+** Call sqlite3WalOpen() to open the WAL handle. If the pager is in
** exclusive-locking mode when this function is called, take an EXCLUSIVE
** lock on the database file and use heap-memory to store the wal-index
** in. Otherwise, use the normal shared-memory.
assert( pPager->pWal==0 && pPager->tempFile==0 );
assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
- /* If the pager is already in exclusive-mode, the WAL module will use
- ** heap-memory for the wal-index instead of the VFS shared-memory
+ /* If the pager is already in exclusive-mode, the WAL module will use
+ ** heap-memory for the wal-index instead of the VFS shared-memory
** implementation. Take the exclusive lock now, before opening the WAL
** file, to make sure this is safe.
*/
rc = pagerExclusiveLock(pPager);
}
- /* Open the connection to the log file. If this operation fails,
+ /* Open the connection to the log file. If this operation fails,
** (e.g. due to malloc() failure), return an error code.
*/
if( rc==SQLITE_OK ){
** If the pager passed as the first argument is open on a real database
** file (not a temp file or an in-memory database), and the WAL file
** is not already open, make an attempt to open it now. If successful,
-** return SQLITE_OK. If an error occurs or the VFS used by the pager does
+** return SQLITE_OK. If an error occurs or the VFS used by the pager does
** not support the xShmXXX() methods, return an error code. *pbOpen is
** not modified in either case.
**
** This function is called to close the connection to the log file prior
** to switching from WAL to rollback mode.
**
-** Before closing the log file, this function attempts to take an
+** Before closing the log file, this function attempts to take an
** EXCLUSIVE lock on the database file. If this cannot be obtained, an
** error (SQLITE_BUSY) is returned and the log connection is not closed.
** If successful, the EXCLUSIVE lock is not released before returning.
rc = pagerOpenWal(pPager);
}
}
-
+
/* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
** the database file, the log and log-summary files will be deleted.
*/
**
*************************************************************************
**
-** This file contains the implementation of a write-ahead log (WAL) used in
+** This file contains the implementation of a write-ahead log (WAL) used in
** "journal_mode=WAL" mode.
**
** WRITE-AHEAD LOG (WAL) FILE FORMAT
** Each frame records the revised content of a single page from the
** database file. All changes to the database are recorded by writing
** frames into the WAL. Transactions commit when a frame is written that
-** contains a commit marker. A single WAL can and usually does record
+** contains a commit marker. A single WAL can and usually does record
** multiple transactions. Periodically, the content of the WAL is
** transferred back into the database file in an operation called a
** "checkpoint".
**
** Immediately following the wal-header are zero or more frames. Each
** frame consists of a 24-byte frame-header followed by a <page-size> bytes
-** of page data. The frame-header is six big-endian 32-bit unsigned
+** of page data. The frame-header is six big-endian 32-bit unsigned
** integer values, as follows:
**
** 0: Page number.
-** 4: For commit records, the size of the database image in pages
+** 4: For commit records, the size of the database image in pages
** after the commit. For all other records, zero.
** 8: Salt-1 (copied from the header)
** 12: Salt-2 (copied from the header)
** the checksum. The checksum is computed by interpreting the input as
** an even number of unsigned 32-bit integers: x[0] through x[N]. The
** algorithm used for the checksum is as follows:
-**
+**
** for i from 0 to n-1 step 2:
** s0 += x[i] + s1;
** s1 += x[i+1] + s0;
**
** Note that s0 and s1 are both weighted checksums using fibonacci weights
** in reverse order (the largest fibonacci weight occurs on the first element
-** of the sequence being summed.) The s1 value spans all 32-bit
+** of the sequence being summed.) The s1 value spans all 32-bit
** terms of the sequence whereas s0 omits the final term.
**
** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the
** multiple concurrent readers to view different versions of the database
** content simultaneously.
**
-** The reader algorithm in the previous paragraphs works correctly, but
+** The reader algorithm in the previous paragraphs works correctly, but
** because frames for page P can appear anywhere within the WAL, the
** reader has to scan the entire WAL looking for page P frames. If the
** WAL is large (multiple megabytes is typical) that scan can be slow,
** and read performance suffers. To overcome this problem, a separate
** data structure called the wal-index is maintained to expedite the
** search for frames of a particular page.
-**
+**
** WAL-INDEX FORMAT
**
** Conceptually, the wal-index is shared memory, though VFS implementations
** might choose to implement the wal-index using a mmapped file. Because
-** the wal-index is shared memory, SQLite does not support journal_mode=WAL
+** the wal-index is shared memory, SQLite does not support journal_mode=WAL
** on a network filesystem. All users of the database must be able to
** share memory.
**
** byte order of the host computer.
**
** The purpose of the wal-index is to answer this question quickly: Given
-** a page number P and a maximum frame index M, return the index of the
+** a page number P and a maximum frame index M, return the index of the
** last frame in the wal before frame M for page P in the WAL, or return
** NULL if there are no frames for page P in the WAL prior to M.
**
** The wal-index consists of a header region, followed by an one or
-** more index blocks.
+** more index blocks.
**
** The wal-index header contains the total number of frames within the WAL
** in the mxFrame field.
**
-** Each index block except for the first contains information on
+** Each index block except for the first contains information on
** HASHTABLE_NPAGE frames. The first index block contains information on
-** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and
+** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and
** HASHTABLE_NPAGE are selected so that together the wal-index header and
** first index block are the same size as all other index blocks in the
** wal-index.
**
** Each index block contains two sections, a page-mapping that contains the
-** database page number associated with each wal frame, and a hash-table
+** database page number associated with each wal frame, and a hash-table
** that allows readers to query an index block for a specific page number.
** The page-mapping is an array of HASHTABLE_NPAGE (or HASHTABLE_NPAGE_ONE
-** for the first index block) 32-bit page numbers. The first entry in the
+** for the first index block) 32-bit page numbers. The first entry in the
** first index-block contains the database page number corresponding to the
** first frame in the WAL file. The first entry in the second index block
** in the WAL file corresponds to the (HASHTABLE_NPAGE_ONE+1)th frame in
**
** The hash table consists of HASHTABLE_NSLOT 16-bit unsigned integers.
** HASHTABLE_NSLOT = 2*HASHTABLE_NPAGE, and there is one entry in the
-** hash table for each page number in the mapping section, so the hash
-** table is never more than half full. The expected number of collisions
+** hash table for each page number in the mapping section, so the hash
+** table is never more than half full. The expected number of collisions
** prior to finding a match is 1. Each entry of the hash table is an
** 1-based index of an entry in the mapping section of the same
** index block. Let K be the 1-based index of the largest entry in
** reached) until an unused hash slot is found. Let the first unused slot
** be at index iUnused. (iUnused might be less than iKey if there was
** wrap-around.) Because the hash table is never more than half full,
-** the search is guaranteed to eventually hit an unused entry. Let
+** the search is guaranteed to eventually hit an unused entry. Let
** iMax be the value between iKey and iUnused, closest to iUnused,
** where aHash[iMax]==P. If there is no iMax entry (if there exists
** no hash slot such that aHash[i]==p) then page P is not in the
** current index block. Otherwise the iMax-th mapping entry of the
-** current index block corresponds to the last entry that references
+** current index block corresponds to the last entry that references
** page P.
**
** A hash search begins with the last index block and moves toward the
** if no values greater than K0 had ever been inserted into the hash table
** in the first place - which is what reader one wants. Meanwhile, the
** second reader using K1 will see additional values that were inserted
-** later, which is exactly what reader two wants.
+** later, which is exactly what reader two wants.
**
** When a rollback occurs, the value of K is decreased. Hash table entries
** that correspond to frames greater than the new K value are removed
** values in the wal-header are correct and (b) the version field is not
** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN.
**
-** Similarly, if a client successfully reads a wal-index header (i.e. the
+** Similarly, if a client successfully reads a wal-index header (i.e. the
** checksum test is successful) and finds that the version field is not
** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite
** returns SQLITE_CANTOPEN.
**
** The szPage value can be any power of 2 between 512 and 32768, inclusive.
** Or it can be 1 to represent a 65536-byte page. The latter case was
-** added in 3.7.1 when support for 64K pages was added.
+** added in 3.7.1 when support for 64K pages was added.
*/
struct WalIndexHdr {
u32 iVersion; /* Wal-index version */
** There is one entry in aReadMark[] for each reader lock. If a reader
** holds read-lock K, then the value in aReadMark[K] is no greater than
** the mxFrame for that reader. The value READMARK_NOT_USED (0xffffffff)
-** for any aReadMark[] means that entry is unused. aReadMark[0] is
+** for any aReadMark[] means that entry is unused. aReadMark[0] is
** a special case; its value is never used and it exists as a place-holder
** to avoid having to offset aReadMark[] indexs by one. Readers holding
** WAL_READ_LOCK(0) always ignore the entire WAL and read all content
** previous sentence is when nBackfill equals mxFrame (meaning that everything
** in the WAL has been backfilled into the database) then new readers
** will choose aReadMark[0] which has value 0 and hence such reader will
-** get all their all content directly from the database file and ignore
+** get all their all content directly from the database file and ignore
** the WAL.
**
** Writers normally append new frames to the end of the WAL. However,
** big-endian format in the first 4 bytes of a WAL file.
**
** If the LSB is set, then the checksums for each frame within the WAL
-** file are calculated by treating all data as an array of 32-bit
-** big-endian words. Otherwise, they are calculated by interpreting
+** file are calculated by treating all data as an array of 32-bit
+** big-endian words. Otherwise, they are calculated by interpreting
** all data as 32-bit little-endian words.
*/
#define WAL_MAGIC 0x377f0682
/*
-** Return the offset of frame iFrame in the write-ahead log file,
+** Return the offset of frame iFrame in the write-ahead log file,
** assuming a database page size of szPage bytes. The offset returned
** is to the start of the write-ahead log frame-header.
*/
** Candidate values for Wal.exclusiveMode.
*/
#define WAL_NORMAL_MODE 0
-#define WAL_EXCLUSIVE_MODE 1
+#define WAL_EXCLUSIVE_MODE 1
#define WAL_HEAPMEMORY_MODE 2
/*
/*
** This structure is used to implement an iterator that loops through
** all frames in the WAL in database page order. Where two or more frames
-** correspond to the same database page, the iterator visits only the
+** correspond to the same database page, the iterator visits only the
** frame most recently written to the WAL (in other words, the frame with
** the largest index).
**
#define HASHTABLE_HASH_1 383 /* Should be prime */
#define HASHTABLE_NSLOT (HASHTABLE_NPAGE*2) /* Must be a power of 2 */
-/*
+/*
** The block of page numbers associated with the first hash-table in a
** wal-index is smaller than usual. This is so that there is a complete
** hash-table on each aligned 32KB page of the wal-index.
pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
}else{
- rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
+ rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
if( rc==SQLITE_READONLY ){
)
/*
-** Generate or extend an 8 byte checksum based on the data in
+** Generate or extend an 8 byte checksum based on the data in
** array aByte[] and the initial values of aIn[0] and aIn[1] (or
** initial values of 0 and 0 if aIn==NULL).
**
/*
** This function encodes a single frame header and writes it to a buffer
-** supplied by the caller. A frame-header is made up of a series of
+** supplied by the caller. A frame-header is made up of a series of
** 4-byte big-endian integers, as follows:
**
** 0: Page number.
-** 4: For commit records, the size of the database image in pages
+** 4: For commit records, the size of the database image in pages
** after the commit. For all other records, zero.
** 8: Salt-1 (copied from the wal-header)
** 12: Salt-2 (copied from the wal-header)
assert( WAL_FRAME_HDRSIZE==24 );
/* A frame is only valid if the salt values in the frame-header
- ** match the salt values in the wal-header.
+ ** match the salt values in the wal-header.
*/
if( memcmp(&pWal->hdr.aSalt, &aFrame[8], 8)!=0 ){
return 0;
}
/* A frame is only valid if a checksum of the WAL header,
- ** all prior frams, the first 16 bytes of this frame-header,
- ** and the frame-data matches the checksum in the last 8
+ ** all prior frams, the first 16 bytes of this frame-header,
+ ** and the frame-data matches the checksum in the last 8
** bytes of this frame-header.
*/
nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
- if( aCksum[0]!=sqlite3Get4byte(&aFrame[16])
- || aCksum[1]!=sqlite3Get4byte(&aFrame[20])
+ if( aCksum[0]!=sqlite3Get4byte(&aFrame[16])
+ || aCksum[1]!=sqlite3Get4byte(&aFrame[20])
){
/* Checksum failed. */
return 0;
}
}
#endif /*defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */
-
+
/*
** Set or release locks on the WAL. Locks are either shared or exclusive.
return (iPriorHash+1)&(HASHTABLE_NSLOT-1);
}
-/*
+/*
** Return pointers to the hash table and page number array stored on
** page iHash of the wal-index. The wal-index is broken into 32KB pages
** numbered starting from 0.
**
** Set output variable *paHash to point to the start of the hash table
-** in the wal-index file. Set *piZero to one less than the frame
+** in the wal-index file. Set *piZero to one less than the frame
** number of the first frame indexed by this hash table. If a
-** slot in the hash table is set to N, it refers to frame number
+** slot in the hash table is set to N, it refers to frame number
** (*piZero+N) in the log.
**
** Finally, set *paPgno so that *paPgno[1] is the page number of the
}else{
iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE;
}
-
+
*paPgno = &aPgno[-1];
*paHash = aHash;
*piZero = iZero;
/*
** Return the number of the wal-index page that contains the hash-table
** and page-number array that contain entries corresponding to WAL frame
-** iFrame. The wal-index is broken up into 32KB pages. Wal-index pages
+** iFrame. The wal-index is broken up into 32KB pages. Wal-index pages
** are numbered starting from 0.
*/
static int walFramePage(u32 iFrame){
if( pWal->hdr.mxFrame==0 ) return;
- /* Obtain pointers to the hash-table and page-number array containing
+ /* Obtain pointers to the hash-table and page-number array containing
** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed
** that the page said hash-table and array reside on is already mapped.
*/
aHash[i] = 0;
}
}
-
+
/* Zero the entries in the aPgno array that correspond to frames with
- ** frame numbers greater than pWal->hdr.mxFrame.
+ ** frame numbers greater than pWal->hdr.mxFrame.
*/
nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]);
memset((void *)&aPgno[iLimit+1], 0, nByte);
idx = iFrame - iZero;
assert( idx <= HASHTABLE_NSLOT/2 + 1 );
-
+
/* If this is the first entry to be added to this hash-table, zero the
- ** entire hash table and aPgno[] array before proceding.
+ ** entire hash table and aPgno[] array before proceding.
*/
if( idx==1 ){
int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]);
/* If the entry in aPgno[] is already set, then the previous writer
** must have exited unexpectedly in the middle of a transaction (after
- ** writing one or more dirty pages to the WAL to free up memory).
- ** Remove the remnants of that writers uncommitted transaction from
+ ** writing one or more dirty pages to the WAL to free up memory).
+ ** Remove the remnants of that writers uncommitted transaction from
** the hash-table before writing any new entries.
*/
if( aPgno[idx] ){
/*
-** Recover the wal-index by reading the write-ahead log file.
+** Recover the wal-index by reading the write-ahead log file.
**
** This routine first tries to establish an exclusive lock on the
** wal-index to prevent other threads/processes from doing anything
}
/* If the database page size is not a power of two, or is greater than
- ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid
+ ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid
** data. Similarly, if the 'magic' value is invalid, ignore the whole
** WAL file.
*/
magic = sqlite3Get4byte(&aBuf[0]);
szPage = sqlite3Get4byte(&aBuf[8]);
- if( (magic&0xFFFFFFFE)!=WAL_MAGIC
- || szPage&(szPage-1)
- || szPage>SQLITE_MAX_PAGE_SIZE
- || szPage<512
+ if( (magic&0xFFFFFFFE)!=WAL_MAGIC
+ || szPage&(szPage-1)
+ || szPage>SQLITE_MAX_PAGE_SIZE
+ || szPage<512
){
goto finished;
}
memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
/* Verify that the WAL header checksum is correct */
- walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN,
+ walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN,
aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum
);
if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24])
pWal->hdr.aFrameCksum[1] = aFrameCksum[1];
walIndexWriteHdr(pWal);
- /* Reset the checkpoint-header. This is safe because this thread is
+ /* Reset the checkpoint-header. This is safe because this thread is
** currently holding locks that exclude all other readers, writers and
** checkpointers.
*/
}
}
-/*
-** Open a connection to the WAL file zWalName. The database file must
+/*
+** Open a connection to the WAL file zWalName. The database file must
** already be opened on connection pDbFd. The buffer that zWalName points
** to must remain valid for the lifetime of the returned Wal* handle.
**
** were to do this just after this client opened one of these files, the
** system would be badly broken.
**
-** If the log file is successfully opened, SQLITE_OK is returned and
+** If the log file is successfully opened, SQLITE_OK is returned and
** *ppWal is set to point to a new WAL handle. If an error occurs,
** an SQLite error code is returned and *ppWal is left unmodified.
*/
ht_slot logpage;
Pgno dbpage;
- if( (iLeft<nLeft)
+ if( (iLeft<nLeft)
&& (iRight>=nRight || aContent[aLeft[iLeft]]<aContent[aRight[iRight]])
){
logpage = aLeft[iLeft++];
#endif
}
-/*
+/*
** Free an iterator allocated by walIteratorInit().
*/
static void walIteratorFree(WalIterator *p){
}
/*
-** Construct a WalInterator object that can be used to loop over all
+** Construct a WalInterator object that can be used to loop over all
** pages in the WAL in ascending order. The caller must hold the checkpoint
** lock.
**
/* Allocate space for the WalIterator object. */
nSegment = walFramePage(iLast) + 1;
- nByte = sizeof(WalIterator)
+ nByte = sizeof(WalIterator)
+ (nSegment-1)*sizeof(struct WalSegment)
+ iLast*sizeof(ht_slot);
p = (WalIterator *)sqlite3ScratchMalloc(nByte);
}
aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero];
iZero++;
-
+
for(j=0; j<nEntry; j++){
aIndex[j] = (ht_slot)j;
}
** that a concurrent reader might be using.
**
** All I/O barrier operations (a.k.a fsyncs) occur in this routine when
-** SQLite is in WAL-mode in synchronous=NORMAL. That means that if
-** checkpoints are always run by a background thread or background
+** SQLite is in WAL-mode in synchronous=NORMAL. That means that if
+** checkpoints are always run by a background thread or background
** process, foreground threads will never block on a lengthy fsync call.
**
** Fsync is called on the WAL before writing content out of the WAL and
** database file.
**
** This routine uses and updates the nBackfill field of the wal-index header.
-** This is the only routine tha will increase the value of nBackfill.
+** This is the only routine tha will increase the value of nBackfill.
** (A WAL reset or recovery will revert nBackfill to zero, but not increase
** its value.)
**
if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
return 1; /* Dirty read */
- }
+ }
if( h1.isInit==0 ){
return 1; /* Malformed header - probably all zeros */
}
** changed by this opertion. If pWal->hdr is unchanged, set *pChanged
** to 0.
**
-** If the wal-index header is successfully read, return SQLITE_OK.
+** If the wal-index header is successfully read, return SQLITE_OK.
** Otherwise an SQLite error code.
*/
static int walIndexReadHdr(Wal *pWal, int *pChanged){
int badHdr; /* True if a header read failed */
volatile u32 *page0; /* Chunk of wal-index containing header */
- /* Ensure that page 0 of the wal-index (the page that contains the
+ /* Ensure that page 0 of the wal-index (the page that contains the
** wal-index header) is mapped. Return early if an error occurs here.
*/
assert( pChanged );
/* If the first page of the wal-index has been mapped, try to read the
** wal-index header immediately, without holding any lock. This usually
- ** works, but may fail if the wal-index header is corrupt or currently
+ ** works, but may fail if the wal-index header is corrupt or currently
** being modified by another thread or process.
*/
badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
**
** The useWal parameter is true to force the use of the WAL and disable
** the case where the WAL is bypassed because it has been completely
-** checkpointed. If useWal==0 then this routine calls walIndexReadHdr()
-** to make a copy of the wal-index header into pWal->hdr. If the
-** wal-index header has changed, *pChanged is set to 1 (as an indication
-** to the caller that the local paget cache is obsolete and needs to be
+** checkpointed. If useWal==0 then this routine calls walIndexReadHdr()
+** to make a copy of the wal-index header into pWal->hdr. If the
+** wal-index header has changed, *pChanged is set to 1 (as an indication
+** to the caller that the local paget cache is obsolete and needs to be
** flushed.) When useWal==1, the wal-index header is assumed to already
** be loaded and the pChanged parameter is unused.
**
** bad luck when there is lots of contention for the wal-index, but that
** possibility is so small that it can be safely neglected, we believe.
**
-** On success, this routine obtains a read lock on
+** On success, this routine obtains a read lock on
** WAL_READ_LOCK(pWal->readLock). The pWal->readLock integer is
** in the range 0 <= pWal->readLock < WAL_NREADER. If pWal->readLock==(-1)
** that means the Wal does not hold any read lock. The reader must not
**
** Circumstances that cause a RETRY should only last for the briefest
** instances of time. No I/O or other system calls are done while the
- ** locks are held, so the locks should not be held for very long. But
+ ** locks are held, so the locks should not be held for very long. But
** if we are unlucky, another process that is holding a lock might get
- ** paged out or take a page-fault that is time-consuming to resolve,
+ ** paged out or take a page-fault that is time-consuming to resolve,
** during the few nanoseconds that it is holding the lock. In that case,
** it might take longer than normal for the lock to free.
**
** After 5 RETRYs, we begin calling sqlite3OsSleep(). The first few
** calls to sqlite3OsSleep() have a delay of 1 microsecond. Really this
** is more of a scheduler yield than an actual delay. But on the 10th
- ** an subsequent retries, the delays start becoming longer and longer,
+ ** an subsequent retries, the delays start becoming longer and longer,
** so that on the 100th (and last) RETRY we delay for 21 milliseconds.
** The total delay time before giving up is less than 1 second.
*/
if( pWal->apWiData[0]==0 ){
/* This branch is taken when the xShmMap() method returns SQLITE_BUSY.
** We assume this is a transient condition, so return WAL_RETRY. The
- ** xShmMap() implementation used by the default unix and win32 VFS
- ** modules may return SQLITE_BUSY due to a race condition in the
- ** code that determines whether or not the shared-memory region
+ ** xShmMap() implementation used by the default unix and win32 VFS
+ ** modules may return SQLITE_BUSY due to a race condition in the
+ ** code that determines whether or not the shared-memory region
** must be zeroed before the requested page is returned.
*/
rc = WAL_RETRY;
** snapshoT. Since holding READ_LOCK(0) prevents a checkpoint from
** happening, this is usually correct.
**
- ** However, if frames have been appended to the log (or if the log
+ ** However, if frames have been appended to the log (or if the log
** is wrapped and written for that matter) before the READ_LOCK(0)
** is obtained, that is not necessarily true. A checkpointer may
** have started to backfill the appended frames but crashed before
**
** This does not guarantee that the copy of the wal-index header is up to
** date before proceeding. That would not be possible without somehow
- ** blocking writers. It only guarantees that a dangerous checkpoint or
+ ** blocking writers. It only guarantees that a dangerous checkpoint or
** log-wrap (either of which would require an exclusive lock on
** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid.
*/
/* If the "last page" field of the wal-index header snapshot is 0, then
** no data will be read from the wal under any circumstances. Return early
- ** in this case as an optimization. Likewise, if pWal->readLock==0,
- ** then the WAL is ignored by the reader so return early, as if the
+ ** in this case as an optimization. Likewise, if pWal->readLock==0,
+ ** then the WAL is ignored by the reader so return early, as if the
** WAL were empty.
*/
if( iLast==0 || pWal->readLock==0 ){
** hash table (each hash table indexes up to HASHTABLE_NPAGE frames).
**
** This code might run concurrently to the code in walIndexAppend()
- ** that adds entries to the wal-index (and possibly to this hash
- ** table). This means the value just read from the hash
- ** slot (aHash[iKey]) may have been added before or after the
+ ** that adds entries to the wal-index (and possibly to this hash
+ ** table). This means the value just read from the hash
+ ** slot (aHash[iKey]) may have been added before or after the
** current read transaction was opened. Values added after the
** read transaction was opened may have been written incorrectly -
** i.e. these slots may contain garbage data. However, we assume
** opened remain unmodified.
**
** For the reasons above, the if(...) condition featured in the inner
- ** loop of the following block is more stringent that would be required
+ ** loop of the following block is more stringent that would be required
** if we had exclusive access to the hash-table:
**
- ** (aPgno[iFrame]==pgno):
+ ** (aPgno[iFrame]==pgno):
** This condition filters out normal hash-table collisions.
**
- ** (iFrame<=iLast):
+ ** (iFrame<=iLast):
** This condition filters out entries that were added to the hash
** table after the current read-transaction had started.
*/
return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset);
}
-/*
+/*
** Return the size of the database in pages (or zero, if unknown).
*/
SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal){
}
-/*
+/*
** This function starts a write transaction on the WAL.
**
** A read transaction must have already been started by a prior call
if( ALWAYS(pWal->writeLock) ){
Pgno iMax = pWal->hdr.mxFrame;
Pgno iFrame;
-
+
/* Restore the clients cache of the wal-index header to the state it
- ** was in before the client began writing to the database.
+ ** was in before the client began writing to the database.
*/
memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
- for(iFrame=pWal->hdr.mxFrame+1;
- ALWAYS(rc==SQLITE_OK) && iFrame<=iMax;
+ for(iFrame=pWal->hdr.mxFrame+1;
+ ALWAYS(rc==SQLITE_OK) && iFrame<=iMax;
iFrame++
){
/* This call cannot fail. Unless the page for which the page number
- ** is passed as the second argument is (a) in the cache and
+ ** is passed as the second argument is (a) in the cache and
** (b) has an outstanding reference, then xUndo is either a no-op
** (if (a) is false) or simply expels the page from the cache (if (b)
** is false).
return rc;
}
-/*
-** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32
-** values. This function populates the array with values required to
-** "rollback" the write position of the WAL handle back to the current
+/*
+** Argument aWalData must point to an array of WAL_SAVEPOINT_NDATA u32
+** values. This function populates the array with values required to
+** "rollback" the write position of the WAL handle back to the current
** point in the event of a savepoint rollback (via WalSavepointUndo()).
*/
SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData){
aWalData[3] = pWal->nCkpt;
}
-/*
+/*
** Move the write position of the WAL back to the point identified by
** the values in the aWalData[] array. aWalData must point to an array
** of WAL_SAVEPOINT_NDATA u32 values that has been previously populated
return rc;
}
-/*
+/*
** Write a set of frames to the log. The caller must hold the write-lock
** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
*/
walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum);
sqlite3Put4byte(&aWalHdr[24], aCksum[0]);
sqlite3Put4byte(&aWalHdr[28], aCksum[1]);
-
+
pWal->szPage = szPage;
pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN;
pWal->hdr.aFrameCksum[0] = aCksum[0];
pWal->truncateOnCommit = 0;
}
- /* Append data to the wal-index. It is not necessary to lock the
+ /* Append data to the wal-index. It is not necessary to lock the
** wal-index to do this as the SQLITE_SHM_WRITE lock held on the wal-index
** guarantees that there are no other writers, and no data that may
** be in use by existing readers is being overwritten.
return rc;
}
-/*
+/*
** This routine is called to implement sqlite3_wal_checkpoint() and
** related interfaces.
**
**
** If the writer lock cannot be obtained, then a passive checkpoint is
** run instead. Since the checkpointer is not holding the writer lock,
- ** there is no point in blocking waiting for any readers. Assuming no
+ ** there is no point in blocking waiting for any readers. Assuming no
** other error occurs, this function will return SQLITE_BUSY to the caller.
*/
if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
}
if( isChanged ){
- /* If a new wal-index header was loaded before the checkpoint was
+ /* If a new wal-index header was loaded before the checkpoint was
** performed, then the pager-cache associated with pWal is now
** out of date. So zero the cached wal-index header to ensure that
** next time the pager opens a snapshot on this database it knows that
** operation must occur while the pager is still holding the exclusive
** lock on the main database file.
**
-** If op is one, then change from locking_mode=NORMAL into
+** If op is one, then change from locking_mode=NORMAL into
** locking_mode=EXCLUSIVE. This means that the pWal->readLock must
** be released. Return 1 if the transition is made and 0 if the
** WAL is already in exclusive-locking mode - meaning that this
assert( pWal->writeLock==0 );
assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 );
- /* pWal->readLock is usually set, but might be -1 if there was a
- ** prior error while attempting to acquire are read-lock. This cannot
+ /* pWal->readLock is usually set, but might be -1 if there was a
+ ** prior error while attempting to acquire are read-lock. This cannot
** happen if the connection is actually in exclusive mode (as no xShmLock
** locks are taken in this case). Nor should the pager attempt to
** upgrade to exclusive-mode following such an error.
return rc;
}
-/*
+/*
** Return true if the argument is non-NULL and the WAL module is using
** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
-** WAL module is using shared-memory, return false.
+** WAL module is using shared-memory, return false.
*/
SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){
return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
** on Ptr(N) and its subpages have values greater than Key(N-1). And
** so forth.
**
-** Finding a particular key requires reading O(log(M)) pages from the
+** Finding a particular key requires reading O(log(M)) pages from the
** disk where M is the number of entries in the tree.
**
-** In this implementation, a single file can hold one or more separate
+** In this implementation, a single file can hold one or more separate
** BTrees. Each BTree is identified by the index of its root page. The
** key and data for any entry are combined to form the "payload". A
** fixed amount of payload can be carried directly on the database
** page. If the payload is larger than the preset amount then surplus
** bytes are stored on overflow pages. The payload for an entry
-** and the preceding pointer are combined to form a "Cell". Each
+** and the preceding pointer are combined to form a "Cell". Each
** page has a small header which contains the Ptr(N) pointer and other
** information such as the size of key and data.
**
**
** OFFSET SIZE DESCRIPTION
** 0 16 Header string: "SQLite format 3\000"
-** 16 2 Page size in bytes.
+** 16 2 Page size in bytes.
** 18 1 File format write version
** 19 1 File format read version
** 20 1 Bytes of unused space at the end of each page
** contiguous or in order, but cell pointers are contiguous and in order.
**
** Cell content makes use of variable length integers. A variable
-** length integer is 1 to 9 bytes where the lower 7 bits of each
+** length integer is 1 to 9 bytes where the lower 7 bits of each
** byte are used. The integer consists of all bytes that have bit 8 set and
** the first byte with bit 8 clear. The most significant byte of the integer
** appears first. A variable-length integer may not be more than 9 bytes long.
** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The
** header must be exactly 16 bytes including the zero-terminator so
** the string itself should be 15 characters long. If you change
-** the header, then your custom library will not be able to read
+** the header, then your custom library will not be able to read
** databases generated by the standard tools and the standard tools
** will not be able to read databases created by your custom library.
*/
/*
** A linked list of the following structures is stored at BtShared.pLock.
-** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
+** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
** is opened on the table with root page BtShared.iTable. Locks are removed
** from this list when a transaction is committed or rolled back, or when
** a btree handle is closed.
** see the internals of this structure and only deals with pointers to
** this structure.
**
-** For some database files, the same underlying database cache might be
+** For some database files, the same underlying database cache might be
** shared between multiple connections. In that case, each connection
** has it own instance of this object. But each instance of this object
** points to the same BtShared object. The database cache and the
** the BtShared object.
**
** All fields in this structure are accessed under sqlite3.mutex.
-** The pBt pointer itself may not be changed while there exists cursors
+** The pBt pointer itself may not be changed while there exists cursors
** in the referenced BtShared that point back to this Btree since those
** cursors have to go through this Btree to find their BtShared and
** they often do so without holding sqlite3.mutex.
/*
** An instance of this object represents a single database file.
-**
+**
** A single database file can be in use at the same time by two
** or more database connections. When two or more connections are
** sharing the same database file, each connection has it own
** particular database connection identified BtCursor.pBtree.db.
**
** Fields in this structure are accessed under the BtShared.mutex
-** found at self->pBt->mutex.
+** found at self->pBt->mutex.
*/
struct BtCursor {
Btree *pBtree; /* The Btree to which this cursor belongs */
** Cursor points to a valid entry. getPayload() etc. may be called.
**
** CURSOR_INVALID:
-** Cursor does not point to a valid entry. This can happen (for example)
+** Cursor does not point to a valid entry. This can happen (for example)
** because the table is empty or because BtreeCursorFirst() has not been
** called.
**
** CURSOR_REQUIRESEEK:
-** The table that this cursor was opened on still exists, but has been
+** The table that this cursor was opened on still exists, but has been
** modified since the cursor was last used. The cursor position is saved
-** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
+** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
** this state, restoreCursorPosition() can be called to attempt to
** seek the cursor to the saved position.
**
#define CURSOR_REQUIRESEEK 2
#define CURSOR_FAULT 3
-/*
+/*
** The database page the PENDING_BYTE occupies. This page is never used.
*/
# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)
/*
-** These macros define the location of the pointer-map entry for a
+** These macros define the location of the pointer-map entry for a
** database page. The first argument to each is the number of usable
** bytes on each page of the database (often 1024). The second is the
** page number to look up in the pointer map.
** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not
** used in this case.
**
-** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number
+** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number
** is not used in this case.
**
-** PTRMAP_OVERFLOW1: The database page is the first page in a list of
+** PTRMAP_OVERFLOW1: The database page is the first page in a list of
** overflow pages. The page number identifies the page that
** contains the cell with a pointer to this overflow page.
**
*/
#define btreeIntegrity(p) \
assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \
- assert( p->pBt->inTransaction>=p->inTrans );
+ assert( p->pBt->inTransaction>=p->inTrans );
/*
** The ISAUTOVACUUM macro is used within balance_nonroot() to determine
** if the database supports auto-vacuum or not. Because it is used
-** within an expression that is an argument to another macro
+** within an expression that is an argument to another macro
** (sqliteMallocRaw), it is not possible to use conditional compilation.
** So, this macro is defined instead.
*/
**
** The aRef[] array is allocated so that there is 1 bit for each page in
** the database. As the integrity-check proceeds, for each page used in
-** the database the corresponding bit is set. This allows integrity-check to
-** detect pages that are used twice and orphaned pages (both of which
+** the database the corresponding bit is set. This allows integrity-check to
+** detect pages that are used twice and orphaned pages (both of which
** indicate corruption).
*/
typedef struct IntegrityCk IntegrityCk;
#define BTALLOC_LE 2 /* Allocate any page <= the parameter */
/*
-** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not
+** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not
** defined, or 0 if it is. For example:
**
** bIncrVacuum = IfNotOmitAV(pBtShared->incrVacuum);
/*
** A list of BtShared objects that are eligible for participation
** in shared cache. This variable has file scope during normal builds,
-** but the test harness needs to access it so we make it global for
+** but the test harness needs to access it so we make it global for
** test builds.
**
** Access to this variable is protected by SQLITE_MUTEX_STATIC_MASTER.
** manipulate entries in the BtShared.pLock linked list used to store
** shared-cache table level locks. If the library is compiled with the
** shared-cache feature disabled, then there is only ever one user
- ** of each BtShared structure and so this locking is not necessary.
+ ** of each BtShared structure and so this locking is not necessary.
** So define the lock related functions as no-ops.
*/
#define querySharedCacheTableLock(a,b,c) SQLITE_OK
/*
**** This function is only used as part of an assert() statement. ***
**
-** Check to see if pBtree holds the required locks to read or write to the
+** Check to see if pBtree holds the required locks to read or write to the
** table with root page iRoot. Return 1 if it does and 0 if not.
**
-** For example, when writing to a table with root-page iRoot via
+** For example, when writing to a table with root-page iRoot via
** Btree connection pBtree:
**
** assert( hasSharedCacheTableLock(pBtree, iRoot, 0, WRITE_LOCK) );
**
-** When writing to an index that resides in a sharable database, the
+** When writing to an index that resides in a sharable database, the
** caller should have first obtained a lock specifying the root page of
** the corresponding table. This makes things a bit more complicated,
** as this module treats each table as a separate structure. To determine
BtLock *pLock;
/* If this database is not shareable, or if the client is reading
- ** and has the read-uncommitted flag set, then no lock is required.
+ ** and has the read-uncommitted flag set, then no lock is required.
** Return true immediately.
*/
if( (pBtree->sharable==0)
iTab = iRoot;
}
- /* Search for the required lock. Either a write-lock on root-page iTab, a
+ /* Search for the required lock. Either a write-lock on root-page iTab, a
** write-lock on the schema table, or (if the client is reading) a
** read-lock on iTab will suffice. Return 1 if any of these are found. */
for(pLock=pBtree->pBt->pLock; pLock; pLock=pLock->pNext){
- if( pLock->pBtree==pBtree
+ if( pLock->pBtree==pBtree
&& (pLock->iTable==iTab || (pLock->eLock==WRITE_LOCK && pLock->iTable==1))
- && pLock->eLock>=eLockType
+ && pLock->eLock>=eLockType
){
return 1;
}
static int hasReadConflicts(Btree *pBtree, Pgno iRoot){
BtCursor *p;
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
- if( p->pgnoRoot==iRoot
+ if( p->pgnoRoot==iRoot
&& p->pBtree!=pBtree
&& 0==(p->pBtree->db->flags & SQLITE_ReadUncommitted)
){
#endif /* #ifdef SQLITE_DEBUG */
/*
-** Query to see if Btree handle p may obtain a lock of type eLock
+** Query to see if Btree handle p may obtain a lock of type eLock
** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return
** SQLITE_OK if the lock may be obtained (by calling
** setSharedCacheTableLock()), or SQLITE_LOCKED if not.
assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
assert( p->db!=0 );
assert( !(p->db->flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 );
-
+
/* If requesting a write-lock, then the Btree must have an open write
- ** transaction on this file. And, obviously, for this to be so there
+ ** transaction on this file. And, obviously, for this to be so there
** must be an open write transaction on the file itself.
*/
assert( eLock==READ_LOCK || (p==pBt->pWriter && p->inTrans==TRANS_WRITE) );
assert( eLock==READ_LOCK || pBt->inTransaction==TRANS_WRITE );
-
+
/* This routine is a no-op if the shared-cache is not enabled */
if( !p->sharable ){
return SQLITE_OK;
}
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
- /* The condition (pIter->eLock!=eLock) in the following if(...)
+ /* The condition (pIter->eLock!=eLock) in the following if(...)
** statement is a simplification of:
**
** (eLock==WRITE_LOCK || pIter->eLock==WRITE_LOCK)
#ifndef SQLITE_OMIT_SHARED_CACHE
/*
** Add a lock on the table with root-page iTable to the shared-btree used
-** by Btree handle p. Parameter eLock must be either READ_LOCK or
+** by Btree handle p. Parameter eLock must be either READ_LOCK or
** WRITE_LOCK.
**
** This function assumes the following:
** with the requested lock (i.e. querySharedCacheTableLock() has
** already been called and returned SQLITE_OK).
**
-** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM
+** SQLITE_OK is returned if the lock is added successfully. SQLITE_NOMEM
** is returned if a malloc attempt fails.
*/
static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
/* A connection with the read-uncommitted flag set will never try to
** obtain a read-lock using this function. The only read-lock obtained
- ** by a connection in read-uncommitted mode is on the sqlite_master
+ ** by a connection in read-uncommitted mode is on the sqlite_master
** table, and that lock is obtained in BtreeBeginTrans(). */
assert( 0==(p->db->flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK );
- /* This function should only be called on a sharable b-tree after it
+ /* This function should only be called on a sharable b-tree after it
** has been determined that no other b-tree holds a conflicting lock. */
assert( p->sharable );
assert( SQLITE_OK==querySharedCacheTableLock(p, iTable, eLock) );
** Release all the table locks (locks obtained via calls to
** the setSharedCacheTableLock() procedure) held by Btree object p.
**
-** This function assumes that Btree p has an open read or write
+** This function assumes that Btree p has an open read or write
** transaction. If it does not, then the BTS_PENDING flag
** may be incorrectly cleared.
*/
pBt->pWriter = 0;
pBt->btsFlags &= ~(BTS_EXCLUSIVE|BTS_PENDING);
}else if( pBt->nTransaction==2 ){
- /* This function is called when Btree p is concluding its
+ /* This function is called when Btree p is concluding its
** transaction. If there currently exists a writer, and p is not
** that writer, then the number of locks held by connections other
** than the writer must be about to drop to zero. In this case
#endif /* SQLITE_OMIT_INCRBLOB */
/*
-** Set bit pgno of the BtShared.pHasContent bitvec. This is called
-** when a page that previously contained data becomes a free-list leaf
+** Set bit pgno of the BtShared.pHasContent bitvec. This is called
+** when a page that previously contained data becomes a free-list leaf
** page.
**
** The BtShared.pHasContent bitvec exists to work around an obscure
** may be lost. In the event of a rollback, it may not be possible
** to restore the database to its original configuration.
**
-** The solution is the BtShared.pHasContent bitvec. Whenever a page is
+** The solution is the BtShared.pHasContent bitvec. Whenever a page is
** moved to become a free-list leaf page, the corresponding bit is
** set in the bitvec. Whenever a leaf page is extracted from the free-list,
** optimization 2 above is omitted if the corresponding bit is already
/*
-** Save the current cursor position in the variables BtCursor.nKey
+** Save the current cursor position in the variables BtCursor.nKey
** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
**
** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID)
-** prior to calling this routine.
+** prior to calling this routine.
*/
static int saveCursorPosition(BtCursor *pCur){
int rc;
/* If this is an intKey table, then the above call to BtreeKeySize()
** stores the integer key in pCur->nKey. In this case this value is
** all that is required. Otherwise, if pCur is not open on an intKey
- ** table, then malloc space for and store the pCur->nKey bytes of key
+ ** table, then malloc space for and store the pCur->nKey bytes of key
** data.
*/
if( 0==pCur->apPage[0]->intKey ){
/*
** Restore the cursor to the position it was in (or as close to as possible)
-** when saveCursorPosition() was called. Note that this call deletes the
+** when saveCursorPosition() was called. Note that this call deletes the
** saved position info stored by saveCursorPosition(), so there can be
-** at most one effective restoreCursorPosition() call after each
+** at most one effective restoreCursorPosition() call after each
** saveCursorPosition().
*/
static int btreeRestoreCursorPosition(BtCursor *pCur){
if( pgno<2 ) return 0;
nPagesPerMapPage = (pBt->usableSize/5)+1;
iPtrMap = (pgno-2)/nPagesPerMapPage;
- ret = (iPtrMap*nPagesPerMapPage) + 2;
+ ret = (iPtrMap*nPagesPerMapPage) + 2;
if( ret==PENDING_BYTE_PAGE(pBt) ){
ret++;
}
/*
** Parse a cell content block and fill in the CellInfo structure. There
-** are two versions of this function. btreeParseCell() takes a
-** cell index as the second argument and btreeParseCellPtr()
+** are two versions of this function. btreeParseCell() takes a
+** cell index as the second argument and btreeParseCellPtr()
** takes a pointer to the body of the cell as its second argument.
**
** Within this file, the parseCell() macro can be called instead of
nSize = 0;
}
- /* pIter now points at the 64-bit integer key value, a variable length
+ /* pIter now points at the 64-bit integer key value, a variable length
** integer. The following block moves pIter to point at the first byte
** past the end of the key value. */
pEnd = &pIter[9];
testcase( pc==iCellLast );
#if !defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK)
/* These conditions have already been verified in btreeInitPage()
- ** if SQLITE_ENABLE_OVERSIZE_CELL_CHECK is defined
+ ** if SQLITE_ENABLE_OVERSIZE_CELL_CHECK is defined
*/
if( pc<iCellFirst || pc>iCellLast ){
return SQLITE_CORRUPT_BKPT;
int gap; /* First byte of gap between cell pointers and cell content */
int rc; /* Integer return code */
int usableSize; /* Usable size of the page */
-
+
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
if( rc ) return rc;
top = get2byteNotZero(&data[hdr+5]);
}else if( gap+2<=top ){
- /* Search the freelist looking for a free slot big enough to satisfy
- ** the request. The allocation is made from the first free slot in
+ /* Search the freelist looking for a free slot big enough to satisfy
+ ** the request. The allocation is made from the first free slot in
** the list that is large enough to accomadate it.
*/
int pc, addr;
** Initialize the auxiliary information for a disk block.
**
** Return SQLITE_OK on success. If we see that the page does
-** not contain a well-formed database page, then return
+** not contain a well-formed database page, then return
** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not
** guarantee that the page is well-formed. It only shows that
** we failed to detect any corruption.
testcase( pPage->nCell==MX_CELL(pBt) );
/* A malformed database page might cause us to read past the end
- ** of page when parsing a cell.
+ ** of page when parsing a cell.
**
** The following block of code checks early to see if a cell extends
- ** past the end of a page boundary and causes SQLITE_CORRUPT to be
+ ** past the end of a page boundary and causes SQLITE_CORRUPT to be
** returned if it does.
*/
iCellFirst = cellOffset + 2*pPage->nCell;
}
}
if( !pPage->leaf ) iCellLast++;
- }
+ }
#endif
/* Compute the total free space on the page */
u16 next, size;
if( pc<iCellFirst || pc>iCellLast ){
/* Start of free block is off the page */
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_BKPT;
}
next = get2byte(&data[pc]);
size = get2byte(&data[pc+2]);
if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){
/* Free blocks must be in ascending order. And the last byte of
** the free-block must lie on the database page. */
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_BKPT;
}
nFree = nFree + size;
pc = next;
** area, according to the page header, lies within the page.
*/
if( nFree>usableSize ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_BKPT;
}
pPage->nFree = (u16)(nFree - iCellFirst);
pPage->isInit = 1;
pPage->pBt = pBt;
pPage->pgno = pgno;
pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
- return pPage;
+ return pPage;
}
/*
){
int rc;
DbPage *pDbPage;
- int flags = (noContent ? PAGER_ACQUIRE_NOCONTENT : 0)
+ int flags = (noContent ? PAGER_ACQUIRE_NOCONTENT : 0)
| (bReadonly ? PAGER_ACQUIRE_READONLY : 0);
assert( noContent==0 || bReadonly==0 );
/*
** Get a page from the pager and initialize it. This routine is just a
-** convenience wrapper around separate calls to btreeGetPage() and
+** convenience wrapper around separate calls to btreeGetPage() and
** btreeInitPage().
**
** If an error occurs, then the value *ppPage is set to is undefined. It
/*
** Open a database file.
-**
+**
** zFilename is the name of the database file. If zFilename is NULL
** then an ephemeral database is created. The ephemeral database might
** be exclusively in memory, or it might use a disk-based memory cache.
-** Either way, the ephemeral database will be automatically deleted
+** Either way, the ephemeral database will be automatically deleted
** when sqlite3BtreeClose() is called.
**
** If zFilename is ":memory:" then an in-memory database is created
/* True if opening an ephemeral, temporary database */
const int isTempDb = zFilename==0 || zFilename[0]==0;
- /* Set the variable isMemdb to true for an in-memory database, or
+ /* Set the variable isMemdb to true for an in-memory database, or
** false for a file-based database.
*/
#ifdef SQLITE_OMIT_MEMORYDB
assert( sizeof(u32)==4 );
assert( sizeof(u16)==2 );
assert( sizeof(Pgno)==4 );
-
+
pBt = sqlite3MallocZero( sizeof(*pBt) );
if( pBt==0 ){
rc = SQLITE_NOMEM;
pBt->db = db;
sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
p->pBt = pBt;
-
+
pBt->pCursor = 0;
pBt->pPage1 = 0;
if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY;
if( rc ) goto btree_open_out;
pBt->usableSize = pBt->pageSize - nReserve;
assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */
-
+
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
/* Add the new BtShared object to the linked list sharable BtShareds.
*/
}
/*
-** Make sure pBt->pTmpSpace points to an allocation of
+** Make sure pBt->pTmpSpace points to an allocation of
** MX_CELL_SIZE(pBt) bytes.
*/
static void allocateTempSpace(BtShared *pBt){
sqlite3BtreeLeave(p);
/* If there are still other outstanding references to the shared-btree
- ** structure, return now. The remainder of this procedure cleans
+ ** structure, return now. The remainder of this procedure cleans
** up the shared-btree.
*/
assert( p->wantToLock==0 && p->locked==0 );
SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree *p){
BtShared *pBt = p->pBt;
int rc;
- assert( sqlite3_mutex_held(p->db->mutex) );
+ assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
assert( pBt && pBt->pPager );
rc = sqlite3PagerNosync(pBt->pPager);
/*
** Change the default pages size and the number of reserved bytes per page.
-** Or, if the page size has already been fixed, return SQLITE_READONLY
+** Or, if the page size has already been fixed, return SQLITE_READONLY
** without changing anything.
**
** The page size must be a power of 2 between 512 and 65536. If the page
** held.
**
** This is useful in one special case in the backup API code where it is
-** known that the shared b-tree mutex is held, but the mutex on the
+** known that the shared b-tree mutex is held, but the mutex on the
** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
** were to be called, it might collide with some other operation on the
** database handle that owns *p, causing undefined behavior.
if( newFlag>=0 ){
p->pBt->btsFlags &= ~BTS_SECURE_DELETE;
if( newFlag ) p->pBt->btsFlags |= BTS_SECURE_DELETE;
- }
+ }
b = (p->pBt->btsFlags & BTS_SECURE_DELETE)!=0;
sqlite3BtreeLeave(p);
return b;
/*
** Change the 'auto-vacuum' property of the database. If the 'autoVacuum'
** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it
-** is disabled. The default value for the auto-vacuum property is
+** is disabled. The default value for the auto-vacuum property is
** determined by the SQLITE_DEFAULT_AUTOVACUUM macro.
*/
SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){
}
/*
-** Return the value of the 'auto-vacuum' property. If auto-vacuum is
+** Return the value of the 'auto-vacuum' property. If auto-vacuum is
** enabled 1 is returned. Otherwise 0.
*/
SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){
** SQLITE_OK is returned on success. If the file is not a
** well-formed database file, then SQLITE_CORRUPT is returned.
** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM
-** is returned if we run out of memory.
+** is returned if we run out of memory.
*/
static int lockBtree(BtShared *pBt){
int rc; /* Result code from subfunctions */
if( rc!=SQLITE_OK ) return rc;
/* Do some checking to help insure the file we opened really is
- ** a valid database file.
+ ** a valid database file.
*/
nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
sqlite3PagerPagecount(pBt->pPager, &nPageFile);
}
/* If the write version is set to 2, this database should be accessed
- ** in WAL mode. If the log is not already open, open it now. Then
+ ** in WAL mode. If the log is not already open, open it now. Then
** return SQLITE_OK and return without populating BtShared.pPage1.
** The caller detects this and calls this function again. This is
** required as the version of page 1 currently in the page1 buffer
}
pageSize = (page1[16]<<8) | (page1[17]<<16);
if( ((pageSize-1)&pageSize)!=0
- || pageSize>SQLITE_MAX_PAGE_SIZE
- || pageSize<=256
+ || pageSize>SQLITE_MAX_PAGE_SIZE
+ || pageSize<=256
){
goto page1_init_failed;
}
BtCursor *pCur;
int r = 0;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
- if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++;
+ if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++;
}
return r;
}
/*
** If there are no outstanding cursors and we are not in the middle
** of a transaction but there is a read lock on the database, then
-** this routine unrefs the first page of the database file which
+** this routine unrefs the first page of the database file which
** has the effect of releasing the read lock.
**
** If there is a transaction in progress, this routine is a no-op.
** upgraded to exclusive by calling this routine a second time - the
** exclusivity flag only works for a new transaction.
**
-** A write-transaction must be started before attempting any
-** changes to the database. None of the following routines
+** A write-transaction must be started before attempting any
+** changes to the database. None of the following routines
** will work unless a transaction is started first:
**
** sqlite3BtreeCreateTable()
** If an initial attempt to acquire the lock fails because of lock contention
** and the database was previously unlocked, then invoke the busy handler
** if there is one. But if there was previously a read-lock, do not
-** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is
+** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is
** returned when there is already a read-lock in order to avoid a deadlock.
**
** Suppose there are two processes A and B. A has a read lock and B has
}
#ifndef SQLITE_OMIT_SHARED_CACHE
- /* If another database handle has already opened a write transaction
+ /* If another database handle has already opened a write transaction
** on this shared-btree structure and a second write transaction is
** requested, return SQLITE_LOCKED.
*/
}
#endif
- /* Any read-only or read-write transaction implies a read-lock on
- ** page 1. So if some other shared-cache client already has a write-lock
+ /* Any read-only or read-write transaction implies a read-lock on
+ ** page 1. So if some other shared-cache client already has a write-lock
** on page 1, the transaction cannot be opened. */
rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
if( SQLITE_OK!=rc ) goto trans_begun;
/* Call lockBtree() until either pBt->pPage1 is populated or
** lockBtree() returns something other than SQLITE_OK. lockBtree()
** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
- ** reading page 1 it discovers that the page-size of the database
+ ** reading page 1 it discovers that the page-size of the database
** file is not pBt->pageSize. In this case lockBtree() will update
** pBt->pageSize to the page-size of the file on disk.
*/
}
}
}
-
+
if( rc!=SQLITE_OK ){
unlockBtreeIfUnused(pBt);
}
/* If the db-size header field is incorrect (as it may be if an old
** client has been writing the database file), update it now. Doing
- ** this sooner rather than later means the database size can safely
+ ** this sooner rather than later means the database size can safely
** re-read the database size from page 1 if a savepoint or transaction
** rollback occurs within the transaction.
*/
** that it points to iTo. Parameter eType describes the type of pointer to
** be modified, as follows:
**
-** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child
+** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child
** page of pPage.
**
** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow
}
}
}
-
+
if( i==nCell ){
- if( eType!=PTRMAP_BTREE ||
+ if( eType!=PTRMAP_BTREE ||
get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
return SQLITE_CORRUPT_BKPT;
}
/*
-** Move the open database page pDbPage to location iFreePage in the
+** Move the open database page pDbPage to location iFreePage in the
** database. The pDbPage reference remains valid.
**
** The isCommit flag indicates that there is no need to remember that
-** the journal needs to be sync()ed before database page pDbPage->pgno
+** the journal needs to be sync()ed before database page pDbPage->pgno
** can be written to. The caller has already promised not to write to that
** page.
*/
Pager *pPager = pBt->pPager;
int rc;
- assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||
+ assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||
eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pDbPage->pBt==pBt );
/* Move page iDbPage from its current location to page number iFreePage */
- TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
+ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
iDbPage, iFreePage, iPtrPage, eType));
rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit);
if( rc!=SQLITE_OK ){
/*
** Perform a single step of an incremental-vacuum. If successful, return
-** SQLITE_OK. If there is no work to do (and therefore no point in
-** calling this function again), return SQLITE_DONE. Or, if an error
+** SQLITE_OK. If there is no work to do (and therefore no point in
+** calling this function again), return SQLITE_DONE. Or, if an error
** occurs, return some other error code.
**
-** More specificly, this function attempts to re-organize the database so
+** More specificly, this function attempts to re-organize the database so
** that the last page of the file currently in use is no longer in use.
**
** Parameter nFin is the number of pages that this database would contain
** were this function called until it returns SQLITE_DONE.
**
-** If the bCommit parameter is non-zero, this function assumes that the
-** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE
-** or an error. bCommit is passed true for an auto-vacuum-on-commmit
+** If the bCommit parameter is non-zero, this function assumes that the
+** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE
+** or an error. bCommit is passed true for an auto-vacuum-on-commmit
** operation, or false for an incremental vacuum.
*/
static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
if( bCommit==0 ){
/* Remove the page from the files free-list. This is not required
** if bCommit is non-zero. In that case, the free-list will be
- ** truncated to zero after this function returns, so it doesn't
+ ** truncated to zero after this function returns, so it doesn't
** matter if it still contains some garbage entries.
*/
Pgno iFreePg;
releasePage(pFreePg);
}while( bCommit && iFreePg>nFin );
assert( iFreePg<iLastPg );
-
+
rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
releasePage(pLastPg);
if( rc!=SQLITE_OK ){
/*
** The database opened by the first argument is an auto-vacuum database
-** nOrig pages in size containing nFree free pages. Return the expected
+** nOrig pages in size containing nFree free pages. Return the expected
** size of the database in pages following an auto-vacuum operation.
*/
static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){
**
** If the incremental vacuum is finished after this function has run,
** SQLITE_DONE is returned. If it is not finished, but no error occurred,
-** SQLITE_OK is returned. Otherwise an SQLite error code.
+** SQLITE_OK is returned. Otherwise an SQLite error code.
*/
SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){
int rc;
** is commited for an auto-vacuum database.
**
** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
-** the database file should be truncated to during the commit process.
+** the database file should be truncated to during the commit process.
** i.e. the database has been reorganized so that only the first *pnTrunc
** pages are in use.
*/
**
** Otherwise, sync the database file for the btree pBt. zMaster points to
** the name of a master journal file that should be written into the
-** individual journal file, or is NULL, indicating no master journal file
+** individual journal file, or is NULL, indicating no master journal file
** (single database transaction).
**
** When this is called, the master journal should already have been
downgradeAllSharedCacheTableLocks(p);
p->inTrans = TRANS_READ;
}else{
- /* If the handle had any kind of transaction open, decrement the
- ** transaction count of the shared btree. If the transaction count
+ /* If the handle had any kind of transaction open, decrement the
+ ** transaction count of the shared btree. If the transaction count
** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused()
** call below will unlock the pager. */
if( p->inTrans!=TRANS_NONE ){
}
}
- /* Set the current transaction state to TRANS_NONE and unlock the
+ /* Set the current transaction state to TRANS_NONE and unlock the
** pager if this call closed the only read or write transaction. */
p->inTrans = TRANS_NONE;
unlockBtreeIfUnused(pBt);
** the rollback journal (which causes the transaction to commit) and
** drop locks.
**
-** Normally, if an error occurs while the pager layer is attempting to
+** Normally, if an error occurs while the pager layer is attempting to
** finalize the underlying journal file, this function returns an error and
** the upper layer will attempt a rollback. However, if the second argument
-** is non-zero then this b-tree transaction is part of a multi-file
-** transaction. In this case, the transaction has already been committed
-** (by deleting a master journal file) and the caller will ignore this
+** is non-zero then this b-tree transaction is part of a multi-file
+** transaction. In this case, the transaction has already been committed
+** (by deleting a master journal file) and the caller will ignore this
** functions return code. So, even if an error occurs in the pager layer,
** reset the b-tree objects internal state to indicate that the write
** transaction has been closed. This is quite safe, as the pager will have
sqlite3BtreeEnter(p);
btreeIntegrity(p);
- /* If the handle has a write-transaction open, commit the shared-btrees
+ /* If the handle has a write-transaction open, commit the shared-btrees
** transaction and set the shared state to TRANS_READ.
*/
if( p->inTrans==TRANS_WRITE ){
/*
** Start a statement subtransaction. The subtransaction can can be rolled
-** back independently of the main transaction. You must start a transaction
-** before starting a subtransaction. The subtransaction is ended automatically
+** back independently of the main transaction. You must start a transaction
+** before starting a subtransaction. The subtransaction is ended automatically
** if the main transaction commits or rolls back.
**
** Statement subtransactions are used around individual SQL statements
/*
** The second argument to this function, op, is always SAVEPOINT_ROLLBACK
** or SAVEPOINT_RELEASE. This function either releases or rolls back the
-** savepoint identified by parameter iSavepoint, depending on the value
+** savepoint identified by parameter iSavepoint, depending on the value
** of op.
**
** Normally, iSavepoint is greater than or equal to zero. However, if op is
-** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the
+** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the
** contents of the entire transaction are rolled back. This is different
** from a normal transaction rollback, as no locks are released and the
** transaction remains open.
assert( sqlite3BtreeHoldsMutex(p) );
assert( wrFlag==0 || wrFlag==1 );
- /* The following assert statements verify that if this is a sharable
- ** b-tree database, the connection is holding the required table locks,
- ** and that no other connection has any open cursor that conflicts with
+ /* The following assert statements verify that if this is a sharable
+ ** b-tree database, the connection is holding the required table locks,
+ ** and that no other connection has any open cursor that conflicts with
** this lock. */
assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, wrFlag+1) );
assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
/*
** Set *pSize to the size of the buffer needed to hold the value of
** the key for the current entry. If the cursor is not pointing
-** to a valid entry, *pSize is set to 0.
+** to a valid entry, *pSize is set to 0.
**
** For a table with the INTKEY flag set, this routine returns the key
** itself, not the number of bytes in the key.
**
** The caller must position the cursor prior to invoking this routine.
-**
-** This routine cannot fail. It always returns SQLITE_OK.
+**
+** This routine cannot fail. It always returns SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
assert( cursorHoldsMutex(pCur) );
/*
** Given the page number of an overflow page in the database (parameter
-** ovfl), this function finds the page number of the next page in the
+** ovfl), this function finds the page number of the next page in the
** linked list of overflow pages. If possible, it uses the auto-vacuum
-** pointer-map data instead of reading the content of page ovfl to do so.
+** pointer-map data instead of reading the content of page ovfl to do so.
**
** If an error occurs an SQLite error code is returned. Otherwise:
**
-** The page number of the next overflow page in the linked list is
-** written to *pPgnoNext. If page ovfl is the last page in its linked
-** list, *pPgnoNext is set to zero.
+** The page number of the next overflow page in the linked list is
+** written to *pPgnoNext. If page ovfl is the last page in its linked
+** list, *pPgnoNext is set to zero.
**
** If ppPage is not NULL, and a reference to the MemPage object corresponding
** to page number pOvfl was obtained, then *ppPage is set to point to that
#ifndef SQLITE_OMIT_AUTOVACUUM
/* Try to find the next page in the overflow list using the
- ** autovacuum pointer-map pages. Guess that the next page in
- ** the overflow list is page number (ovfl+1). If that guess turns
- ** out to be wrong, fall back to loading the data of page
+ ** autovacuum pointer-map pages. Guess that the next page in
+ ** the overflow list is page number (ovfl+1). If that guess turns
+ ** out to be wrong, fall back to loading the data of page
** number ovfl to determine the next page number.
*/
if( pBt->autoVacuum ){
**
** If the BtCursor.isIncrblobHandle flag is set, and the current
** cursor entry uses one or more overflow pages, this function
-** allocates space for and lazily popluates the overflow page-list
+** allocates space for and lazily popluates the overflow page-list
** cache array (BtCursor.aOverflow). Subsequent calls use this
** cache to make seeking to the supplied offset more efficient.
**
BtCursor *pCur, /* Cursor pointing to entry to read from */
u32 offset, /* Begin reading this far into payload */
u32 amt, /* Read this many bytes */
- unsigned char *pBuf, /* Write the bytes into this buffer */
+ unsigned char *pBuf, /* Write the bytes into this buffer */
int eOp /* zero to read. non-zero to write. */
){
unsigned char *aPayload;
aPayload = pCur->info.pCell + pCur->info.nHeader;
nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey);
- if( NEVER(offset+amt > nKey+pCur->info.nData)
+ if( NEVER(offset+amt > nKey+pCur->info.nData)
|| &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
){
/* Trying to read or write past the end of the data is an error */
#ifndef SQLITE_OMIT_INCRBLOB
if( pCur->aOverflow && pCur->aOverflow[iIdx+1] ){
nextPage = pCur->aOverflow[iIdx+1];
- } else
+ } else
#endif
rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
offset -= ovflSize;
#ifdef SQLITE_DIRECT_OVERFLOW_READ
/* If all the following are true:
**
- ** 1) this is a read operation, and
+ ** 1) this is a read operation, and
** 2) data is required from the start of this overflow page, and
** 3) the database is file-backed, and
** 4) there is no open write-transaction, and
}
/*
-** Return a pointer to payload information from the entry that the
+** Return a pointer to payload information from the entry that the
** pCur cursor is pointing to. The pointer is to the beginning of
** the key if skipKey==0 and it points to the beginning of data if
** skipKey==1. The number of bytes of available key/data is written
#if 0
/*
-** Page pParent is an internal (non-leaf) tree page. This function
+** Page pParent is an internal (non-leaf) tree page. This function
** asserts that page number iChild is the left-child if the iIdx'th
** cell in page pParent. Or, if iIdx is equal to the total number of
** cells in pParent, that page number iChild is the right-child of
}
}
#else
-# define assertParentIndex(x,y,z)
+# define assertParentIndex(x,y,z)
#endif
/*
/* UPDATE: It is actually possible for the condition tested by the assert
** below to be untrue if the database file is corrupt. This can occur if
- ** one cursor has modified page pParent while a reference to it is held
+ ** one cursor has modified page pParent while a reference to it is held
** by a second cursor. Which can only happen if a single page is linked
** into more than one b-tree structure in a corrupt database. */
#if 0
assertParentIndex(
- pCur->apPage[pCur->iPage-1],
- pCur->aiIdx[pCur->iPage-1],
+ pCur->apPage[pCur->iPage-1],
+ pCur->aiIdx[pCur->iPage-1],
pCur->apPage[pCur->iPage]->pgno
);
#endif
**
** If the table has a virtual root page, then the cursor is moved to point
** to the virtual root page instead of the actual root page. A table has a
-** virtual root page when the actual root page contains no cells and a
+** virtual root page when the actual root page contains no cells and a
** single child page. This can only happen with the table rooted at page 1.
**
-** If the b-tree structure is empty, the cursor state is set to
+** If the b-tree structure is empty, the cursor state is set to
** CURSOR_INVALID. Otherwise, the cursor is set to point to the first
** cell located on the root (or virtual root) page and the cursor state
** is set to CURSOR_VALID.
**
** If this function returns successfully, it may be assumed that the
-** page-header flags indicate that the [virtual] root-page is the expected
+** page-header flags indicate that the [virtual] root-page is the expected
** kind of b-tree page (i.e. if when opening the cursor the caller did not
** specify a KeyInfo structure the flags byte is set to 0x05 or 0x0D,
-** indicating a table b-tree, or if the caller did specify a KeyInfo
+** indicating a table b-tree, or if the caller did specify a KeyInfo
** structure the flags byte is set to 0x02 or 0x0A, indicating an index
** b-tree).
*/
/* Assert that the root page is of the correct type. This must be the
** case as the call to this function that loaded the root-page (either
- ** this call or a previous invocation) would have detected corruption
- ** if the assumption were not true, and it is not possible for the flags
+ ** this call or a previous invocation) would have detected corruption
+ ** if the assumption were not true, and it is not possible for the flags
** byte to have been modified while this cursor is holding a reference
** to the page. */
pRoot = pCur->apPage[0];
*/
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
int rc;
-
+
assert( cursorHoldsMutex(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
/* If the cursor already points to the last entry, this is a no-op. */
if( CURSOR_VALID==pCur->eState && pCur->atLast ){
#ifdef SQLITE_DEBUG
- /* This block serves to assert() that the cursor really does point
+ /* This block serves to assert() that the cursor really does point
** to the last entry in the b-tree. */
int ii;
for(ii=0; ii<pCur->iPage; ii++){
return rc;
}
-/* Move the cursor so that it points to an entry near the key
+/* Move the cursor so that it points to an entry near the key
** specified by pIdxKey or intKey. Return a success code.
**
-** For INTKEY tables, the intKey parameter is used. pIdxKey
+** For INTKEY tables, the intKey parameter is used. pIdxKey
** must be NULL. For index tables, pIdxKey is used and intKey
** is ignored.
**
** before or after the key.
**
** An integer is written into *pRes which is the result of
-** comparing the key with the entry to which the cursor is
+** comparing the key with the entry to which the cursor is
** pointing. The meaning of the integer written into
** *pRes is as follows:
**
/* If the cursor is already positioned at the point we are trying
** to move to, then just return without doing any work */
- if( pCur->eState==CURSOR_VALID && pCur->validNKey
- && pCur->apPage[0]->intKey
+ if( pCur->eState==CURSOR_VALID && pCur->validNKey
+ && pCur->apPage[0]->intKey
){
if( pCur->info.nKey==intKey ){
*pRes = 0;
/* The maximum supported page-size is 65536 bytes. This means that
** the maximum number of record bytes stored on an index B-Tree
** page is less than 16384 bytes and may be stored as a 2-byte
- ** varint. This information is used to attempt to avoid parsing
- ** the entire cell by checking for the cases where the record is
- ** stored entirely within the b-tree page by inspecting the first
+ ** varint. This information is used to attempt to avoid parsing
+ ** the entire cell by checking for the cases where the record is
+ ** stored entirely within the b-tree page by inspecting the first
** 2 bytes of the cell.
*/
int nCell = pCell[0];
** b-tree page. */
testcase( pCell+nCell+1==pPage->aDataEnd );
c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
- }else if( !(pCell[1] & 0x80)
+ }else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
/* && (pCell+nCell+2)<=pPage->aDataEnd */
){
- /* The record-size field is a 2 byte varint and the record
+ /* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
testcase( pCell+nCell+2==pPage->aDataEnd );
c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
idx = ++pCur->aiIdx[pCur->iPage];
assert( pPage->isInit );
- /* If the database file is corrupt, it is possible for the value of idx
+ /* If the database file is corrupt, it is possible for the value of idx
** to be invalid here. This can only occur if a second cursor modifies
** the page while cursor pCur is holding a reference to it. Which can
** only happen if the database is corrupt in such a way as to link the
** an error. *ppPage and *pPgno are undefined in the event of an error.
** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned.
**
-** If the "nearby" parameter is not 0, then an effort is made to
+** If the "nearby" parameter is not 0, then an effort is made to
** locate a page close to the page number "nearby". This can be used in an
** attempt to keep related pages close to each other in the database file,
** which in turn can make database access faster.
/* There are pages on the freelist. Reuse one of those pages. */
Pgno iTrunk;
u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
-
+
/* If eMode==BTALLOC_EXACT and a query of the pointer-map
** shows that the page 'nearby' is somewhere on the free-list, then
** the entire-list will be searched for that page.
k = get4byte(&pTrunk->aData[4]); /* # of leaves on this trunk page */
if( k==0 && !searchList ){
- /* The trunk has no leaves and the list is not being searched.
- ** So extract the trunk page itself and use it as the newly
+ /* The trunk has no leaves and the list is not being searched.
+ ** So extract the trunk page itself and use it as the newly
** allocated page */
assert( pPrevTrunk==0 );
rc = sqlite3PagerWrite(pTrunk->pDbPage);
rc = SQLITE_CORRUPT_BKPT;
goto end_allocate_page;
#ifndef SQLITE_OMIT_AUTOVACUUM
- }else if( searchList
- && (nearby==iTrunk || (iTrunk<nearby && eMode==BTALLOC_LE))
+ }else if( searchList
+ && (nearby==iTrunk || (iTrunk<nearby && eMode==BTALLOC_LE))
){
/* The list is being searched and this trunk page is the page
** to allocate, regardless of whether it has leaves.
memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4);
}
}else{
- /* The trunk page is required by the caller but it contains
+ /* The trunk page is required by the caller but it contains
** pointers to free-list leaves. The first leaf becomes a trunk
** page in this case.
*/
MemPage *pNewTrunk;
Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
- if( iNewTrunk>mxPage ){
+ if( iNewTrunk>mxPage ){
rc = SQLITE_CORRUPT_BKPT;
goto end_allocate_page;
}
goto end_allocate_page;
}
testcase( iPage==mxPage );
- if( !searchList
- || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE))
+ if( !searchList
+ || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE))
){
int noContent;
*pPgno = iPage;
** not set the no-content flag. This causes the pager to load and journal
** the current page content before overwriting it.
**
- ** Note that the pager will not actually attempt to load or journal
+ ** Note that the pager will not actually attempt to load or journal
** content for any page that really does lie past the end of the database
** file on disk. So the effects of disabling the no-content optimization
** here are confined to those pages that lie between the end of the
}
/*
-** This function is used to add page iPage to the database file free-list.
+** This function is used to add page iPage to the database file free-list.
** It is assumed that the page is not already a part of the free-list.
**
** The value passed as the second argument to this function is optional.
-** If the caller happens to have a pointer to the MemPage object
-** corresponding to page iPage handy, it may pass it as the second value.
+** If the caller happens to have a pointer to the MemPage object
+** corresponding to page iPage handy, it may pass it as the second value.
** Otherwise, it may pass NULL.
**
** If a pointer to a MemPage object is passed as the second argument,
*/
static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
MemPage *pTrunk = 0; /* Free-list trunk page */
- Pgno iTrunk = 0; /* Page number of free-list trunk page */
+ Pgno iTrunk = 0; /* Page number of free-list trunk page */
MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */
MemPage *pPage; /* Page being freed. May be NULL. */
int rc; /* Return Code */
/* If control flows to this point, then it was not possible to add the
** the page being freed as a leaf page of the first trunk in the free-list.
- ** Possibly because the free-list is empty, or possibly because the
+ ** Possibly because the free-list is empty, or possibly because the
** first trunk in the free-list is full. Either way, the page being freed
** will become the new first trunk page in the free-list.
*/
Pgno iNext = 0;
MemPage *pOvfl = 0;
if( ovflPgno<2 || ovflPgno>btreePagecount(pBt) ){
- /* 0 is not a legal page number and page 1 cannot be an
- ** overflow page. Therefore if ovflPgno<2 or past the end of the
+ /* 0 is not a legal page number and page 1 cannot be an
+ ** overflow page. Therefore if ovflPgno<2 or past the end of the
** file the database must be corrupt. */
return SQLITE_CORRUPT_BKPT;
}
if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) )
&& sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1
){
- /* There is no reason any cursor should have an outstanding reference
+ /* There is no reason any cursor should have an outstanding reference
** to an overflow page belonging to a cell that is being deleted/updated.
- ** So if there exists more than one reference to this page, then it
- ** must not really be an overflow page and the database must be corrupt.
- ** It is helpful to detect this before calling freePage2(), as
+ ** So if there exists more than one reference to this page, then it
+ ** must not really be an overflow page and the database must be corrupt.
+ ** It is helpful to detect this before calling freePage2(), as
** freePage2() may zero the page contents if secure-delete mode is
** enabled. If this 'overflow' page happens to be a page that the
** caller is iterating through or using in some other way, this
assert( info.nHeader==nHeader );
assert( info.nKey==nKey );
assert( info.nData==(u32)(nData+nZero) );
-
+
/* Fill in the payload */
nPayload = nData + nZero;
if( pPage->intKey ){
pSrc = pData;
nSrc = nData;
nData = 0;
- }else{
+ }else{
if( NEVER(nKey>0x7fffffff || pKey==0) ){
return SQLITE_CORRUPT_BKPT;
}
if( pBt->autoVacuum ){
do{
pgnoOvfl++;
- } while(
- PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt)
+ } while(
+ PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt)
);
}
#endif
#ifndef SQLITE_OMIT_AUTOVACUUM
/* If the database supports auto-vacuum, and the second or subsequent
** overflow page is being allocated, add an entry to the pointer-map
- ** for that page now.
+ ** for that page now.
**
- ** If this is the first overflow page, then write a partial entry
+ ** If this is the first overflow page, then write a partial entry
** to the pointer-map. If we write nothing to this pointer-map slot,
** then the optimistic overflow chain processing in clearCell()
** may misinterpret the uninitialized values and delete the
** will not fit, then make a copy of the cell content into pTemp if
** pTemp is not null. Regardless of pTemp, allocate a new entry
** in pPage->apOvfl[] and make it point to the cell content (either
-** in pTemp or the original pCell) and also record its index.
-** Allocating a new entry in pPage->aCell[] implies that
+** in pTemp or the original pCell) and also record its index.
+** Allocating a new entry in pPage->aCell[] implies that
** pPage->nOverflow is incremented.
**
** If nSkip is non-zero, then do not copy the first nSkip bytes of the
** cell. The caller will overwrite them after this function returns. If
-** nSkip is non-zero, then pCell may not point to an invalid memory location
+** nSkip is non-zero, then pCell may not point to an invalid memory location
** (but pCell+nSkip is always valid).
*/
static void insertCell(
/* This error condition is now caught prior to reaching this function */
if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT;
- /* Allocate a new page. This page will become the right-sibling of
+ /* Allocate a new page. This page will become the right-sibling of
** pPage. Make the parent page writable, so that the new divider cell
** may be inserted. If both these operations are successful, proceed.
*/
assemblePage(pNew, 1, &pCell, &szCell);
/* If this is an auto-vacuum database, update the pointer map
- ** with entries for the new page, and any pointer from the
+ ** with entries for the new page, and any pointer from the
** cell on the page to an overflow page. If either of these
** operations fails, the return code is set, but the contents
** of the parent page are still manipulated by thh code below.
ptrmapPutOvflPtr(pNew, pCell, &rc);
}
}
-
+
/* Create a divider cell to insert into pParent. The divider cell
** consists of a 4-byte page number (the page number of pPage) and
** a variable length key value (which must be the same value as the
** largest key on pPage).
**
- ** To find the largest key value on pPage, first find the right-most
- ** cell on pPage. The first two fields of this cell are the
+ ** To find the largest key value on pPage, first find the right-most
+ ** cell on pPage. The first two fields of this cell are the
** record-length (a variable length integer at most 32-bits in size)
** and the key value (a variable length integer, may have any value).
** The first of the while(...) loops below skips over the record-length
/* Set the right-child pointer of pParent to point to the new page. */
put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
-
+
/* Release the reference to the new page. */
releasePage(pNew);
}
#if 0
/*
** This function does not contribute anything to the operation of SQLite.
-** it is sometimes activated temporarily while debugging code responsible
+** it is sometimes activated temporarily while debugging code responsible
** for setting pointer-map entries.
*/
static int ptrmapCheckPages(MemPage **apPage, int nPage){
for(j=0; j<pPage->nCell; j++){
CellInfo info;
u8 *z;
-
+
z = findCell(pPage, j);
btreeParseCellPtr(pPage, z, &info);
if( info.iOverflow ){
#endif
/*
-** This function is used to copy the contents of the b-tree node stored
+** This function is used to copy the contents of the b-tree node stored
** on page pFrom to page pTo. If page pFrom was not a leaf page, then
** the pointer-map entries for each child page are updated so that the
** parent page stored in the pointer map is page pTo. If pFrom contained
** map entries are also updated so that the parent page is page pTo.
**
** If pFrom is currently carrying any overflow cells (entries in the
-** MemPage.apOvfl[] array), they are not copied to pTo.
+** MemPage.apOvfl[] array), they are not copied to pTo.
**
** Before returning, page pTo is reinitialized using btreeInitPage().
**
-** The performance of this function is not critical. It is only used by
+** The performance of this function is not critical. It is only used by
** the balance_shallower() and balance_deeper() procedures, neither of
** which are called often under normal circumstances.
*/
int const iToHdr = ((pTo->pgno==1) ? 100 : 0);
int rc;
int iData;
-
-
+
+
assert( pFrom->isInit );
assert( pFrom->nFree>=iToHdr );
assert( get2byte(&aFrom[iFromHdr+5]) <= (int)pBt->usableSize );
-
+
/* Copy the b-tree node content from page pFrom to page pTo. */
iData = get2byte(&aFrom[iFromHdr+5]);
memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData);
memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell);
-
+
/* Reinitialize page pTo so that the contents of the MemPage structure
** match the new data. The initialization of pTo can actually fail under
- ** fairly obscure circumstances, even though it is a copy of initialized
+ ** fairly obscure circumstances, even though it is a copy of initialized
** page pFrom.
*/
pTo->isInit = 0;
*pRC = rc;
return;
}
-
+
/* If this is an auto-vacuum database, update the pointer-map entries
** for any b-tree or overflow pages that pTo now contains the pointers to.
*/
** (hereafter "the page") and up to 2 siblings so that all pages have about the
** same amount of free space. Usually a single sibling on either side of the
** page are used in the balancing, though both siblings might come from one
-** side if the page is the first or last child of its parent. If the page
+** side if the page is the first or last child of its parent. If the page
** has fewer than 2 siblings (something which can only happen if the page
** is a root page or a child of a root page) then all available siblings
** participate in the balancing.
**
-** The number of siblings of the page might be increased or decreased by
-** one or two in an effort to keep pages nearly full but not over full.
+** The number of siblings of the page might be increased or decreased by
+** one or two in an effort to keep pages nearly full but not over full.
**
** Note that when this routine is called, some of the cells on the page
** might not actually be stored in MemPage.aData[]. This can happen
** inserted into or removed from the parent page (pParent). Doing so
** may cause the parent page to become overfull or underfull. If this
** happens, it is the responsibility of the caller to invoke the correct
-** balancing routine to fix this problem (see the balance() routine).
+** balancing routine to fix this problem (see the balance() routine).
**
** If this routine fails for any reason, it might leave the database
** in a corrupted state. So if this routine fails, the database should
** of the page-size, the aOvflSpace[] buffer is guaranteed to be large
** enough for all overflow cells.
**
-** If aOvflSpace is set to a null pointer, this function returns
+** If aOvflSpace is set to a null pointer, this function returns
** SQLITE_NOMEM.
*/
#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM)
#endif
/* At this point pParent may have at most one overflow cell. And if
- ** this overflow cell is present, it must be the cell with
+ ** this overflow cell is present, it must be the cell with
** index iParentIdx. This scenario comes about when this function
** is called (indirectly) from sqlite3BtreeDelete().
*/
return SQLITE_NOMEM;
}
- /* Find the sibling pages to balance. Also locate the cells in pParent
- ** that divide the siblings. An attempt is made to find NN siblings on
- ** either side of pPage. More siblings are taken from one side, however,
+ /* Find the sibling pages to balance. Also locate the cells in pParent
+ ** that divide the siblings. An attempt is made to find NN siblings on
+ ** either side of pPage. More siblings are taken from one side, however,
** if there are fewer than NN siblings on the other side. If pParent
- ** has NB or fewer children then all children of pParent are taken.
+ ** has NB or fewer children then all children of pParent are taken.
**
** This loop also drops the divider cells from the parent page. This
** way, the remainder of the function does not have to deal with any
nxDiv = 0;
}else{
assert( bBulk==0 || bBulk==1 );
- if( iParentIdx==0 ){
+ if( iParentIdx==0 ){
nxDiv = 0;
}else if( iParentIdx==i ){
nxDiv = i-2+bBulk;
** This is safe because dropping a cell only overwrites the first
** four bytes of it, and this function does not need the first
** four bytes of the divider cell. So the pointer is safe to use
- ** later on.
+ ** later on.
**
** But not if we are in secure-delete mode. In secure-delete mode,
** the dropCell() routine will overwrite the entire cell with zeroes.
+ nMaxCells*sizeof(u16) /* szCell */
+ pBt->pageSize /* aSpace1 */
+ k*nOld; /* Page copies (apCopy) */
- apCell = sqlite3ScratchMalloc( szScratch );
+ apCell = sqlite3ScratchMalloc( szScratch );
if( apCell==0 ){
rc = SQLITE_NOMEM;
goto balance_cleanup;
leafData = apOld[0]->hasData;
for(i=0; i<nOld; i++){
int limit;
-
+
/* Before doing anything else, take a copy of the i'th original sibling
** The rest of this function will use data from the copies rather
** that the original pages since the original pages will be in the
szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
nCell++;
}
- }
+ }
if( i<nOld-1 && !leafData){
u16 sz = (u16)szNew[i];
u8 *pTemp;
** Figure out the number of pages needed to hold all nCell cells.
** Store this number in "k". Also compute szNew[] which is the total
** size of all cells on the i-th page and cntNew[] which is the index
- ** in apCell[] of the cell that divides page i from page i+1.
+ ** in apCell[] of the cell that divides page i from page i+1.
** cntNew[k] should equal nCell.
**
** Values computed by this block:
** cntNew[i]: Index in apCell[] and szCell[] for the first cell to
** the right of the i-th sibling page.
** usableSpace: Number of bytes of space available on each sibling.
- **
+ **
*/
usableSpace = pBt->usableSize - 12 + leafCorrection;
for(subtotal=k=i=0; i<nCell; i++){
d = r + 1 - leafData;
assert( d<nMaxCells );
assert( r<nMaxCells );
- while( szRight==0
- || (!bBulk && szRight+szCell[d]+2<=szLeft-(szCell[r]+2))
+ while( szRight==0
+ || (!bBulk && szRight+szCell[d]+2<=szLeft-(szCell[r]+2))
){
szRight += szCell[d] + 2;
szLeft -= szCell[r] + 2;
#endif
TRACE(("BALANCE: old: %d %d %d ",
- apOld[0]->pgno,
+ apOld[0]->pgno,
nOld>=2 ? apOld[1]->pgno : 0,
nOld>=3 ? apOld[2]->pgno : 0
));
if( !pNew->leaf ){
memcpy(&pNew->aData[8], pCell, 4);
}else if( leafData ){
- /* If the tree is a leaf-data tree, and the siblings are leaves,
- ** then there is no divider cell in apCell[]. Instead, the divider
- ** cell consists of the integer key for the right-most cell of
+ /* If the tree is a leaf-data tree, and the siblings are leaves,
+ ** then there is no divider cell in apCell[]. Instead, the divider
+ ** cell consists of the integer key for the right-most cell of
** the sibling-page assembled above only.
*/
CellInfo info;
pCell -= 4;
/* Obscure case for non-leaf-data trees: If the cell at pCell was
** previously stored on a leaf node, and its reported size was 4
- ** bytes, then it may actually be smaller than this
+ ** bytes, then it may actually be smaller than this
** (see btreeParseCellPtr(), 4 bytes is the minimum size of
- ** any cell). But it is important to pass the correct size to
+ ** any cell). But it is important to pass the correct size to
** insertCell(), so reparse the cell now.
**
** Note that this can never happen in an SQLite data file, as all
** b-tree structure by one. This is described as the "balance-shallower"
** sub-algorithm in some documentation.
**
- ** If this is an auto-vacuum database, the call to copyNodeContent()
- ** sets all pointer-map entries corresponding to database image pages
+ ** If this is an auto-vacuum database, the call to copyNodeContent()
+ ** sets all pointer-map entries corresponding to database image pages
** for which the pointer is stored within the content being copied.
**
** The second assert below verifies that the child page is defragmented
** is important if the parent page happens to be page 1 of the database
** image. */
assert( nNew==1 );
- assert( apNew[0]->nFree ==
- (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
+ assert( apNew[0]->nFree ==
+ (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
);
copyNodeContent(apNew[0], pParent, &rc);
freePage(apNew[0], &rc);
}else if( ISAUTOVACUUM ){
- /* Fix the pointer-map entries for all the cells that were shifted around.
+ /* Fix the pointer-map entries for all the cells that were shifted around.
** There are several different types of pointer-map entries that need to
** be dealt with by this routine. Some of these have been set already, but
** many have not. The following is a summary:
** of those.
**
** 2) The pointer-map entries associated with the first overflow
- ** page in any overflow chains used by new divider cells. These
+ ** page in any overflow chains used by new divider cells. These
** have also already been taken care of by the insertCell() code.
**
** 3) If the sibling pages are not leaves, then the child pages of
nOverflow = pOld->nOverflow;
iOverflow = i + !leafData + pOld->aiOvfl[0];
}
- isDivider = !leafData;
+ isDivider = !leafData;
}
assert(nOverflow>0 || iOverflow<i );
#if 0
/* The ptrmapCheckPages() contains assert() statements that verify that
- ** all pointer map pages are set correctly. This is helpful while
+ ** all pointer map pages are set correctly. This is helpful while
** debugging. This is usually disabled because a corrupt database may
** cause an assert() statement to fail. */
ptrmapCheckPages(apNew, nNew);
**
** A new child page is allocated and the contents of the current root
** page, including overflow cells, are copied into the child. The root
-** page is then overwritten to make it an empty page with the right-child
+** page is then overwritten to make it an empty page with the right-child
** pointer pointing to the new page.
**
-** Before returning, all pointer-map entries corresponding to pages
+** Before returning, all pointer-map entries corresponding to pages
** that the new child-page now contains pointers to are updated. The
** entry corresponding to the new right-child pointer of the root
** page is also updated.
**
-** If successful, *ppChild is set to contain a reference to the child
+** If successful, *ppChild is set to contain a reference to the child
** page and SQLITE_OK is returned. In this case the caller is required
** to call releasePage() on *ppChild exactly once. If an error occurs,
** an error code is returned and *ppChild is set to 0.
assert( pRoot->nOverflow>0 );
assert( sqlite3_mutex_held(pBt->mutex) );
- /* Make pRoot, the root page of the b-tree, writable. Allocate a new
+ /* Make pRoot, the root page of the b-tree, writable. Allocate a new
** page that will become the new right-child of pPage. Copy the contents
** of the node stored on pRoot into the new child page.
*/
/*
** The page that pCur currently points to has just been modified in
** some way. This function figures out if this modification means the
-** tree needs to be balanced, and if so calls the appropriate balancing
+** tree needs to be balanced, and if so calls the appropriate balancing
** routine. Balancing routines are:
**
** balance_quick()
** balance_deeper() function to create a new child for the root-page
** and copy the current contents of the root-page to it. The
** next iteration of the do-loop will balance the child page.
- */
+ */
assert( (balance_deeper_called++)==0 );
rc = balance_deeper(pPage, &pCur->apPage[1]);
if( rc==SQLITE_OK ){
/* Call balance_quick() to create a new sibling of pPage on which
** to store the overflow cell. balance_quick() inserts a new cell
** into pParent, which may cause pParent overflow. If this
- ** happens, the next interation of the do-loop will balance pParent
+ ** happens, the next interation of the do-loop will balance pParent
** use either balance_nonroot() or balance_deeper(). Until this
** happens, the overflow cell is stored in the aBalanceQuickSpace[]
- ** buffer.
+ ** buffer.
**
** The purpose of the following assert() is to check that only a
** single call to balance_quick() is made for each call to this
** modifying the contents of pParent, which may cause pParent to
** become overfull or underfull. The next iteration of the do-loop
** will balance the parent page to correct this.
- **
+ **
** If the parent page becomes overfull, the overflow cell or cells
- ** are stored in the pSpace buffer allocated immediately below.
+ ** are stored in the pSpace buffer allocated immediately below.
** A subsequent iteration of the do-loop will deal with this by
** calling balance_nonroot() (balance_deeper() may be called first,
** but it doesn't deal with overflow cells - just moves them to a
- ** different page). Once this subsequent call to balance_nonroot()
+ ** different page). Once this subsequent call to balance_nonroot()
** has completed, it is safe to release the pSpace buffer used by
- ** the previous call, as the overflow cell data will have been
+ ** the previous call, as the overflow cell data will have been
** copied either into the body of a database page or into the new
** pSpace buffer passed to the latter call to balance_nonroot().
*/
u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints);
if( pFree ){
- /* If pFree is not NULL, it points to the pSpace buffer used
+ /* If pFree is not NULL, it points to the pSpace buffer used
** by a previous call to balance_nonroot(). Its contents are
- ** now stored either on real database pages or within the
+ ** now stored either on real database pages or within the
** new pSpace buffer, so it may be safely freed here. */
sqlite3PageFree(pFree);
}
** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already
** been performed. seekResult is the search result returned (a negative
** number if pCur points at an entry that is smaller than (pKey, nKey), or
-** a positive value if pCur points at an etry that is larger than
-** (pKey, nKey)).
+** a positive value if pCur points at an etry that is larger than
+** (pKey, nKey)).
**
** If the seekResult parameter is non-zero, then the caller guarantees that
** cursor pCur is pointing at the existing copy of a row that is to be
**
** In some cases, the call to btreeMoveto() below is a no-op. For
** example, when inserting data into a table with auto-generated integer
- ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
- ** integer key to use. It then calls this function to actually insert the
+ ** keys, the VDBE layer invokes sqlite3BtreeLast() to figure out the
+ ** integer key to use. It then calls this function to actually insert the
** data into the intkey B-Tree. In this case btreeMoveto() recognizes
** that the cursor is already where it needs to be and returns without
** doing any work. To avoid thwarting these optimizations, it is important
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
- /* If this is an insert into a table b-tree, invalidate any incrblob
+ /* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced (assuming this is a replace
** operation - if it is not, the following is a no-op). */
if( pCur->pKeyInfo==0 ){
insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
- /* If no error has occurred and pPage has an overflow cell, call balance()
+ /* If no error has occurred and pPage has an overflow cell, call balance()
** to redistribute the cells within the tree. Since balance() may move
** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
** variables.
rc = balance(pCur);
/* Must make sure nOverflow is reset to zero even if the balance()
- ** fails. Internal data structure corruption will result otherwise.
+ ** fails. Internal data structure corruption will result otherwise.
** Also, set the cursor state to invalid. This stops saveCursorPosition()
** from trying to save the current position of the cursor. */
pCur->apPage[pCur->iPage]->nOverflow = 0;
*/
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
Btree *p = pCur->pBtree;
- BtShared *pBt = p->pBt;
+ BtShared *pBt = p->pBt;
int rc; /* Return code */
MemPage *pPage; /* Page to delete cell from */
unsigned char *pCell; /* Pointer to cell to delete */
int iCellIdx; /* Index of cell to delete */
- int iCellDepth; /* Depth of node containing pCell */
+ int iCellDepth; /* Depth of node containing pCell */
assert( cursorHoldsMutex(pCur) );
assert( pBt->inTransaction==TRANS_WRITE );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
- if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell)
+ if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell)
|| NEVER(pCur->eState!=CURSOR_VALID)
){
return SQLITE_ERROR; /* Something has gone awry. */
}
/* Save the positions of any other cursors open on this table before
- ** making any modifications. Make the page containing the entry to be
- ** deleted writable. Then free any overflow pages associated with the
- ** entry and finally remove the cell itself from within the page.
+ ** making any modifications. Make the page containing the entry to be
+ ** deleted writable. Then free any overflow pages associated with the
+ ** entry and finally remove the cell itself from within the page.
*/
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
** on the leaf node first. If the balance proceeds far enough up the
** tree that we can be sure that any problem in the internal node has
** been corrected, so be it. Otherwise, after balancing the leaf node,
- ** walk the cursor up the tree to the internal node and balance it as
+ ** walk the cursor up the tree to the internal node and balance it as
** well. */
rc = balance(pCur);
if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
}
}else{
pRoot = pPageMove;
- }
+ }
/* Update the pointer-map and meta-data with the new root-page number. */
ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0, &rc);
** cursors on the table.
**
** If AUTOVACUUM is enabled and the page at iTable is not the last
-** root page in the database file, then the last root page
+** root page in the database file, then the last root page
** in the database file is moved into the slot formerly occupied by
** iTable and that last slot formerly occupied by the last root page
** is added to the freelist instead of iTable. In this say, all
** root pages are kept at the beginning of the database file, which
-** is necessary for AUTOVACUUM to work right. *piMoved is set to the
+** is necessary for AUTOVACUUM to work right. *piMoved is set to the
** page number that used to be the last root page in the file before
** the move. If no page gets moved, *piMoved is set to 0.
** The last root page is recorded in meta[3] and the value of
/* It is illegal to drop a table if any cursors are open on the
** database. This is because in auto-vacuum mode the backend may
** need to move another root-page to fill a gap left by the deleted
- ** root page. If an open cursor was using this page a problem would
+ ** root page. If an open cursor was using this page a problem would
** occur.
**
** This error is caught long before control reaches this point.
if( iTable==maxRootPgno ){
/* If the table being dropped is the table with the largest root-page
- ** number in the database, put the root page on the free list.
+ ** number in the database, put the root page on the free list.
*/
freePage(pPage, &rc);
releasePage(pPage);
}
}else{
/* The table being dropped does not have the largest root-page
- ** number in the database. So move the page that does into the
+ ** number in the database. So move the page that does into the
** gap left by the deleted root-page.
*/
MemPage *pMove;
}else{
/* If sqlite3BtreeDropTable was called on page 1.
** This really never should happen except in a corrupt
- ** database.
+ ** database.
*/
zeroPage(pPage, PTF_INTKEY|PTF_LEAF );
releasePage(pPage);
}
- return rc;
+ return rc;
}
SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
int rc;
** is the number of free pages currently in the database. Meta[1]
** through meta[15] are available for use by higher layers. Meta[0]
** is read-only, the others are read/write.
-**
+**
** The schema layer numbers meta values differently. At the schema
** layer (and the SetCookie and ReadCookie opcodes) the number of
** free pages is not visible. So Cookie[0] is the same as Meta[1].
** The first argument, pCur, is a cursor opened on some b-tree. Count the
** number of entries in the b-tree and write the result to *pnEntry.
**
-** SQLITE_OK is returned if the operation is successfully executed.
+** SQLITE_OK is returned if the operation is successfully executed.
** Otherwise, if an error is encountered (i.e. an IO error or database
** corruption) an SQLite error code is returned.
*/
rc = moveToRoot(pCur);
/* Unless an error occurs, the following loop runs one iteration for each
- ** page in the B-Tree structure (not including overflow pages).
+ ** page in the B-Tree structure (not including overflow pages).
*/
while( rc==SQLITE_OK ){
int iIdx; /* Index of child node in parent */
MemPage *pPage; /* Current page of the b-tree */
- /* If this is a leaf page or the tree is not an int-key tree, then
+ /* If this is a leaf page or the tree is not an int-key tree, then
** this page contains countable entries. Increment the entry counter
** accordingly.
*/
nEntry += pPage->nCell;
}
- /* pPage is a leaf node. This loop navigates the cursor so that it
+ /* pPage is a leaf node. This loop navigates the cursor so that it
** points to the first interior cell that it points to the parent of
** the next page in the tree that has not yet been visited. The
** pCur->aiIdx[pCur->iPage] value is set to the index of the parent cell
pPage = pCur->apPage[pCur->iPage];
}
- /* Descend to the child node of the cell that the cursor currently
+ /* Descend to the child node of the cell that the cursor currently
** points at. This is the right-child if (iIdx==pPage->nCell).
*/
iIdx = pCur->aiIdx[pCur->iPage];
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
-** Check that the entry in the pointer-map for page iChild maps to
+** Check that the entry in the pointer-map for page iChild maps to
** page iParent, pointer type ptrType. If not, append an error message
** to pCheck.
*/
}
if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
- checkAppendMsg(pCheck, zContext,
- "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
+ checkAppendMsg(pCheck, zContext,
+ "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
iChild, eType, iParent, ePtrmapType, iPtrmapParent);
}
}
** Do various sanity checks on a single page of a tree. Return
** the tree depth. Root pages return 0. Parents of root pages
** return 1, and so forth.
-**
+**
** These checks are done:
**
** 1. Make sure that cells and freeblocks do not overlap
IntegrityCk *pCheck, /* Context for the sanity check */
int iPage, /* Page number of the page to check */
char *zParentContext, /* Parent context */
- i64 *pnParentMinKey,
+ i64 *pnParentMinKey,
i64 *pnParentMaxKey
){
MemPage *pPage;
pPage->isInit = 0;
if( (rc = btreeInitPage(pPage))!=0 ){
assert( rc==SQLITE_CORRUPT ); /* The only possible error from InitPage */
- checkAppendMsg(pCheck, zContext,
+ checkAppendMsg(pCheck, zContext,
"btreeInitPage() returns error code %d", rc);
releasePage(pPage);
return 0;
else if( i==0 ) nMinKey = nMaxKey = info.nKey;
else{
if( info.nKey <= nMaxKey ){
- checkAppendMsg(pCheck, zContext,
+ checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
}
nMaxKey = info.nKey;
}
assert( sz==info.nPayload );
- if( (sz>info.nLocal)
+ if( (sz>info.nLocal)
&& (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
){
int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
if( !pPage->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
- sqlite3_snprintf(sizeof(zContext), zContext,
+ sqlite3_snprintf(sizeof(zContext), zContext,
"On page %d at right child: ", iPage);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
#endif
checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey);
}
-
+
/* For intKey leaf pages, check that the min/max keys are in order
** with any left/parent/right pages.
*/
/* if we are the left most child page */
if( !pnParentMaxKey ){
if( nMaxKey > *pnParentMinKey ){
- checkAppendMsg(pCheck, zContext,
+ checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (max larger than parent min of %lld)",
nMaxKey, *pnParentMinKey);
}
}else{
if( nMinKey <= *pnParentMinKey ){
- checkAppendMsg(pCheck, zContext,
+ checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (min less than parent min of %lld)",
nMinKey, *pnParentMinKey);
}
if( nMaxKey > *pnParentMaxKey ){
- checkAppendMsg(pCheck, zContext,
+ checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (max larger than parent max of %lld)",
nMaxKey, *pnParentMaxKey);
}
/* else if we're a right child page */
} else if( pnParentMaxKey ){
if( nMinKey <= *pnParentMaxKey ){
- checkAppendMsg(pCheck, zContext,
+ checkAppendMsg(pCheck, zContext,
"Rowid %lld out of order (min less than parent max of %lld)",
nMinKey, *pnParentMaxKey);
}
size = cellSizePtr(pPage, &data[pc]);
}
if( (int)(pc+size-1)>=usableSize ){
- checkAppendMsg(pCheck, 0,
+ checkAppendMsg(pCheck, 0,
"Corruption detected in cell %d on page %d",i,iPage);
}else{
for(j=pc+size-1; j>=pc; j--) hit[j]++;
}
}
if( cnt!=data[hdr+7] ){
- checkAppendMsg(pCheck, 0,
+ checkAppendMsg(pCheck, 0,
"Fragmentation of %d bytes reported as %d on page %d",
cnt, data[hdr+7], iPage);
}
/* If the database supports auto-vacuum, make sure no tables contain
** references to pointer-map pages.
*/
- if( getPageReferenced(&sCheck, i)==0 &&
+ if( getPageReferenced(&sCheck, i)==0 &&
(PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
}
- if( getPageReferenced(&sCheck, i)!=0 &&
+ if( getPageReferenced(&sCheck, i)!=0 &&
(PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i);
}
** of the integrity check.
*/
if( NEVER(nRef != sqlite3PagerRefcount(pBt->pPager)) ){
- checkAppendMsg(&sCheck, 0,
+ checkAppendMsg(&sCheck, 0,
"Outstanding page count goes from %d to %d during this analysis",
nRef, sqlite3PagerRefcount(pBt->pPager)
);
/*
** Run a checkpoint on the Btree passed as the first argument.
**
-** Return SQLITE_LOCKED if this or any other connection has an open
+** Return SQLITE_LOCKED if this or any other connection has an open
** transaction on the shared-cache the argument Btree is connected to.
**
** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
/*
** This function returns a pointer to a blob of memory associated with
** a single shared-btree. The memory is used by client code for its own
-** purposes (for example, to store a high-level schema associated with
+** purposes (for example, to store a high-level schema associated with
** the shared-btree). The btree layer manages reference counting issues.
**
** The first time this is called on a shared-btree, nBytes bytes of memory
-** are allocated, zeroed, and returned to the caller. For each subsequent
+** are allocated, zeroed, and returned to the caller. For each subsequent
** call the nBytes parameter is ignored and a pointer to the same blob
-** of memory returned.
+** of memory returned.
**
** If the nBytes parameter is 0 and the blob of memory has not yet been
** allocated, a null pointer is returned. If the blob has already been
** allocated, it is returned as normal.
**
-** Just before the shared-btree is closed, the function passed as the
-** xFree argument when the memory allocation was made is invoked on the
+** Just before the shared-btree is closed, the function passed as the
+** xFree argument when the memory allocation was made is invoked on the
** blob of allocated memory. The xFree function should not call sqlite3_free()
** on the memory, the btree layer does that.
*/
}
/*
-** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared
-** btree as the argument handle holds an exclusive lock on the
+** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared
+** btree as the argument handle holds an exclusive lock on the
** sqlite_master table. Otherwise SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *p){
#ifndef SQLITE_OMIT_INCRBLOB
/*
-** Argument pCsr must be a cursor opened for writing on an
-** INTKEY table currently pointing at a valid table entry.
+** Argument pCsr must be a cursor opened for writing on an
+** INTKEY table currently pointing at a valid table entry.
** This function modifies the data stored as part of that entry.
**
-** Only the data content may only be modified, it is not possible to
+** Only the data content may only be modified, it is not possible to
** change the length of the data stored. If this function is called with
** parameters that attempt to write past the end of the existing data,
** no modifications are made and SQLITE_CORRUPT is returned.
VVA_ONLY(rc =) saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr);
assert( rc==SQLITE_OK );
- /* Check some assumptions:
+ /* Check some assumptions:
** (a) the cursor is open for writing,
** (b) there is a read/write transaction open,
** (c) the connection holds a write-lock on the table (if required),
return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
}
-/*
-** Set a flag on this cursor to cache the locations of pages from the
+/*
+** Set a flag on this cursor to cache the locations of pages from the
** overflow list for the current row. This is used by cursors opened
** for incremental blob IO only.
**
#endif
/*
-** Set both the "read version" (single byte at byte offset 18) and
+** Set both the "read version" (single byte at byte offset 18) and
** "write version" (single byte at byte offset 19) fields in the database
** header to iVersion.
*/
SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
BtShared *pBt = pBtree->pBt;
int rc; /* Return code */
-
+
assert( iVersion==1 || iVersion==2 );
/* If setting the version fields to 1, do not automatically open the
** May you share freely, never taking more than you give.
**
*************************************************************************
-** This file contains the implementation of the sqlite3_backup_XXX()
+** This file contains the implementation of the sqlite3_backup_XXX()
** API functions and the related features.
*/
** Once it has been created using backup_init(), a single sqlite3_backup
** structure may be accessed via two groups of thread-safe entry points:
**
-** * Via the sqlite3_backup_XXX() API function backup_step() and
+** * Via the sqlite3_backup_XXX() API function backup_step() and
** backup_finish(). Both these functions obtain the source database
-** handle mutex and the mutex associated with the source BtShared
+** handle mutex and the mutex associated with the source BtShared
** structure, in that order.
**
** * Via the BackupUpdate() and BackupRestart() functions, which are
** invoked by the pager layer to report various state changes in
** the page cache associated with the source database. The mutex
-** associated with the source database BtShared structure will always
+** associated with the source database BtShared structure will always
** be held when either of these functions are invoked.
**
** The other sqlite3_backup_XXX() API functions, backup_remaining() and
** in connection handle pDb. If such a database cannot be found, return
** a NULL pointer and write an error message to pErrorDb.
**
-** If the "temp" database is requested, it may need to be opened by this
-** function. If an error occurs while doing so, return 0 and write an
+** If the "temp" database is requested, it may need to be opened by this
+** function. If an error occurs while doing so, return 0 and write an
** error message to pErrorDb.
*/
static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
}
/*
-** Argument rc is an SQLite error code. Return true if this error is
+** Argument rc is an SQLite error code. Return true if this error is
** considered fatal if encountered during a backup operation. All errors
** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED.
*/
}
/*
-** Parameter zSrcData points to a buffer containing the data for
-** page iSrcPg from the source database. Copy this data into the
+** Parameter zSrcData points to a buffer containing the data for
+** page iSrcPg from the source database. Copy this data into the
** destination database.
*/
static int backupOnePage(
assert( zSrcData );
/* Catch the case where the destination is an in-memory database and the
- ** page sizes of the source and destination differ.
+ ** page sizes of the source and destination differ.
*/
if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){
rc = SQLITE_READONLY;
}
#endif
- /* This loop runs once for each destination page spanned by the source
+ /* This loop runs once for each destination page spanned by the source
** page. For each iteration, variable iOff is set to the byte offset
** of the destination page.
*/
** Then clear the Btree layer MemPage.isInit flag. Both this module
** and the pager code use this trick (clearing the first byte
** of the page 'extra' space to invalidate the Btree layers
- ** cached parse of the page). MemPage.isInit is marked
+ ** cached parse of the page). MemPage.isInit is marked
** "MUST BE FIRST" for this purpose.
*/
memcpy(zOut, zIn, nCopy);
** exactly iSize bytes. If pFile is not larger than iSize bytes, then
** this function is a no-op.
**
-** Return SQLITE_OK if everything is successful, or an SQLite error
+** Return SQLITE_OK if everything is successful, or an SQLite error
** code if an error occurs.
*/
static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){
/* Lock the destination database, if it is not locked already. */
if( SQLITE_OK==rc && p->bDestLocked==0
- && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2))
+ && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2))
){
p->bDestLocked = 1;
sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema);
if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){
rc = SQLITE_READONLY;
}
-
+
/* Now that there is a read-lock on the source database, query the
** source pager for the number of pages in the database.
*/
attachBackupObject(p);
}
}
-
+
/* Update the schema version field in the destination database. This
** is to make sure that the schema-version really does change in
** the case where the source and destination databases have the
int nDestTruncate;
/* Set nDestTruncate to the final number of pages in the destination
** database. The complication here is that the destination page
- ** size may be different to the source page size.
+ ** size may be different to the source page size.
**
- ** If the source page size is smaller than the destination page size,
+ ** If the source page size is smaller than the destination page size,
** round up. In this case the call to sqlite3OsTruncate() below will
** fix the size of the file. However it is important to call
- ** sqlite3PagerTruncateImage() here so that any pages in the
+ ** sqlite3PagerTruncateImage() here so that any pages in the
** destination file that lie beyond the nDestTruncate page mark are
** journalled by PagerCommitPhaseOne() before they are destroyed
** by the file truncation.
**
** * The destination may need to be truncated, and
**
- ** * Data stored on the pages immediately following the
+ ** * Data stored on the pages immediately following the
** pending-byte page in the source database may need to be
** copied into the destination database.
*/
i64 iEnd;
assert( pFile );
- assert( nDestTruncate==0
+ assert( nDestTruncate==0
|| (i64)nDestTruncate*(i64)pgszDest >= iSize || (
nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
&& iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
** database has been stored in the journal for pDestPager and the
** journal synced to disk. So at this point we may safely modify
** the database file in any way, knowing that if a power failure
- ** occurs, the original database will be reconstructed from the
+ ** occurs, the original database will be reconstructed from the
** journal file. */
sqlite3PagerPagecount(pDestPager, &nDstPage);
for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
/* Write the extra pages and truncate the database file as required */
iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
for(
- iOff=PENDING_BYTE+pgszSrc;
- rc==SQLITE_OK && iOff<iEnd;
+ iOff=PENDING_BYTE+pgszSrc;
+ rc==SQLITE_OK && iOff<iEnd;
iOff+=pgszSrc
){
PgHdr *pSrcPg = 0;
sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
}
-
+
/* Finish committing the transaction to the destination database. */
if( SQLITE_OK==rc
&& SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
}
}
}
-
+
/* If bCloseTrans is true, then this function opened a read transaction
** on the source database. Close the read transaction here. There is
** no need to check the return values of the btree methods here, as
TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0);
assert( rc2==SQLITE_OK );
}
-
+
if( rc==SQLITE_IOERR_NOMEM ){
rc = SQLITE_NOMEM;
}
}
/*
-** Return the total number of pages in the source database as of the most
+** Return the total number of pages in the source database as of the most
** recent call to sqlite3_backup_step().
*/
SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p){
/*
** This function is called after the contents of page iPage of the
-** source database have been modified. If page iPage has already been
+** source database have been modified. If page iPage has already been
** copied into the destination database, then the data written to the
** destination is now invalidated. The destination copy of iPage needs
** to be updated with the new data before the backup operation is
** Restart the backup process. This is called when the pager layer
** detects that the database has been modified by an external database
** connection. In this case there is no way of knowing which of the
-** pages that have been copied into the destination database are still
+** pages that have been copied into the destination database are still
** valid and which are not, so the entire process needs to be restarted.
**
** It is assumed that the mutex associated with the BtShared object
** Copy the complete content of pBtFrom into pBtTo. A transaction
** must be active for both files.
**
-** The size of file pTo may be reduced by this operation. If anything
-** goes wrong, the transaction on pTo is rolled back. If successful, the
+** The size of file pTo may be reduced by this operation. If anything
+** goes wrong, the transaction on pTo is rolled back. If successful, the
** transaction is committed before returning.
*/
SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
/* 0x7FFFFFFF is the hard limit for the number of pages in a database
** file. By passing this as the number of pages to copy to
- ** sqlite3_backup_step(), we can guarantee that the copy finishes
+ ** sqlite3_backup_step(), we can guarantee that the copy finishes
** within a single call (unless an error occurs). The assert() statement
- ** checks this assumption - (p->rc) should be set to either SQLITE_DONE
+ ** checks this assumption - (p->rc) should be set to either SQLITE_DONE
** or an error code.
*/
sqlite3_backup_step(&b, 0x7FFFFFFF);
}
/*
-** Make sure pMem->z points to a writable allocation of at least
+** Make sure pMem->z points to a writable allocation of at least
** n bytes.
**
** If the third argument passed to this function is true, then memory
** any current string or blob value may be discarded.
**
** This function sets the MEM_Dyn flag and clears any xDel callback.
-** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
+** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
** not set, Mem.n is zeroed.
*/
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
assert( 1 >=
((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
- (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
- ((pMem->flags&MEM_Ephem) ? 1 : 0) +
+ (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
+ ((pMem->flags&MEM_Ephem) ? 1 : 0) +
((pMem->flags&MEM_Static) ? 1 : 0)
);
assert( (pMem->flags&MEM_RowSet)==0 );
/* For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8
** string representation of the value. Then, if the required encoding
** is UTF-16le or UTF-16be do a translation.
- **
+ **
** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
*/
if( fg & MEM_Int ){
pMem->flags = MEM_Null;
}else{
assert( pMem->zMalloc );
- pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc,
+ pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc,
sqlite3DbMallocSize(db, pMem->zMalloc));
assert( pMem->u.pRowSet!=0 );
pMem->flags = MEM_RowSet;
}
return n>p->db->aLimit[SQLITE_LIMIT_LENGTH];
}
- return 0;
+ return 0;
}
#ifdef SQLITE_DEBUG
** Change the value of a Mem to be a string or a BLOB.
**
** The memory management strategy depends on the value of the xDel
-** parameter. If the value passed is SQLITE_TRANSIENT, then the
-** string is copied into a (possibly existing) buffer managed by the
+** parameter. If the value passed is SQLITE_TRANSIENT, then the
+** string is copied into a (possibly existing) buffer managed by the
** Mem structure. Otherwise, any existing buffer is freed and the
** pointer copied.
**
f2 = pMem2->flags;
combined_flags = f1|f2;
assert( (combined_flags & MEM_RowSet)==0 );
-
+
/* If one value is NULL, it is less than the other. If both values
** are NULL, return 0.
*/
}
assert( pMem1->enc==pMem2->enc );
- assert( pMem1->enc==SQLITE_UTF8 ||
+ assert( pMem1->enc==SQLITE_UTF8 ||
pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
/* The collation sequence must be defined at this point, even if
/* If a NULL pointer was passed as the collate function, fall through
** to the blob case and use memcmp(). */
}
-
+
/* Both values must be blobs. Compare using memcmp(). */
rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
if( rc==0 ){
assert( sqlite3BtreeCursorIsValid(pCur) );
- /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert()
+ /* Note: the calls to BtreeKeyFetch() and DataFetch() below assert()
** that both the BtShared and database handle mutexes are held. */
assert( (pMem->flags & MEM_RowSet)==0 );
if( key ){
#endif
/*
-** Resize the Vdbe.aOp array so that it is at least one op larger than
+** Resize the Vdbe.aOp array so that it is at least one op larger than
** it was.
**
** If an out-of-memory error occurs while resizing the array, return
-** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
-** unchanged (this is so that any opcodes already allocated can be
+** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
+** unchanged (this is so that any opcodes already allocated can be
** correctly deallocated along with the rest of the Vdbe).
*/
static int growOpArray(Vdbe *p){
int i = p->nLabel++;
assert( p->magic==VDBE_MAGIC_INIT );
if( (i & (i-1))==0 ){
- p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
+ p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
(i*2+1)*sizeof(p->aLabel[0]));
}
if( p->aLabel ){
/*
** The following type and function are used to iterate through all opcodes
-** in a Vdbe main program and each of the sub-programs (triggers) it may
+** in a Vdbe main program and each of the sub-programs (triggers) it may
** invoke directly or indirectly. It should be used as follows:
**
** Op *pOp;
** VdbeOpIter sIter;
**
** memset(&sIter, 0, sizeof(sIter));
-** sIter.v = v; // v is of type Vdbe*
+** sIter.v = v; // v is of type Vdbe*
** while( (pOp = opIterNext(&sIter)) ){
** // Do something with pOp
** }
** sqlite3DbFree(v->db, sIter.apSub);
-**
+**
*/
typedef struct VdbeOpIter VdbeOpIter;
struct VdbeOpIter {
p->iSub++;
p->iAddr = 0;
}
-
+
if( pRet->p4type==P4_SUBPROGRAM ){
int nByte = (p->nSub+1)*sizeof(SubProgram*);
int j;
while( (pOp = opIterNext(&sIter))!=0 ){
int opcode = pOp->opcode;
- if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
+ if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
#ifndef SQLITE_OMIT_FOREIGN_KEY
- || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1)
+ || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1)
#endif
- || ((opcode==OP_Halt || opcode==OP_HaltIfNull)
+ || ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
){
hasAbort = 1;
**
** This routine is called once after all opcodes have been inserted.
**
-** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument
-** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by
+** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument
+** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by
** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.
**
** The Op.opflags field is set on all opcodes.
/*
** This function returns a pointer to the array of opcodes associated with
** the Vdbe passed as the first argument. It is the callers responsibility
-** to arrange for the returned array to be eventually freed using the
+** to arrange for the returned array to be eventually freed using the
** vdbeFreeOpArray() function.
**
** Before returning, *pnOp is set to the number of entries in the returned
-** array. Also, *pnMaxArg is set to the larger of its current value and
-** the number of entries in the Vdbe.apArg[] array required to execute the
+** array. Also, *pnMaxArg is set to the larger of its current value and
+** the number of entries in the Vdbe.apArg[] array required to execute the
** returned program.
*/
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
/*
** Free the space allocated for aOp and any p4 values allocated for the
-** opcodes contained within. If aOp is not NULL it is assumed to contain
-** nOp entries.
+** opcodes contained within. If aOp is not NULL it is assumed to contain
+** nOp entries.
*/
static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
if( aOp ){
freeP4(db, pOp->p4type, pOp->p4.p);
#ifdef SQLITE_DEBUG
sqlite3DbFree(db, pOp->zComment);
-#endif
+#endif
}
}
sqlite3DbFree(db, aOp);
** A copy is made of the KeyInfo structure into memory obtained from
** sqlite3_malloc, to be freed when the Vdbe is finalized.
** n==P4_KEYINFO_HANDOFF indicates that zP4 points to a KeyInfo structure
-** stored in memory that the caller has obtained from sqlite3_malloc. The
+** stored in memory that the caller has obtained from sqlite3_malloc. The
** caller should not free the allocation, it will be freed when the Vdbe is
** finalized.
-**
+**
** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points
** to a string or structure that is guaranteed to exist for the lifetime of
** the Vdbe. In these cases we can just copy the pointer.
** routine, then a pointer to a dummy VdbeOp will be returned. That opcode
** is readable but not writable, though it is cast to a writable value.
** The return of a dummy opcode allows the call to continue functioning
-** after a OOM fault without having to check to see if the return from
+** after a OOM fault without having to check to see if the return from
** this routine is a valid pointer. But because the dummy.opcode is 0,
** dummy will never be written to. This is verified by code inspection and
** by running with Valgrind.
**
** If SQLite is not threadsafe but does support shared-cache mode, then
** sqlite3BtreeEnter() is invoked to set the BtShared.db variables
-** of all of BtShared structures accessible via the database handle
+** of all of BtShared structures accessible via the database handle
** associated with the VM.
**
** If SQLite is not threadsafe and does not support shared-cache mode, this
** function is a no-op.
**
-** The p->btreeMask field is a bitmask of all btrees that the prepared
+** The p->btreeMask field is a bitmask of all btrees that the prepared
** statement p will ever use. Let N be the number of bits in p->btreeMask
** corresponding to btrees that use shared cache. Then the runtime of
** this routine is N*N. But as N is rarely more than 1, this should not
static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n";
if( pOut==0 ) pOut = stdout;
zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
- fprintf(pOut, zFormat1, pc,
+ fprintf(pOut, zFormat1, pc,
sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
#ifdef SQLITE_DEBUG
pOp->zComment ? pOp->zComment : ""
assert( (&p[1])==pEnd || p[0].db==p[1].db );
/* This block is really an inlined version of sqlite3VdbeMemRelease()
- ** that takes advantage of the fact that the memory cell value is
+ ** that takes advantage of the fact that the memory cell value is
** being set to NULL after releasing any dynamic resources.
**
- ** The justification for duplicating code is that according to
- ** callgrind, this causes a certain test case to hit the CPU 4.7
- ** percent less (x86 linux, gcc version 4.1.2, -O6) than if
+ ** The justification for duplicating code is that according to
+ ** callgrind, this causes a certain test case to hit the CPU 4.7
+ ** percent less (x86 linux, gcc version 4.1.2, -O6) than if
** sqlite3MemRelease() were called from here. With -O2, this jumps
- ** to 6.6 percent. The test case is inserting 1000 rows into a table
- ** with no indexes using a single prepared INSERT statement, bind()
+ ** to 6.6 percent. The test case is inserting 1000 rows into a table
+ ** with no indexes using a single prepared INSERT statement, bind()
** and reset(). Inserts are grouped into a transaction.
*/
if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
pMem->type = SQLITE_INTEGER;
pMem->u.i = i; /* Program counter */
pMem++;
-
+
pMem->flags = MEM_Static|MEM_Str|MEM_Term;
pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
assert( pMem->z!=0 );
pMem->type = SQLITE_TEXT;
pMem->enc = SQLITE_UTF8;
pMem++;
-
+
#ifdef SQLITE_DEBUG
if( pOp->zComment ){
pMem->flags = MEM_Str|MEM_Term;
** creating the virtual machine. This involves things such
** as allocating stack space and initializing the program counter.
** After the VDBE has be prepped, it can be executed by one or more
-** calls to sqlite3VdbeExec().
+** calls to sqlite3VdbeExec().
**
** This function may be called exact once on a each virtual machine.
** After this routine is called the VM has been "packaged" and is ready
-** to run. After this routine is called, futher calls to
+** to run. After this routine is called, futher calls to
** sqlite3VdbeAddOp() functions are prohibited. This routine disconnects
** the Vdbe from the Parse object that helped generate it so that the
** the Vdbe becomes an independent entity and the Parse object can be
nArg = pParse->nMaxArg;
nOnce = pParse->nOnce;
if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */
-
+
/* For each cursor required, also allocate a memory cell. Memory
** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
** the vdbe program. Instead they are used to allocate space for
- ** VdbeCursor/BtCursor structures. The blob of memory associated with
+ ** VdbeCursor/BtCursor structures. The blob of memory associated with
** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1)
** stores the blob of memory associated with cursor 1, etc.
**
*/
nMem += nCursor;
- /* Allocate space for memory registers, SQL variables, VDBE cursors and
+ /* Allocate space for memory registers, SQL variables, VDBE cursors and
** an array to marshal SQL function arguments in.
*/
zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
p->expired = 0;
/* Memory for registers, parameters, cursor, etc, is allocated in two
- ** passes. On the first pass, we try to reuse unused space at the
+ ** passes. On the first pass, we try to reuse unused space at the
** end of the opcode array. If we are unable to satisfy all memory
** requirements by reusing the opcode array tail, then the second
- ** pass will fill in the rest using a fresh allocation.
+ ** pass will fill in the rest using a fresh allocation.
**
** This two-pass approach that reuses as much memory as possible from
** the leftover space at the end of the opcode array can significantly
}
/*
-** Close a VDBE cursor and release all the resources that cursor
+** Close a VDBE cursor and release all the resources that cursor
** happens to hold.
*/
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
/*
** Close all cursors.
**
-** Also release any dynamic memory held by the VM in the Vdbe.aMem memory
+** Also release any dynamic memory held by the VM in the Vdbe.aMem memory
** cell array. This is necessary as the memory cell array may contain
** pointers to VdbeFrame objects, which may in turn contain pointers to
** open cursors.
sqlite3 *db = p->db;
#ifdef SQLITE_DEBUG
- /* Execute assert() statements to ensure that the Vdbe.apCsr[] and
+ /* Execute assert() statements to ensure that the Vdbe.apCsr[] and
** Vdbe.aMem[] arrays have already been cleaned up. */
int i;
if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
int needXcommit = 0;
#ifdef SQLITE_OMIT_VIRTUALTABLE
- /* With this option, sqlite3VtabSync() is defined to be simply
- ** SQLITE_OK so p is not used.
+ /* With this option, sqlite3VtabSync() is defined to be simply
+ ** SQLITE_OK so p is not used.
*/
UNUSED_PARAMETER(p);
#endif
/* Before doing anything else, call the xSync() callback for any
** virtual module tables written in this transaction. This has to
- ** be done before determining whether a master journal file is
+ ** be done before determining whether a master journal file is
** required, as an xSync() callback may add an attached database
** to the transaction.
*/
rc = sqlite3VtabSync(db, &p->zErrMsg);
/* This loop determines (a) if the commit hook should be invoked and
- ** (b) how many database files have open write transactions, not
- ** including the temp database. (b) is important because if more than
+ ** (b) how many database files have open write transactions, not
+ ** including the temp database. (b) is important because if more than
** one database file has an open write transaction, a master journal
** file is required for an atomic commit.
- */
- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
+ */
+ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( sqlite3BtreeIsInTrans(pBt) ){
needXcommit = 1;
** master-journal.
**
** If the return value of sqlite3BtreeGetFilename() is a zero length
- ** string, it means the main database is :memory: or a temp file. In
- ** that case we do not support atomic multi-file commits, so use the
+ ** string, it means the main database is :memory: or a temp file. In
+ ** that case we do not support atomic multi-file commits, so use the
** simple case then too.
*/
if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt))
}
}
- /* Do the commit only if all databases successfully complete phase 1.
+ /* Do the commit only if all databases successfully complete phase 1.
** If one of the BtreeCommitPhaseOne() calls fails, this indicates an
** IO error while deleting or truncating a journal file. It is unlikely,
** but could happen. In this case abandon processing and return the error.
}while( rc==SQLITE_OK && res );
if( rc==SQLITE_OK ){
/* Open the master journal. */
- rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
+ rc = sqlite3OsOpenMalloc(pVfs, zMaster, &pMaster,
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|
SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
);
sqlite3DbFree(db, zMaster);
return rc;
}
-
+
/* Write the name of each database file in the transaction into the new
** master journal file. If an error occurs at this point close
** and delete the master journal file. All the individual journal files
/* Sync the master journal file. If the IOCAP_SEQUENTIAL device
** flag is set this is not required.
*/
- if( needSync
+ if( needSync
&& 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)
&& SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))
){
** in case the master journal file name was written into the journal
** file before the failure occurred.
*/
- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
+ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster);
*/
disable_simulated_io_errors();
sqlite3BeginBenignMalloc();
- for(i=0; i<db->nDb; i++){
+ for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
sqlite3BtreeCommitPhaseTwo(pBt, 1);
return rc;
}
-/*
+/*
** This routine checks that the sqlite3.activeVdbeCnt count variable
** matches the number of vdbe's in the list sqlite3.pVdbe that are
** currently active. An assertion fails if the two counts do not match.
** If the Vdbe passed as the first argument opened a statement-transaction,
** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
-** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
+** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
** statement transaction is commtted.
**
-** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
+** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
** Otherwise SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
sqlite3 *const db = p->db;
int rc = SQLITE_OK;
- /* If p->iStatement is greater than zero, then this Vdbe opened a
+ /* If p->iStatement is greater than zero, then this Vdbe opened a
** statement transaction that should be closed here. The only exception
** is that an IO error may have occurred, causing an emergency rollback.
** In this case (db->nStatement==0), and there is nothing to do.
assert( db->nStatement>0 );
assert( p->iStatement==(db->nStatement+db->nSavepoint) );
- for(i=0; i<db->nDb; i++){
+ for(i=0; i<db->nDb; i++){
int rc2 = SQLITE_OK;
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
}
}
- /* If the statement transaction is being rolled back, also restore the
- ** database handles deferred constraint counter to the value it had when
+ /* If the statement transaction is being rolled back, also restore the
+ ** database handles deferred constraint counter to the value it had when
** the statement transaction was opened. */
if( eOp==SAVEPOINT_ROLLBACK ){
db->nDeferredCons = p->nStmtDefCons;
}
/*
-** This function is called when a transaction opened by the database
-** handle associated with the VM passed as an argument is about to be
+** This function is called when a transaction opened by the database
+** handle associated with the VM passed as an argument is about to be
** committed. If there are outstanding deferred foreign key constraint
** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
**
-** If there are outstanding FK violations and this function returns
+** If there are outstanding FK violations and this function returns
** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
** and write an error message to it. Then return SQLITE_ERROR.
*/
/* This function contains the logic that determines if a statement or
** transaction will be committed or rolled back as a result of the
- ** execution of this virtual machine.
+ ** execution of this virtual machine.
**
** If any of the following errors occur:
**
isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
|| mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
if( isSpecialError ){
- /* If the query was read-only and the error code is SQLITE_INTERRUPT,
- ** no rollback is necessary. Otherwise, at least a savepoint
- ** transaction must be rolled back to restore the database to a
+ /* If the query was read-only and the error code is SQLITE_INTERRUPT,
+ ** no rollback is necessary. Otherwise, at least a savepoint
+ ** transaction must be rolled back to restore the database to a
** consistent state.
**
** Even if the statement is read-only, it is important to perform
- ** a statement or transaction rollback operation. If the error
+ ** a statement or transaction rollback operation. If the error
** occurred while writing to the journal, sub-journal or database
** file as part of an effort to free up cache space (see function
- ** pagerStress() in pager.c), the rollback is required to restore
+ ** pagerStress() in pager.c), the rollback is required to restore
** the pager to a consistent state.
*/
if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){
if( p->rc==SQLITE_OK ){
sqlite3VdbeCheckFk(p, 0);
}
-
- /* If the auto-commit flag is set and this is the only active writer
- ** VM, then we do either a commit or rollback of the current transaction.
+
+ /* If the auto-commit flag is set and this is the only active writer
+ ** VM, then we do either a commit or rollback of the current transaction.
**
- ** Note: This block also runs if one of the special errors handled
- ** above has occurred.
+ ** Note: This block also runs if one of the special errors handled
+ ** above has occurred.
*/
- if( !sqlite3VtabInSync(db)
- && db->autoCommit
- && db->writeVdbeCnt==(p->readOnly==0)
+ if( !sqlite3VtabInSync(db)
+ && db->autoCommit
+ && db->writeVdbeCnt==(p->readOnly==0)
){
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
rc = sqlite3VdbeCheckFk(p, 1);
return SQLITE_ERROR;
}
rc = SQLITE_CONSTRAINT_FOREIGNKEY;
- }else{
- /* The auto-commit flag is true, the vdbe program was successful
+ }else{
+ /* The auto-commit flag is true, the vdbe program was successful
** or hit an 'OR FAIL' constraint and there are no deferred foreign
- ** key constraints to hold up the transaction. This means a commit
+ ** key constraints to hold up the transaction. This means a commit
** is required. */
rc = vdbeCommit(db, p);
}
db->autoCommit = 1;
}
}
-
+
/* If eStatementOp is non-zero, then a statement transaction needs to
** be committed or rolled back. Call sqlite3VdbeCloseStatement() to
** do so. If this operation returns an error, and the current statement
db->autoCommit = 1;
}
}
-
+
/* If this was an INSERT, UPDATE or DELETE and no statement transaction
- ** has been rolled back, update the database connection change-counter.
+ ** has been rolled back, update the database connection change-counter.
*/
if( p->changeCntOn ){
if( eStatementOp!=SAVEPOINT_ROLLBACK ){
}
/* If the auto-commit flag is set to true, then any locks that were held
- ** by connection db have now been released. Call sqlite3ConnectionUnlocked()
+ ** by connection db have now been released. Call sqlite3ConnectionUnlocked()
** to invoke any required unlock-notify callbacks.
*/
if( db->autoCommit ){
/*
** Copy the error code and error message belonging to the VDBE passed
-** as the first argument to its database handle (so that they will be
+** as the first argument to its database handle (so that they will be
** returned by calls to sqlite3_errcode() and sqlite3_errmsg()).
**
** This function does not clear the VDBE error code or message, just
#ifdef SQLITE_ENABLE_SQLLOG
/*
-** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run,
+** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run,
** invoke it.
*/
static void vdbeInvokeSqllog(Vdbe *v){
p->magic = VDBE_MAGIC_INIT;
return p->rc & db->errMask;
}
-
+
/*
** Clean up and delete a VDBE after execution. Return an integer which is
** the result code. Write any error message text into *pzErrMsg.
}
/*
-** If we are on an architecture with mixed-endian floating
-** points (ex: ARM7) then swap the lower 4 bytes with the
+** If we are on an architecture with mixed-endian floating
+** points (ex: ARM7) then swap the lower 4 bytes with the
** upper 4 bytes. Return the result.
**
** For most architectures, this is a no-op.
** (2007-08-30) Frank van Vugt has studied this problem closely
** and has send his findings to the SQLite developers. Frank
** writes that some Linux kernels offer floating point hardware
-** emulation that uses only 32-bit mantissas instead of a full
+** emulation that uses only 32-bit mantissas instead of a full
** 48-bits as required by the IEEE standard. (This is the
** CONFIG_FPE_FASTFPE option.) On such systems, floating point
** byte swapping becomes very complicated. To avoid problems,
#endif
/*
-** Write the serialized data blob for the value stored in pMem into
+** Write the serialized data blob for the value stored in pMem into
** buf. It is assumed that the caller has allocated sufficient space.
** Return the number of bytes written.
**
** Return the number of bytes actually written into buf[]. The number
** of bytes in the zero-filled tail is included in the return value only
** if those bytes were zeroed in buf[].
-*/
+*/
SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){
u32 serial_type = sqlite3VdbeSerialType(pMem, file_format);
u32 len;
/*
** Deserialize the data blob pointed to by buf as serial type serial_type
** and store the result in pMem. Return the number of bytes read.
-*/
+*/
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
const unsigned char *buf, /* Buffer to deserialize from */
u32 serial_type, /* Serial type to deserialize */
** The space is either allocated using sqlite3DbMallocRaw() or from within
** the unaligned buffer passed via the second and third arguments (presumably
** stack space). If the former, then *ppFree is set to a pointer that should
-** be eventually freed by the caller using sqlite3DbFree(). Or, if the
+** be eventually freed by the caller using sqlite3DbFree(). Or, if the
** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
** before returning.
**
int nByte; /* Number of bytes required for *p */
/* We want to shift the pointer pSpace up such that it is 8-byte aligned.
- ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
+ ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
** it by. If pSpace is already 8-byte aligned, nOff should be zero.
*/
nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
}
/*
-** Given the nKey-byte encoding of a record in pKey[], populate the
+** Given the nKey-byte encoding of a record in pKey[], populate the
** UnpackedRecord structure indicated by the fourth argument with the
** contents of the decoded record.
-*/
+*/
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
KeyInfo *pKeyInfo, /* Information about the record format */
int nKey, /* Size of the binary record */
UnpackedRecord *p /* Populate this structure before returning. */
){
const unsigned char *aKey = (const unsigned char *)pKey;
- int d;
+ int d;
u32 idx; /* Offset in aKey[] to read from */
u16 u; /* Unsigned loop counter */
u32 szHdr;
/*
** This function compares the two table rows or index records
** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
-** or positive integer if key1 is less than, equal to or
+** or positive integer if key1 is less than, equal to or
** greater than key2. The {nKey1, pKey1} key must be a blob
** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
** key must be a parsed key such as obtained from
** sqlite3VdbeParseRecord.
**
** Key1 and Key2 do not have to contain the same number of fields.
-** The key with fewer fields is usually compares less than the
+** The key with fewer fields is usually compares less than the
** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set
** and the common prefixes are equal, then key1 is less than key2.
** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
/* Compilers may complain that mem1.u.i is potentially uninitialized.
** We could initialize it, as shown here, to silence those complaints.
- ** But in fact, mem1.u.i will never actually be used uninitialized, and doing
+ ** But in fact, mem1.u.i will never actually be used uninitialized, and doing
** the unnecessary initialization has a measurable negative performance
** impact, since this routine is a very high runner. And so, we choose
** to ignore the compiler warnings and leave this variable uninitialized.
*/
/* mem1.u.i = 0; // not needed, here to silence compiler warning */
-
+
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
nField = pKeyInfo->nField;
if( i<nField && pKeyInfo->aSortOrder[i] ){
rc = -rc;
}
-
+
/* If the PREFIX_SEARCH flag is set and all fields except the final
- ** rowid field were equal, then clear the PREFIX_SEARCH flag and set
+ ** rowid field were equal, then clear the PREFIX_SEARCH flag and set
** pPKey2->rowid to the value of the rowid field in (pKey1, nKey1).
** This is used by the OP_IsUnique opcode.
*/
pPKey2->flags &= ~UNPACKED_PREFIX_SEARCH;
pPKey2->rowid = mem1.u.i;
}
-
+
return rc;
}
i++;
** all the fields up to that point were equal. If the UNPACKED_INCRKEY
** flag is set, then break the tie by treating key2 as larger.
** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
- ** are considered to be equal. Otherwise, the longer key is the
+ ** are considered to be equal. Otherwise, the longer key is the
** larger. As it happens, the pPKey2 will always be the longer
** if there is a difference.
*/
}
return rc;
}
-
+
/*
** pCur points at an index entry created using the OP_MakeRecord opcode.
/* Get the size of the index entry. Only indices entries of less
** than 2GiB are support - anything large must be database corruption.
** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so
- ** this code can safely assume that nCellKey is 32-bits
+ ** this code can safely assume that nCellKey is 32-bits
*/
assert( sqlite3BtreeCursorIsValid(pCur) );
VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
**
** pUnpacked is either created without a rowid or is truncated so that it
** omits the rowid at the end. The rowid at the end of the index entry
-** is ignored as well. Hence, this routine only compares the prefixes
+** is ignored as well. Hence, this routine only compares the prefixes
** of the keys prior to the final rowid, not the entire key.
*/
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
/*
** This routine sets the value to be returned by subsequent calls to
-** sqlite3_changes() on the database handle 'db'.
+** sqlite3_changes() on the database handle 'db'.
*/
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
assert( sqlite3_mutex_held(db->mutex) );
/*
** Return a pointer to an sqlite3_value structure containing the value bound
-** parameter iVar of VM v. Except, if the value is an SQL NULL, return
+** parameter iVar of VM v. Except, if the value is an SQL NULL, return
** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE_AFF_*
** constants) to the value before returning it.
**
}
}
SQLITE_API void sqlite3_result_blob(
- sqlite3_context *pCtx,
- const void *z,
- int n,
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
void (*xDel)(void *)
){
assert( n>=0 );
sqlite3VdbeMemSetNull(&pCtx->s);
}
SQLITE_API void sqlite3_result_text(
- sqlite3_context *pCtx,
- const char *z,
+ sqlite3_context *pCtx,
+ const char *z,
int n,
void (*xDel)(void *)
){
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API void sqlite3_result_text16(
- sqlite3_context *pCtx,
- const void *z,
- int n,
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel);
}
SQLITE_API void sqlite3_result_text16be(
- sqlite3_context *pCtx,
- const void *z,
- int n,
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel);
}
SQLITE_API void sqlite3_result_text16le(
- sqlite3_context *pCtx,
- const void *z,
- int n,
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
pCtx->isError = errCode;
if( pCtx->s.flags & MEM_Null ){
- sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1,
+ sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1,
SQLITE_UTF8, SQLITE_STATIC);
}
}
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
pCtx->isError = SQLITE_TOOBIG;
- sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1,
+ sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1,
SQLITE_UTF8, SQLITE_STATIC);
}
}
/*
-** This function is called after a transaction has been committed. It
+** This function is called after a transaction has been committed. It
** invokes callbacks registered with sqlite3_wal_hook() as required.
*/
static int doWalCallbacks(sqlite3 *db){
** statement is completely executed or an error occurs.
**
** This routine implements the bulk of the logic behind the sqlite_step()
-** API. The only thing omitted is the automatic recompile if a
+** API. The only thing omitted is the automatic recompile if a
** schema change has occurred. That detail is handled by the
** outer sqlite3_step() wrapper procedure.
*/
** sqlite3_step() after any error or after SQLITE_DONE. But beginning
** with version 3.7.0, we changed this so that sqlite3_reset() would
** be called automatically instead of throwing the SQLITE_MISUSE error.
- ** This "automatic-reset" change is not technically an incompatibility,
+ ** This "automatic-reset" change is not technically an incompatibility,
** since any application that receives an SQLITE_MISUSE is broken by
** definition.
**
** Nevertheless, some published applications that were originally written
- ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
+ ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
** returns, and those were broken by the automatic-reset change. As a
** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
- ** legacy behavior of returning SQLITE_MISUSE for cases where the
+ ** legacy behavior of returning SQLITE_MISUSE for cases where the
** previous sqlite3_step() returned something other than a SQLITE_LOCKED
** or SQLITE_BUSY error.
*/
p->rc = SQLITE_NOMEM;
}
end_of_step:
- /* At this point local variable rc holds the value that should be
- ** returned if this statement was compiled using the legacy
+ /* At this point local variable rc holds the value that should be
+ ** returned if this statement was compiled using the legacy
** sqlite3_prepare() interface. According to the docs, this can only
- ** be one of the values in the first assert() below. Variable p->rc
- ** contains the value that would be returned if sqlite3_finalize()
+ ** be one of the values in the first assert() below. Variable p->rc
+ ** contains the value that would be returned if sqlite3_finalize()
** were called on statement p.
*/
- assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR
+ assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR
|| rc==SQLITE_BUSY || rc==SQLITE_MISUSE
);
assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
/* If this statement was prepared using sqlite3_prepare_v2(), and an
** error has occurred, then return the error code in p->rc to the
** caller. Set the error code in the database handle to the same value.
- */
+ */
rc = sqlite3VdbeTransferError(p);
}
return (rc&db->errMask);
assert( v->expired==0 );
}
if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
- /* This case occurs after failing to recompile an sql statement.
- ** The error message from the SQL compiler has already been loaded
- ** into the database handle. This block copies the error message
+ /* This case occurs after failing to recompile an sql statement.
+ ** The error message from the SQL compiler has already been loaded
+ ** into the database handle. This block copies the error message
** from the database handle into the statement and sets the statement
- ** program counter to 0 to ensure that when the statement is
+ ** program counter to 0 to ensure that when the statement is
** finalized or reset the parser error message is available via
** sqlite3_errmsg() and sqlite3_errcode().
*/
- const char *zErr = (const char *)sqlite3_value_text(db->pErr);
+ const char *zErr = (const char *)sqlite3_value_text(db->pErr);
sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
** deleted by calling the delete function specified when it was set.
*/
SQLITE_API void sqlite3_set_auxdata(
- sqlite3_context *pCtx,
- int iArg,
- void *pAux,
+ sqlite3_context *pCtx,
+ int iArg,
+ void *pAux,
void (*xDelete)(void*)
){
struct AuxData *pAuxData;
#ifndef SQLITE_OMIT_DEPRECATED
/*
-** Return the number of times the Step function of a aggregate has been
+** Return the number of times the Step function of a aggregate has been
** called.
**
** This function is deprecated. Do not use it for new code. It is
** these assert()s from failing, when building with SQLITE_DEBUG defined
** using gcc, we force nullMem to be 8-byte aligned using the magical
** __attribute__((aligned(8))) macro. */
- static const Mem nullMem
+ static const Mem nullMem
#if defined(SQLITE_DEBUG) && defined(__GNUC__)
- __attribute__((aligned(8)))
+ __attribute__((aligned(8)))
#endif
= {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0,
#ifdef SQLITE_DEBUG
}
/*
-** This function is called after invoking an sqlite3_value_XXX function on a
+** This function is called after invoking an sqlite3_value_XXX function on a
** column value (i.e. a value returned by evaluating an SQL expression in the
-** select list of a SELECT statement) that may cause a malloc() failure. If
+** select list of a SELECT statement) that may cause a malloc() failure. If
** malloc() has failed, the threads mallocFailed flag is cleared and the result
** code of statement pStmt set to SQLITE_NOMEM.
**
const void *val;
val = sqlite3_value_blob( columnMem(pStmt,i) );
/* Even though there is no encoding conversion, value_blob() might
- ** need to call malloc() to expand the result of a zeroblob()
- ** expression.
+ ** need to call malloc() to expand the result of a zeroblob()
+ ** expression.
*/
columnMallocFailure(pStmt);
return val;
Vdbe *p = (Vdbe *)pStmt;
int n;
sqlite3 *db = p->db;
-
+
assert( db!=0 );
n = sqlite3_column_count(pStmt);
if( N<n && N>=0 ){
/******************************* sqlite3_bind_ ***************************
-**
+**
** Routines used to attach values to wildcards in a compiled SQL statement.
*/
/*
-** Unbind the value bound to variable i in virtual machine p. This is the
+** Unbind the value bound to variable i in virtual machine p. This is the
** the same as binding a NULL value to the column. If the "i" parameter is
** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK.
**
if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
sqlite3Error(p->db, SQLITE_MISUSE, 0);
sqlite3_mutex_leave(p->db->mutex);
- sqlite3_log(SQLITE_MISUSE,
+ sqlite3_log(SQLITE_MISUSE,
"bind on a busy prepared statement: [%s]", p->zSql);
return SQLITE_MISUSE_BKPT;
}
pVar->flags = MEM_Null;
sqlite3Error(p->db, SQLITE_OK, 0);
- /* If the bit corresponding to this variable in Vdbe.expmask is set, then
+ /* If the bit corresponding to this variable in Vdbe.expmask is set, then
** binding a new value to this variable invalidates the current query plan.
**
** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
** Bind a blob value to an SQL statement variable.
*/
SQLITE_API int sqlite3_bind_blob(
- sqlite3_stmt *pStmt,
- int i,
- const void *zData,
- int nData,
+ sqlite3_stmt *pStmt,
+ int i,
+ const void *zData,
+ int nData,
void (*xDel)(void*)
){
return bindText(pStmt, i, zData, nData, xDel, 0);
}
return rc;
}
-SQLITE_API int sqlite3_bind_text(
- sqlite3_stmt *pStmt,
- int i,
- const char *zData,
- int nData,
+SQLITE_API int sqlite3_bind_text(
+ sqlite3_stmt *pStmt,
+ int i,
+ const char *zData,
+ int nData,
void (*xDel)(void*)
){
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API int sqlite3_bind_text16(
- sqlite3_stmt *pStmt,
- int i,
- const void *zData,
- int nData,
+ sqlite3_stmt *pStmt,
+ int i,
+ const void *zData,
+ int nData,
void (*xDel)(void*)
){
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
/*
** Return the number of wildcards that can be potentially bound to.
-** This routine is added to support DBD::SQLite.
+** This routine is added to support DBD::SQLite.
*/
SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
/*
** This function returns a pointer to a nul-terminated string in memory
** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the
-** string contains a copy of zRawSql but with host parameters expanded to
-** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1,
+** string contains a copy of zRawSql but with host parameters expanded to
+** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1,
** then the returned string holds a copy of zRawSql with "-- " prepended
** to each line of text.
**
char zBase[100]; /* Initial working space */
db = p->db;
- sqlite3StrAccumInit(&out, zBase, sizeof(zBase),
+ sqlite3StrAccumInit(&out, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
out.db = db;
if( db->vdbeExecCnt>1 ){
nOut = SQLITE_TRACE_SIZE_LIMIT;
while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; }
}
-#endif
+#endif
sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z);
#ifdef SQLITE_TRACE_SIZE_LIMIT
if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
return p && p->str.zText && p->str.nChar
&& p->str.zText[p->str.nChar-1]=='\n';
}
-
+
/*
** Append text to the indentation
*/
int n = p->nIndent;
if( n>ArraySize(p->aIndent) ) n = ArraySize(p->aIndent);
sqlite3AppendSpace(&p->str, p->aIndent[n-1]);
- }
+ }
va_start(ap, zFormat);
sqlite3VXPrintf(&p->str, 1, zFormat, ap);
va_end(ap);
** May you share freely, never taking more than you give.
**
*************************************************************************
-** The code in this file implements execution method of the
+** The code in this file implements execution method of the
** Virtual Database Engine (VDBE). A separate file ("vdbeaux.c")
** handles housekeeping details such as creating and deleting
** VDBE instances. This file is solely interested in executing
** to a VDBE.
**
** The SQL parser generates a program which is then executed by
-** the VDBE to do the work of the SQL statement. VDBE programs are
+** the VDBE to do the work of the SQL statement. VDBE programs are
** similar in form to assembly language. The program consists of
-** a linear sequence of operations. Each operation has an opcode
-** and 5 operands. Operands P1, P2, and P3 are integers. Operand P4
+** a linear sequence of operations. Each operation has an opcode
+** and 5 operands. Operands P1, P2, and P3 are integers. Operand P4
** is a null-terminated string. Operand P5 is an unsigned character.
** Few opcodes use all 5 operands.
**
** either an integer, a null-terminated string, a floating point
** number, or the SQL "NULL" value. An implicit conversion from one
** type to the other occurs as necessary.
-**
+**
** Most of the code in this file is taken up by the sqlite3VdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
/*
** Argument pMem points at a register that will be passed to a
** user-defined function or returned to the user as the result of a query.
-** This routine sets the pMem->type variable used by the sqlite3_value_*()
+** This routine sets the pMem->type variable used by the sqlite3_value_*()
** routines.
*/
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem){
int isBtreeCursor /* True for B-Tree. False for pseudo-table or vtab */
){
/* Find the memory cell that will be used to store the blob of memory
- ** required for this VdbeCursor structure. It is convenient to use a
+ ** required for this VdbeCursor structure. It is convenient to use a
** vdbe memory cell to manage the memory allocation required for a
** VdbeCursor structure for the following reasons:
**
int nByte;
VdbeCursor *pCx = 0;
- nByte =
- ROUND8(sizeof(VdbeCursor)) +
- (isBtreeCursor?sqlite3BtreeCursorSize():0) +
+ nByte =
+ ROUND8(sizeof(VdbeCursor)) +
+ (isBtreeCursor?sqlite3BtreeCursorSize():0) +
2*nField*sizeof(u32);
assert( iCur<p->nCursor );
** SQLITE_AFF_INTEGER:
** SQLITE_AFF_REAL:
** SQLITE_AFF_NUMERIC:
-** Try to convert pRec to an integer representation or a
+** Try to convert pRec to an integer representation or a
** floating-point representation if an integer representation
** is not possible. Note that the integer representation is
** always preferred, even if the affinity is REAL, because
}
/*
-** Exported version of applyAffinity(). This one works on sqlite3_value*,
+** Exported version of applyAffinity(). This one works on sqlite3_value*,
** not the internal Mem* type.
*/
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(
- sqlite3_value *pVal,
- u8 affinity,
+ sqlite3_value *pVal,
+ u8 affinity,
u8 enc
){
applyAffinity((Mem *)pVal, affinity, enc);
#ifdef VDBE_PROFILE
-/*
-** hwtime.h contains inline assembler code for implementing
+/*
+** hwtime.h contains inline assembler code for implementing
** high-performance timing routines.
*/
/************** Include hwtime.h in the middle of vdbe.c *********************/
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
}
-
+
#elif (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
/*
** This function is only called from within an assert() expression. It
** checks that the sqlite3.nTransaction variable is correctly set to
-** the number of non-transaction savepoints currently in the
+** the number of non-transaction savepoints currently in the
** linked list starting at sqlite3.pSavepoint.
-**
+**
** Usage:
**
** assert( checkSavepointCount(db) );
sqlite3VdbePrintOp(p->trace, pc, pOp);
}
#endif
-
+
/* Check to see if we need to simulate an interrupt. This only happens
** if we have a special test build.
memAboutToChange(p, &aMem[pOp->p3]);
}
#endif
-
+
switch( pOp->opcode ){
/*****************************************************************************
/* Opcode: Goto * P2 * * *
**
** An unconditional jump to address P2.
-** The next instruction executed will be
+** The next instruction executed will be
** the one at index P2 from the beginning of
** the program.
*/
** whether or not to rollback the current transaction. Do not rollback
** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort,
** then back out all changes that have occurred during this execution of the
-** VDBE, but do not rollback the transaction.
+** VDBE, but do not rollback the transaction.
**
** If P4 is not null then it is an error message string.
**
pc = sqlite3VdbeFrameRestore(pFrame);
lastRowid = db->lastRowid;
if( pOp->p2==OE_Ignore ){
- /* Instruction pc is the OP_Program that invoked the sub-program
+ /* Instruction pc is the OP_Program that invoked the sub-program
** currently being halted. If the p2 instruction of this OP_Halt
** instruction is set to OE_Ignore, then the sub-program is throwing
** an IGNORE exception. In this case jump to the address specified
/* Opcode: String8 * P2 * P4 *
**
-** P4 points to a nul terminated UTF-8 string. This opcode is transformed
+** P4 points to a nul terminated UTF-8 string. This opcode is transformed
** into an OP_String before it is executed for the first time.
*/
case OP_String8: { /* same as TK_STRING, out2-prerelease */
}
/* Fall through to the next case, OP_String */
}
-
+
/* Opcode: String P1 P2 * P4 *
**
** The string value P4 of length P1 (bytes) is stored in register P2.
/* Opcode: Divide P1 P2 P3 * *
**
** Divide the value in register P1 by the value in register P2
-** and store the result in register P3 (P3=P2/P1). If the value in
-** register P1 is zero, then the result is NULL. If either input is
+** and store the result in register P3 (P3=P2/P1). If the value in
+** register P1 is zero, then the result is NULL. If either input is
** NULL, the result is NULL.
*/
/* Opcode: Remainder P1 P2 P3 * *
**
** Compute the remainder after integer division of the value in
-** register P1 by the value in register P2 and store the result in P3.
+** register P1 by the value in register P2 and store the result in P3.
** If the value in register P2 is zero the result is NULL.
** If either operand is NULL, the result is NULL.
*/
** successors. The result of the function is stored in register P3.
** Register P3 must not be one of the function inputs.
**
-** P1 is a 32-bit bitmask indicating whether or not each argument to the
+** P1 is a 32-bit bitmask indicating whether or not each argument to the
** function was determined to be constant at compile time. If the first
** argument was constant then bit 0 of P1 is set. This is used to determine
** whether meta data associated with a user function argument using the
}
/* Opcode: AddImm P1 P2 * * *
-**
+**
** Add the constant P2 to the value in register P1.
** The result is always an integer.
**
}
/* Opcode: MustBeInt P1 P2 * * *
-**
+**
** Force the value in register P1 to be an integer. If the value
** in P1 is not an integer and cannot be converted into an integer
** without data loss, then jump immediately to P2, or if P2==0
** Force the value in register P1 to be numeric (either an
** integer or a floating-point number.)
** If the value is text or blob, try to convert it to an using the
-** equivalent of atoi() or atof() and store 0 if no such conversion
+** equivalent of atoi() or atof() and store 0 if no such conversion
** is possible.
**
** A NULL value is not changed by this routine. It remains NULL.
/* Opcode: Lt P1 P2 P3 P4 P5
**
** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then
-** jump to address P2.
+** jump to address P2.
**
** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or
-** reg(P3) is NULL then take the jump. If the SQLITE_JUMPIFNULL
+** reg(P3) is NULL then take the jump. If the SQLITE_JUMPIFNULL
** bit is clear then fall through if either operand is NULL.
**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
-** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
+** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
** to coerce both inputs according to this affinity before the
** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric
** affinity is used. Note that the affinity conversions are stored
** back into the input registers P1 and P3. So this opcode can cause
** persistent changes to registers P1 and P3.
**
-** Once any conversions have taken place, and neither value is NULL,
+** Once any conversions have taken place, and neither value is NULL,
** the values are compared. If both values are blobs then memcmp() is
** used to determine the results of the comparison. If both values
** are text, then the appropriate collating function specified in
** of integers in P4.
**
** The permutation is only valid until the next OP_Compare that has
-** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
+** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
** occur immediately prior to the OP_Compare.
*/
case OP_Permutation: {
/* Opcode: Not P1 P2 * * *
**
** Interpret the value in register P1 as a boolean value. Store the
-** boolean complement in register P2. If the value in register P1 is
+** boolean complement in register P2. If the value in register P1 is
** NULL, then a NULL is stored in P2.
*/
case OP_Not: { /* same as TK_NOT, in1, out2 */
/* Opcode: NotNull P1 P2 * * *
**
-** Jump to P2 if the value in register P1 is not NULL.
+** Jump to P2 if the value in register P1 is not NULL.
*/
case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
pIn1 = &aMem[pOp->p1];
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction. (See the MakeRecord opcode for additional
** information about the format of the data.) Extract the P2-th column
-** from this record. If there are less that (P2+1)
+** from this record. If there are less that (P2+1)
** values in the record, extract a NULL.
**
** The value extracted is stored in register P3.
/* Opcode: Count P1 P2 * * *
**
-** Store the number of entries (an integer value) in the table or index
+** Store the number of entries (an integer value) in the table or index
** opened by cursor P1 in register P2
*/
#ifndef SQLITE_OMIT_BTREECOUNT
/* Opcode: SetCookie P1 P2 P3 * *
**
** Write the content of register P3 (interpreted as an integer)
-** into cookie number P2 of database P1. P2==1 is the schema version.
-** P2==2 is the database format. P2==3 is the recommended pager cache
-** size, and so forth. P1==0 is the main database file and P1==1 is the
+** into cookie number P2 of database P1. P2==1 is the schema version.
+** P2==2 is the database format. P2==3 is the recommended pager cache
+** size, and so forth. P1==0 is the main database file and P1==1 is the
** database file used to store temporary tables.
**
** A transaction must be started before executing this opcode.
/* Opcode: OpenRead P1 P2 P3 P4 P5
**
** Open a read-only cursor for the database table whose root page is
-** P2 in a database file. The database file is determined by P3.
-** P3==0 means the main database, P3==1 means the database used for
+** P2 in a database file. The database file is determined by P3.
+** P3==0 means the main database, P3==1 means the database used for
** temporary tables, and P3>1 means used the corresponding attached
** database. Give the new cursor an identifier of P1. The P1
** values need not be contiguous but all P1 values should be small integers.
** SQLITE_BUSY error code.
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
-** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
-** structure, then said structure defines the content and collating
-** sequence of the index being opened. Otherwise, if P4 is an integer
+** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
+** structure, then said structure defines the content and collating
+** sequence of the index being opened. Otherwise, if P4 is an integer
** value, it is set to the number of columns in the table.
**
** See also OpenWrite.
** root page.
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
-** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
-** structure, then said structure defines the content and collating
-** sequence of the index being opened. Otherwise, if P4 is an integer
+** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
+** structure, then said structure defines the content and collating
+** sequence of the index being opened. Otherwise, if P4 is an integer
** value, it is set to the number of columns in the table, or to the
** largest index of any column of the table that is actually used.
**
/* Opcode: OpenEphemeral P1 P2 * P4 P5
**
** Open a new cursor P1 to a transient table.
-** The cursor is always opened read/write even if
+** The cursor is always opened read/write even if
** the main database is read-only. The ephemeral
** table is deleted automatically when the cursor is closed.
**
** by this opcode will be used for automatically created transient
** indices in joins.
*/
-case OP_OpenAutoindex:
+case OP_OpenAutoindex:
case OP_OpenEphemeral: {
#if 0 /* local variables moved into u.az */
VdbeCursor *pCx;
**
** Open a new cursor that points to a fake table that contains a single
** row of data. The content of that one row in the content of memory
-** register P2 when P5==0. In other words, cursor P1 becomes an alias for the
+** register P2 when P5==0. In other words, cursor P1 becomes an alias for the
** MEM_Blob content contained in register P2. When P5==1, then the
** row is represented by P3 consecutive registers beginning with P2.
**
/* Opcode: SeekGe P1 P2 P3 P4 *
**
-** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the value in register P3 as the key. If cursor P1 refers
-** to an SQL index, then P3 is the first in an array of P4 registers
-** that are used as an unpacked index key.
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the value in register P3 as the key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
**
-** Reposition cursor P1 so that it points to the smallest entry that
-** is greater than or equal to the key value. If there are no records
+** Reposition cursor P1 so that it points to the smallest entry that
+** is greater than or equal to the key value. If there are no records
** greater than or equal to the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe
*/
/* Opcode: SeekGt P1 P2 P3 P4 *
**
-** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the value in register P3 as a key. If cursor P1 refers
-** to an SQL index, then P3 is the first in an array of P4 registers
-** that are used as an unpacked index key.
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
**
-** Reposition cursor P1 so that it points to the smallest entry that
-** is greater than the key value. If there are no records greater than
+** Reposition cursor P1 so that it points to the smallest entry that
+** is greater than the key value. If there are no records greater than
** the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe
*/
-/* Opcode: SeekLt P1 P2 P3 P4 *
+/* Opcode: SeekLt P1 P2 P3 P4 *
**
-** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the value in register P3 as a key. If cursor P1 refers
-** to an SQL index, then P3 is the first in an array of P4 registers
-** that are used as an unpacked index key.
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
**
-** Reposition cursor P1 so that it points to the largest entry that
-** is less than the key value. If there are no records less than
+** Reposition cursor P1 so that it points to the largest entry that
+** is less than the key value. If there are no records less than
** the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe
*/
/* Opcode: SeekLe P1 P2 P3 P4 *
**
-** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the value in register P3 as a key. If cursor P1 refers
-** to an SQL index, then P3 is the first in an array of P4 registers
-** that are used as an unpacked index key.
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
+** use the value in register P3 as a key. If cursor P1 refers
+** to an SQL index, then P3 is the first in an array of P4 registers
+** that are used as an unpacked index key.
**
-** Reposition cursor P1 so that it points to the largest entry that
-** is less than or equal to the key value. If there are no records
+** Reposition cursor P1 so that it points to the largest entry that
+** is less than or equal to the key value. If there are no records
** less than or equal to the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
}
break;
}
-
+
/* Opcode: Found P1 P2 P3 P4 *
**
** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
** P4>0 then register P3 is the first of P4 registers that form an unpacked
** record.
-**
+**
** Cursor P1 is on an index btree. If the record identified by P3 and P4
-** is not the prefix of any entry in P1 then a jump is made to P2. If P1
+** is not the prefix of any entry in P1 then a jump is made to P2. If P1
** does contain an entry whose prefix matches the P3/P4 record then control
** falls through to the next instruction and P1 is left pointing at the
** matching entry.
** the list field being the integer ROWID of the entry that the index
** entry refers to.
**
-** The P3 register contains an integer record number. Call this record
+** The P3 register contains an integer record number. Call this record
** number R. Register P4 is the first in a set of N contiguous registers
** that make up an unpacked index key that can be used with cursor P1.
** The value of N can be inferred from the cursor. N includes the rowid
/* Opcode: NotExists P1 P2 P3 * *
**
-** Use the content of register P3 as an integer key. If a record
-** with that key does not exist in table of P1, then jump to P2.
-** If the record does exist, then fall through. The cursor is left
+** Use the content of register P3 as an integer key. If a record
+** with that key does not exist in table of P1, then jump to P2.
+** If the record does exist, then fall through. The cursor is left
** pointing to the record if it exists.
**
** The difference between this operation and NotFound is that this
** Find the next available sequence number for cursor P1.
** Write the sequence number into register P2.
** The sequence number on the cursor is incremented after this
-** instruction.
+** instruction.
*/
case OP_Sequence: { /* out2-prerelease */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
** table that cursor P1 points to. The new record number is written
** written to register P2.
**
-** If P3>0 then P3 is a register in the root frame of this VDBE that holds
+** If P3>0 then P3 is a register in the root frame of this VDBE that holds
** the largest previously generated record number. No new record numbers are
-** allowed to be less than this value. When this value reaches its maximum,
+** allowed to be less than this value. When this value reaches its maximum,
** an SQLITE_FULL error is generated. The P3 register is updated with the '
** generated record number. This P3 mechanism is used to help implement the
** AUTOINCREMENT feature.
** the update hook.
**
** Parameter P4 may point to a string containing the table-name, or
-** may be NULL. If it is not NULL, then the update-hook
+** may be NULL. If it is not NULL, then the update-hook
** (sqlite3.xUpdateCallback) is invoked following a successful insert.
**
** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically
** This works exactly like OP_Insert except that the key is the
** integer value P3, not the value of the integer stored in register P3.
*/
-case OP_Insert:
+case OP_Insert:
case OP_InsertInt: {
#if 0 /* local variables moved into u.bi */
Mem *pData; /* MEM cell holding data for the record to be inserted */
/* Opcode: SorterCompare P1 P2 P3
**
-** P1 is a sorter cursor. This instruction compares the record blob in
+** P1 is a sorter cursor. This instruction compares the record blob in
** register P3 with the entry that the sorter cursor currently points to.
** If, excluding the rowid fields at the end, the two records are a match,
** fall through to the next instruction. Otherwise, jump to instruction P2.
/* Opcode: RowData P1 P2 * * *
**
** Write into register P2 the complete row data for cursor P1.
-** There is no interpretation of the data.
-** It is just copied onto the P2 register exactly as
+** There is no interpretation of the data.
+** It is just copied onto the P2 register exactly as
** it is found in the database file.
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
/* Opcode: RowKey P1 P2 * * *
**
** Write into register P2 the complete row key for cursor P1.
-** There is no interpretation of the data.
-** The key is copied onto the P3 register exactly as
+** There is no interpretation of the data.
+** The key is copied onto the P3 register exactly as
** it is found in the database file.
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
/* Opcode: Last P1 P2 * * *
**
-** The next use of the Rowid or Column or Next instruction for P1
+** The next use of the Rowid or Column or Next instruction for P1
** will refer to the last entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
}
/* Opcode: Rewind P1 P2 * * *
**
-** The next use of the Rowid or Column or Next instruction for P1
+** The next use of the Rowid or Column or Next instruction for P1
** will refer to the first entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
/* Opcode: IdxDelete P1 P2 P3 * *
**
** The content of P3 registers starting at register P2 form
-** an unpacked index key. This opcode removes that entry from the
+** an unpacked index key. This opcode removes that entry from the
** index opened by cursor P1.
*/
case OP_IdxDelete: {
/* Opcode: IdxGE P1 P2 P3 P4 P5
**
-** The P4 register values beginning with P3 form an unpacked index
-** key that omits the ROWID. Compare this key value against the index
+** The P4 register values beginning with P3 form an unpacked index
+** key that omits the ROWID. Compare this key value against the index
** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
**
** If the P1 index entry is greater than or equal to the key value
** then jump to P2. Otherwise fall through to the next instruction.
**
-** If P5 is non-zero then the key value is increased by an epsilon
+** If P5 is non-zero then the key value is increased by an epsilon
** prior to the comparison. This make the opcode work like IdxGT except
** that if the key from register P3 is a prefix of the key in the cursor,
** the result is false whereas it would be true with IdxGT.
*/
/* Opcode: IdxLT P1 P2 P3 P4 P5
**
-** The P4 register values beginning with P3 form an unpacked index
-** key that omits the ROWID. Compare this key value against the index
+** The P4 register values beginning with P3 form an unpacked index
+** key that omits the ROWID. Compare this key value against the index
** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
**
** If the P1 index entry is less than the key value then jump to P2.
** Otherwise fall through to the next instruction.
**
-** If P5 is non-zero then the key value is increased by an epsilon prior
+** If P5 is non-zero then the key value is increased by an epsilon prior
** to the comparison. This makes the opcode work like IdxLE.
*/
case OP_IdxLT: /* jump */
** might be moved into the newly deleted root page in order to keep all
** root pages contiguous at the beginning of the database. The former
** value of the root page that moved - its value before the move occurred -
-** is stored in register P2. If no page
-** movement was required (because the table being dropped was already
+** is stored in register P2. If no page
+** movement was required (because the table being dropped was already
** the last one in the database) then a zero is stored in register P2.
** If AUTOVACUUM is disabled then a zero is stored in register P2.
**
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
** If the P3 value is non-zero, then the table referred to must be an
-** intkey table (an SQL table, not an index). In this case the row change
-** count is incremented by the number of rows in the table being cleared.
+** intkey table (an SQL table, not an index). In this case the row change
+** count is incremented by the number of rows in the table being cleared.
** If P3 is greater than zero, then the value stored in register P3 is
** also incremented by the number of rows in the table being cleared.
**
/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
-** that match the WHERE clause P4.
+** that match the WHERE clause P4.
**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine. It is thus a re-entrant opcode.
case OP_LoadAnalysis: {
assert( pOp->p1>=0 && pOp->p1<db->nDb );
rc = sqlite3AnalysisLoad(db, pOp->p1);
- break;
+ break;
}
#endif /* !defined(SQLITE_OMIT_ANALYZE) */
**
** The register P3 contains the maximum number of allowed errors.
** At most reg(P3) errors will be reported.
-** In other words, the analysis stops as soon as reg(P1) errors are
+** In other words, the analysis stops as soon as reg(P1) errors are
** seen. Reg(P1) is updated with the number of errors remaining.
**
** The root page numbers of all tables in the database are integer
/* Opcode: Program P1 P2 P3 P4 *
**
-** Execute the trigger program passed as P4 (type P4_SUBPROGRAM).
+** Execute the trigger program passed as P4 (type P4_SUBPROGRAM).
**
-** P1 contains the address of the memory cell that contains the first memory
-** cell in an array of values used as arguments to the sub-program. P2
-** contains the address to jump to if the sub-program throws an IGNORE
-** exception using the RAISE() function. Register P3 contains the address
-** of a memory cell in this (the parent) VM that is used to allocate the
+** P1 contains the address of the memory cell that contains the first memory
+** cell in an array of values used as arguments to the sub-program. P2
+** contains the address to jump to if the sub-program throws an IGNORE
+** exception using the RAISE() function. Register P3 contains the address
+** of a memory cell in this (the parent) VM that is used to allocate the
** memory required by the sub-vdbe at runtime.
**
** P4 is a pointer to the VM containing the trigger program.
/* Opcode: Param P1 P2 * * *
**
-** This opcode is only ever present in sub-programs called via the
-** OP_Program instruction. Copy a value currently stored in a memory
-** cell of the calling (parent) frame to cell P2 in the current frames
-** address space. This is used by trigger programs to access the new.*
+** This opcode is only ever present in sub-programs called via the
+** OP_Program instruction. Copy a value currently stored in a memory
+** cell of the calling (parent) frame to cell P2 in the current frames
+** address space. This is used by trigger programs to access the new.*
** and old.* values.
**
** The address of the cell in the parent frame is determined by adding
/* Opcode: FkCounter P1 P2 * * *
**
** Increment a "constraint counter" by P2 (P2 may be negative or positive).
-** If P1 is non-zero, the database constraint counter is incremented
-** (deferred foreign key constraints). Otherwise, if P1 is zero, the
+** If P1 is non-zero, the database constraint counter is incremented
+** (deferred foreign key constraints). Otherwise, if P1 is zero, the
** statement counter is incremented (immediate foreign key constraints).
*/
case OP_FkCounter: {
/* Opcode: FkIfZero P1 P2 * * *
**
** This opcode tests if a foreign key constraint-counter is currently zero.
-** If so, jump to instruction P2. Otherwise, fall through to the next
+** If so, jump to instruction P2. Otherwise, fall through to the next
** instruction.
**
** If P1 is non-zero, then the jump is taken if the database constraint-counter
**
** P1 is a register in the root frame of this VM (the root frame is
** different from the current frame if this instruction is being executed
-** within a sub-program). Set the value of register P1 to the maximum of
+** within a sub-program). Set the value of register P1 to the maximum of
** its current value and the value in register P2.
**
** This instruction throws an error if the memory cell is not initially
/* Opcode: IfNeg P1 P2 * * *
**
-** If the value of register P1 is less than zero, jump to P2.
+** If the value of register P1 is less than zero, jump to P2.
**
** It is illegal to use this instruction on a register that does
** not contain an integer. An assertion fault will result if you try.
/* Opcode: IfZero P1 P2 P3 * *
**
** The register P1 must contain an integer. Add literal P3 to the
-** value in register P1. If the result is exactly 0, jump to P2.
+** value in register P1. If the result is exactly 0, jump to P2.
**
** It is illegal to use this instruction on a register that does
** not contain an integer. An assertion fault will result if you try.
sqlite3VdbeMemSetInt64(u.ci.pMem, (i64)u.ci.aRes[u.ci.i]);
}
break;
-};
+};
#endif
#ifndef SQLITE_OMIT_PRAGMA
/* Opcode: Expire P1 * * * *
**
** Cause precompiled statements to become expired. An expired statement
-** fails with an error code of SQLITE_SCHEMA if it is ever executed
+** fails with an error code of SQLITE_SCHEMA if it is ever executed
** (via sqlite3_step()).
-**
+**
** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
-** then only the currently executing statement is affected.
+** then only the currently executing statement is affected.
*/
case OP_Expire: {
if( !pOp->p1 ){
/* Opcode: TableLock P1 P2 P3 P4 *
**
** Obtain a lock on a particular table. This instruction is only used when
-** the shared-cache feature is enabled.
+** the shared-cache feature is enabled.
**
** P1 is the index of the database in sqlite3.aDb[] of the database
** on which the lock is acquired. A readlock is obtained if P3==0 or
case OP_TableLock: {
u8 isWriteLock = (u8)pOp->p3;
if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
- int p1 = pOp->p1;
+ int p1 = pOp->p1;
assert( p1>=0 && p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<p1))!=0 );
assert( isWriteLock==0 || isWriteLock==1 );
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VBegin * * * P4 *
**
-** P4 may be a pointer to an sqlite3_vtab structure. If so, call the
+** P4 may be a pointer to an sqlite3_vtab structure. If so, call the
** xBegin method for that table.
**
** Also, whether or not P4 is set, check that this is not being called from
/* Opcode: VColumn P1 P2 P3 * *
**
** Store the value of the P2-th column of
-** the row of the virtual-table that the
+** the row of the virtual-table that the
** P1 cursor is pointing to into register P3.
*/
case OP_VColumn: {
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
** This opcode invokes the corresponding xUpdate method. P2 values
-** are contiguous memory cells starting at P3 to pass to the xUpdate
-** invocation. The value in register (P3+P2-1) corresponds to the
+** are contiguous memory cells starting at P3 to pass to the xUpdate
+** invocation. The value in register (P3+P2-1) corresponds to the
** p2th element of the argv array passed to xUpdate.
**
** The xUpdate method will do a DELETE or an INSERT or both.
** The argv[0] element (which corresponds to memory cell P3)
-** is the rowid of a row to delete. If argv[0] is NULL then no
-** deletion occurs. The argv[1] element is the rowid of the new
-** row. This can be NULL to have the virtual table select the new
-** rowid for itself. The subsequent elements in the array are
+** is the rowid of a row to delete. If argv[0] is NULL then no
+** deletion occurs. The argv[1] element is the rowid of the new
+** row. This can be NULL to have the virtual table select the new
+** rowid for itself. The subsequent elements in the array are
** the values of columns in the new row.
**
** If P2==1 then no insert is performed. argv[0] is the rowid of
** a row to delete.
**
** P1 is a boolean flag. If it is set to true and the xUpdate call
-** is successful, then the value returned by sqlite3_last_insert_rowid()
+** is successful, then the value returned by sqlite3_last_insert_rowid()
** is set to the value of the rowid for the row just inserted.
*/
case OP_VUpdate: {
assert( rc );
p->rc = rc;
testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(rc, "statement aborts at %d: [%s] %s",
+ sqlite3_log(rc, "statement aborts at %d: [%s] %s",
pc, p->zSql, p->zErrMsg);
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
** sqlite3DbFree().
**
** If an error does occur, then the b-tree cursor is closed. All subsequent
-** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will
+** calls to sqlite3_blob_read(), blob_write() or blob_reopen() will
** immediately return SQLITE_ABORT.
*/
static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
char *zErr = 0; /* Error message */
Vdbe *v = (Vdbe *)p->pStmt;
- /* Set the value of the SQL statements only variable to integer iRow.
- ** This is done directly instead of using sqlite3_bind_int64() to avoid
+ /* Set the value of the SQL statements only variable to integer iRow.
+ ** This is done directly instead of using sqlite3_bind_int64() to avoid
** triggering asserts related to mutexes.
*/
assert( v->aVar[0].flags&MEM_Int );
int nAttempt = 0;
int iCol; /* Index of zColumn in row-record */
- /* This VDBE program seeks a btree cursor to the identified
+ /* This VDBE program seeks a btree cursor to the identified
** db/table/row entry. The reason for using a vdbe program instead
** of writing code to use the b-tree layer directly is that the
** vdbe program will take advantage of the various transaction,
**
** After seeking the cursor, the vdbe executes an OP_ResultRow.
** Code external to the Vdbe then "borrows" the b-tree cursor and
- ** uses it to implement the blob_read(), blob_write() and
+ ** uses it to implement the blob_read(), blob_write() and
** blob_bytes() functions.
**
** The sqlite3_blob_close() function finalizes the vdbe program,
- ** which closes the b-tree cursor and (possibly) commits the
+ ** which closes the b-tree cursor and (possibly) commits the
** transaction.
*/
static const VdbeOpList openBlob[] = {
}
/* If the value is being opened for writing, check that the
- ** column is not indexed, and that it is not part of a foreign key.
+ ** column is not indexed, and that it is not part of a foreign key.
** It is against the rules to open a column to which either of these
** descriptions applies for writing. */
if( flags ){
if( db->flags&SQLITE_ForeignKeys ){
/* Check that the column is not part of an FK child key definition. It
** is not necessary to check if it is part of a parent key, as parent
- ** key columns must be indexed. The check below will pick up this
+ ** key columns must be indexed. The check below will pick up this
** case. */
FKey *pFKey;
for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration);
/* Make sure a mutex is held on the table to be accessed */
- sqlite3VdbeUsesBtree(v, iDb);
+ sqlite3VdbeUsesBtree(v, iDb);
/* Configure the OP_TableLock instruction */
#ifdef SQLITE_OMIT_SHARED_CACHE
sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
#endif
- /* Remove either the OP_OpenWrite or OpenRead. Set the P2
+ /* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum. */
sqlite3VdbeChangeToNoop(v, 4 - flags);
sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
** think that the table has one more column than it really
** does. An OP_Column to retrieve this imaginary column will
** always return an SQL NULL. This is useful because it means
- ** we can invoke OP_Column to fill in the vdbe cursors type
+ ** we can invoke OP_Column to fill in the vdbe cursors type
** and offset cache without causing any IO.
*/
sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
sqlite3VdbeMakeReady(v, pParse);
}
}
-
+
pBlob->flags = flags;
pBlob->iCol = iCol;
pBlob->db = db;
** Perform a read or write operation on a blob
*/
static int blobReadWrite(
- sqlite3_blob *pBlob,
- void *z,
- int n,
- int iOffset,
+ sqlite3_blob *pBlob,
+ void *z,
+ int n,
+ int iOffset,
int (*xCall)(BtCursor*, u32, u32, void*)
){
int rc;
**
** If an error occurs, or if the specified row does not exist or does not
** contain a blob or text value, then an error code is returned and the
-** database handle error code and message set. If this happens, then all
-** subsequent calls to sqlite3_blob_xxx() functions (except blob_close())
+** database handle error code and message set. If this happens, then all
+** subsequent calls to sqlite3_blob_xxx() functions (except blob_close())
** immediately return SQLITE_ABORT.
*/
SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
** the same as the cache-size allowed for temporary databases. In order
** to allow the caller to extract keys from the sorter in sorted order,
** all PMAs currently stored on disk must be merged together. This comment
-** describes the data structure used to do so. The structure supports
-** merging any number of arrays in a single pass with no redundant comparison
+** describes the data structure used to do so. The structure supports
+** merging any number of arrays in a single pass with no redundant comparison
** operations.
**
** The aIter[] array contains an iterator for each of the PMAs being merged.
-** An aIter[] iterator either points to a valid key or else is at EOF. For
-** the purposes of the paragraphs below, we assume that the array is actually
-** N elements in size, where N is the smallest power of 2 greater to or equal
-** to the number of iterators being merged. The extra aIter[] elements are
+** An aIter[] iterator either points to a valid key or else is at EOF. For
+** the purposes of the paragraphs below, we assume that the array is actually
+** N elements in size, where N is the smallest power of 2 greater to or equal
+** to the number of iterators being merged. The extra aIter[] elements are
** treated as if they are empty (always at EOF).
**
** The aTree[] array is also N elements in size. The value of N is stored in
** the VdbeSorter.nTree variable.
**
** The final (N/2) elements of aTree[] contain the results of comparing
-** pairs of iterator keys together. Element i contains the result of
+** pairs of iterator keys together. Element i contains the result of
** comparing aIter[2*i-N] and aIter[2*i-N+1]. Whichever key is smaller, the
-** aTree element is set to the index of it.
+** aTree element is set to the index of it.
**
** For the purposes of this comparison, EOF is considered greater than any
** other key value. If the keys are equal (only possible with two EOF
** values), it doesn't matter which index is stored.
**
-** The (N/4) elements of aTree[] that preceed the final (N/2) described
+** The (N/4) elements of aTree[] that preceed the final (N/2) described
** above contains the index of the smallest of each block of 4 iterators.
-** And so on. So that aTree[1] contains the index of the iterator that
+** And so on. So that aTree[1] contains the index of the iterator that
** currently points to the smallest key value. aTree[0] is unused.
**
** Example:
**
** aTree[] = { X, 5 0, 5 0, 3, 5, 6 }
**
-** The current element is "Apple" (the value of the key indicated by
+** The current element is "Apple" (the value of the key indicated by
** iterator 5). When the Next() operation is invoked, iterator 5 will
** be advanced to the next key in its segment. Say the next key is
** "Eggplant":
};
/*
-** The following type is an iterator for a PMA. It caches the current key in
+** The following type is an iterator for a PMA. It caches the current key in
** variables nKey/aKey. If the iterator is at EOF, pFile==0.
*/
struct VdbeSorterIter {
/*
** A structure to store a single record. All in-memory records are connected
-** together into a linked list headed at VdbeSorter.pRecord using the
+** together into a linked list headed at VdbeSorter.pRecord using the
** SorterRecord.pNext pointer.
*/
struct SorterRecord {
int nAvail; /* Bytes of data available in buffer */
assert( p->aBuffer );
- /* If there is no more data to be read from the buffer, read the next
+ /* If there is no more data to be read from the buffer, read the next
** p->nBuffer bytes of data from the file into it. Or, if there are less
** than p->nBuffer bytes remaining in the PMA, read all remaining data. */
iBuf = p->iReadOff % p->nBuffer;
assert( rc!=SQLITE_IOERR_SHORT_READ );
if( rc!=SQLITE_OK ) return rc;
}
- nAvail = p->nBuffer - iBuf;
+ nAvail = p->nBuffer - iBuf;
if( nByte<=nAvail ){
/* The requested data is available in the in-memory buffer. In this
- ** case there is no need to make a copy of the data, just return a
+ ** case there is no need to make a copy of the data, just return a
** pointer into the buffer to the caller. */
*ppOut = &p->aBuffer[iBuf];
p->iReadOff += nByte;
/*
** Initialize iterator pIter to scan through the PMA stored in file pFile
-** starting at offset iStart and ending at offset iEof-1. This function
-** leaves the iterator pointing to the first key in the PMA (or EOF if the
+** starting at offset iStart and ending at offset iEof-1. This function
+** leaves the iterator pointing to the first key in the PMA (or EOF if the
** PMA is empty).
*/
static int vdbeSorterIterInit(
/*
-** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2,
+** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2,
** size nKey2 bytes). Argument pKeyInfo supplies the collation functions
** used by the comparison. If an error occurs, return an SQLite error code.
** Otherwise, return SQLITE_OK and set *pRes to a negative, zero or positive
}
/*
-** This function is called to compare two iterator keys when merging
-** multiple b-tree segments. Parameter iOut is the index of the aTree[]
+** This function is called to compare two iterator keys when merging
+** multiple b-tree segments. Parameter iOut is the index of the aTree[]
** value to recalculate.
*/
static int vdbeSorterDoCompare(const VdbeCursor *pCsr, int iOut){
if( pSorter==0 ){
return SQLITE_NOMEM;
}
-
+
pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pCsr->pKeyInfo, 0, 0, &d);
if( pSorter->pUnpacked==0 ) return SQLITE_NOMEM;
assert( pSorter->pUnpacked==(UnpackedRecord *)d );
memcpy(&p->aBuffer[p->iBufEnd], &pData[nData-nRem], nCopy);
p->iBufEnd += nCopy;
if( p->iBufEnd==p->nBuffer ){
- p->eFWErr = sqlite3OsWrite(p->pFile,
- &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
+ p->eFWErr = sqlite3OsWrite(p->pFile,
+ &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
p->iWriteOff + p->iBufStart
);
p->iBufStart = p->iBufEnd = 0;
/*
** Flush any buffered data to disk and clean up the file-writer object.
** The results of using the file-writer after this call are undefined.
-** Return SQLITE_OK if flushing the buffered data succeeds or is not
+** Return SQLITE_OK if flushing the buffered data succeeds or is not
** required. Otherwise, return an SQLite error code.
**
** Before returning, set *piEof to the offset immediately following the
static int fileWriterFinish(sqlite3 *db, FileWriter *p, i64 *piEof){
int rc;
if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){
- p->eFWErr = sqlite3OsWrite(p->pFile,
- &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
+ p->eFWErr = sqlite3OsWrite(p->pFile,
+ &p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
p->iWriteOff + p->iBufStart
);
}
}
/*
-** Write value iVal encoded as a varint to the file-write object. Return
+** Write value iVal encoded as a varint to the file-write object. Return
** SQLITE_OK if successful, or an SQLite error code if an error occurs.
*/
static void fileWriterWriteVarint(FileWriter *p, u64 iVal){
- int nByte;
+ int nByte;
u8 aByte[10];
nByte = sqlite3PutVarint(aByte, iVal);
fileWriterWrite(p, aByte, nByte);
** * A varint. This varint contains the total number of bytes of content
** in the PMA (not including the varint itself).
**
-** * One or more records packed end-to-end in order of ascending keys.
-** Each record consists of a varint followed by a blob of data (the
+** * One or more records packed end-to-end in order of ascending keys.
+** Each record consists of a varint followed by a blob of data (the
** key). The varint is the number of bytes in the blob of data.
*/
static int vdbeSorterListToPMA(sqlite3 *db, const VdbeCursor *pCsr){
/* See if the contents of the sorter should now be written out. They
** are written out when either of the following are true:
**
- ** * The total memory allocated for the in-memory list is greater
+ ** * The total memory allocated for the in-memory list is greater
** than (page-size * cache-size), or
**
- ** * The total memory allocated for the in-memory list is greater
+ ** * The total memory allocated for the in-memory list is greater
** than (page-size * 10) and sqlite3HeapNearlyFull() returns true.
*/
if( rc==SQLITE_OK && pSorter->mxPmaSize>0 && (
}
/*
-** Helper function for sqlite3VdbeSorterRewind().
+** Helper function for sqlite3VdbeSorterRewind().
*/
static int vdbeSorterInitMerge(
sqlite3 *db, /* Database handle */
do {
int iNew; /* Index of new, merged, PMA */
- for(iNew=0;
- rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNT<pSorter->nPMA;
+ for(iNew=0;
+ rc==SQLITE_OK && iNew*SORTER_MAX_MERGE_COUNT<pSorter->nPMA;
iNew++
){
int rc2; /* Return code from fileWriterFinish() */
}
/*
-** Return a pointer to a buffer owned by the sorter that contains the
+** Return a pointer to a buffer owned by the sorter that contains the
** current key.
*/
static void *vdbeSorterRowkey(
** be used to service read() and write() requests. The actual file
** on disk is not created or populated until either:
**
-** 1) The in-memory representation grows too large for the allocated
+** 1) The in-memory representation grows too large for the allocated
** buffer, or
** 2) The sqlite3JournalCreate() function is called.
*/
typedef struct JournalFile JournalFile;
/*
-** If it does not already exists, create and populate the on-disk file
+** If it does not already exists, create and populate the on-disk file
** for JournalFile p.
*/
static int createFile(JournalFile *p){
}
if( rc!=SQLITE_OK ){
/* If an error occurred while writing to the file, close it before
- ** returning. This way, SQLite uses the in-memory journal data to
+ ** returning. This way, SQLite uses the in-memory journal data to
** roll back changes made to the internal page-cache before this
** function was called. */
sqlite3OsClose(pReal);
0 /* xShmUnmap */
};
-/*
+/*
** Open a journal file.
*/
SQLITE_PRIVATE int sqlite3JournalOpen(
return (p->pMethods!=&JournalFileMethods || ((JournalFile *)p)->pReal!=0);
}
-/*
+/*
** Return the number of bytes required to store a JournalFile that uses vfs
** pVfs to create the underlying on-disk files.
*/
if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
sqlite3_int64 iOff = 0;
- for(pChunk=p->pFirst;
+ for(pChunk=p->pFirst;
ALWAYS(pChunk) && (iOff+JOURNAL_CHUNKSIZE)<=iOfst;
pChunk=pChunk->pNext
){
0 /* xUnfetch */
};
-/*
+/*
** Open a journal file.
*/
SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){
}
/*
-** Return true if the file-handle passed as an argument is
-** an in-memory journal
+** Return true if the file-handle passed as an argument is
+** an in-memory journal
*/
SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *pJfd){
return pJfd->pMethods==&MemJournalMethods;
}
-/*
+/*
** Return the number of bytes required to store a MemJournal file descriptor.
*/
SQLITE_PRIVATE int sqlite3MemJournalSize(void){
** Walk the parse trees associated with all subqueries in the
** FROM clause of SELECT statement p. Do not invoke the select
** callback on p, but do invoke it on each FROM clause subquery
-** and on any subqueries further down in the tree. Return
+** and on any subqueries further down in the tree. Return
** WRC_Abort or WRC_Continue;
*/
SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
}
}
return WRC_Continue;
-}
+}
/*
** Call sqlite3WalkExpr() for every expression in Select statement p.
**
** The reason for suppressing the TK_AS term when the expression is a simple
** column reference is so that the column reference will be recognized as
-** usable by indices within the WHERE clause processing logic.
+** usable by indices within the WHERE clause processing logic.
**
** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means
** that in a GROUP BY clause, the expression is evaluated twice. Hence:
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
- /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
+ /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
** prevents ExprDelete() from deleting the Expr structure itself,
** allowing it to be repopulated by the memcpy() on the following line.
** The pExpr->u.zToken might point into memory that will be freed by the
/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
-** that name in the set of source tables in pSrcList and make the pExpr
+** that name in the set of source tables in pSrcList and make the pExpr
** expression node refer back to that source column. The following changes
** are made to pExpr:
**
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
Table *pTab;
Column *pCol;
-
+
pTab = pItem->pTab;
assert( pTab!=0 && pTab->zName!=0 );
assert( pTab->nCol>0 );
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
/* If there has been exactly one prior match and this match
- ** is for the right-hand table of a NATURAL JOIN or is in a
+ ** is for the right-hand table of a NATURAL JOIN or is in a
** USING clause, then skip this match.
*/
if( cnt==1 ){
} /* if( pSrcList ) */
#ifndef SQLITE_OMIT_TRIGGER
- /* If we have not already resolved the name, then maybe
+ /* If we have not already resolved the name, then maybe
** it is a new.* or old.* trigger argument reference
*/
if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){
pTab = pParse->pTriggerTab;
}
- if( pTab ){
+ if( pTab ){
int iCol;
pSchema = pTab->pSchema;
cntTab++;
assert( zTab==0 && zDb==0 );
goto lookupname_end;
}
- }
+ }
}
/* Advance to the next name context. The loop will exit when either
SrcList *pSrcList = pNC->pSrcList;
struct SrcList_item *pItem;
assert( pSrcList && pSrcList->nSrc==1 );
- pItem = pSrcList->a;
+ pItem = pSrcList->a;
pExpr->op = TK_COLUMN;
pExpr->pTab = pItem->pTab;
pExpr->iTable = pItem->iCursor;
case TK_ID: {
return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);
}
-
+
/* A table name and column name: ID.ID
** Or a database, table and column: ID.ID.ID
*/
pNC->ncFlags |= NC_AllowAgg;
}
/* FIX ME: Compute pExpr->affinity based on the expected return
- ** type of the function
+ ** type of the function
*/
return WRC_Prune;
}
int i, /* The index (1-based) of the term out of range */
int mx /* Largest permissible value of i */
){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"%r %s BY term out of range - should be "
"between 1 and %d", i, zType, mx);
}
ExprList *pGroupBy; /* The GROUP BY clause */
Select *pLeftmost; /* Left-most of SELECT of a compound */
sqlite3 *db; /* Database connection */
-
+
assert( p!=0 );
if( p->selFlags & SF_Resolved ){
sqlite3ResolveExprNames(&sNC, p->pOffset) ){
return WRC_Abort;
}
-
+
/* Recursively resolve names in all subqueries
*/
for(i=0; i<p->pSrc->nSrc; i++){
pItem->isCorrelated = (nRef!=0);
}
}
-
+
/* Set up the local name-context to pass to sqlite3ResolveExprNames() to
** resolve the result-set expression list.
*/
sNC.ncFlags = NC_AllowAgg;
sNC.pSrcList = p->pSrc;
sNC.pNext = pOuterNC;
-
+
/* Resolve names in the result set. */
pEList = p->pEList;
assert( pEList!=0 );
return WRC_Abort;
}
}
-
- /* If there are no aggregate functions in the result-set, and no GROUP BY
+
+ /* If there are no aggregate functions in the result-set, and no GROUP BY
** expression, do not allow aggregates in any of the other expressions.
*/
assert( (p->selFlags & SF_Aggregate)==0 );
}else{
sNC.ncFlags &= ~NC_AllowAgg;
}
-
+
/* If a HAVING clause is present, then there must be a GROUP BY clause.
*/
if( p->pHaving && !pGroupBy ){
sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
return WRC_Abort;
}
-
+
/* Add the expression list to the name-context before parsing the
** other expressions in the SELECT statement. This is so that
** expressions in the WHERE clause (etc.) can refer to expressions by
sNC.ncFlags &= ~NC_AsMaybe;
/* The ORDER BY and GROUP BY clauses may not refer to terms in
- ** outer queries
+ ** outer queries
*/
sNC.pNext = 0;
sNC.ncFlags |= NC_AllowAgg;
if( db->mallocFailed ){
return WRC_Abort;
}
-
- /* Resolve the GROUP BY clause. At the same time, make sure
+
+ /* Resolve the GROUP BY clause. At the same time, make sure
** the GROUP BY clause does not contain aggregate functions.
*/
if( pGroupBy ){
struct ExprList_item *pItem;
-
+
if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){
return WRC_Abort;
}
** checking on function usage and set a flag if any aggregate functions
** are seen.
**
-** To resolve table columns references we look for nodes (or subtrees) of the
+** To resolve table columns references we look for nodes (or subtrees) of the
** form X.Y.Z or Y.Z or just Z where
**
** X: The name of a database. Ex: "main" or "temp" or
**
** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
**
-** Function calls are checked to make sure that the function is
+** Function calls are checked to make sure that the function is
** defined and that the correct number of arguments are specified.
** If the function is an aggregate function, then the NC_HasAgg flag is
** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
** An error message is left in pParse if anything is amiss. The number
** if errors is returned.
*/
-SQLITE_PRIVATE int sqlite3ResolveExprNames(
+SQLITE_PRIVATE int sqlite3ResolveExprNames(
NameContext *pNC, /* Namespace to resolve expressions in. */
Expr *pExpr /* The expression to be analyzed. */
){
** Return the 'affinity' of the expression pExpr if any.
**
** If pExpr is a column, a reference to a column via an 'AS' alias,
-** or a sub-select with a column as the return value, then the
+** or a sub-select with a column as the return value, then the
** affinity of that column is returned. Otherwise, 0x00 is returned,
** indicating no affinity for the expression.
**
return sqlite3AffinityType(pExpr->u.zToken);
}
#endif
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
&& pExpr->pTab!=0
){
/* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally
break;
}
}
- if( sqlite3CheckCollSeq(pParse, pColl) ){
+ if( sqlite3CheckCollSeq(pParse, pColl) ){
pColl = 0;
}
return pColl;
** it is not considered.
*/
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(
- Parse *pParse,
- Expr *pLeft,
+ Parse *pParse,
+ Expr *pLeft,
Expr *pRight
){
CollSeq *pColl;
int rc = SQLITE_OK;
int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH];
if( nHeight>mxHeight ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"Expression tree is too large (maximum depth %d)", mxHeight
);
rc = SQLITE_ERROR;
}
/*
-** Set the Expr.nHeight variable in the structure passed as an
-** argument. An expression with no children, Expr.pList or
+** Set the Expr.nHeight variable in the structure passed as an
+** argument. An expression with no children, Expr.pList or
** Expr.pSelect member has a height of 1. Any other expression
-** has a height equal to the maximum height of any other
+** has a height equal to the maximum height of any other
** referenced Expr plus one.
*/
static void exprSetHeight(Expr *p){
assert( pToken->z!=0 || pToken->n==0 );
if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n);
pNew->u.zToken[pToken->n] = 0;
- if( dequote && nExtra>=3
+ if( dequote && nExtra>=3
&& ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){
sqlite3Dequote(pNew->u.zToken);
if( c=='"' ) pNew->flags |= EP_DblQuoted;
}
#if SQLITE_MAX_EXPR_DEPTH>0
pNew->nHeight = 1;
-#endif
+#endif
}
return pNew;
}
/*
** Return 1 if an expression must be FALSE in all cases and 0 if the
** expression might be true. This is an optimization. If is OK to
-** return 0 here even if the expression really is always false (a
+** return 0 here even if the expression really is always false (a
** false negative). But it is a bug to return 1 if the expression
** might be true in some rare circumstances (a false positive.)
**
/*
** Assign a variable number to an expression that encodes a wildcard
-** in the original SQL statement.
+** in the original SQL statement.
**
** Wildcards consisting of a single "?" are assigned the next sequential
** variable number.
pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
}
}
- }
+ }
if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
sqlite3ErrorMsg(pParse, "too many SQL variables");
}
}
/*
-** Return the number of bytes allocated for the expression structure
+** Return the number of bytes allocated for the expression structure
** passed as the first argument. This is always one of EXPR_FULLSIZE,
** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
*/
** to store a copy of an expression or expression tree. They differ in
** how much of the tree is measured.
**
-** dupedExprStructSize() Size of only the Expr structure
+** dupedExprStructSize() Size of only the Expr structure
** dupedExprNodeSize() Size of Expr + space for token
** dupedExprSize() Expr + token + subtree components
**
***************************************************************************
**
-** The dupedExprStructSize() function returns two values OR-ed together:
-** (1) the space required for a copy of the Expr structure only and
+** The dupedExprStructSize() function returns two values OR-ed together:
+** (1) the space required for a copy of the Expr structure only and
** (2) the EP_xxx flags that indicate what the structure size should be.
** The return values is always one of:
**
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
- assert( !ExprHasProperty(p, EP_FromJoin) );
+ assert( !ExprHasProperty(p, EP_FromJoin) );
assert( (p->flags2 & EP2_MallocedToken)==0 );
assert( (p->flags2 & EP2_Irreducible)==0 );
if( p->pLeft || p->pRight || p->x.pList ){
}
/*
-** This function returns the space in bytes required to store the copy
+** This function returns the space in bytes required to store the copy
** of the Expr structure and a copy of the Expr.u.zToken string (if that
** string is defined.)
*/
}
/*
-** Return the number of bytes required to create a duplicate of the
+** Return the number of bytes required to create a duplicate of the
** expression passed as the first argument. The second argument is a
** mask containing EXPRDUP_XXX flags.
**
** The value returned includes space to create a copy of the Expr struct
** itself and the buffer referred to by Expr.u.zToken, if any.
**
-** If the EXPRDUP_REDUCE flag is set, then the return value includes
-** space to duplicate all Expr nodes in the tree formed by Expr.pLeft
-** and Expr.pRight variables (but not for any structures pointed to or
+** If the EXPRDUP_REDUCE flag is set, then the return value includes
+** space to duplicate all Expr nodes in the tree formed by Expr.pLeft
+** and Expr.pRight variables (but not for any structures pointed to or
** descended from the Expr.x.pList or Expr.x.pSelect variables).
*/
static int dupedExprSize(Expr *p, int flags){
}
/*
-** This function is similar to sqlite3ExprDup(), except that if pzBuffer
-** is not NULL then *pzBuffer is assumed to point to a buffer large enough
+** This function is similar to sqlite3ExprDup(), except that if pzBuffer
+** is not NULL then *pzBuffer is assumed to point to a buffer large enough
** to store the copy of expression p, the copies of p->u.zToken
** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
** if any. Before returning, *pzBuffer is set to the first byte passed the
** without effecting the originals.
**
** The expression list, ID, and source lists return by sqlite3ExprListDup(),
-** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded
+** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded
** by subsequent calls to sqlite*ListAppend() routines.
**
** Any tables that the SrcList might point to are not duplicated.
if( pItem==0 ){
sqlite3DbFree(db, pNew);
return 0;
- }
+ }
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
Expr *pOldExpr = pOldItem->pExpr;
/*
** If cursors, triggers, views and subqueries are all omitted from
-** the build, then none of the following routines, except for
+** the build, then none of the following routines, except for
** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes
** called with a NULL argument.
*/
}
return pList;
-no_mem:
+no_mem:
/* Avoid leaking memory if malloc has failed. */
sqlite3ExprDelete(db, pExpr);
sqlite3ExprListDelete(db, pList);
** Return FALSE if there is no chance that the expression can be NULL.
**
** If the expression might be NULL or if the expression is too complex
-** to tell return TRUE.
+** to tell return TRUE.
**
** This routine is used as an optimization, to skip OP_IsNull opcodes
** when we know that a value cannot be NULL. Hence, a false positive
/*
** Generate an OP_IsNull instruction that tests register iReg and jumps
-** to location iDest if the value in iReg is NULL. The value in iReg
+** to location iDest if the value in iReg is NULL. The value in iReg
** was computed by pExpr. If we can look at pExpr at compile-time and
** determine that it can never generate a NULL, then the OP_IsNull operation
** can be omitted.
#endif /* SQLITE_OMIT_SUBQUERY */
/*
-** Code an OP_Once instruction and allocate space for its flag. Return the
+** Code an OP_Once instruction and allocate space for its flag. Return the
** address of the new instruction.
*/
SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
** If the RHS of the IN operator is a list or a more complex subquery, then
** an ephemeral table might need to be generated from the RHS and then
** pX->iTable made to point to the ephermeral table instead of an
-** existing table.
+** existing table.
**
** If the prNotFound parameter is 0, then the b-tree will be used to iterate
** through the set members, skipping any duplicates. In this case an
** to be unique - either because it is an INTEGER PRIMARY KEY or it
** has a UNIQUE constraint or UNIQUE index.
**
-** If the prNotFound parameter is not 0, then the b-tree will be used
-** for fast set membership tests. In this case an epheremal table must
-** be used unless <column> is an INTEGER PRIMARY KEY or an index can
+** If the prNotFound parameter is not 0, then the b-tree will be used
+** for fast set membership tests. In this case an epheremal table must
+** be used unless <column> is an INTEGER PRIMARY KEY or an index can
** be found with <column> as its left-most column.
**
** When the b-tree is being used for membership tests, the calling function
-** needs to know whether or not the structure contains an SQL NULL
+** needs to know whether or not the structure contains an SQL NULL
** value in order to correctly evaluate expressions like "X IN (Y, Z)".
** If there is any chance that the (...) might contain a NULL value at
** runtime, then a register is allocated and the register number written
assert( pX->op==TK_IN );
/* Check to see if an existing table or index can be used to
- ** satisfy the query. This is preferable to generating a new
+ ** satisfy the query. This is preferable to generating a new
** ephemeral table.
*/
p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
pTab = p->pSrc->a[0].pTab;
pExpr = p->pEList->a[0].pExpr;
iCol = pExpr->iColumn;
-
+
/* Code an OP_VerifyCookie and OP_TableLock for <table>. */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3CodeVerifySchema(pParse, iDb);
** to this collation sequence. */
CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr);
- /* Check that the affinity that will be used to perform the
+ /* Check that the affinity that will be used to perform the
** comparison is the same as the affinity of the column. If
** it is not, it is not possible to use any index.
*/
){
int iAddr;
char *pKey;
-
+
pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
iAddr = sqlite3CodeOnce(pParse);
-
+
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
pKey,P4_KEYINFO_HANDOFF);
VdbeComment((v, "%s", pIdx->zName));
affinity = sqlite3ExprAffinity(pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
- ** expression it is handled the same way. An ephemeral table is
+ ** expression it is handled the same way. An ephemeral table is
** filled with single-field index keys representing the results
** from the SELECT or the <exprlist>.
**
return 0;
}
pEList = pExpr->x.pSelect->pEList;
- if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){
+ if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){
keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
pEList->a[0].pExpr);
}
** if the LHS is NULL or if the LHS is not contained within the RHS and the
** RHS contains one or more NULL values.
**
-** This routine generates code will jump to destIfFalse if the LHS is not
+** This routine generates code will jump to destIfFalse if the LHS is not
** contained within the RHS. If due to NULLs we cannot determine if the LHS
** is contained in the RHS then jump to destIfNull. If the LHS is contained
** within the RHS then fall through.
*/
sqlite3VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);
- /* If the set membership test fails, then the result of the
+ /* If the set membership test fails, then the result of the
** "x IN (...)" expression must be either 0 or NULL. If the set
- ** contains no NULL values, then the result is 0. If the set
+ ** contains no NULL values, then the result is 0. If the set
** contains one or more NULL values, then the result of the
** expression is also NULL.
*/
sqlite3VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull);
sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse);
- /* The OP_Found at the top of this branch jumps here when true,
+ /* The OP_Found at the top of this branch jumps here when true,
** causing the overall IN expression evaluation to fall through.
*/
sqlite3VdbeJumpHere(v, j1);
** Generate an instruction that will put the floating point
** value described by z[0..n-1] into register iMem.
**
-** The z[] string will probably not be zero-terminated. But the
+** The z[] string will probably not be zero-terminated. But the
** z[n] character is guaranteed to be something that does not look
** like the continuation of the number.
*/
sqlite3ExprCachePinRegister(pParse, p->iReg);
return p->iReg;
}
- }
+ }
assert( v!=0 );
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
if( p5 ){
sqlite3VdbeChangeP5(v, p5);
- }else{
+ }else{
sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
}
return iReg;
assert( pExpr->u.zToken[0]!=0 );
sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
if( pExpr->u.zToken[1]!=0 ){
- assert( pExpr->u.zToken[0]=='?'
+ assert( pExpr->u.zToken[0]=='?'
|| strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 );
sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC);
}
case TK_BITOR:
case TK_SLASH:
case TK_LSHIFT:
- case TK_RSHIFT:
+ case TK_RSHIFT:
case TK_CONCAT: {
assert( TK_AND==OP_And );
assert( TK_OR==OP_Or );
** see if it is a column in a virtual table. This is done because
** the left operand of infix functions (the operand we want to
** control overloading) ends up as the second argument to the
- ** function. The expression "A glob B" is equivalent to
+ ** function. The expression "A glob B" is equivalent to
** "glob(B,A). We want to use the A in "A glob B" to test
** for function overloading. But we use the B term in "glob(B,A)".
*/
}
}
if( pDef->flags & SQLITE_FUNC_NEEDCOLL ){
- if( !pColl ) pColl = db->pDfltColl;
+ if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
sqlite3ReleaseTempReg(pParse, r4);
break;
}
- case TK_COLLATE:
+ case TK_COLLATE:
case TK_UPLUS: {
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
break;
**
** The expression is implemented using an OP_Param opcode. The p1
** parameter is set to 0 for an old.rowid reference, or to (i+1)
- ** to reference another column of the old.* pseudo-table, where
+ ** to reference another column of the old.* pseudo-table, where
** i is the index of the column. For a new.rowid reference, p1 is
** set to (n+1), where n is the number of columns in each pseudo-table.
** For a reference to any other column in the new.* pseudo-table, p1
**
** p1==0 -> old.rowid p1==3 -> new.rowid
** p1==1 -> old.a p1==4 -> new.a
- ** p1==2 -> old.b p1==5 -> new.b
+ ** p1==2 -> old.b p1==5 -> new.b
*/
Table *pTab = pExpr->pTab;
int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
#ifndef SQLITE_OMIT_FLOATING_POINT
/* If the column has REAL affinity, it may currently be stored as an
** integer. Use OP_RealAffinity to make sure it is really real. */
- if( pExpr->iColumn>=0
+ if( pExpr->iColumn>=0
&& pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
){
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
- assert( db->mallocFailed || pParse->nErr>0
+ assert( db->mallocFailed || pParse->nErr>0
|| pParse->iCacheLevel==iCacheLevel );
sqlite3VdbeResolveLabel(v, endLabel);
break;
}
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
- assert( pExpr->affinity==OE_Rollback
+ assert( pExpr->affinity==OE_Rollback
|| pExpr->affinity==OE_Abort
|| pExpr->affinity==OE_Fail
|| pExpr->affinity==OE_Ignore
** and modify the expression so that the next time it is evaluated,
** the result is a copy of the cache register.
**
-** This routine is used for expressions that are used multiple
+** This routine is used for expressions that are used multiple
** times. They are evaluated once and the results of the expression
** are reused.
*/
** no way for a TK_REGISTER to exist here. But it seems prudent to
** keep the ALWAYS() in case the conditions above change with future
** modifications or enhancements. */
- if( ALWAYS(pExpr->op!=TK_REGISTER) ){
+ if( ALWAYS(pExpr->op!=TK_REGISTER) ){
int iMem;
iMem = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
** is set to the column of the pseudo-table to read, or to -1 to
** read the rowid field.
*/
- sqlite3ExplainPrintf(pOut, "%s(%d)",
+ sqlite3ExplainPrintf(pOut, "%s(%d)",
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
break;
}
**
** * Any expression that evaluates to two or more opcodes.
**
-** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null,
-** or OP_Variable that does not need to be placed in a
+** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null,
+** or OP_Variable that does not need to be placed in a
** specific register.
**
** There is no point in factoring out single-instruction constant
-** expressions that need to be placed in a particular register.
+** expressions that need to be placed in a particular register.
** We could factor them out, but then we would end up adding an
** OP_SCopy instruction to move the value into the correct register
** later. We might as well just use the original instruction and
case TK_CONST_FUNC: {
/* The arguments to a function have a fixed destination.
** Mark them this way to avoid generated unneeded OP_SCopy
- ** instructions.
+ ** instructions.
*/
ExprList *pList = pExpr->x.pList;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
**
** x BETWEEN y AND z
**
-** The above is equivalent to
+** The above is equivalent to
**
** x>=y AND x<=z
**
}
}
sqlite3ReleaseTempReg(pParse, regFree1);
- sqlite3ReleaseTempReg(pParse, regFree2);
+ sqlite3ReleaseTempReg(pParse, regFree2);
}
/*
}
/*
-** Compare two ExprList objects. Return 0 if they are identical and
+** Compare two ExprList objects. Return 0 if they are identical and
** non-zero if they differ in any way.
**
** This routine might return non-zero for equivalent ExprLists. The
/*
** An instance of the following structure is used by the tree walker
-** to count references to table columns in the arguments of an
+** to count references to table columns in the arguments of an
** aggregate function, in order to implement the
** sqlite3FunctionThisSrc() routine.
*/
&i
);
return i;
-}
+}
/*
** Add a new element to the pAggInfo->aFunc[] array. Return the index of
static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
int i;
pInfo->aFunc = sqlite3ArrayAllocate(
- db,
+ db,
pInfo->aFunc,
sizeof(pInfo->aFunc[0]),
&pInfo->nFunc,
&i
);
return i;
-}
+}
/*
** This is the xExprCallback for a tree walker. It is used to
assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
if( pExpr->iTable==pItem->iCursor ){
/* If we reach this point, it means that pExpr refers to a table
- ** that is in the FROM clause of the aggregate query.
+ ** that is in the FROM clause of the aggregate query.
**
** Make an entry for the column in pAggInfo->aCol[] if there
** is not an entry there already.
}
}
if( (k>=pAggInfo->nColumn)
- && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
+ && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
){
pCol = &pAggInfo->aCol[k];
pCol->pTab = pExpr->pTab;
if( (pNC->ncFlags & NC_InAggFunc)==0
&& pWalker->walkerDepth==pExpr->op2
){
- /* Check to see if pExpr is a duplicate of another aggregate
+ /* Check to see if pExpr is a duplicate of another aggregate
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
/*
-** This function is used by SQL generated to implement the
+** This function is used by SQL generated to implement the
** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
-** CREATE INDEX command. The second is a table name. The table name in
+** CREATE INDEX command. The second is a table name. The table name in
** the CREATE TABLE or CREATE INDEX statement is replaced with the third
** argument and the result returned. Examples:
**
UNUSED_PARAMETER(NotUsed);
- /* The principle used to locate the table name in the CREATE TABLE
+ /* The principle used to locate the table name in the CREATE TABLE
** statement is that the table name is the first non-space token that
** is immediately followed by a TK_LP or TK_USING token.
*/
assert( len>0 );
} while( token!=TK_LP && token!=TK_USING );
- zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
+ zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
zTableName, tname.z+tname.n);
sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
}
/*
** This C function implements an SQL user function that is used by SQL code
** generated by the ALTER TABLE ... RENAME command to modify the definition
-** of any foreign key constraints that use the table being renamed as the
+** of any foreign key constraints that use the table being renamed as the
** parent table. It is passed three arguments:
**
** 1) The complete text of the CREATE TABLE statement being modified,
if( zParent==0 ) break;
sqlite3Dequote(zParent);
if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){
- char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"",
+ char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"",
(zOutput?zOutput:""), z-zInput, zInput, (const char *)zNew
);
sqlite3DbFree(db, zOutput);
}
}
- zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput),
+ zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput),
sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC);
sqlite3DbFree(db, zOutput);
}
#ifndef SQLITE_OMIT_TRIGGER
/* This function is used by SQL generated to implement the
-** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
-** statement. The second is a table name. The table name in the CREATE
-** TRIGGER statement is replaced with the third argument and the result
+** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
+** statement. The second is a table name. The table name in the CREATE
+** TRIGGER statement is replaced with the third argument and the result
** returned. This is analagous to renameTableFunc() above, except for CREATE
** TRIGGER, not CREATE INDEX and CREATE TABLE.
*/
UNUSED_PARAMETER(NotUsed);
- /* The principle used to locate the table name in the CREATE TRIGGER
+ /* The principle used to locate the table name in the CREATE TRIGGER
** statement is that the table name is the first token that is immediatedly
** preceded by either TK_ON or TK_DOT and immediatedly followed by one
** of TK_WHEN, TK_BEGIN or TK_FOR.
assert( len>0 );
/* Variable 'dist' stores the number of tokens read since the most
- ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN
+ ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN
** token is read and 'dist' equals 2, the condition stated above
** to be met.
**
** Note that ON cannot be a database, table or column name, so
- ** there is no need to worry about syntax like
+ ** there is no need to worry about syntax like
** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
*/
dist++;
/* Variable tname now contains the token that is the old table-name
** in the CREATE TRIGGER statement.
*/
- zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
+ zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", ((u8*)tname.z) - zSql, zSql,
zTableName, tname.z+tname.n);
sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
}
**
** name=<constant1> OR name=<constant2> OR ...
**
-** If argument zWhere is NULL, then a pointer string containing the text
+** If argument zWhere is NULL, then a pointer string containing the text
** "name=<constant>" is returned, where <constant> is the quoted version
** of the string passed as argument zConstant. The returned buffer is
** allocated using sqlite3DbMalloc(). It is the responsibility of the
** caller to ensure that it is eventually freed.
**
-** If argument zWhere is not NULL, then the string returned is
+** If argument zWhere is not NULL, then the string returned is
** "<where> OR name=<constant>", where <where> is the contents of zWhere.
** In this case zWhere is passed to sqlite3DbFree() before returning.
-**
+**
*/
static char *whereOrName(sqlite3 *db, char *zWhere, char *zConstant){
char *zNew;
/*
** Generate the text of a WHERE expression which can be used to select all
** temporary triggers on table pTab from the sqlite_temp_master table. If
-** table pTab has no temporary triggers, or is itself stored in the
+** table pTab has no temporary triggers, or is itself stored in the
** temporary database, NULL is returned.
*/
static char *whereTempTriggers(Parse *pParse, Table *pTab){
char *zWhere = 0;
const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */
- /* If the table is not located in the temp-db (in which case NULL is
+ /* If the table is not located in the temp-db (in which case NULL is
** returned, loop through the tables list of triggers. For each trigger
- ** that is not part of the temp-db schema, add a clause to the WHERE
+ ** that is not part of the temp-db schema, add a clause to the WHERE
** expression being built up in zWhere.
*/
if( pTab->pSchema!=pTempSchema ){
** pTab from the database, including triggers and temporary triggers.
** Argument zName is the name of the table in the database schema at
** the time the generated code is executed. This can be different from
-** pTab->zName if this function is being called to code part of an
+** pTab->zName if this function is being called to code part of an
** "ALTER TABLE RENAME TO" statement.
*/
static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
#ifndef SQLITE_OMIT_TRIGGER
- /* Now, if the table is not stored in the temp database, reload any temp
- ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
+ /* Now, if the table is not stored in the temp database, reload any temp
+ ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
*/
if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
sqlite3VdbeAddParseSchemaOp(v, 1, zWhere);
}
/*
-** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
-** command.
+** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
+** command.
*/
SQLITE_PRIVATE void sqlite3AlterRenameTable(
Parse *pParse, /* Parser context. */
int iDb; /* Database that contains the table */
char *zDb; /* Name of database iDb */
Table *pTab; /* Table being renamed */
- char *zName = 0; /* NULL-terminated version of pName */
+ char *zName = 0; /* NULL-terminated version of pName */
sqlite3 *db = pParse->db; /* Database connection */
int nTabName; /* Number of UTF-8 characters in zTabName */
const char *zTabName; /* Original name of the table */
VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
int savedDbFlags; /* Saved value of db->flags */
- savedDbFlags = db->flags;
+ savedDbFlags = db->flags;
if( NEVER(db->mallocFailed) ) goto exit_rename_table;
assert( pSrc->nSrc==1 );
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
** in database iDb. If so, this is an error.
*/
if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"there is already another table or index with this name: %s", zName);
goto exit_rename_table;
}
}
#endif
- /* Begin a transaction and code the VerifyCookie for database iDb.
+ /* Begin a transaction and code the VerifyCookie for database iDb.
** Then modify the schema cookie (since the ALTER TABLE modifies the
** schema). Open a statement transaction if the table is a virtual
** table.
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
if( db->flags&SQLITE_ForeignKeys ){
- /* If foreign-key support is enabled, rewrite the CREATE TABLE
+ /* If foreign-key support is enabled, rewrite the CREATE TABLE
** statements corresponding to all child tables of foreign key constraints
** for which the renamed table is the parent table. */
if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
- sqlite3NestedParse(pParse,
+ sqlite3NestedParse(pParse,
"UPDATE \"%w\".%s SET "
"sql = sqlite_rename_parent(sql, %Q, %Q) "
"WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere);
"'sqlite_autoindex_' || %Q || substr(name,%d+18) "
"ELSE name END "
"WHERE tbl_name=%Q COLLATE nocase AND "
- "(type='table' OR type='index' OR type='trigger');",
- zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
+ "(type='table' OR type='index' OR type='trigger');",
+ zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
#ifndef SQLITE_OMIT_TRIGGER
zName,
#endif
);
#ifndef SQLITE_OMIT_AUTOINCREMENT
- /* If the sqlite_sequence table exists in this database, then update
+ /* If the sqlite_sequence table exists in this database, then update
** it with the new table name.
*/
if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
** the temp database.
*/
if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
- sqlite3NestedParse(pParse,
+ sqlite3NestedParse(pParse,
"UPDATE sqlite_temp_master SET "
"sql = sqlite_rename_trigger(sql, %Q), "
"tbl_name = %Q "
}
#endif
- /* If the default value for the new column was specified with a
+ /* If the default value for the new column was specified with a
** literal NULL, then set pDflt to 0. This simplifies checking
** for an SQL NULL default below.
*/
return;
}
if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"Cannot add a REFERENCES column with non-NULL default value");
return;
}
if( pCol->notNull && !pDflt ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"Cannot add a NOT NULL column with default value NULL");
return;
}
*zEnd-- = '\0';
}
db->flags |= SQLITE_PreferBuiltin;
- sqlite3NestedParse(pParse,
+ sqlite3NestedParse(pParse,
"UPDATE \"%w\".%s SET "
"sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
- "WHERE type = 'table' AND name = %Q",
+ "WHERE type = 'table' AND name = %Q",
zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
zTab
);
/*
** This function is called by the parser after the table-name in
-** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
+** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
** pSrc is the full-name of the table being altered.
**
** This routine makes a (partial) copy of the Table structure
** for the table being altered and sets Parse.pNewTable to point
** to it. Routines called by the parser as the column definition
-** is parsed (i.e. sqlite3AddColumn()) add the new Column data to
-** the copy. The copy of the Table structure is deleted by tokenize.c
+** is parsed (i.e. sqlite3AddColumn()) add the new Column data to
+** the copy. The copy of the Table structure is deleted by tokenize.c
** after parsing is finished.
**
** Routine sqlite3AlterFinishAddColumn() will be called to complete
** The sqlite_stat2 table is superceded by sqlite_stat3, which is only
** created and used by SQLite versions 3.7.9 and later and with
** SQLITE_ENABLE_STAT3 defined. The fucntionality of sqlite_stat3
-** is a superset of sqlite_stat2.
+** is a superset of sqlite_stat2.
**
** Format of sqlite_stat1:
**
** integer is the average number of rows in the index that have the same
** value in the first column of the index. The third integer is the average
** number of rows in the index that have the same value for the first two
-** columns. The N-th integer (for N>1) is the average number of rows in
+** columns. The N-th integer (for N>1) is the average number of rows in
** the index which have the same value for the first N-1 columns. For
** a K-column index, there will be K+1 integers in the stat column. If
** the index is unique, then the last integer will be 1.
** must be separated from the last integer by a single space. If the
** "unordered" keyword is present, then the query planner assumes that
** the index is unordered and will not use the index for a range query.
-**
+**
** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat
** column contains a single integer which is the (estimated) number of
** rows in the table identified by sqlite_stat1.tbl.
** Format for sqlite_stat3:
**
** The sqlite_stat3 is an enhancement to sqlite_stat2. A new name is
-** used to avoid compatibility problems.
+** used to avoid compatibility problems.
**
** The format of the sqlite_stat3 table is similar to the format of
** the sqlite_stat2 table. There are multiple entries for each index.
**
** If the sqlite_stat1 tables does not previously exist, it is created.
** Similarly, if the sqlite_stat3 table does not exist and the library
-** is compiled with SQLITE_ENABLE_STAT3 defined, it is created.
+** is compiled with SQLITE_ENABLE_STAT3 defined, it is created.
**
** Argument zWhere may be a pointer to a buffer containing a table name,
** or it may be a NULL pointer. If it is not NULL, then all entries in
const char *zTab = aTable[i].zName;
Table *pStat;
if( (pStat = sqlite3FindTable(db, zTab, pDb->zName))==0 ){
- /* The sqlite_stat[12] table does not exist. Create it. Note that a
- ** side-effect of the CREATE TABLE statement is to leave the rootpage
- ** of the new table in register pParse->regRoot. This is important
+ /* The sqlite_stat[12] table does not exist. Create it. Note that a
+ ** side-effect of the CREATE TABLE statement is to leave the rootpage
+ ** of the new table in register pParse->regRoot. This is important
** because the OpenWrite opcode below will be needing it. */
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
aRoot[i] = pParse->regRoot;
aCreateTbl[i] = OPFLAG_P2ISREG;
}else{
- /* The table already exists. If zWhere is not NULL, delete all entries
+ /* The table already exists. If zWhere is not NULL, delete all entries
** associated with the table zWhere. If zWhere is NULL, delete the
** entire contents of the table. */
aRoot[i] = pStat->tnum;
/*
** Implementation of the stat3_push(nEq,nLt,nDLt,rowid,P) SQL function. The
-** arguments describe a single key instance. This routine makes the
+** arguments describe a single key instance. This routine makes the
** decision about whether or not to retain this key for the sqlite_stat3
** table.
**
/* The block of memory cells initialized here is used as follows.
**
- ** iMem:
+ ** iMem:
** The total number of rows in the table.
**
- ** iMem+1 .. iMem+nCol:
- ** Number of distinct entries in index considering the
- ** left-most N columns only, where N is between 1 and nCol,
+ ** iMem+1 .. iMem+nCol:
+ ** Number of distinct entries in index considering the
+ ** left-most N columns only, where N is between 1 and nCol,
** inclusive.
**
- ** iMem+nCol+1 .. Mem+2*nCol:
+ ** iMem+nCol+1 .. Mem+2*nCol:
** Previous value of indexed columns, from left to right.
**
- ** Cells iMem through iMem+nCol are initialized to 0. The others are
+ ** Cells iMem through iMem+nCol are initialized to 0. The others are
** initialized to contain an SQL NULL.
*/
for(i=0; i<=nCol; i++){
sqlite3VdbeAddOp3(v, OP_Add, regNumEq, regNumLt, regNumLt);
sqlite3VdbeAddOp2(v, OP_AddImm, regNumDLt, 1);
sqlite3VdbeAddOp2(v, OP_Integer, 1, regNumEq);
-#endif
+#endif
}
sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1);
(char*)&stat3PushFuncdef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, 5);
sqlite3VdbeAddOp2(v, OP_Integer, -1, regLoop);
- shortJump =
+ shortJump =
sqlite3VdbeAddOp2(v, OP_AddImm, regLoop, 1);
sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regTemp1,
(char*)&stat3GetFuncdef, P4_FUNCDEF);
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regNewRowid);
sqlite3VdbeAddOp2(v, OP_Goto, 0, shortJump);
sqlite3VdbeJumpHere(v, shortJump+2);
-#endif
+#endif
/* Store the results in sqlite_stat1.
**
**
** I = (K+D-1)/D
**
- ** If K==0 then no entry is made into the sqlite_stat1 table.
+ ** If K==0 then no entry is made into the sqlite_stat1 table.
** If K>0 then it is always the case the D>0 so division by zero
** is never possible.
*/
}
sqlite3DbFree(db, z);
}
- }
+ }
}
}
/*
** This callback is invoked once for each index when reading the
-** sqlite_stat1 table.
+** sqlite_stat1 table.
**
** argv[0] = name of the table
** argv[1] = name of the index (might be NULL)
return SQLITE_OK;
}
- zSql = sqlite3MPrintf(db,
+ zSql = sqlite3MPrintf(db,
"SELECT idx,count(*) FROM %Q.sqlite_stat3"
" GROUP BY idx", zDb);
if( !zSql ){
rc = sqlite3_finalize(pStmt);
if( rc ) return rc;
- zSql = sqlite3MPrintf(db,
+ zSql = sqlite3MPrintf(db,
"SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat3", zDb);
if( !zSql ){
return SQLITE_NOMEM;
** Index.aSample[] arrays.
**
** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR
-** is returned. In this case, even if SQLITE_ENABLE_STAT3 was defined
-** during compilation and the sqlite_stat3 table is present, no data is
+** is returned. In this case, even if SQLITE_ENABLE_STAT3 was defined
+** during compilation and the sqlite_stat3 table is present, no data is
** read from it.
**
-** If SQLITE_ENABLE_STAT3 was defined during compilation and the
+** If SQLITE_ENABLE_STAT3 was defined during compilation and the
** sqlite_stat3 table is not present in the database, SQLITE_ERROR is
** returned. However, in this case, data is read from the sqlite_stat1
** table (if it is present) before returning.
}
/* Load new statistics out of the sqlite_stat1 table */
- zSql = sqlite3MPrintf(db,
+ zSql = sqlite3MPrintf(db,
"SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
if( zSql==0 ){
rc = SQLITE_NOMEM;
** * Specified database name already being used.
*/
if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
- zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d",
+ zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d",
db->aLimit[SQLITE_LIMIT_ATTACHED]
);
goto attach_error;
if( !aNew->pSchema ){
rc = SQLITE_NOMEM;
}else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
- zErrDyn = sqlite3MPrintf(db,
+ zErrDyn = sqlite3MPrintf(db,
"attached databases must use the same text encoding as main database");
rc = SQLITE_ERROR;
}
zErrDyn = sqlite3DbStrDup(db, "Invalid key value");
rc = SQLITE_ERROR;
break;
-
+
case SQLITE_TEXT:
case SQLITE_BLOB:
nKey = sqlite3_value_bytes(argv[2]);
#endif
/* If the file was opened successfully, read the schema for the new database.
- ** If this fails, or if opening the file failed, then close the file and
+ ** If this fails, or if opening the file failed, then close the file and
** remove the entry from the db->aDb[] array. i.e. put everything back the way
** we found it.
*/
}
goto attach_error;
}
-
+
return;
attach_error:
memset(&sName, 0, sizeof(NameContext));
sName.pParse = pParse;
- if(
+ if(
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
*/
sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH));
}
-
+
attach_end:
sqlite3ExprDelete(db, pFilename);
sqlite3ExprDelete(db, pDbname);
/*
** The pExpr should be a TK_COLUMN expression. The table referred to
-** is in pTabList or else it is the NEW or OLD table of a trigger.
+** is in pTabList or else it is the NEW or OLD table of a trigger.
** Check to see if it is OK to read this particular column.
**
-** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN
+** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN
** instruction into a TK_NULL. If the auth function returns SQLITE_DENY,
** then generate an error.
*/
*/
SQLITE_PRIVATE void sqlite3AuthContextPush(
Parse *pParse,
- AuthContext *pContext,
+ AuthContext *pContext,
const char *zContext
){
assert( pParse );
};
/*
-** Record the fact that we want to lock a table at run-time.
+** Record the fact that we want to lock a table at run-time.
**
** The table to be locked has root page iTab and is found in database iDb.
** A read or a write lock can be taken depending on isWritelock.
*/
static void codeTableLocks(Parse *pParse){
int i;
- Vdbe *pVdbe;
+ Vdbe *pVdbe;
pVdbe = sqlite3GetVdbe(pParse);
assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */
** vdbe program
*/
v = sqlite3GetVdbe(pParse);
- assert( !pParse->isMultiWrite
+ assert( !pParse->isMultiWrite
|| sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
if( v ){
sqlite3VdbeAddOp0(v, OP_Halt);
}
#endif
- /* Once all the cookies have been verified and transactions opened,
- ** obtain the required table-locks. This is a no-op unless the
+ /* Once all the cookies have been verified and transactions opened,
+ ** obtain the required table-locks. This is a no-op unless the
** shared-cache feature is enabled.
*/
codeTableLocks(pParse);
** sqlite3FixSrcList() for details.
*/
SQLITE_PRIVATE Table *sqlite3LocateTableItem(
- Parse *pParse,
- int isView,
+ Parse *pParse,
+ int isView,
struct SrcList_item *p
){
const char *zDb;
}
/*
-** Locate the in-memory structure that describes
+** Locate the in-memory structure that describes
** a particular index given the name of that index
** and the name of the database that contains the index.
** Return NULL if not found.
**
** This routine just deletes the data structure. It does not unlink
** the table data structure from the hash table. But it does destroy
-** memory structures of the indices and foreign keys associated with
+** memory structures of the indices and foreign keys associated with
** the table.
**
-** The db parameter is optional. It is needed if the Table object
+** The db parameter is optional. It is needed if the Table object
** contains lookaside memory. (Table objects in the schema do not use
** lookaside memory, but some ephemeral Table objects do.) Or the
** db parameter can be used with db->pnBytesFreed to measure the memory
pNext = pIndex->pNext;
assert( pIndex->pSchema==pTable->pSchema );
if( !db || db->pnBytesFreed==0 ){
- char *zName = pIndex->zName;
+ char *zName = pIndex->zName;
TESTONLY ( Index *pOld = ) sqlite3HashInsert(
&pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
);
Db *pDb;
int n = sqlite3Strlen30(zName);
for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
- if( (!OMIT_TEMPDB || i!=1 ) && n==sqlite3Strlen30(pDb->zName) &&
+ if( (!OMIT_TEMPDB || i!=1 ) && n==sqlite3Strlen30(pDb->zName) &&
0==sqlite3StrICmp(pDb->zName, zName) ){
break;
}
/*
** The token *pName contains the name of a database (either "main" or
** "temp" or the name of an attached db). This routine returns the
-** index of the named database in db->aDb[], or -1 if the named db
+** index of the named database in db->aDb[], or -1 if the named db
** does not exist.
*/
SQLITE_PRIVATE int sqlite3FindDb(sqlite3 *db, Token *pName){
** pName1 and pName2. If the table name was fully qualified, for example:
**
** CREATE TABLE xxx.yyy (...);
-**
+**
** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
** the table name is not fully qualified, i.e.:
**
** is reserved for internal use.
*/
SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){
- if( !pParse->db->init.busy && pParse->nested==0
+ if( !pParse->db->init.busy && pParse->nested==0
&& (pParse->db->flags & SQLITE_WriteSchema)==0
&& 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
** pName1 and pName2. If the table name was fully qualified, for example:
**
** CREATE TABLE xxx.yyy (...);
- **
+ **
** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
** the table name is not fully qualified, i.e.:
**
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
if( iDb<0 ) return;
if( !OMIT_TEMPDB && isTemp && pName2->n>0 && iDb!=1 ){
- /* If creating a temp table, the name may not be qualified. Unless
+ /* If creating a temp table, the name may not be qualified. Unless
** the database name is "temp" anyway. */
sqlite3ErrorMsg(pParse, "temporary table name must be unqualified");
return;
** the SQLITE_MASTER table. Note in particular that we must go ahead
** and allocate the record number for the table entry now. Before any
** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause
- ** indices to be created and the table record must come before the
+ ** indices to be created and the table record must come before the
** indices. Hence, the record number for the table must be allocated
** now.
*/
}
#endif
- /* If the file format and encoding in the database have not been set,
+ /* If the file format and encoding in the database have not been set,
** set them now.
*/
reg1 = pParse->regRowid = ++pParse->nMem;
pCol = &p->aCol[p->nCol];
memset(pCol, 0, sizeof(p->aCol[0]));
pCol->zName = z;
-
+
/* If there is no type specified, columns have the default affinity
** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
** be called next to set pCol->affinity correctly.
** Scan the column type name zType (length nType) and return the
** associated affinity type.
**
-** This routine does a case-independent search of zType for the
+** This routine does a case-independent search of zType for the
** substrings in the following table. If one of the substrings is
** found, the corresponding affinity is returned. If zType contains
-** more than one of the substrings, entries toward the top of
-** the table take priority. For example, if zType is 'BLOBINT',
+** more than one of the substrings, entries toward the top of
+** the table take priority. For example, if zType is 'BLOBINT',
** SQLITE_AFF_INTEGER is returned.
**
** Substring | Affinity
h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
zIn++;
if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
- aff = SQLITE_AFF_TEXT;
+ aff = SQLITE_AFF_TEXT;
}else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
aff = SQLITE_AFF_TEXT;
}else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
** in the sequence. Use this information to construct a string
** that contains the typename of the column and store that string
** in zType.
-*/
+*/
SQLITE_PRIVATE void sqlite3AddColumnType(Parse *pParse, Token *pType){
Table *p;
Column *pCol;
}
/*
-** Designate the PRIMARY KEY for the table. pList is a list of names
+** Designate the PRIMARY KEY for the table. pList is a list of names
** of columns that form the primary key. If pList is NULL, then the
** most recently added column of the table is the primary key.
**
int iCol = -1, i;
if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
if( pTab->tabFlags & TF_HasPrimaryKey ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"table \"%s\" has more than one primary key", pTab->zName);
goto primary_key_exit;
}
if( sqlite3LocateCollSeq(pParse, zColl) ){
Index *pIdx;
p->aCol[i].zColl = zColl;
-
+
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
** then an index may have been created on this column before the
** collation type was added. Correct this if it is the case.
}
/*
-** The first parameter is a pointer to an output buffer. The second
+** The first parameter is a pointer to an output buffer. The second
** parameter is a pointer to an integer that contains the offset at
** which to write into the output buffer. This function copies the
** nul-terminated string pointed to by the third parameter, zSignedIdent,
** to the specified offset in the buffer and updates *pIdx to refer
** to the first byte after the last byte written before returning.
-**
+**
** If the string zSignedIdent consists entirely of alpha-numeric
** characters, does not begin with a digit and is not an SQL keyword,
** then it is copied to the output buffer exactly as it is. Otherwise,
n += identLength(pCol->zName) + 5;
}
n += identLength(p->zName);
- if( n<50 ){
+ if( n<50 ){
zSep = "";
zSep2 = ",";
zEnd = ")";
testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
testcase( pCol->affinity==SQLITE_AFF_INTEGER );
testcase( pCol->affinity==SQLITE_AFF_REAL );
-
+
zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
len = sqlite3Strlen30(zType);
- assert( pCol->affinity==SQLITE_AFF_NONE
+ assert( pCol->affinity==SQLITE_AFF_NONE
|| pCol->affinity==sqlite3AffinityType(zType) );
memcpy(&zStmt[k], zType, len);
k += len;
** the sqlite_master table. We do not want to create it again.
**
** If the pSelect argument is not NULL, it means that this routine
-** was called to create a table generated from a
+** was called to create a table generated from a
** "CREATE TABLE ... AS SELECT ..." statement. The column names of
** the new table will match the result set of the SELECT.
*/
sqlite3VdbeAddOp1(v, OP_Close, 0);
- /*
+ /*
** Initialize zType for the new view or table.
*/
if( p->pSelect==0 ){
zStmt = createTableStmt(db, p);
}else{
n = (int)(pEnd->z - pParse->sNameToken.z) + 1;
- zStmt = sqlite3MPrintf(db,
+ zStmt = sqlite3MPrintf(db,
"CREATE %s %.*s", zType2, n, pParse->sNameToken.z
);
}
- /* A slot for the record has already been allocated in the
+ /* A slot for the record has already been allocated in the
** SQLITE_MASTER table. We just need to update that slot with all
** the information we've collected.
*/
** Actually, the error above is now caught prior to reaching this point.
** But the following test is still important as it does come up
** in the following:
- **
+ **
** CREATE TABLE main.ex1(a);
** CREATE TEMP VIEW ex1 AS SELECT a FROM ex1;
** SELECT * FROM temp.ex1;
nErr++;
}
#endif /* SQLITE_OMIT_VIEW */
- return nErr;
+ return nErr;
}
#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
** on tables and/or indices that are the process of being deleted.
** If you are unlucky, one of those deleted indices or tables might
** have the same rootpage number as the real table or index that is
-** being moved. So we cannot stop searching after the first match
+** being moved. So we cannot stop searching after the first match
** because the first match might be for one of the deleted indices
** or tables and not the table/index that is actually being moved.
** We must continue looping until all tables and indices with
** Also write code to modify the sqlite_master table and internal schema
** if a root-page of another table is moved by the btree-layer whilst
** erasing iTable (this can happen with an auto-vacuum database).
-*/
+*/
static void destroyRootPage(Parse *pParse, int iTable, int iDb){
Vdbe *v = sqlite3GetVdbe(pParse);
int r1 = sqlite3GetTempReg(pParse);
** is in register NNN. See grammar rules associated with the TK_REGISTER
** token for additional information.
*/
- sqlite3NestedParse(pParse,
+ sqlite3NestedParse(pParse,
"UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable, r1, r1);
#endif
#else
/* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
** is not defined), then it is important to call OP_Destroy on the
- ** table and index root-pages in order, starting with the numerically
+ ** table and index root-pages in order, starting with the numerically
** largest root-page number. This guarantees that none of the root-pages
** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the
** following were coded:
** OP_Destroy 5 0
**
** and root page 5 happened to be the largest root-page number in the
- ** database, then root page 5 would be moved to page 4 by the
+ ** database, then root page 5 would be moved to page 4 by the
** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit
** a free-list page.
*/
*/
pTrigger = sqlite3TriggerList(pParse, pTab);
while( pTrigger ){
- assert( pTrigger->pSchema==pTab->pSchema ||
+ assert( pTrigger->pSchema==pTab->pSchema ||
pTrigger->pSchema==db->aDb[1].pSchema );
sqlite3DropTriggerPtr(pParse, pTrigger);
pTrigger = pTrigger->pNext;
** created in the temp database that refers to a table in another
** database.
*/
- sqlite3NestedParse(pParse,
+ sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
if( !isView && !IsVirtual(pTab) ){
}
}
#endif
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){
sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
goto exit_drop_table;
}
}
if( j>=p->nCol ){
- sqlite3ErrorMsg(pParse,
- "unknown column \"%s\" in foreign key definition",
+ sqlite3ErrorMsg(pParse,
+ "unknown column \"%s\" in foreign key definition",
pFromCol->a[i].zName);
goto fk_end;
}
pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff); /* ON UPDATE action */
assert( sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
- pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash,
+ pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash,
pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey
);
if( pNextTo==pFKey ){
sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
}
pKey = sqlite3IndexKeyinfo(pParse, pIndex);
- sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
+ sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
(char *)pKey, P4_KEYINFO_HANDOFF);
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
}
/*
-** Create a new index for an SQL table. pName1.pName2 is the name of the index
-** and pTblList is the name of the table that is to be indexed. Both will
+** Create a new index for an SQL table. pName1.pName2 is the name of the index
+** and pTblList is the name of the table that is to be indexed. Both will
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable
** as the table to be indexed. pParse->pNewTable is a table that is
**
** pList is a list of columns to be indexed. pList will be NULL if this
** is a primary key or unique-constraint on the most recent column added
-** to the table currently under construction.
+** to the table currently under construction.
**
** If the index is created successfully, return a pointer to the new Index
** structure. This is used by sqlite3AddPrimaryKey() to mark the index
*/
if( pTblName!=0 ){
- /* Use the two-part index name to determine the database
+ /* Use the two-part index name to determine the database
** to search for the table. 'Fix' the table name to this db
** before looking up the table.
*/
assert( pTab!=0 );
assert( pParse->nErr==0 );
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
/*
** Find the name of the index. Make sure there is not already another
- ** index or table with the same name.
+ ** index or table with the same name.
**
** Exception: If we are reading the names of permanent indices from the
** sqlite_master table (because some other process changed the schema) and
}
}
- /*
- ** Allocate the index structure.
+ /*
+ ** Allocate the index structure.
*/
nName = sqlite3Strlen30(zName);
nCol = pList->nExpr;
- pIndex = sqlite3DbMallocZero(db,
+ pIndex = sqlite3DbMallocZero(db,
ROUND8(sizeof(Index)) + /* Index structure */
ROUND8(sizeof(tRowcnt)*(nCol+1)) + /* Index.aiRowEst */
sizeof(char *)*nCol + /* Index.azColl */
** TODO: Add a test to make sure that the same column is not named
** more than once within the same index. Only the first instance of
** the column will ever be used by the optimizer. Note that using the
- ** same column more than once cannot be an error because that would
+ ** same column more than once cannot be an error because that would
** break backwards compatibility - it needs to be a warning.
*/
for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
if( pIdx->onError!=pIndex->onError ){
/* This constraint creates the same index as a previous
** constraint specified somewhere in the CREATE TABLE statement.
- ** However the ON CONFLICT clauses are different. If both this
+ ** However the ON CONFLICT clauses are different. If both this
** constraint and the previous equivalent constraint have explicit
** ON CONFLICT clauses this is an error. Otherwise, use the
** explicitly specified behavior for the index.
*/
if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"conflicting ON CONFLICT clauses specified", 0);
}
if( pIdx->onError==OE_Default ){
}
/* Link the new Index structure to its table and to the other
- ** in-memory database structures.
+ ** in-memory database structures.
*/
if( db->init.busy ){
Index *p;
assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
- p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
+ p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
pIndex->zName, sqlite3Strlen30(pIndex->zName),
pIndex);
if( p ){
** involves writing the index into the master table and filling in the
** index with the current table contents.
**
- ** The db->init.busy is 0 when the user first enters a CREATE INDEX
- ** command. db->init.busy is 1 when a database is opened and
+ ** The db->init.busy is 0 when the user first enters a CREATE INDEX
+ ** command. db->init.busy is 1 when a database is opened and
** CREATE INDEX statements are read out of the master table. In
** the latter case the index already exists on disk, which is why
** we don't want to recreate it.
/* Add an entry in sqlite_master for this index
*/
- sqlite3NestedParse(pParse,
+ sqlite3NestedParse(pParse,
"INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
pIndex->zName,
** sure all indices labeled OE_Replace come after all those labeled
** OE_Ignore. This is necessary for the correct constraint check
** processing (in sqlite3GenerateConstraintChecks()) as part of
- ** UPDATE and INSERT statements.
+ ** UPDATE and INSERT statements.
*/
if( db->init.busy || pTblName==0 ){
if( onError!=OE_Replace || pTab->pIndex==0
** database name prefix. Like this: "database.table". The pDatabase
** points to the table name and the pTable points to the database name.
** The SrcList.a[].zName field is filled with the table name which might
-** come from pTable (if pDatabase is NULL) or from pDatabase.
+** come from pTable (if pDatabase is NULL) or from pDatabase.
** SrcList.a[].zDatabase is filled with the database name from pTable,
** or with NULL if no database is specified.
**
struct SrcList_item *pItem;
sqlite3 *db = pParse->db;
if( !p && (pOn || pUsing) ){
- sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
+ sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
(pOn ? "ON" : "USING")
);
goto append_from_error;
}
/*
-** Add an INDEXED BY or NOT INDEXED clause to the most recently added
+** Add an INDEXED BY or NOT INDEXED clause to the most recently added
** element of the source-list passed as the second argument.
*/
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
struct SrcList_item *pItem = &p->a[p->nSrc-1];
assert( pItem->notIndexed==0 && pItem->zIndex==0 );
if( pIndexedBy->n==1 && !pIndexedBy->z ){
- /* A "NOT INDEXED" clause was supplied. See parse.y
+ /* A "NOT INDEXED" clause was supplied. See parse.y
** construct "indexed_opt" for details. */
pItem->notIndexed = 1;
}else{
/*
** This function is called by the parser when it parses a command to create,
-** release or rollback an SQL savepoint.
+** release or rollback an SQL savepoint.
*/
SQLITE_PRIVATE void sqlite3Savepoint(Parse *pParse, int op, Token *pName){
char *zName = sqlite3NameFromToken(pParse->db, pName);
if( db->aDb[1].pBt==0 && !pParse->explain ){
int rc;
Btree *pBt;
- static const int flags =
+ static const int flags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE |
}
/*
-** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each
+** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each
** attached database. Otherwise, invoke it for the database named zDb only.
*/
SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){
pToplevel->isMultiWrite = 1;
}
-/*
+/*
** The code generator calls this routine if is discovers that it is
-** possible to abort a statement prior to completion. In order to
+** possible to abort a statement prior to completion. In order to
** perform this abort without corrupting the database, we need to make
** sure that the statement is protected by a statement transaction.
**
** such that the abort must occur after the multiwrite. This makes
** some statements involving the REPLACE conflict resolution algorithm
** go a little faster. But taking advantage of this time dependency
-** makes it more difficult to prove that the code is correct (in
+** makes it more difficult to prove that the code is correct (in
** particular, it prevents us from writing an effective
** implementation of sqlite3AssertMayAbort()) and so we have chosen
** to take the safe route and skip the optimization.
** with OP_OpenRead or OP_OpenWrite to access database index pIdx.
**
** If successful, a pointer to the new structure is returned. In this case
-** the caller is responsible for calling sqlite3DbFree(db, ) on the returned
-** pointer. If an error occurs (out of memory or missing collation
+** the caller is responsible for calling sqlite3DbFree(db, ) on the returned
+** pointer. If an error occurs (out of memory or missing collation
** sequence), NULL is returned and the state of pParse updated to reflect
** the error.
*/
/************** End of build.c ***********************************************/
/************** Begin file callback.c ****************************************/
/*
-** 2005 May 23
+** 2005 May 23
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
** This function is responsible for invoking the collation factory callback
** or substituting a collation sequence of a different encoding when the
** requested collation sequence is not available in the desired encoding.
-**
-** If it is not NULL, then pColl must point to the database native encoding
+**
+** If it is not NULL, then pColl must point to the database native encoding
** collation sequence with name zName, length nName.
**
** The return value is either the collation sequence to be used in database
** that have not been defined by sqlite3_create_collation() etc.
**
** If required, this routine calls the 'collation needed' callback to
-** request a definition of the collating sequence. If this doesn't work,
+** request a definition of the collating sequence. If this doesn't work,
** an equivalent collating sequence that uses a text encoding different
** from the main database is substituted, if one is available.
*/
pColl[0].zName[nName] = 0;
pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
- /* If a malloc() failure occurred in sqlite3HashInsert(), it will
+ /* If a malloc() failure occurred in sqlite3HashInsert(), it will
** return the pColl pointer to be deleted (because it wasn't added
** to the hash table).
*/
** is also -1. In other words, we are searching for a function that
** takes a variable number of arguments.
**
-** If nArg is -2 that means that we are searching for any function
+** If nArg is -2 that means that we are searching for any function
** regardless of the number of arguments it uses, so return a positive
** match score for any
**
pHash->a[h] = pDef;
}
}
-
-
+
+
/*
** Locate a user function given a name, a number of arguments and a flag
** have fields overwritten with new information appropriate for the
** new function. But the FuncDefs for built-in functions are read-only.
** So we must not search for built-ins when creating a new function.
- */
+ */
if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){
FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
bestScore = 0;
** exact match for the name, number of arguments and encoding, then add a
** new entry to the hash table and return it.
*/
- if( createFlag && bestScore<FUNC_PERFECT_MATCH &&
+ if( createFlag && bestScore<FUNC_PERFECT_MATCH &&
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
pBest->zName = (char *)&pBest[1];
pBest->nArg = (u16)nArg;
/*
** Free all resources held by the schema structure. The void* argument points
-** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the
+** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the
** pointer itself, it just cleans up subsidiary resources (i.e. the contents
** of the schema hash tables).
**
** (as in the FROM clause of a SELECT statement) in this case it contains
** the name of a single table, as one might find in an INSERT, DELETE,
** or UPDATE statement. Look up that table in the symbol table and
-** return a pointer. Set an error message and return NULL if the table
+** return a pointer. Set an error message and return NULL if the table
** name is not found or if any other error occurs.
**
** The following fields are initialized appropriate in pSrc:
** 1) It is a virtual table and no implementation of the xUpdate method
** has been provided, or
** 2) It is a system table (i.e. sqlite_master), this call is not
- ** part of a nested parse and writable_schema pragma has not
+ ** part of a nested parse and writable_schema pragma has not
** been specified.
**
** In either case leave an error message in pParse and return non-zero.
*/
- if( ( IsVirtual(pTab)
+ if( ( IsVirtual(pTab)
&& sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 )
|| ( (pTab->tabFlags & TF_Readonly)!=0
&& (pParse->db->flags & SQLITE_WriteSchema)==0
return pWhere;
}
- /* Generate a select expression tree to enforce the limit/offset
+ /* Generate a select expression tree to enforce the limit/offset
** term for the DELETE or UPDATE statement. For example:
** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
** becomes:
- ** DELETE FROM table_a WHERE rowid IN (
+ ** DELETE FROM table_a WHERE rowid IN (
** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
** );
*/
#ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
/* Special case: A DELETE without a WHERE clause deletes everything.
** It is easier just to erase the whole table. Prior to version 3.6.5,
- ** this optimization caused the row change count (the value returned by
+ ** this optimization caused the row change count (the value returned by
** API function sqlite3_count_changes) to be set incorrectly. */
- if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
+ if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab)
&& 0==sqlite3FkRequired(pParse, pTab, 0, 0)
){
assert( !isView );
** because deleting an item can change the scan order. */
end = sqlite3VdbeMakeLabel(v);
- /* Unless this is a view, open cursors for the table we are
+ /* Unless this is a view, open cursors for the table we are
** deleting from and all its indices. If this is a view, then the
- ** only effect this statement has is to fire the INSTEAD OF
+ ** only effect this statement has is to fire the INSTEAD OF
** triggers. */
if( !isView ){
sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
sqlite3AutoincrementEnd(pParse);
}
- /* Return the number of rows that were deleted. If this routine is
+ /* Return the number of rows that were deleted. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
** 3. The record number of the row to be deleted must be stored in
** memory cell iRowid.
**
-** This routine generates code to remove both the table record and all
+** This routine generates code to remove both the table record and all
** index entries that point to that record.
*/
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
/* Vdbe is guaranteed to have been allocated by this stage. */
assert( v );
- /* Seek cursor iCur to the row to delete. If this row no longer exists
+ /* Seek cursor iCur to the row to delete. If this row no longer exists
** (this can happen if a trigger program has already deleted it), do
** not attempt to delete it or fire any DELETE triggers. */
iLabel = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
-
+
/* If there are any triggers to fire, allocate a range of registers to
** use for the old.* references in the triggers. */
if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
iOld = pParse->nMem+1;
pParse->nMem += (1 + pTab->nCol);
- /* Populate the OLD.* pseudo-table register array. These values will be
+ /* Populate the OLD.* pseudo-table register array. These values will be
** used by any BEFORE and AFTER triggers that exist. */
sqlite3VdbeAddOp2(v, OP_Copy, iRowid, iOld);
for(iCol=0; iCol<pTab->nCol; iCol++){
}
/* Invoke BEFORE DELETE trigger programs. */
- sqlite3CodeRowTrigger(pParse, pTrigger,
+ sqlite3CodeRowTrigger(pParse, pTrigger,
TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
);
/* Seek the cursor to the row to be deleted again. It may be that
** the BEFORE triggers coded above have already removed the row
- ** being deleted. Do not attempt to delete the row a second time, and
+ ** being deleted. Do not attempt to delete the row a second time, and
** do not fire AFTER triggers. */
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
/* Do FK processing. This call checks that any FK constraints that
- ** refer to this table (i.e. constraints attached to other tables)
+ ** refer to this table (i.e. constraints attached to other tables)
** are not violated by deleting this row. */
sqlite3FkCheck(pParse, pTab, iOld, 0);
}
/* Delete the index and table entries. Skip this step if pTab is really
** a view (in which case the only effect of the DELETE statement is to
- ** fire the INSTEAD OF triggers). */
+ ** fire the INSTEAD OF triggers). */
if( pTab->pSelect==0 ){
sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0);
sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
** handle rows (possibly in other tables) that refer via a foreign key
- ** to the row just deleted. */
+ ** to the row just deleted. */
sqlite3FkActions(pParse, pTab, 0, iOld);
/* Invoke AFTER DELETE trigger programs. */
- sqlite3CodeRowTrigger(pParse, pTrigger,
+ sqlite3CodeRowTrigger(pParse, pTrigger,
TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
);
/* Jump here if the row had already been deleted before any BEFORE
- ** trigger programs were invoked. Or if a trigger program throws a
+ ** trigger programs were invoked. Or if a trigger program throws a
** RAISE(IGNORE) exception. */
sqlite3VdbeResolveLabel(v, iLabel);
}
**
*************************************************************************
** This file contains the C functions that implement various SQL
-** functions of SQLite.
+** functions of SQLite.
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** Implementation of the abs() function.
**
** IMP: R-23979-26855 The abs(X) function returns the absolute value of
-** the numeric argument X.
+** the numeric argument X.
*/
static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
assert( argc==1 );
return;
}
iVal = -iVal;
- }
+ }
sqlite3_result_int64(context, iVal);
break;
}
/* Because sqlite3_value_double() returns 0.0 if the argument is not
** something that can be converted into a number, we have:
** IMP: R-57326-31541 Abs(X) return 0.0 if X is a string or blob that
- ** cannot be converted to a numeric value.
+ ** cannot be converted to a numeric value.
*/
double rVal = sqlite3_value_double(argv[0]);
if( rVal<0 ) rVal = -rVal;
#define ifnullFunc versionFunc /* Substitute function - never called */
/*
-** Implementation of random(). Return a random integer.
+** Implementation of random(). Return a random integer.
*/
static void randomFunc(
sqlite3_context *context,
UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_randomness(sizeof(r), &r);
if( r<0 ){
- /* We need to prevent a random number of 0x8000000000000000
+ /* We need to prevent a random number of 0x8000000000000000
** (or -9223372036854775808) since when you do abs() of that
** number of you get the same value back again. To do this
** in a way that is testable, mask the sign bit off of negative
- ** values, resulting in a positive value. Then take the
+ ** values, resulting in a positive value. Then take the
** 2s complement of that positive value. The end result can
** therefore be no less than -9223372036854775807.
*/
** value is the same as the sqlite3_last_insert_rowid() API function.
*/
static void last_insert_rowid(
- sqlite3_context *context,
- int NotUsed,
+ sqlite3_context *context,
+ int NotUsed,
sqlite3_value **NotUsed2
){
sqlite3 *db = sqlite3_context_db_handle(context);
u8 matchOne = pInfo->matchOne;
u8 matchAll = pInfo->matchAll;
u8 matchSet = pInfo->matchSet;
- u8 noCase = pInfo->noCase;
+ u8 noCase = pInfo->noCase;
int prevEscape = 0; /* True if the previous character was 'escape' */
while( (c = sqlite3Utf8Read(&zPattern))!=0 ){
** the GLOB operator.
*/
static void likeFunc(
- sqlite3_context *context,
- int argc,
+ sqlite3_context *context,
+ int argc,
sqlite3_value **argv
){
const unsigned char *zA, *zB;
const unsigned char *zEsc = sqlite3_value_text(argv[2]);
if( zEsc==0 ) return;
if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){
- sqlite3_result_error(context,
+ sqlite3_result_error(context,
"ESCAPE expression must be a single character", -1);
return;
}
#ifdef SQLITE_TEST
sqlite3_like_count++;
#endif
-
+
sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
}
}
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
/*
-** Implementation of the sqlite_compileoption_get() function.
-** The result is a string that identifies the compiler options
+** Implementation of the sqlite_compileoption_get() function.
+** The result is a string that identifies the compiler options
** used to build SQLite.
*/
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
** digits. */
static const char hexdigits[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
/*
char const *zBlob = sqlite3_value_blob(argv[0]);
int nBlob = sqlite3_value_bytes(argv[0]);
assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
- zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4);
+ zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4);
if( zText ){
int i;
for(i=0; i<nBlob; i++){
/*
** The unicode() function. Return the integer unicode code-point value
-** for the first character of the input string.
+** for the first character of the input string.
*/
static void unicodeFunc(
sqlite3_context *context,
if( zOut==0 ){
return;
}
- loopLimit = nStr - nPattern;
+ loopLimit = nStr - nPattern;
for(i=j=0; i<=loopLimit; i++){
if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
zOut[j++] = zStr[i];
** Compute the soundex encoding of a word.
**
** IMP: R-59782-00072 The soundex(X) function returns a string that is the
-** soundex encoding of the string X.
+** soundex encoding of the string X.
*/
static void soundexFunc(
sqlite3_context *context,
typedef struct SumCtx SumCtx;
struct SumCtx {
double rSum; /* Floating point sum */
- i64 iSum; /* Integer sum */
+ i64 iSum; /* Integer sum */
i64 cnt; /* Number of elements summed */
u8 overflow; /* True if integer overflow seen */
u8 approx; /* True if non-integer value was input to the sum */
#ifndef SQLITE_OMIT_DEPRECATED
/* The sqlite3_aggregate_count() function is deprecated. But just to make
- ** sure it still operates correctly, verify that its count agrees with our
+ ** sure it still operates correctly, verify that its count agrees with our
** internal count when using count(*) and when the total count can be
** expressed as a 32-bit integer. */
assert( argc==1 || p==0 || p->n>0x7fffffff
|| p->n==sqlite3_aggregate_count(context) );
#endif
-}
+}
static void countFinalize(sqlite3_context *context){
CountCtx *p;
p = sqlite3_aggregate_context(context, 0);
** Routines to implement min() and max() aggregate functions.
*/
static void minmaxStep(
- sqlite3_context *context,
- int NotUsed,
+ sqlite3_context *context,
+ int NotUsed,
sqlite3_value **argv
){
Mem *pArg = (Mem *)argv[0];
sqlite3_result_error_toobig(context);
}else if( pAccum->mallocFailed ){
sqlite3_result_error_nomem(context);
- }else{
- sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1,
+ }else{
+ sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1,
sqlite3_free);
}
}
}
sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0);
sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0);
- sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8,
+ sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8,
(struct compareInfo*)&globInfo, likeFunc, 0, 0, 0);
setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
- setLikeOptFlag(db, "like",
+ setLikeOptFlag(db, "like",
caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE);
}
*/
SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
- if( pExpr->op!=TK_FUNCTION
- || !pExpr->x.pList
+ if( pExpr->op!=TK_FUNCTION
+ || !pExpr->x.pList
|| pExpr->x.pList->nExpr!=2
){
return 0;
}
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- pDef = sqlite3FindFunction(db, pExpr->u.zToken,
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken,
sqlite3Strlen30(pExpr->u.zToken),
2, SQLITE_UTF8, 0);
if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize),
AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize),
-
+
LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
#ifdef SQLITE_CASE_SENSITIVE_LIKE
LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
** Foreign keys in SQLite come in two flavours: deferred and immediate.
** If an immediate foreign key constraint is violated,
** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current
-** statement transaction rolled back. If a
-** deferred foreign key constraint is violated, no action is taken
-** immediately. However if the application attempts to commit the
+** statement transaction rolled back. If a
+** deferred foreign key constraint is violated, no action is taken
+** immediately. However if the application attempts to commit the
** transaction before fixing the constraint violation, the attempt fails.
**
** Deferred constraints are implemented using a simple counter associated
-** with the database handle. The counter is set to zero each time a
-** database transaction is opened. Each time a statement is executed
+** with the database handle. The counter is set to zero each time a
+** database transaction is opened. Each time a statement is executed
** that causes a foreign key violation, the counter is incremented. Each
** time a statement is executed that removes an existing violation from
** the database, the counter is decremented. When the transaction is
** committed, the commit fails if the current value of the counter is
** greater than zero. This scheme has two big drawbacks:
**
-** * When a commit fails due to a deferred foreign key constraint,
+** * When a commit fails due to a deferred foreign key constraint,
** there is no way to tell which foreign constraint is not satisfied,
** or which row it is not satisfied for.
**
-** * If the database contains foreign key violations when the
+** * If the database contains foreign key violations when the
** transaction is opened, this may cause the mechanism to malfunction.
**
** Despite these problems, this approach is adopted as it seems simpler
** the parent table for a match. If none is found increment the
** constraint counter.
**
-** I.2) For each FK for which the table is the parent table,
+** I.2) For each FK for which the table is the parent table,
** search the child table for rows that correspond to the new
** row in the parent table. Decrement the counter for each row
** found (as the constraint is now satisfied).
**
** DELETE operations:
**
-** D.1) For each FK for which the table is the child table,
-** search the parent table for a row that corresponds to the
-** deleted row in the child table. If such a row is not found,
+** D.1) For each FK for which the table is the child table,
+** search the parent table for a row that corresponds to the
+** deleted row in the child table. If such a row is not found,
** decrement the counter.
**
-** D.2) For each FK for which the table is the parent table, search
-** the child table for rows that correspond to the deleted row
+** D.2) For each FK for which the table is the parent table, search
+** the child table for rows that correspond to the deleted row
** in the parent table. For each found increment the counter.
**
** UPDATE operations:
**
** An UPDATE command requires that all 4 steps above are taken, but only
-** for FK constraints for which the affected columns are actually
+** for FK constraints for which the affected columns are actually
** modified (values must be compared at runtime).
**
** Note that I.1 and D.1 are very similar operations, as are I.2 and D.2.
** For the purposes of immediate FK constraints, the OR REPLACE conflict
** resolution is considered to delete rows before the new row is inserted.
** If a delete caused by OR REPLACE violates an FK constraint, an exception
-** is thrown, even if the FK constraint would be satisfied after the new
+** is thrown, even if the FK constraint would be satisfied after the new
** row is inserted.
**
-** Immediate constraints are usually handled similarly. The only difference
+** Immediate constraints are usually handled similarly. The only difference
** is that the counter used is stored as part of each individual statement
** object (struct Vdbe). If, after the statement has run, its immediate
** constraint counter is greater than zero,
** INSERT violates a foreign key constraint. This is necessary as such
** an INSERT does not open a statement transaction.
**
-** TODO: How should dropping a table be handled? How should renaming a
+** TODO: How should dropping a table be handled? How should renaming a
** table be handled?
**
**
** for those two operations needs to know whether or not the operation
** requires any FK processing and, if so, which columns of the original
** row are required by the FK processing VDBE code (i.e. if FKs were
-** implemented using triggers, which of the old.* columns would be
+** implemented using triggers, which of the old.* columns would be
** accessed). No information is required by the code-generator before
** coding an INSERT operation. The functions used by the UPDATE/DELETE
** generation code to query for this information are:
/*
** A foreign key constraint requires that the key columns in the parent
** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
-** Given that pParent is the parent table for foreign key constraint pFKey,
-** search the schema for a unique index on the parent key columns.
+** Given that pParent is the parent table for foreign key constraint pFKey,
+** search the schema for a unique index on the parent key columns.
+**
+** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
+** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
+** is set to point to the unique index.
**
-** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
-** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
-** is set to point to the unique index.
-**
** If the parent key consists of a single column (the foreign key constraint
** is not a composite foreign key), output variable *paiCol is set to NULL.
** Otherwise, it is set to point to an allocated array of size N, where
** PRIMARY KEY, or
**
** 4) No parent key columns were provided explicitly as part of the
-** foreign key definition, and the PRIMARY KEY of the parent table
-** consists of a a different number of columns to the child key in
+** foreign key definition, and the PRIMARY KEY of the parent table
+** consists of a a different number of columns to the child key in
** the child table.
**
** then non-zero is returned, and a "foreign key mismatch" error loaded
assert( !paiCol || *paiCol==0 );
assert( pParse );
- /* If this is a non-composite (single column) foreign key, check if it
- ** maps to the INTEGER PRIMARY KEY of table pParent. If so, leave *ppIdx
- ** and *paiCol set to zero and return early.
+ /* If this is a non-composite (single column) foreign key, check if it
+ ** maps to the INTEGER PRIMARY KEY of table pParent. If so, leave *ppIdx
+ ** and *paiCol set to zero and return early.
**
** Otherwise, for a composite foreign key (more than one column), allocate
** space for the aiCol array (returned via output parameter *paiCol).
if( nCol==1 ){
/* The FK maps to the IPK if any of the following are true:
**
- ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly
+ ** 1) There is an INTEGER PRIMARY KEY column and the FK is implicitly
** mapped to the primary key of table pParent, or
** 2) The FK is explicitly mapped to a column declared as INTEGER
** PRIMARY KEY.
}
for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->nColumn==nCol && pIdx->onError!=OE_None ){
+ if( pIdx->nColumn==nCol && pIdx->onError!=OE_None ){
/* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
** of columns. If each indexed column corresponds to a foreign key
** column of pFKey, then this index is a winner. */
if( zKey==0 ){
- /* If zKey is NULL, then this foreign key is implicitly mapped to
- ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be
+ /* If zKey is NULL, then this foreign key is implicitly mapped to
+ ** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be
** identified by the test (Index.autoIndex==2). */
if( pIdx->autoIndex==2 ){
if( aiCol ){
}
/*
-** This function is called when a row is inserted into or deleted from the
-** child table of foreign key constraint pFKey. If an SQL UPDATE is executed
+** This function is called when a row is inserted into or deleted from the
+** child table of foreign key constraint pFKey. If an SQL UPDATE is executed
** on the child table of pFKey, this function is invoked twice for each row
** affected - once to "delete" the old row, and then again to "insert" the
** new row.
**
** Each time it is called, this function generates VDBE code to locate the
-** row in the parent table that corresponds to the row being inserted into
-** or deleted from the child table. If the parent row can be found, no
+** row in the parent table that corresponds to the row being inserted into
+** or deleted from the child table. If the parent row can be found, no
** special action is taken. Otherwise, if the parent row can *not* be
** found in the parent table:
**
**
** DELETE deferred Decrement the "deferred constraint counter".
**
-** These operations are identified in the comment at the top of this file
+** These operations are identified in the comment at the top of this file
** (fkey.c) as "I.1" and "D.1".
*/
static void fkLookupParent(
** outstanding constraints to resolve. If there are not, there is no need
** to check if deleting this row resolves any outstanding violations.
**
- ** Check if any of the key columns in the child table row are NULL. If
- ** any are, then the constraint is considered satisfied. No need to
+ ** Check if any of the key columns in the child table row are NULL. If
+ ** any are, then the constraint is considered satisfied. No need to
** search for a matching row in the parent table. */
if( nIncr<0 ){
sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk);
** column of the parent table (table pTab). */
int iMustBeInt; /* Address of MustBeInt instruction */
int regTemp = sqlite3GetTempReg(pParse);
-
- /* Invoke MustBeInt to coerce the child key value to an integer (i.e.
+
+ /* Invoke MustBeInt to coerce the child key value to an integer (i.e.
** apply the affinity of the parent key). If this fails, then there
** is no matching parent key. Before using MustBeInt, make a copy of
** the value. Otherwise, the value inserted into the child key column
** will have INTEGER affinity applied to it, which may not be correct. */
sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp);
iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0);
-
+
/* If the parent table is the same as the child table, and we are about
** to increment the constraint-counter (i.e. this is an INSERT operation),
** then check if the row being inserted matches itself. If so, do not
if( pTab==pFKey->pFrom && nIncr==1 ){
sqlite3VdbeAddOp3(v, OP_Eq, regData, iOk, regTemp);
}
-
+
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regTemp);
sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
int regTemp = sqlite3GetTempRange(pParse, nCol);
int regRec = sqlite3GetTempReg(pParse);
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
-
+
sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i);
}
-
+
/* If the parent table is the same as the child table, and we are about
** to increment the constraint-counter (i.e. this is an INSERT operation),
** then check if the row being inserted matches itself. If so, do not
- ** increment the constraint-counter.
+ ** increment the constraint-counter.
**
- ** If any of the parent-key values are NULL, then the row cannot match
+ ** If any of the parent-key values are NULL, then the row cannot match
** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
** of the parent-key values are NULL (at this point it is known that
** none of the child key values are).
}
sqlite3VdbeAddOp2(v, OP_Goto, 0, iOk);
}
-
+
sqlite3VdbeAddOp3(v, OP_MakeRecord, regTemp, nCol, regRec);
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);
-
+
sqlite3ReleaseTempReg(pParse, regRec);
sqlite3ReleaseTempRange(pParse, regTemp, nCol);
}
/*
** This function is called to generate code executed when a row is deleted
-** from the parent table of foreign key constraint pFKey and, if pFKey is
+** from the parent table of foreign key constraint pFKey and, if pFKey is
** deferred, when a row is inserted into the same table. When generating
** code for an SQL UPDATE operation, this function may be called twice -
** once to "delete" the old row and once to "insert" the new row.
**
** INSERT deferred Decrement the "deferred constraint counter".
**
-** These operations are identified in the comment at the top of this file
+** These operations are identified in the comment at the top of this file
** (fkey.c) as "I.2" and "D.2".
*/
static void fkScanChildren(
Expr *pLeft; /* Value from parent table row */
Expr *pRight; /* Column ref to child table */
Expr *pEq; /* Expression (pLeft = pRight) */
- int iCol; /* Index of column in child table */
+ int iCol; /* Index of column in child table */
const char *zCol; /* Name of column in child table */
pLeft = sqlite3Expr(db, TK_REGISTER, 0);
/* If the child table is the same as the parent table, and this scan
** is taking place as part of a DELETE operation (operation D.2), omit the
- ** row being deleted from the scan by adding ($rowid != rowid) to the WHERE
+ ** row being deleted from the scan by adding ($rowid != rowid) to the WHERE
** clause, where $rowid is the rowid of the row being deleted. */
if( pTab==pFKey->pFrom && nIncr>0 ){
Expr *pEq; /* Expression (pLeft = pRight) */
}
/*
-** The second argument is a Trigger structure allocated by the
+** The second argument is a Trigger structure allocated by the
** fkActionTrigger() routine. This function deletes the Trigger structure
** and all of its sub-components.
**
**
** (a) The table is the parent table of a FK constraint, or
** (b) The table is the child table of a deferred FK constraint and it is
-** determined at runtime that there are outstanding deferred FK
+** determined at runtime that there are outstanding deferred FK
** constraint violations in the database,
**
** then the equivalent of "DELETE FROM <tbl>" is executed before dropping
assert( v ); /* VDBE has already been allocated */
if( sqlite3FkReferences(pTab)==0 ){
/* Search for a deferred foreign key constraint for which this table
- ** is the child table. If one cannot be found, return without
+ ** is the child table. If one cannot be found, return without
** generating any VDBE code. If one can be found, then jump over
** the entire DELETE if there are no outstanding deferred constraints
** when this statement is run. */
sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0);
pParse->disableTriggers = 0;
- /* If the DELETE has generated immediate foreign key constraint
+ /* If the DELETE has generated immediate foreign key constraint
** violations, halt the VDBE and return an error at this point, before
** any modifications to the schema are made. This is because statement
** transactions are not able to rollback schema changes. */
/*
** This function is called when inserting, deleting or updating a row of
-** table pTab to generate VDBE code to perform foreign key constraint
+** table pTab to generate VDBE code to perform foreign key constraint
** processing for the operation.
**
** For a DELETE operation, parameter regOld is passed the index of the
** For an UPDATE operation, this function is called twice. Once before
** the original record is deleted from the table using the calling convention
** described for DELETE. Then again after the original record is deleted
-** but before the new record is inserted using the INSERT convention.
+** but before the new record is inserted using the INSERT convention.
*/
SQLITE_PRIVATE void sqlite3FkCheck(
Parse *pParse, /* Parse context */
- Table *pTab, /* Row is being deleted from this table */
+ Table *pTab, /* Row is being deleted from this table */
int regOld, /* Previous row data is stored here */
int regNew /* New row data is stored here */
){
int i;
int isIgnore = 0;
- /* Find the parent table of this foreign key. Also find a unique index
- ** on the parent key columns in the parent table. If either of these
- ** schema items cannot be located, set an error in pParse and return
+ /* Find the parent table of this foreign key. Also find a unique index
+ ** on the parent key columns in the parent table. If either of these
+ ** schema items cannot be located, set an error in pParse and return
** early. */
if( pParse->disableTriggers ){
pTo = sqlite3FindTable(db, pFKey->zTo, zDb);
aiCol[i] = -1;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
- /* Request permission to read the parent key columns. If the
+ /* Request permission to read the parent key columns. If the
** authorization callback returns SQLITE_IGNORE, behave as if any
** values read from the parent table are NULL. */
if( db->xAuth ){
#endif
}
- /* Take a shared-cache advisory read-lock on the parent table. Allocate
- ** a cursor to use to search the unique index on the parent key columns
+ /* Take a shared-cache advisory read-lock on the parent table. Allocate
+ ** a cursor to use to search the unique index on the parent key columns
** in the parent table. */
sqlite3TableLock(pParse, iDb, pTo->tnum, 0, pTo->zName);
pParse->nTab++;
if( regOld!=0 ){
/* A row is being removed from the child table. Search for the parent.
- ** If the parent does not exist, removing the child row resolves an
+ ** If the parent does not exist, removing the child row resolves an
** outstanding foreign key constraint violation. */
fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore);
}
if( regNew!=0 ){
/* A row is being added to the child table. If a parent row cannot
- ** be found, adding the child row has violated the FK constraint. */
+ ** be found, adding the child row has violated the FK constraint. */
fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore);
}
}
assert( aiCol || pFKey->nCol==1 );
- /* Create a SrcList structure containing a single table (the table
+ /* Create a SrcList structure containing a single table (the table
** the foreign key that refers to this table is attached to). This
** is required for the sqlite3WhereXXX() interface. */
pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
pItem->zName = pFKey->pFrom->zName;
pItem->pTab->nRef++;
pItem->iCursor = pParse->nTab++;
-
+
if( regNew!=0 ){
fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
}
if( regOld!=0 ){
/* If there is a RESTRICT action configured for the current operation
- ** on the parent table of this FK, then throw an exception
+ ** on the parent table of this FK, then throw an exception
** immediately if the FK constraint is violated, even if this is a
** deferred trigger. That's what RESTRICT means. To defer checking
** the constraint, the FK should specify NO ACTION (represented
#define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x)))
/*
-** This function is called before generating code to update or delete a
+** This function is called before generating code to update or delete a
** row contained in table pTab.
*/
SQLITE_PRIVATE u32 sqlite3FkOldmask(
}
/*
-** This function is called before generating code to update or delete a
+** This function is called before generating code to update or delete a
** row contained in table pTab. If the operation is a DELETE, then
** parameter aChange is passed a NULL value. For an UPDATE, aChange points
** to an array of size N, where N is the number of columns in table pTab.
-** If the i'th column is not modified by the UPDATE, then the corresponding
+** If the i'th column is not modified by the UPDATE, then the corresponding
** entry in the aChange[] array is set to -1. If the column is modified,
** the value is 0 or greater. Parameter chngRowid is set to true if the
** UPDATE statement modifies the rowid fields of the table.
**
** If any foreign key processing will be required, this function returns
-** true. If there is no foreign key related processing, this function
+** true. If there is no foreign key related processing, this function
** returns false.
*/
SQLITE_PRIVATE int sqlite3FkRequired(
){
if( pParse->db->flags&SQLITE_ForeignKeys ){
if( !aChange ){
- /* A DELETE operation. Foreign key processing is required if the
- ** table in question is either the child or parent table for any
+ /* A DELETE operation. Foreign key processing is required if the
+ ** table in question is either the child or parent table for any
** foreign key constraint. */
return (sqlite3FkReferences(pTab) || pTab->pFKey);
}else{
}
/*
-** This function is called when an UPDATE or DELETE operation is being
+** This function is called when an UPDATE or DELETE operation is being
** compiled on table pTab, which is the parent table of foreign-key pFKey.
** If the current operation is an UPDATE, then the pChanges parameter is
** passed a pointer to the list of columns being modified. If it is a
** returned (these actions require no special handling by the triggers
** sub-system, code for them is created by fkScanChildren()).
**
-** For example, if pFKey is the foreign key and pTab is table "p" in
+** For example, if pFKey is the foreign key and pTab is table "p" in
** the following schema:
**
** CREATE TABLE p(pk PRIMARY KEY);
** END;
**
** The returned pointer is cached as part of the foreign key object. It
-** is eventually freed along with the rest of the foreign key object by
+** is eventually freed along with the rest of the foreign key object by
** sqlite3FkDelete().
*/
static Trigger *fkActionTrigger(
** that the affinity and collation sequence associated with the
** parent table are used for the comparison. */
pEq = sqlite3PExpr(pParse, TK_EQ,
- sqlite3PExpr(pParse, TK_DOT,
+ sqlite3PExpr(pParse, TK_DOT,
sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
, 0),
*/
if( pChanges ){
pEq = sqlite3PExpr(pParse, TK_IS,
- sqlite3PExpr(pParse, TK_DOT,
+ sqlite3PExpr(pParse, TK_DOT,
sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
0),
- sqlite3PExpr(pParse, TK_DOT,
+ sqlite3PExpr(pParse, TK_DOT,
sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
0),
0);
pWhen = sqlite3ExprAnd(db, pWhen, pEq);
}
-
+
if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){
Expr *pNew;
if( action==OE_Cascade ){
- pNew = sqlite3PExpr(pParse, TK_DOT,
+ pNew = sqlite3PExpr(pParse, TK_DOT,
sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
, 0);
if( action==OE_Restrict ){
Token tFrom;
- Expr *pRaise;
+ Expr *pRaise;
tFrom.z = zFrom;
tFrom.n = nFrom;
if( pRaise ){
pRaise->affinity = OE_Abort;
}
- pSelect = sqlite3SelectNew(pParse,
+ pSelect = sqlite3SelectNew(pParse,
sqlite3ExprListAppend(pParse, 0, pRaise),
sqlite3SrcListAppend(db, 0, &tFrom, 0),
pWhere,
enableLookaside = db->lookaside.bEnabled;
db->lookaside.bEnabled = 0;
- pTrigger = (Trigger *)sqlite3DbMallocZero(db,
+ pTrigger = (Trigger *)sqlite3DbMallocZero(db,
sizeof(Trigger) + /* struct Trigger */
sizeof(TriggerStep) + /* Single step in trigger program */
nFrom + 1 /* Space for pStep->target.z */
pStep->target.z = (char *)&pStep[1];
pStep->target.n = nFrom;
memcpy((char *)pStep->target.z, zFrom, nFrom);
-
+
pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE);
pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
switch( action ){
case OE_Restrict:
- pStep->op = TK_SELECT;
+ pStep->op = TK_SELECT;
break;
- case OE_Cascade:
- if( !pChanges ){
- pStep->op = TK_DELETE;
- break;
+ case OE_Cascade:
+ if( !pChanges ){
+ pStep->op = TK_DELETE;
+ break;
}
default:
pStep->op = TK_UPDATE;
ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */
int regOld /* Address of array containing old row */
){
- /* If foreign-key support is enabled, iterate through all FKs that
- ** refer to table pTab. If there is an action associated with the FK
- ** for this operation (either update or delete), invoke the associated
+ /* If foreign-key support is enabled, iterate through all FKs that
+ ** refer to table pTab. If there is an action associated with the FK
+ ** for this operation (either update or delete), invoke the associated
** trigger sub-program. */
if( pParse->db->flags&SQLITE_ForeignKeys ){
FKey *pFKey; /* Iterator variable */
/*
** Return a pointer to the column affinity string associated with index
-** pIdx. A column affinity string has one character for each column in
+** pIdx. A column affinity string has one character for each column in
** the table, according to the affinity of the column:
**
** Character Column affinity
pIdx->zColAff[n++] = SQLITE_AFF_INTEGER;
pIdx->zColAff[n] = 0;
}
-
+
return pIdx->zColAff;
}
*/
SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
/* The first time a column affinity string for a particular table
- ** is required, it is allocated and populated here. It is then
+ ** is required, it is allocated and populated here. It is then
** stored as a member of the Table structure for subsequent use.
**
** The column affinity string will eventually be deleted by
/*
** Return non-zero if the table pTab in database iDb or any of its indices
** have been opened at any point in the VDBE program beginning at location
-** iStartAddr throught the end of the program. This is used to see if
-** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can
-** run without using temporary table for the results of the SELECT.
+** iStartAddr throught the end of the program. This is used to see if
+** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can
+** run without using temporary table for the results of the SELECT.
*/
static int readsTable(Parse *p, int iStartAddr, int iDb, Table *pTab){
Vdbe *v = sqlite3GetVdbe(p);
/*
** This routine generates code that will initialize all of the
-** register used by the autoincrement tracker.
+** register used by the autoincrement tracker.
*/
SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){
AutoincInfo *p; /* Information about an AUTOINCREMENT */
** This routine handles all of the register allocation and fills in the
** pDest structure appropriately.
**
-** Here is a schematic of the generated code assuming that X is the
+** Here is a schematic of the generated code assuming that X is the
** co-routine entry-point register reg[pDest->iSDParm], that EOF is the
** completed flag reg[pDest->iSDParm+1], and R and S are the range of
** registers that hold the result set, reg[pDest->iSdst] through
assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );
/* If pTab is really a view, make sure it has been initialized.
- ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual
+ ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual
** module table).
*/
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
}
/* Ensure that:
- * (a) the table is not read-only,
+ * (a) the table is not read-only,
* (b) that if it is a view then ON INSERT triggers exist
*/
if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
** the destination table (template 3).
**
** A temp table must be used if the table being updated is also one
- ** of the tables being read by the SELECT statement. Also use a
+ ** of the tables being read by the SELECT statement. Also use a
** temp table in the case of row triggers.
*/
if( pTrigger || readsTable(pParse, addrSelect, iDb, pTab) ){
}
}
if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"table %S has %d columns but %d values were supplied",
pTabList, 0, pTab->nCol-nHidden, nColumn);
goto insert_cleanup;
}
/* If the INSERT statement included an IDLIST term, then make sure
- ** all elements of the IDLIST really are columns of the table and
+ ** all elements of the IDLIST really are columns of the table and
** remember the column indices.
**
** If the table has an INTEGER PRIMARY KEY column and that column
if( pColumn==0 && nColumn>0 ){
keyColumn = pTab->iPKey;
}
-
+
/* Initialize the count of rows to be inserted
*/
if( db->flags & SQLITE_CountRows ){
if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId) ){
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1);
}else if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1);
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1);
}else{
assert( pSelect==0 ); /* Otherwise useTempTable is true */
sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1);
}
/* Fire BEFORE or INSTEAD OF triggers */
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE,
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE,
pTab, regCols-pTab->nCol-1, onError, endOfLoop);
sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
/* Push the record number for the new entry onto the stack. The
** record number is a randomly generate integer created by NewRowid
** except when the table has an INTEGER PRIMARY KEY column, in which
- ** case the record number is the same as that column.
+ ** case the record number is the same as that column.
*/
if( !isView ){
if( IsVirtual(pTab) ){
if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore);
}else if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore);
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore);
}else if( pSelect ){
sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
}else{
if( pTrigger ){
/* Code AFTER triggers */
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER,
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER,
pTab, regData-2-pTab->nCol, onError, endOfLoop);
}
}
/*
- ** Return the number of rows inserted. If this routine is
+ ** Return the number of rows inserted. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
** If isUpdate is true and rowidChng is non-zero, then rowidChng contains
** the address of a register containing the rowid before the update takes
** place. isUpdate is true for UPDATEs and false for INSERTs. If isUpdate
-** is false, indicating an INSERT statement, then a non-zero rowidChng
+** is false, indicating an INSERT statement, then a non-zero rowidChng
** indicates that the rowid was explicitly specified as part of the
** INSERT statement. If rowidChng is false, it means that the rowid is
-** computed automatically in an insert or that the rowid value is not
+** computed automatically in an insert or that the rowid value is not
** modified by an update.
**
** The code generated by this routine store new index entries into
}else if( onError==OE_Default ){
onError = OE_Abort;
}
-
+
if( isUpdate ){
j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng);
}
** the triggers and remove both the table and index b-tree entries.
**
** Otherwise, if there are no triggers or the recursive-triggers
- ** flag is not set, but the table has one or more indexes, call
- ** GenerateRowIndexDelete(). This removes the index b-tree entries
- ** only. The table b-tree entry will be replaced by the new entry
- ** when it is inserted.
+ ** flag is not set, but the table has one or more indexes, call
+ ** GenerateRowIndexDelete(). This removes the index b-tree entries
+ ** only. The table b-tree entry will be replaced by the new entry
+ ** when it is inserted.
**
** If either GenerateRowDelete() or GenerateRowIndexDelete() is called,
** also invoke MultiWrite() to indicate that this VDBE may require
/* Find out what action to take in case there is an indexing conflict */
onError = pIdx->onError;
- if( onError==OE_None ){
+ if( onError==OE_None ){
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
continue; /* pIdx is not a UNIQUE index */
}
if( onError==OE_Ignore ) onError = OE_Replace;
else if( onError==OE_Fail ) onError = OE_Abort;
}
-
+
/* Check to see if the new index entry will be unique */
regR = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR);
sqlite3VdbeJumpHere(v, j3);
sqlite3ReleaseTempReg(pParse, regR);
}
-
+
if( pbMayReplace ){
*pbMayReplace = seenReplace;
}
**
** INSERT INTO tab1 SELECT * FROM tab2;
**
-** The xfer optimization transfers raw records from tab2 over to tab1.
+** The xfer optimization transfers raw records from tab2 over to tab1.
** Columns are not decoded and reassemblied, which greatly improves
** performance. Raw index records are transferred in the same way.
**
#ifndef SQLITE_OMIT_FOREIGN_KEY
/* Disallow the transfer optimization if the destination table constains
** any foreign key constraints. This is more restrictive than necessary.
- ** But the main beneficiary of the transfer optimization is the VACUUM
+ ** But the main beneficiary of the transfer optimization is the VACUUM
** command, and the VACUUM command disables foreign key constraints. So
** the extra complication to make this rule less restrictive is probably
** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
** (If the destination is not initially empty, the rowid fields
** of index entries might need to change.)
**
- ** (2) The destination has a unique index. (The xfer optimization
+ ** (2) The destination has a unique index. (The xfer optimization
** is unable to test uniqueness.)
**
** (3) onError is something other than OE_Abort and OE_Rollback.
rc = sqlite3_step(pStmt);
/* Invoke the callback function if required */
- if( xCallback && (SQLITE_ROW==rc ||
+ if( xCallback && (SQLITE_ROW==rc ||
(SQLITE_DONE==rc && !callbackIsInit
&& db->flags&SQLITE_NullCallback)) ){
if( !callbackIsInit ){
** This header file defines the SQLite interface for use by
** shared libraries that want to be imported as extensions into
** an SQLite instance. Shared libraries that intend to be loaded
-** as extensions by SQLite should #include this file instead of
+** as extensions by SQLite should #include this file instead of
** sqlite3.h.
*/
#ifndef _SQLITE3EXT_H_
#endif /* SQLITE_CORE */
#ifndef SQLITE_CORE
- /* This case when the file really is being compiled as a loadable
+ /* This case when the file really is being compiled as a loadable
** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
#else
- /* This case when the file is being statically linked into the
+ /* This case when the file is being statically linked into the
** application */
# define SQLITE_EXTENSION_INIT1 /*no-op*/
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
sqlite3_memory_highwater,
sqlite3_memory_used,
#ifdef SQLITE_MUTEX_OMIT
- 0,
- 0,
+ 0,
+ 0,
0,
0,
0,
**
** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong.
**
-** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with
+** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with
** error message text. The calling function should free this memory
** by calling sqlite3DbFree(db, ).
*/
/* Shared library endings to try if zFile cannot be loaded as written */
static const char *azEndings[] = {
#if SQLITE_OS_WIN
- "dll"
+ "dll"
#elif defined(__APPLE__)
"dylib"
#else
if( pzErrMsg ){
*pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
if( zErrmsg ){
- sqlite3_snprintf(nMsg, zErrmsg,
+ sqlite3_snprintf(nMsg, zErrmsg,
"unable to open shared library [%s]", zFile);
sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
}
/* If no entry point was specified and the default legacy
** entry point name "sqlite3_extension_init" was not found, then
** construct an entry point name "sqlite3_X_init" where the X is
- ** replaced by the lowercase value of every ASCII alphabetic
+ ** replaced by the lowercase value of every ASCII alphabetic
** character in the filename after the last "/" upto the first ".",
- ** and eliding the first three characters if they are "lib".
+ ** and eliding the first three characters if they are "lib".
** Examples:
**
** /usr/local/lib/libExample5.4.3.so ==> sqlite3_example_init
*/
typedef struct sqlite3AutoExtList sqlite3AutoExtList;
static SQLITE_WSD struct sqlite3AutoExtList {
- int nExt; /* Number of entries in aExt[] */
+ int nExt; /* Number of entries in aExt[] */
void (**aExt)(void); /* Pointers to the extension init functions */
} sqlite3Autoext = { 0, 0 };
/*
** Interpret the given string as a safety level. Return 0 for OFF,
-** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
+** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
** unrecognized string argument. The FULL option is disallowed
** if the omitFull parameter it 1.
**
/*
** Interpret the given string as an auto-vacuum mode value.
**
-** The following strings, "none", "full" and "incremental" are
+** The following strings, "none", "full" and "incremental" are
** acceptable, as are their numeric equivalents: 0, 1 and 2 respectively.
*/
static int getAutoVacuum(const char *z){
db->flags &= ~mask;
}
- /* Many of the flag-pragmas modify the code generated by the SQL
+ /* Many of the flag-pragmas modify the code generated by the SQL
** compiler (eg. count_changes). So add an opcode to expire all
** compiled SQL statements after modifying a pragma value.
*/
case OE_SetDflt: zName = "SET DEFAULT"; break;
case OE_Cascade: zName = "CASCADE"; break;
case OE_Restrict: zName = "RESTRICT"; break;
- default: zName = "NO ACTION";
+ default: zName = "NO ACTION";
assert( action==OE_None ); break;
}
return zName;
}
/*
-** Process a pragma statement.
+** Process a pragma statement.
**
** Pragmas are of this form:
**
** id and pId2 is any empty string.
*/
SQLITE_PRIVATE void sqlite3Pragma(
- Parse *pParse,
+ Parse *pParse,
Token *pId1, /* First part of [database.]id field */
Token *pId2, /* Second part of [database.]id field, or NULL */
Token *pValue, /* Token for <value>, or NULL */
if( iDb<0 ) return;
pDb = &db->aDb[iDb];
- /* If the temp database has been explicitly named as part of the
- ** pragma, make sure it is open.
+ /* If the temp database has been explicitly named as part of the
+ ** pragma, make sure it is open.
*/
if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){
return;
pParse->nErr++;
pParse->rc = rc;
}else
-
-
+
+
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
/*
** PRAGMA [database.]default_cache_size
** PRAGMA [database.]max_page_count=N
**
** The first form reports the current setting for the
- ** maximum number of pages in the database file. The
+ ** maximum number of pages in the database file. The
** second form attempts to change this setting. Both
** forms return the current setting.
**
if( sqlite3Tolower(zLeft[0])=='p' ){
sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
}else{
- sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg,
+ sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg,
sqlite3AbsInt32(sqlite3Atoi(zRight)));
}
sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1);
*/
rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
- /* When setting the auto_vacuum mode to either "full" or
+ /* When setting the auto_vacuum mode to either "full" or
** "incremental", write the value of meta[6] in the database
** file. Before writing to meta[6], check that meta[3] indicates
** that this really is an auto-vacuum capable database.
if( !zRight ){
if( sqlite3_temp_directory ){
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
"temp_store_directory", SQLITE_STATIC);
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_temp_directory, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
if( !zRight ){
if( sqlite3_data_directory ){
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
"data_store_directory", SQLITE_STATIC);
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_data_directory, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
Pager *pPager = sqlite3BtreePager(pDb->pBt);
char *proxy_file_path = NULL;
sqlite3_file *pFile = sqlite3PagerFile(pPager);
- sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE,
+ sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE,
&proxy_file_path);
-
+
if( proxy_file_path ){
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
"lock_proxy_file", SQLITE_STATIC);
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, proxy_file_path, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
sqlite3_file *pFile = sqlite3PagerFile(pPager);
int res;
if( zRight[0] ){
- res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
+ res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
zRight);
} else {
- res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
+ res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
NULL);
}
if( res!=SQLITE_OK ){
}
}
}else
-#endif /* SQLITE_ENABLE_LOCKING_STYLE */
-
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
+
/*
** PRAGMA [database.]synchronous
** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL
returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
}else{
if( !db->autoCommit ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"Safety level may not be changed inside a transaction");
}else{
pDb->safety_level = getSafetyLevel(zRight,0,1)+1;
v = sqlite3GetVdbe(pParse);
pIdx = pTab->pIndex;
if( pIdx ){
- int i = 0;
+ int i = 0;
sqlite3VdbeSetNumCols(v, 3);
pParse->nMem = 3;
sqlite3CodeVerifySchema(pParse, iDb);
v = sqlite3GetVdbe(pParse);
pFK = pTab->pFKey;
if( pFK ){
- int i = 0;
+ int i = 0;
sqlite3VdbeSetNumCols(v, 8);
pParse->nMem = 8;
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
}
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
- sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
pFK->zTo, P4_TRANSIENT);
sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
#endif
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
- /* Pragma "quick_check" is an experimental reduced version of
+ /* Pragma "quick_check" is an experimental reduced version of
** integrity_check designed to detect most database corruption
** without most of the overhead of a full integrity-check.
*/
if( sqlite3StrICmp(zLeft, "integrity_check")==0
- || sqlite3StrICmp(zLeft, "quick_check")==0
+ || sqlite3StrICmp(zLeft, "quick_check")==0
){
int i, j, addr, mxErr;
sqlite3VdbeChangeP1(v, addr+3, j+2);
sqlite3VdbeChangeP2(v, addr+3, addr+2);
sqlite3VdbeJumpHere(v, addr+4);
- sqlite3VdbeChangeP4(v, addr+6,
+ sqlite3VdbeChangeP4(v, addr+6,
"wrong # of entries in index ", P4_STATIC);
sqlite3VdbeChangeP4(v, addr+7, pIdx->zName, P4_TRANSIENT);
}
- }
+ }
}
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
sqlite3VdbeChangeP2(v, addr, -mxErr);
** encoding that will be used for the main database file if a new file
** is created. If an existing main database file is opened, then the
** default text encoding for the existing database is used.
- **
+ **
** In all cases new databases created using the ATTACH command are
** created to use the same default text encoding as the main database. If
** the main database has not been initialized and/or created when ATTACH
** will be overwritten when the schema is next loaded. If it does not
** already exists, it will be created to use the new encoding value.
*/
- if(
- !(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
- DbHasProperty(db, 0, DB_Empty)
+ if(
+ !(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
+ DbHasProperty(db, 0, DB_Empty)
){
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
** The user-version is not used internally by SQLite. It may be used by
** applications for any purpose.
*/
- if( sqlite3StrICmp(zLeft, "schema_version")==0
- || sqlite3StrICmp(zLeft, "user_version")==0
- || sqlite3StrICmp(zLeft, "freelist_count")==0
- || sqlite3StrICmp(zLeft, "application_id")==0
+ if( sqlite3StrICmp(zLeft, "schema_version")==0
+ || sqlite3StrICmp(zLeft, "user_version")==0
+ || sqlite3StrICmp(zLeft, "freelist_count")==0
+ || sqlite3StrICmp(zLeft, "application_id")==0
){
int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */
sqlite3VdbeUsesBtree(v, iDb);
if( zRight ){
sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight));
}
- returnSingleInt(pParse, "wal_autocheckpoint",
- db->xWalCallback==sqlite3WalDefaultHook ?
+ returnSingleInt(pParse, "wal_autocheckpoint",
+ db->xWalCallback==sqlite3WalDefaultHook ?
SQLITE_PTR_TO_INT(db->pWalArg) : 0);
}else
#endif
pBt = db->aDb[i].pBt;
if( pBt==0 || sqlite3BtreePager(pBt)==0 ){
zState = "closed";
- }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0,
+ }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0,
SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
zState = azLockName[j];
}
}else
#endif
-
+
{/* Empty ELSE clause */}
/*
sqlite3SetString(pData->pzErrMsg, db,
"malformed database schema (%s)", zObj);
if( zExtra ){
- *pData->pzErrMsg = sqlite3MAppendf(db, *pData->pzErrMsg,
+ *pData->pzErrMsg = sqlite3MAppendf(db, *pData->pzErrMsg,
"%s - %s", *pData->pzErrMsg, zExtra);
}
}
/*
** The master database table has a structure like this
*/
- static const char master_schema[] =
+ static const char master_schema[] =
"CREATE TABLE sqlite_master(\n"
" type text,\n"
" name text,\n"
")"
;
#ifndef SQLITE_OMIT_TEMPDB
- static const char temp_master_schema[] =
+ static const char temp_master_schema[] =
"CREATE TEMP TABLE sqlite_temp_master(\n"
" type text,\n"
" name text,\n"
}
/* If there is not already a read-only (or read-write) transaction opened
- ** on the b-tree database, open one now. If a transaction is opened, it
+ ** on the b-tree database, open one now. If a transaction is opened, it
** will be closed before this function returns. */
sqlite3BtreeEnter(pDb->pBt);
if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
assert( db->init.busy );
{
char *zSql;
- zSql = sqlite3MPrintf(db,
+ zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid",
db->aDb[iDb].zName, zMasterName);
#ifndef SQLITE_OMIT_AUTHORIZATION
}
if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){
/* Black magic: If the SQLITE_RecoveryMode flag is set, then consider
- ** the schema loaded, even if errors occurred. In this situation the
+ ** the schema loaded, even if errors occurred. In this situation the
** current sqlite3_prepare() operation will fail, but the following one
** will attempt to compile the supplied statement against whatever subset
** of the schema was loaded before the error occurred. The primary
SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
int i, rc;
int commit_internal = !(db->flags&SQLITE_InternChanges);
-
+
assert( sqlite3_mutex_held(db->mutex) );
rc = SQLITE_OK;
db->init.busy = 1;
sqlite3CommitInternalChanges(db);
}
- return rc;
+ return rc;
}
/*
if( pBt==0 ) continue;
/* If there is not already a read-only (or read-write) transaction opened
- ** on the b-tree database, open one now. If a transaction is opened, it
+ ** on the b-tree database, open one now. If a transaction is opened, it
** will be closed immediately after reading the meta-value. */
if( !sqlite3BtreeIsInReadTrans(pBt) ){
rc = sqlite3BtreeBeginTrans(pBt, 0);
openedTransaction = 1;
}
- /* Read the schema cookie from the database. If it does not match the
+ /* Read the schema cookie from the database. If it does not match the
** value stored as part of the in-memory schema representation,
** set Parse.rc to SQLITE_SCHEMA. */
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
int i = -1000000;
- /* If pSchema is NULL, then return -1000000. This happens when code in
+ /* If pSchema is NULL, then return -1000000. This happens when code in
** expr.c is trying to resolve a reference to a transient table (i.e. one
- ** created by a sub-select). In this case the return value of this
+ ** created by a sub-select). In this case the return value of this
** function should never be used.
**
** We return -1000000 instead of the more usual -1 simply because using
- ** -1000000 as the incorrect index into db->aDb[] is much
+ ** -1000000 as the incorrect index into db->aDb[] is much
** more likely to cause a segfault than -1 (of course there are assert()
** statements too, but it never hurts to play the odds).
*/
** This thread is currently holding mutexes on all Btrees (because
** of the sqlite3BtreeEnterAll() in sqlite3LockAndPrepare()) so it
** is not possible for another thread to start a new schema change
- ** while this routine is running. Hence, we do not need to hold
- ** locks on the schema, we just need to make sure nobody else is
+ ** while this routine is running. Hence, we do not need to hold
+ ** locks on the schema, we just need to make sure nobody else is
** holding them.
**
** Note that setting READ_UNCOMMITTED overrides most lock detection,
** Compile the UTF-16 encoded SQL statement zSql into a statement handle.
*/
static int sqlite3Prepare16(
- sqlite3 *db, /* Database handle. */
+ sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-16 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */
int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8));
*pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
}
- sqlite3DbFree(db, zSql8);
+ sqlite3DbFree(db, zSql8);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
** occurs.
*/
SQLITE_API int sqlite3_prepare16(
- sqlite3 *db, /* Database handle. */
+ sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-16 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
return rc;
}
SQLITE_API int sqlite3_prepare16_v2(
- sqlite3 *db, /* Database handle. */
+ sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-16 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
for(i=0; i<3 && apAll[i]; i++){
p = apAll[i];
for(j=0; j<ArraySize(aKeyword); j++){
- if( p->n==aKeyword[j].nChar
+ if( p->n==aKeyword[j].nChar
&& sqlite3StrNICmp((char*)p->z, &zKeyText[aKeyword[j].i], p->n)==0 ){
jointype |= aKeyword[j].code;
break;
sqlite3ErrorMsg(pParse, "unknown or unsupported join type: "
"%T %T%s%T", pA, pB, zSp, pC);
jointype = JT_INNER;
- }else if( (jointype & JT_OUTER)!=0
+ }else if( (jointype & JT_OUTER)!=0
&& (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"RIGHT and FULL OUTER JOINs are not currently supported");
jointype = JT_INNER;
}
/*
** Search the first N tables in pSrc, from left to right, looking for a
-** table that has a column named zCol.
+** table that has a column named zCol.
**
** When found, set *piTab and *piCol to the table index and column index
** of the matching column and return TRUE.
**
** (tab1.col1 = tab2.col2)
**
-** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the
+** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the
** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is
** column iColRight of tab2.
*/
p->iRightJoinTable = (i16)iTable;
setJoinExpr(p->pLeft, iTable);
p = p->pRight;
- }
+ }
}
/*
}
/* Create extra terms on the WHERE clause for each column named
- ** in the USING clause. Example: If the two tables to be joined are
+ ** in the USING clause. Example: If the two tables to be joined are
** A and B and the USING clause names X, Y, and Z, then add this
** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
** Report an error if any column mentioned in the USING clause is
pDest->iSdst = pParse->nMem+1;
pDest->nSdst = nResultCol;
pParse->nMem += nResultCol;
- }else{
+ }else{
assert( pDest->nSdst==nResultCol );
}
regResult = pDest->iSdst;
** where iSub1 and iSub2 are the integers passed as the corresponding
** function parameters, and op is the text representation of the parameter
** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT,
-** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is
+** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is
** false, or the second form if it is true.
*/
static void explainComposite(
#endif
default: {
int i;
- assert( eDest==SRT_Output || eDest==SRT_Coroutine );
+ assert( eDest==SRT_Output || eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
testcase( eDest==SRT_Coroutine );
for(i=0; i<nColumn; i++){
** original CREATE TABLE statement if the expression is a column. The
** declaration type for a ROWID field is INTEGER. Exactly when an expression
** is considered a column can be complex in the presence of subqueries. The
-** result-set expression in all of the following SELECT statements is
+** result-set expression in all of the following SELECT statements is
** considered a column by this function.
**
** SELECT col FROM tbl;
** SELECT (SELECT col FROM tbl;
** SELECT (SELECT col FROM tbl);
** SELECT abc FROM (SELECT col AS abc FROM tbl);
-**
+**
** The declaration type for any expression other than a column is NULL.
*/
static const char *columnType(
- NameContext *pNC,
+ NameContext *pNC,
Expr *pExpr,
const char **pzOriginDb,
const char **pzOriginTab,
if( pTab==0 ){
/* At one time, code such as "SELECT new.x" within a trigger would
** cause this condition to run. Since then, we have restructured how
- ** trigger code is generated and so this condition is no longer
+ ** trigger code is generated and so this condition is no longer
** possible. However, it can still be true for statements like
** the following:
**
** CREATE TABLE t1(col INTEGER);
** SELECT (SELECT t1.col) FROM FROM t1;
**
- ** when columnType() is called on the expression "t1.col" in the
+ ** when columnType() is called on the expression "t1.col" in the
** sub-select. In this case, set the column type to NULL, even
** though it should really be "INTEGER".
**
** This is not a problem, as the column type of "t1.col" is never
- ** used. When columnType() is called on the expression
+ ** used. When columnType() is called on the expression
** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT
** branch below. */
break;
*/
if( iCol>=0 && ALWAYS(iCol<pS->pEList->nExpr) ){
/* If iCol is less than zero, then the expression requests the
- ** rowid of the sub-select or view. This expression is legal (see
+ ** rowid of the sub-select or view. This expression is legal (see
** test case misc2.2.2) - it always evaluates to NULL.
*/
NameContext sNC;
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
+ zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
}
}else if( ALWAYS(pTab->pSchema) ){
/* A real table */
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
+ zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
break;
}
#endif
}
-
+
if( pzOriginDb ){
assert( pzOriginTab && pzOriginCol );
*pzOriginDb = zOriginDb;
const char *zOrigCol = 0;
zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
- /* The vdbe must make its own copy of the column-type and other
+ /* The vdbe must make its own copy of the column-type and other
** column specific strings, in case the schema is reset before this
** virtual machine is deleted.
*/
zCol = pTab->aCol[iCol].zName;
}
if( !shortNames && !fullNames ){
- sqlite3VdbeSetColName(v, i, COLNAME_NAME,
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME,
sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
}else if( fullNames ){
char *zName = 0;
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
}
}else{
- sqlite3VdbeSetColName(v, i, COLNAME_NAME,
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME,
sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
}
}
/*
** Add type and collation information to a column list based on
** a SELECT statement.
-**
+**
** The column list presumably came from selectColumnNamesFromExprList().
** The column list has only names, not types or collations. This
** routine goes through and adds the types and collations.
** Compute the iLimit and iOffset fields of the SELECT based on the
** pLimit and pOffset expressions. pLimit and pOffset hold the expressions
** that appear in the original SQL statement after the LIMIT and OFFSET
-** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
-** are the integer memory register numbers for counters used to compute
-** the limit and offset. If there is no limit and/or offset, then
+** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
+** are the integer memory register numbers for counters used to compute
+** the limit and offset. If there is no limit and/or offset, then
** iLimit and iOffset are negative.
**
** This routine changes the values of iLimit and iOffset only if
int addr1, n;
if( p->iLimit ) return;
- /*
+ /*
** "LIMIT -1" always shows all rows. There is some
** contraversy about what the correct behavior should be.
** The current implementation interprets "LIMIT 0" to mean
**
** "p" points to the right-most of the two queries. the query on the
** left is p->pPrior. The left query could also be a compound query
-** in which case this routine will be called recursively.
+** in which case this routine will be called recursively.
**
** The results of the total query are to be written into a destination
** of type eDest with parameter iParm.
p->nSelectRow += pPrior->nSelectRow;
if( pPrior->pLimit
&& sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
- && p->nSelectRow > (double)nLimit
+ && p->nSelectRow > (double)nLimit
){
p->nSelectRow = (double)nLimit;
}
explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL);
- /* Compute collating sequences used by
+ /* Compute collating sequences used by
** temporary tables needed to implement the compound select.
** Attach the KeyInfo structure to all temporary tables.
**
addr = sqlite3VdbeCurrentAddr(v);
iContinue = sqlite3VdbeMakeLabel(v);
- /* Suppress duplicates for UNION, EXCEPT, and INTERSECT
+ /* Suppress duplicates for UNION, EXCEPT, and INTERSECT
*/
if( regPrev ){
int j1, j2;
case SRT_Set: {
int r1;
assert( pIn->nSdst==1 );
- pDest->affSdst =
+ pDest->affSdst =
sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst);
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1);
** SRT_Output. This routine is never called with any other
** destination other than the ones handled above or SRT_Output.
**
- ** For SRT_Output, results are stored in a sequence of registers.
+ ** For SRT_Output, results are stored in a sequence of registers.
** Then the OP_ResultRow opcode is used to cause sqlite3_step() to
** return the next row of result.
*/
**
** EofB: Called when data is exhausted from selectB.
**
-** The implementation of the latter five subroutines depend on which
+** The implementation of the latter five subroutines depend on which
** <operator> is used:
**
**
/* Patch up the ORDER BY clause
*/
- op = p->op;
+ op = p->op;
pPrior = p->pPrior;
assert( pPrior->pOrderBy==0 );
pOrderBy = p->pOrderBy;
}
}
}
-
+
/* Separate the left and the right query from one another
*/
p->pPrior = 0;
sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
VdbeNoopComment((v, "End coroutine for left SELECT"));
- /* Generate a coroutine to evaluate the SELECT statement on
+ /* Generate a coroutine to evaluate the SELECT statement on
** the right - the "B" select
*/
addrSelectB = sqlite3VdbeCurrentAddr(v);
savedLimit = p->iLimit;
savedOffset = p->iOffset;
p->iLimit = regLimitB;
- p->iOffset = 0;
+ p->iOffset = 0;
explainSetInteger(iSub2, pParse->iNextSelectId);
sqlite3Select(pParse, p, &destB);
p->iLimit = savedLimit;
addrOutA = generateOutputSubroutine(pParse,
p, &destA, pDest, regOutA,
regPrev, pKeyDup, P4_KEYINFO_HANDOFF, labelEnd);
-
+
/* Generate a subroutine that outputs the current row of the B
** select as the next output row of the compound select.
*/
VdbeNoopComment((v, "eof-A subroutine"));
if( op==TK_EXCEPT || op==TK_INTERSECT ){
addrEofA = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd);
- }else{
+ }else{
addrEofA = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd);
sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
if( op==TK_INTERSECT ){
addrEofB = addrEofA;
if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
- }else{
+ }else{
VdbeNoopComment((v, "eof-B subroutine"));
addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
/*
** Scan through the expression pExpr. Replace every reference to
** a column in table number iTable with a copy of the iColumn-th
-** entry in pEList. (But leave references to the ROWID column
+** entry in pEList. (But leave references to the ROWID column
** unchanged.)
**
** This routine is part of the flattening procedure. A subquery
** whose result set is defined by pEList appears as entry in the
** FROM clause of a SELECT such that the VDBE cursor assigned to that
-** FORM clause entry is iTable. This routine make the necessary
+** FORM clause entry is iTable. This routine make the necessary
** changes to pExpr so that it refers directly to the source table
** of the subquery rather the result set of the subquery.
*/
** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5
**
** The code generated for this simpification gives the same result
-** but only has to scan the data once. And because indices might
+** but only has to scan the data once. And because indices might
** exist on the table t1, a complete scan of the data might be
** avoided.
**
** (4) The subquery is not DISTINCT.
**
** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT
-** sub-queries that were excluded from this optimization. Restriction
+** sub-queries that were excluded from this optimization. Restriction
** (4) has since been expanded to exclude all DISTINCT subqueries.
**
** (6) The subquery does not use aggregates or the outer query is not
**
** (16) The outer query is not an aggregate or the subquery does
** not contain ORDER BY. (Ticket #2942) This used to not matter
-** until we introduced the group_concat() function.
+** until we introduced the group_concat() function.
**
-** (17) The sub-query is not a compound select, or it is a UNION ALL
-** compound clause made up entirely of non-aggregate queries, and
+** (17) The sub-query is not a compound select, or it is a UNION ALL
+** compound clause made up entirely of non-aggregate queries, and
** the parent query:
**
** * is not itself part of a compound select,
** syntax error and return a detailed message.
**
** (18) If the sub-query is a compound select, then all terms of the
-** ORDER by clause of the parent must be simple references to
+** ORDER by clause of the parent must be simple references to
** columns of the sub-query.
**
** (19) The subquery does not use LIMIT or the outer query does not
}
/* OBSOLETE COMMENT 1:
- ** Restriction 3: If the subquery is a join, make sure the subquery is
+ ** Restriction 3: If the subquery is a join, make sure the subquery is
** not used as the right operand of an outer join. Examples of why this
** is not allowed:
**
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
assert( pSub->pSrc!=0 );
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
- || (pSub1->pPrior && pSub1->op!=TK_ALL)
+ || (pSub1->pPrior && pSub1->op!=TK_ALL)
|| pSub1->pSrc->nSrc<1
|| pSub->pEList->nExpr!=pSub1->pEList->nExpr
){
pParse->zAuthContext = zSavedAuthContext;
/* If the sub-query is a compound SELECT statement, then (by restrictions
- ** 17 and 18 above) it must be a UNION ALL and the parent query must
+ ** 17 and 18 above) it must be a UNION ALL and the parent query must
** be of the form:
**
- ** SELECT <expr-list> FROM (<sub-query>) <where-clause>
+ ** SELECT <expr-list> FROM (<sub-query>) <where-clause>
**
** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block
- ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or
+ ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or
** OFFSET clauses and joins them to the left-hand-side of the original
** using UNION ALL operators. In this case N is the number of simple
** select statements in the compound sub-query.
if( db->mallocFailed ) return 1;
}
- /* Begin flattening the iFrom-th entry of the FROM clause
+ /* Begin flattening the iFrom-th entry of the FROM clause
** in the outer query.
*/
pSub = pSub1 = pSubitem->pSelect;
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
pSrc->a[iFrom].jointype = jointype;
-
- /* Now begin substituting subquery result set expressions for
+
+ /* Now begin substituting subquery result set expressions for
** references to the iParent in the outer query.
- **
+ **
** Example:
**
** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
pParent->pHaving = pParent->pWhere;
pParent->pWhere = pWhere;
pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
- pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving,
+ pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving,
sqlite3ExprDup(db, pSub->pHaving, 0));
assert( pParent->pGroupBy==0 );
pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList);
pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere);
}
-
+
/* The flattened query is distinct if either the inner or the
- ** outer query is distinct.
+ ** outer query is distinct.
*/
pParent->selFlags |= pSub->selFlags & SF_Distinct;
-
+
/*
** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
**
** * the argument to the aggregate function is a column value.
**
** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX
-** is returned as appropriate. Also, *ppMinMax is set to point to the
+** is returned as appropriate. Also, *ppMinMax is set to point to the
** list of arguments passed to the aggregate before returning.
**
** Or, if the conditions above are not met, *ppMinMax is set to 0 and
/*
** The select statement passed as the first argument is an aggregate query.
-** The second argment is the associated aggregate-info object. This
+** The second argment is the associated aggregate-info object. This
** function tests if the SELECT is of the form:
**
** SELECT count(*) FROM <tbl>
assert( !p->pGroupBy );
- if( p->pWhere || p->pEList->nExpr!=1
+ if( p->pWhere || p->pEList->nExpr!=1
|| p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect
){
return 0;
/*
** If the source-list item passed as an argument was augmented with an
** INDEXED BY clause, then try to locate the specified index. If there
-** was such a clause and the named index cannot be found, return
-** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
+** was such a clause and the named index cannot be found, return
+** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
** pFrom->pIndex and return SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
Table *pTab = pFrom->pTab;
char *zIndex = pFrom->zIndex;
Index *pIdx;
- for(pIdx=pTab->pIndex;
- pIdx && sqlite3StrICmp(pIdx->zName, zIndex);
+ for(pIdx=pTab->pIndex;
+ pIdx && sqlite3StrICmp(pIdx->zName, zIndex);
pIdx=pIdx->pNext
);
if( !pIdx ){
return SQLITE_OK;
}
/*
-** Detect compound SELECT statements that use an ORDER BY clause with
+** Detect compound SELECT statements that use an ORDER BY clause with
** an alternative collating sequence.
**
** SELECT ... FROM t1 EXCEPT SELECT ... FROM t2 ORDER BY .. COLLATE ...
** (1) Make sure VDBE cursor numbers have been assigned to every
** element of the FROM clause.
**
-** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
+** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
** defines FROM clause. When views appear in the FROM clause,
** fill pTabList->a[].pSelect with a copy of the SELECT statement
** that implements the view. A copy is made of the view's SELECT
if( (pFrom->jointype & JT_NATURAL)!=0
&& tableAndColumnIndex(pTabList, i, zName, 0, 0)
){
- /* In a NATURAL join, omit the join columns from the
+ /* In a NATURAL join, omit the join columns from the
** table to the right of the join */
continue;
}
**
** When this routine is the Walker.xExprCallback then expression trees
** are walked without any actions being taken at each node. Presumably,
-** when this routine is used for Walker.xExprCallback then
-** Walker.xSelectCallback is set to do something useful for every
+** when this routine is used for Walker.xExprCallback then
+** Walker.xSelectCallback is set to do something useful for every
** subquery in the parser tree.
*/
static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
}
/* Before populating the accumulator registers, clear the column cache.
- ** Otherwise, if any of the required column values are already present
+ ** Otherwise, if any of the required column values are already present
** in registers, sqlite3ExprCode() may use OP_SCopy to copy the value
** to pC->iMem. But by the time the value is used, the original register
** may have been used, invalidating the underlying buffer holding the
){
if( pParse->explain==2 ){
char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s %s%s(~%d rows)",
- pTab->zName,
+ pTab->zName,
pIdx ? "USING COVERING INDEX " : "",
pIdx ? pIdx->zName : "",
pTab->nRowEst
#endif
/*
-** Generate code for the SELECT statement given in the p argument.
+** Generate code for the SELECT statement given in the p argument.
**
** The results are distributed in various ways depending on the
** contents of the SelectDest structure pointed to by argument pDest
** of the query. This destination implies "LIMIT 1".
**
** SRT_Set The result must be a single column. Store each
-** row of result as the key in table pDest->iSDParm.
+** row of result as the key in table pDest->iSDParm.
** Apply the affinity pDest->affSdst before storing
** results. Used to implement "IN (SELECT ...)".
**
-** SRT_Union Store results as a key in a temporary table
+** SRT_Union Store results as a key in a temporary table
** identified by pDest->iSDParm.
**
** SRT_Except Remove results from the temporary table pDest->iSDParm.
memset(&sAggInfo, 0, sizeof(sAggInfo));
if( IgnorableOrderby(pDest) ){
- assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
+ assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
/* If ORDER BY makes no difference in the output then neither does
** DISTINCT so it can be removed too. */
addrEof = ++pParse->nMem;
/* Before coding the OP_Goto to jump to the start of the main routine,
** ensure that the jump to the verify-schema routine has already
- ** been coded. Otherwise, the verify-schema would likely be coded as
- ** part of the co-routine. If the main routine then accessed the
- ** database before invoking the co-routine for the first time (for
- ** example to initialize a LIMIT register from a sub-select), it would
- ** be doing so without having verified the schema version and obtained
+ ** been coded. Otherwise, the verify-schema would likely be coded as
+ ** part of the co-routine. If the main routine then accessed the
+ ** database before invoking the co-routine for the first time (for
+ ** example to initialize a LIMIT register from a sub-select), it would
+ ** be doing so without having verified the schema version and obtained
** the required db locks. See ticket d6b36be38. */
sqlite3CodeVerifySchema(pParse, -1);
sqlite3VdbeAddOp0(v, OP_Goto);
pOrderBy = 0;
}
- /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
+ /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
** if the select-list is the same as the ORDER BY list, then this query
** can be rewritten as a GROUP BY. In other words, this:
**
**
** SELECT xyz FROM ... GROUP BY xyz
**
- ** The second form is preferred as a single index (or temp-table) may be
- ** used for both the ORDER BY and DISTINCT processing. As originally
- ** written the query must use a temp-table for at least one of the ORDER
+ ** The second form is preferred as a single index (or temp-table) may be
+ ** used for both the ORDER BY and DISTINCT processing. As originally
+ ** written the query must use a temp-table for at least one of the ORDER
** BY and DISTINCT, and an index or separate temp-table for the other.
*/
- if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
+ if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
&& sqlite3ExprListCompare(pOrderBy, p->pEList)==0
){
p->selFlags &= ~SF_Distinct;
}
/* If there is an ORDER BY clause, then this sorting
- ** index might end up being unused if the data can be
+ ** index might end up being unused if the data can be
** extracted in pre-sorted order. If that is the case, then the
** OP_OpenEphemeral instruction will be changed to an OP_Noop once
** we figure out that the sorting index is not needed. The addrSortIndex
if( pWInfo->eDistinct ) sDistinct.eTnctType = pWInfo->eDistinct;
if( pOrderBy && pWInfo->nOBSat==pOrderBy->nExpr ) pOrderBy = 0;
- /* If sorting index that was created by a prior OP_OpenEphemeral
+ /* If sorting index that was created by a prior OP_OpenEphemeral
** instruction ended up not being needed, then change the OP_OpenEphemeral
** into an OP_Noop.
*/
p->nSelectRow = (double)1;
}
-
+
/* Create a label to jump to when we want to abort the query */
addrEnd = sqlite3VdbeMakeLabel(v);
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
** that we do not need it after all, the OP_SorterOpen instruction
- ** will be converted into a Noop.
+ ** will be converted into a Noop.
*/
sAggInfo.sortingIdx = pParse->nTab++;
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
- addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
- sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
+ addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
+ sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
/* Initialize memory locations used by GROUP BY aggregate processing
int nCol;
int nGroupBy;
- explainTempTable(pParse,
+ explainTempTable(pParse,
(sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ?
"DISTINCT" : "GROUP BY");
int r1 = j + regBase;
int r2;
- r2 = sqlite3ExprCodeGetColumn(pParse,
+ r2 = sqlite3ExprCodeGetColumn(pParse,
pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
if( r1!=r2 ){
sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
sqlite3VdbeResolveLabel(v, addrReset);
resetAccumulator(pParse, &sAggInfo);
sqlite3VdbeAddOp1(v, OP_Return, regReset);
-
+
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
ExprList *pDel = 0;
**
** (2011-04-15) Do not do a full scan of an unordered index.
**
- ** In practice the KeyInfo structure will not be used. It is only
+ ** In practice the KeyInfo structure will not be used. It is only
** passed to keep OP_OpenRead happy.
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
** SELECT max(x) FROM ...
**
** If it is, then ask the code in where.c to attempt to sort results
- ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause.
+ ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause.
** If where.c is able to produce results sorted in this order, then
- ** add vdbe code to break out of the processing loop after the
- ** first iteration (since the first iteration of the loop is
- ** guaranteed to operate on the row with the minimum or maximum
+ ** add vdbe code to break out of the processing loop after the
+ ** first iteration (since the first iteration of the loop is
+ ** guaranteed to operate on the row with the minimum or maximum
** value of x, the only row required).
**
** A special flag must be passed to sqlite3WhereBegin() to slightly
** for x.
**
** + The optimizer code in where.c (the thing that decides which
- ** index or indices to use) should place a different priority on
+ ** index or indices to use) should place a different priority on
** satisfying the 'ORDER BY' clause than it does in other cases.
** Refer to code and comments in where.c for details.
*/
ExprList *pMinMax = 0;
u8 flag = WHERE_ORDERBY_NORMAL;
-
+
assert( p->pGroupBy==0 );
assert( flag==0 );
if( p->pHaving==0 ){
pMinMax->a[0].pExpr->op = TK_COLUMN;
}
}
-
+
/* This case runs if the aggregate has no GROUP BY clause. The
** processing is much simpler since there is only a single row
** of output.
pOrderBy = 0;
sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
- selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, 0,
+ selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, 0,
pDest, addrEnd, addrEnd);
sqlite3ExprListDelete(db, pDel);
}
sqlite3VdbeResolveLabel(v, addrEnd);
-
+
} /* endif aggregate query */
if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){
** at the conclusion of the call.
**
** The result that is written to ***pazResult is held in memory obtained
-** from malloc(). But the caller cannot free this memory directly.
+** from malloc(). But the caller cannot free this memory directly.
** Instead, the entire table should be passed to sqlite3_free_table() when
** the calling procedure is finished using it.
*/
}
/*
-** Given table pTab, return a list of all the triggers attached to
+** Given table pTab, return a list of all the triggers attached to
** the table. The list is connected by Trigger.pNext pointers.
**
** All of the triggers on pTab that are in the same database as pTab
for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
Trigger *pTrig = (Trigger *)sqliteHashData(p);
if( pTrig->pTabSchema==pTab->pSchema
- && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
+ && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
){
pTrig->pNext = (pList ? pList : pTab->pTrigger);
pList = pTrig;
/* Ensure the table name matches database name and that the table exists */
if( db->mallocFailed ) goto trigger_cleanup;
assert( pTableName->nSrc==1 );
- if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
+ if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
sqlite3FixSrcList(&sFix, pTableName) ){
goto trigger_cleanup;
}
** of triggers.
*/
if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
- sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
+ sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
(tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
goto trigger_cleanup;
}
}
nameToken.z = pTrig->zName;
nameToken.n = sqlite3Strlen30(nameToken.z);
- if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
+ if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
&& sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
goto triggerfinish_cleanup;
}
** a trigger step. Return a pointer to a TriggerStep structure.
**
** The parser calls this routine when it finds a SELECT statement in
-** body of a TRIGGER.
+** body of a TRIGGER.
*/
SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
return pTriggerStep;
}
-/*
+/*
** Recursively delete a Trigger structure
*/
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
}
/*
-** This function is called to drop a trigger from the database schema.
+** This function is called to drop a trigger from the database schema.
**
** This may be called directly from the parser and therefore identifies
** the trigger by name. The sqlite3DropTriggerPtr() routine does the
/*
-** Drop a trigger given a pointer to that trigger.
+** Drop a trigger given a pointer to that trigger.
*/
SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
Table *pTable;
for(e=0; e<pEList->nExpr; e++){
if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
}
- return 0;
+ return 0;
}
/*
** Return a list of all triggers on table pTab if there exists at least
-** one trigger that must be fired when an operation of type 'op' is
+** one trigger that must be fired when an operation of type 'op' is
** performed on the table, and, if that operation is an UPDATE, if at
** least one of the columns in pChanges is being modified.
*/
}
/*
-** Generate VDBE code for the statements inside the body of a single
+** Generate VDBE code for the statements inside the body of a single
** trigger.
*/
static int codeTriggerProgram(
Parse *pParse, /* The parser context */
TriggerStep *pStepList, /* List of statements inside the trigger body */
- int orconf /* Conflict algorithm. (OE_Abort, etc) */
+ int orconf /* Conflict algorithm. (OE_Abort, etc) */
){
TriggerStep *pStep;
Vdbe *v = pParse->pVdbe;
*/
pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
- /* Clear the cookieGoto flag. When coding triggers, the cookieGoto
+ /* Clear the cookieGoto flag. When coding triggers, the cookieGoto
** variable is used as a flag to indicate to sqlite3ExprCodeConstants()
** that it is not safe to refactor constants (this happens after the
- ** start of the first loop in the SQL statement is coded - at that
- ** point code may be conditionally executed, so it is no longer safe to
+ ** start of the first loop in the SQL statement is coded - at that
+ ** point code may be conditionally executed, so it is no longer safe to
** initialize constant register values). */
assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 );
pParse->cookieGoto = 0;
switch( pStep->op ){
case TK_UPDATE: {
- sqlite3Update(pParse,
+ sqlite3Update(pParse,
targetSrcList(pParse, pStep),
- sqlite3ExprListDup(db, pStep->pExprList, 0),
- sqlite3ExprDup(db, pStep->pWhere, 0),
+ sqlite3ExprListDup(db, pStep->pExprList, 0),
+ sqlite3ExprDup(db, pStep->pWhere, 0),
pParse->eOrconf
);
break;
}
case TK_INSERT: {
- sqlite3Insert(pParse,
+ sqlite3Insert(pParse,
targetSrcList(pParse, pStep),
- sqlite3ExprListDup(db, pStep->pExprList, 0),
- sqlite3SelectDup(db, pStep->pSelect, 0),
- sqlite3IdListDup(db, pStep->pIdList),
+ sqlite3ExprListDup(db, pStep->pExprList, 0),
+ sqlite3SelectDup(db, pStep->pSelect, 0),
+ sqlite3IdListDup(db, pStep->pIdList),
pParse->eOrconf
);
break;
}
case TK_DELETE: {
- sqlite3DeleteFrom(pParse,
+ sqlite3DeleteFrom(pParse,
targetSrcList(pParse, pStep),
sqlite3ExprDup(db, pStep->pWhere, 0)
);
sqlite3SelectDelete(db, pSelect);
break;
}
- }
+ }
if( pStep->op!=TK_SELECT ){
sqlite3VdbeAddOp0(v, OP_ResetCount);
}
}
/*
-** Create and populate a new TriggerPrg object with a sub-program
+** Create and populate a new TriggerPrg object with a sub-program
** implementing trigger pTrigger with ON CONFLICT policy orconf.
*/
static TriggerPrg *codeRowTrigger(
assert( pTop->pVdbe );
/* Allocate the TriggerPrg and SubProgram objects. To ensure that they
- ** are freed if an error occurs, link them into the Parse.pTriggerPrg
+ ** are freed if an error occurs, link them into the Parse.pTriggerPrg
** list of the top-level Parse object sooner rather than later. */
pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg));
if( !pPrg ) return 0;
pPrg->aColmask[0] = 0xffffffff;
pPrg->aColmask[1] = 0xffffffff;
- /* Allocate and populate a new Parse context to use for coding the
+ /* Allocate and populate a new Parse context to use for coding the
** trigger sub-program. */
pSubParse = sqlite3StackAllocZero(db, sizeof(Parse));
if( !pSubParse ) return 0;
v = sqlite3GetVdbe(pSubParse);
if( v ){
- VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)",
+ VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)",
pTrigger->zName, onErrorText(orconf),
(pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"),
(pTrigger->op==TK_UPDATE ? "UPDATE" : ""),
pTab->zName
));
#ifndef SQLITE_OMIT_TRACE
- sqlite3VdbeChangeP4(v, -1,
+ sqlite3VdbeChangeP4(v, -1,
sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC
);
#endif
/* If one was specified, code the WHEN clause. If it evaluates to false
- ** (or NULL) the sub-vdbe is immediately halted by jumping to the
+ ** (or NULL) the sub-vdbe is immediately halted by jumping to the
** OP_Halt inserted at the end of the program. */
if( pTrigger->pWhen ){
pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0);
- if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
- && db->mallocFailed==0
+ if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
+ && db->mallocFailed==0
){
iEndTrigger = sqlite3VdbeMakeLabel(v);
sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
return pPrg;
}
-
+
/*
** Return a pointer to a TriggerPrg object containing the sub-program for
** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such
** process of being coded). If this is the case, then an entry with
** a matching TriggerPrg.pTrigger field will be present somewhere
** in the Parse.pTriggerPrg list. Search for such an entry. */
- for(pPrg=pRoot->pTriggerPrg;
- pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf);
+ for(pPrg=pRoot->pTriggerPrg;
+ pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf);
pPrg=pPrg->pNext
);
}
/*
-** Generate code for the trigger program associated with trigger p on
+** Generate code for the trigger program associated with trigger p on
** table pTab. The reg, orconf and ignoreJump parameters passed to this
** function are the same as those described in the header function for
** sqlite3CodeRowTrigger()
pPrg = getRowTrigger(pParse, p, pTab, orconf);
assert( pPrg || pParse->nErr || pParse->db->mallocFailed );
- /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
+ /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
** is a pointer to the sub-vdbe containing the trigger program. */
if( pPrg ){
int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers));
** If there are no triggers that fire at the specified time for the specified
** operation on pTab, this function is a no-op.
**
-** The reg argument is the address of the first in an array of registers
+** The reg argument is the address of the first in an array of registers
** that contain the values substituted for the new.* and old.* references
** in the trigger program. If N is the number of columns in table pTab
** (a copy of pTab->nCol), then registers are populated as follows:
** reg+N+N+1 NEW.* value of right-most column of pTab
**
** For ON DELETE triggers, the registers containing the NEW.* values will
-** never be accessed by the trigger program, so they are not allocated or
-** populated by the caller (there is no data to populate them with anyway).
+** never be accessed by the trigger program, so they are not allocated or
+** populated by the caller (there is no data to populate them with anyway).
** Similarly, for ON INSERT triggers the values stored in the OLD.* registers
** are never accessed, and so are not allocated by the caller. So, for an
** ON INSERT trigger, the value passed to this function as parameter reg
-** is not a readable register, although registers (reg+N) through
+** is not a readable register, although registers (reg+N) through
** (reg+N+N+1) are.
**
** Parameter orconf is the default conflict resolution algorithm for the
** or else it must be a TEMP trigger. */
assert( p->pSchema!=0 );
assert( p->pTabSchema!=0 );
- assert( p->pSchema==p->pTabSchema
+ assert( p->pSchema==p->pTabSchema
|| p->pSchema==pParse->db->aDb[1].pSchema );
/* Determine whether we should code this trigger */
- if( p->op==op
- && p->tr_tm==tr_tm
+ if( p->op==op
+ && p->tr_tm==tr_tm
&& checkColumnOverlap(p->pColumns, pChanges)
){
sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
}
/*
-** Triggers may access values stored in the old.* or new.* pseudo-table.
-** This function returns a 32-bit bitmask indicating which columns of the
-** old.* or new.* tables actually are used by triggers. This information
+** Triggers may access values stored in the old.* or new.* pseudo-table.
+** This function returns a 32-bit bitmask indicating which columns of the
+** old.* or new.* tables actually are used by triggers. This information
** may be used by the caller, for example, to avoid having to load the entire
** old.* record into memory when executing an UPDATE or DELETE command.
**
** are more than 32 columns in the table, and at least one of the columns
** with an index greater than 32 may be accessed, 0xffffffff is returned.
**
-** It is not possible to determine if the old.rowid or new.rowid column is
+** It is not possible to determine if the old.rowid or new.rowid column is
** accessed by triggers. The caller must always assume that it is.
**
** Parameter isNew must be either 1 or 0. If it is 0, then the mask returned
/*
** The most recently coded instruction was an OP_Column to retrieve the
-** i-th column of table pTab. This routine sets the P4 parameter of the
+** i-th column of table pTab. This routine sets the P4 parameter of the
** OP_Column to the default value, if any.
**
-** The default value of a column is specified by a DEFAULT clause in the
+** The default value of a column is specified by a DEFAULT clause in the
** column definition. This was either supplied by the user when the table
** was created, or added later to the table definition by an ALTER TABLE
** command. If the latter, then the row-records in the table btree on disk
** If the former, then all row-records are guaranteed to include a value
** for the column and the P4 value is not required.
**
-** Column definitions created by an ALTER TABLE command may only have
+** Column definitions created by an ALTER TABLE command may only have
** literal default values specified: a number, null or a string. (If a more
-** complicated default expression value was provided, it is evaluated
+** complicated default expression value was provided, it is evaluated
** when the ALTER TABLE is executed and one of the literal values written
** into the sqlite_master table.)
**
** sqlite3_value objects.
**
** If parameter iReg is not negative, code an OP_RealAffinity instruction
-** on register iReg. This is used when an equivalent integer value is
-** stored in place of an 8-byte floating point value in order to save
+** on register iReg. This is used when an equivalent integer value is
+** stored in place of an 8-byte floating point value in order to save
** space.
*/
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
Column *pCol = &pTab->aCol[i];
VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
assert( i<pTab->nCol );
- sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc,
+ sqlite3ValueFromExpr(sqlite3VdbeDb(v), pCol->pDflt, enc,
pCol->affinity, &pValue);
if( pValue ){
sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM);
}
assert( pTabList->nSrc==1 );
- /* Locate the table which we want to update.
+ /* Locate the table which we want to update.
*/
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ) goto update_cleanup;
}
if( !isView ){
- /*
+ /*
** Open every index that needs updating. Note that if any
- ** index could potentially invoke a REPLACE conflict resolution
+ ** index could potentially invoke a REPLACE conflict resolution
** action, then we need to open all indices because we might need
** to be deleting some records.
*/
- if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
+ if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
if( onError==OE_Replace ){
openAll = 1;
}else{
sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid);
}
- /* If there are triggers on this table, populate an array of registers
+ /* If there are triggers on this table, populate an array of registers
** with the required old.* column data. */
if( hasFK || pTrigger ){
u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0);
- oldmask |= sqlite3TriggerColmask(pParse,
+ oldmask |= sqlite3TriggerColmask(pParse,
pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
);
for(i=0; i<pTab->nCol; i++){
** If there are one or more BEFORE triggers, then do not populate the
** registers associated with columns that are (a) not modified by
** this UPDATE statement and (b) not accessed by new.* references. The
- ** values for registers not modified by the UPDATE must be reloaded from
- ** the database after the BEFORE triggers are fired anyway (as the trigger
+ ** values for registers not modified by the UPDATE must be reloaded from
+ ** the database after the BEFORE triggers are fired anyway (as the trigger
** may have modified them). So not loading those that are not going to
** be used eliminates some redundant opcodes.
*/
if( j>=0 ){
sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
}else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){
- /* This branch loads the value of a column that will not be changed
+ /* This branch loads the value of a column that will not be changed
** into a register. This is done if there are no BEFORE triggers, or
** if there are one or more BEFORE triggers that use this value via
** a new.* reference in a trigger program.
if( tmask&TRIGGER_BEFORE ){
sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol);
sqlite3TableAffinityStr(v, pTab);
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
TRIGGER_BEFORE, pTab, regOldRowid, onError, addr);
/* The row-trigger may have deleted the row being updated. In this
- ** case, jump to the next row. No updates or AFTER triggers are
+ ** case, jump to the next row. No updates or AFTER triggers are
** required. This behavior - what happens when the row being updated
** is deleted or renamed by a BEFORE trigger - is left undefined in the
** documentation.
*/
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);
- /* If it did not delete it, the row-trigger may still have modified
- ** some of the columns of the row being updated. Load the values for
- ** all columns not modified by the update statement into their
+ /* If it did not delete it, the row-trigger may still have modified
+ ** some of the columns of the row being updated. Load the values for
+ ** all columns not modified by the update statement into their
** registers in case this has happened.
*/
for(i=0; i<pTab->nCol; i++){
/* Delete the index entries associated with the current record. */
j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid);
sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx);
-
+
/* If changing the record number, delete the old record. */
if( hasFK || chngRowid ){
sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0);
if( hasFK ){
sqlite3FkCheck(pParse, pTab, 0, regNewRowid);
}
-
+
/* Insert the new index entries and the new record. */
sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx, 1, 0, 0);
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
** handle rows (possibly in other tables) that refer via a foreign key
- ** to the row just updated. */
+ ** to the row just updated. */
if( hasFK ){
sqlite3FkActions(pParse, pTab, pChanges, regOldRowid);
}
}
- /* Increment the row counter
+ /* Increment the row counter
*/
if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab){
sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
}
- sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
+ sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
TRIGGER_AFTER, pTab, regOldRowid, onError, addr);
/* Repeat the above with the next record to be updated, until
}
/*
- ** Return the number of rows that were changed. If this routine is
+ ** Return the number of rows that were changed. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
SelectDest dest;
/* Construct the SELECT statement that will find the new values for
- ** all updated rows.
+ ** all updated rows.
*/
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, "_rowid_"));
if( pRowid ){
pEList = sqlite3ExprListAppend(pParse, pEList, pExpr);
}
pSelect = sqlite3SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
-
+
/* Create the ephemeral table into which the update results will
** be stored.
*/
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
- /* fill the ephemeral table
+ /* fill the ephemeral table
*/
sqlite3SelectDestInit(&dest, SRT_Table, ephemTab);
sqlite3Select(pParse, pSelect, &dest);
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
/* Cleanup */
- sqlite3SelectDelete(db, pSelect);
+ sqlite3SelectDelete(db, pSelect);
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
return SQLITE_ERROR;
}
- /* Save the current value of the database flags so that it can be
+ /* Save the current value of the database flags so that it can be
** restored before returning. Then set the writable-schema flag, and
** disable CHECK and foreign key constraints. */
saved_flags = db->flags;
);
if( rc ) goto end_of_vacuum;
- /* At this point, there is a write transaction open on both the
+ /* At this point, there is a write transaction open on both the
** vacuum database and the main database. Assuming no error occurs,
** both transactions are closed by this block - the main database
** transaction by sqlite3BtreeCopyFile() and the other by an explicit
}
/* This both clears the schemas and reduces the size of the db->aDb[]
- ** array. */
+ ** array. */
sqlite3ResetAllSchemasOfConnection(db);
return rc;
/*
** Before a virtual table xCreate() or xConnect() method is invoked, the
** sqlite3.pVtabCtx member variable is set to point to an instance of
-** this struct allocated on the stack. It is used by the implementation of
+** this struct allocated on the stack. It is used by the implementation of
** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which
** are invoked only from within xCreate and xConnect methods.
*/
/*
** Lock the virtual table so that it cannot be disconnected.
** Locks nest. Every lock should have a corresponding unlock.
-** If an unlock is omitted, resources leaks will occur.
+** If an unlock is omitted, resources leaks will occur.
**
** If a disconnect is attempted while a virtual table is locked,
** the disconnect is deferred until all locks have been removed.
/*
** pTab is a pointer to a Table structure representing a virtual-table.
-** Return a pointer to the VTable object used by connection db to access
+** Return a pointer to the VTable object used by connection db to access
** this virtual-table, if one has been created, or NULL otherwise.
*/
SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
/*
** Table p is a virtual table. This function moves all elements in the
** p->pVTable list to the sqlite3.pDisconnect lists of their associated
-** database connections to be disconnected at the next opportunity.
+** database connections to be disconnected at the next opportunity.
** Except, if argument db is not NULL, then the entry associated with
** connection db is left in the p->pVTable list.
*/
VTable *pVTable = p->pVTable;
p->pVTable = 0;
- /* Assert that the mutex (if any) associated with the BtShared database
- ** that contains table p is held by the caller. See header comments
+ /* Assert that the mutex (if any) associated with the BtShared database
+ ** that contains table p is held by the caller. See header comments
** above function sqlite3VtabUnlockList() for an explanation of why
** this makes it safe to access the sqlite3.pDisconnect list of any
** database connection that may have an entry in the p->pVTable list.
** Disconnect all the virtual table objects in the sqlite3.pDisconnect list.
**
** This function may only be called when the mutexes associated with all
-** shared b-tree databases opened using connection db are held by the
+** shared b-tree databases opened using connection db are held by the
** caller. This is done to protect the sqlite3.pDisconnect list. The
** sqlite3.pDisconnect list is accessed only as follows:
**
** or, if the virtual table is stored in a non-sharable database, then
** the database handle mutex is held.
**
-** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously
+** As a result, a sqlite3.pDisconnect cannot be accessed simultaneously
** by multiple threads. It is thread-safe.
*/
SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){
** record.
**
** Since it is a virtual-table, the Table structure contains a pointer
-** to the head of a linked list of VTable structures. Each VTable
+** to the head of a linked list of VTable structures. Each VTable
** structure is associated with a single sqlite3* user of the schema.
-** The reference count of the VTable structure associated with database
-** connection db is decremented immediately (which may lead to the
+** The reference count of the VTable structure associated with database
+** connection db is decremented immediately (which may lead to the
** structure being xDisconnected and free). Any other VTable structures
-** in the list are moved to the sqlite3.pDisconnect list of the associated
+** in the list are moved to the sqlite3.pDisconnect list of the associated
** database connection.
*/
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
** The second call, to obtain permission to create the table, is made now.
*/
if( pTable->azModuleArg ){
- sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
+ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
pTable->azModuleArg[0], pParse->db->aDb[iDb].zName);
}
#endif
addArgumentToVtab(pParse);
pParse->sArg.z = 0;
if( pTab->nModuleArg<1 ) return;
-
+
/* If the CREATE VIRTUAL TABLE statement is being entered for the
** first time (in other words if the virtual table is actually being
** created now instead of just being read out of sqlite_master) then
}
zStmt = sqlite3MPrintf(db, "CREATE VIRTUAL TABLE %T", &pParse->sNameToken);
- /* A slot for the record has already been allocated in the
+ /* A slot for the record has already been allocated in the
** SQLITE_MASTER table. We just need to update that slot with all
- ** the information we've collected.
+ ** the information we've collected.
**
** The VM register number pParse->regRowid holds the rowid of an
** entry in the sqlite_master table tht was created for this vtab
sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
- sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0,
+ sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0,
pTab->zName, sqlite3Strlen30(pTab->zName) + 1);
}
** to this procedure.
*/
static int vtabCallConstructor(
- sqlite3 *db,
+ sqlite3 *db,
Table *pTab,
Module *pMod,
int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
}else{
int iCol;
/* If everything went according to plan, link the new VTable structure
- ** into the linked list headed by pTab->pVTable. Then loop through the
+ ** into the linked list headed by pTab->pVTable. Then loop through the
** columns of the table to see if any of them contain the token "hidden".
** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
** the type string. */
/*
** This function is invoked by the parser to call the xConnect() method
-** of the virtual table pTab. If an error occurs, an error code is returned
+** of the virtual table pTab. If an error occurs, an error code is returned
** and an error left in pParse.
**
** This call is a no-op if table pTab is not a virtual table.
/*
** This function is invoked by the vdbe to call the xCreate method
-** of the virtual table named zTab in database iDb.
+** of the virtual table named zTab in database iDb.
**
** If an error occurs, *pzErr is set to point an an English language
** description of the error and an SQLITE_XXX error code is returned.
zMod = pTab->azModuleArg[0];
pMod = (Module*)sqlite3HashFind(&db->aModule, zMod, sqlite3Strlen30(zMod));
- /* If the module has been registered and includes a Create method,
- ** invoke it now. If the module has not been registered, return an
+ /* If the module has been registered and includes a Create method,
+ ** invoke it now. If the module has not been registered, return an
** error. Otherwise, do nothing.
*/
if( !pMod ){
pParse->declareVtab = 1;
pParse->db = db;
pParse->nQueryLoop = 1;
-
- if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr)
+
+ if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr)
&& pParse->pNewTable
&& !db->mallocFailed
&& !pParse->pNewTable->pSelect
rc = SQLITE_ERROR;
}
pParse->declareVtab = 0;
-
+
if( pParse->pVdbe ){
sqlite3VdbeFinalize(pParse->pVdbe);
}
** called is identified by the second argument, "offset", which is
** the offset of the method to call in the sqlite3_module structure.
**
-** The array is cleared after invoking the callbacks.
+** The array is cleared after invoking the callbacks.
*/
static void callFinaliser(sqlite3 *db, int offset){
int i;
** array. Return the error code for the first error that occurs, or
** SQLITE_OK if all xSync operations are successful.
**
-** Set *pzErrmsg to point to a buffer that should be released using
+** Set *pzErrmsg to point to a buffer that should be released using
** sqlite3DbFree() containing an error message, if one is available.
*/
SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
}
/*
-** Invoke the xRollback method of all virtual tables in the
+** Invoke the xRollback method of all virtual tables in the
** sqlite3.aVTrans array. Then clear the array itself.
*/
SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db){
}
/*
-** Invoke the xCommit method of all virtual tables in the
+** Invoke the xCommit method of all virtual tables in the
** sqlite3.aVTrans array. Then clear the array itself.
*/
SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db){
/* Special case: If db->aVTrans is NULL and db->nVTrans is greater
** than zero, then this function is being called from within a
- ** virtual module xSync() callback. It is illegal to write to
+ ** virtual module xSync() callback. It is illegal to write to
** virtual module tables in this case, so return SQLITE_LOCKED.
*/
if( sqlite3VtabInSync(db) ){
}
if( !pVTab ){
return SQLITE_OK;
- }
+ }
pModule = pVTab->pVtab->pModule;
if( pModule->xBegin ){
}
}
- /* Invoke the xBegin method. If successful, add the vtab to the
+ /* Invoke the xBegin method. If successful, add the vtab to the
** sqlite3.aVTrans[] array. */
rc = growVTrans(db);
if( rc==SQLITE_OK ){
** as the second argument to the virtual table method invoked.
**
** If op is SAVEPOINT_BEGIN, the xSavepoint method is invoked. If it is
-** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is
+** SAVEPOINT_ROLLBACK, the xRollbackTo method. Otherwise, if op is
** SAVEPOINT_RELEASE, then the xRelease method of each virtual table with
** an open transaction is invoked.
**
-** If any virtual table method returns an error code other than SQLITE_OK,
+** If any virtual table method returns an error code other than SQLITE_OK,
** processing is abandoned and the error returned to the caller of this
** function immediately. If all calls to virtual table methods are successful,
** SQLITE_OK is returned.
** This routine is used to allow virtual table implementations to
** overload MATCH, LIKE, GLOB, and REGEXP operators.
**
-** Return either the pDef argument (indicating no change) or a
+** Return either the pDef argument (indicating no change) or a
** new FuncDef structure that is marked as ephemeral using the
** SQLITE_FUNC_EPHEM flag.
*/
assert( pVtab->pModule!=0 );
pMod = (sqlite3_module *)pVtab->pModule;
if( pMod->xFindFunction==0 ) return pDef;
-
+
/* Call the xFindFunction method on the virtual table implementation
- ** to see if the implementation wants to overload this function
+ ** to see if the implementation wants to overload this function
*/
zLowerName = sqlite3DbStrDup(db, pDef->zName);
if( zLowerName ){
** within an xUpdate method.
*/
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){
- static const unsigned char aMap[] = {
- SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE
+ static const unsigned char aMap[] = {
+ SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE
};
assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 );
assert( OE_Ignore==4 && OE_Replace==5 );
}
/*
-** Call from within the xCreate() or xConnect() methods to provide
+** Call from within the xCreate() or xConnect() methods to provide
** the SQLite core with additional information about the behavior
** of the virtual table being implemented.
*/
** clause subexpression is separated from the others by AND operators,
** usually, or sometimes subexpressions separated by OR.
**
-** All WhereTerms are collected into a single WhereClause structure.
+** All WhereTerms are collected into a single WhereClause structure.
** The following identity holds:
**
** WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm
** An instance of the following structure keeps track of a mapping
** between VDBE cursor numbers and bits of the bitmasks in WhereTerm.
**
-** The VDBE cursor numbers are small integers contained in
-** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE
+** The VDBE cursor numbers are small integers contained in
+** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE
** clause, the cursor numbers might not begin with 0 and they might
** contain gaps in the numbering sequence. But we want to make maximum
** use of the bits in our bitmasks. This structure provides a mapping
#define WHERE_REVERSE 0x01000000 /* Scan in reverse order */
#define WHERE_UNIQUE 0x02000000 /* Selects no more than one row */
#define WHERE_ALL_UNIQUE 0x04000000 /* This and all prior have one row */
-#define WHERE_OB_UNIQUE 0x00004000 /* Values in ORDER BY columns are
+#define WHERE_OB_UNIQUE 0x00004000 /* Values in ORDER BY columns are
** different for every output row */
#define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
#define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
** If left/right precedence rules come into play when determining the
** collating
** side of the comparison, it remains associated with the same side after
-** the commutation. So "Y collate NOCASE op X" becomes
+** the commutation. So "Y collate NOCASE op X" becomes
** "X op Y". This is because any collation sequence on
-** the left hand side of a comparison overrides any collation sequence
+** the left hand side of a comparison overrides any collation sequence
** attached to the right. For the same reason the EP_Collate flag
** is not commuted.
*/
if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){
CollSeq *pColl;
char idxaff;
-
+
pX = pTerm->pExpr;
pParse = pWC->pParse;
idxaff = pIdx->pTable->aCol[iOrigCol].affinity;
if( !sqlite3IndexAffinityOk(pX, idxaff) ){
continue;
}
-
+
/* Figure out the collation sequence required from an index for
** it to be useful for optimising expression pX. Store this
** value in variable pColl.
assert(pX->pLeft);
pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight);
if( pColl==0 ) pColl = pParse->db->pDfltColl;
-
+
for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){
if( NEVER(j>=pIdx->nColumn) ) return 0;
}
static void exprAnalyze(SrcList*, WhereClause*, int);
/*
-** Call exprAnalyze on all terms in a WHERE clause.
+** Call exprAnalyze on all terms in a WHERE clause.
**
**
*/
** so and false if not.
**
** In order for the operator to be optimizible, the RHS must be a string
-** literal that does not begin with a wildcard.
+** literal that does not begin with a wildcard.
*/
static int isLikeOrGlob(
Parse *pParse, /* Parsing and code generating context */
#endif
pList = pExpr->x.pList;
pLeft = pList->a[1].pExpr;
- if( pLeft->op!=TK_COLUMN
- || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
+ if( pLeft->op!=TK_COLUMN
+ || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|| IsVirtual(pLeft->pTab)
){
/* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
** function, then no OP_Variable will be added to the program.
** This causes problems for the sqlite3_bind_parameter_name()
** API. To workaround them, add a dummy OP_Variable here.
- */
+ */
int r1 = sqlite3GetTempReg(pParse);
sqlite3ExprCodeTarget(pParse, pRight, r1);
sqlite3VdbeChangeP3(v, sqlite3VdbeCurrentAddr(v)-1, 0);
** WhereTerm.u.pOrInfo->indexable |= the cursor number for table T
**
** A subterm is "indexable" if it is of the form
-** "T.C <op> <expr>" where C is any column of table T and
+** "T.C <op> <expr>" where C is any column of table T and
** <op> is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN".
** A subterm is also indexable if it is an AND of two or more
-** subsubterms at least one of which is indexable. Indexable AND
+** subsubterms at least one of which is indexable. Indexable AND
** subterms have their eOperator set to WO_AND and they have
** u.pAndInfo set to a dynamically allocated WhereAndTerm object.
**
if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ){
/* This term must be of the form t1.a==t2.b where t2 is in the
** chngToIN set but t1 is not. This term will be either preceeded
- ** or follwed by an inverted copy (t2.b==t1.a). Skip this term
+ ** or follwed by an inverted copy (t2.b==t1.a). Skip this term
** and use its inversion. */
testcase( pOrTerm->wtFlags & TERM_COPIED );
testcase( pOrTerm->wtFlags & TERM_VIRTUAL );
}
/* At this point, okToChngToIN is true if original pTerm satisfies
- ** case 1. In that case, construct a new virtual term that is
+ ** case 1. In that case, construct a new virtual term that is
** pTerm converted into an IN operator.
**
** EV: R-00211-15100
for(i=0; i<2; i++){
Expr *pNewExpr;
int idxNew;
- pNewExpr = sqlite3PExpr(pParse, ops[i],
+ pNewExpr = sqlite3PExpr(pParse, ops[i],
sqlite3ExprDup(db, pExpr->pLeft, 0),
sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
** The last character of the prefix "abc" is incremented to form the
** termination condition "abd".
*/
- if( pWC->op==TK_AND
+ if( pWC->op==TK_AND
&& isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
){
Expr *pLeft; /* LHS of LIKE/GLOB operator */
if( noCase ){
/* The point is to increment the last character before the first
** wildcard. But if we increment '@', that will push it into the
- ** alphabetic range where case conversions will mess up the
+ ** alphabetic range where case conversions will mess up the
** inequality. To avoid this, make sure to also run the full
** LIKE on all candidate expressions by clearing the isComplete flag
*/
sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
sCollSeqName.n = 6;
pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
- pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
+ pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
pStr1, 0);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
prereqColumn = exprTableUsage(pMaskSet, pLeft);
if( (prereqExpr & prereqColumn)==0 ){
Expr *pNewExpr;
- pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
+ pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
0, sqlite3ExprDup(db, pRight, 0), 0);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
** index for the outer loop guarantees that rows with equal values for
** all expressions in the pDistinct list are delivered grouped together.
**
-** For example, the query
+** For example, the query
**
** SELECT DISTINCT a, b, c FROM tbl WHERE a = ?
**
){
Table *pTab;
Index *pIdx;
- int i;
+ int i;
int iBase;
/* If there is more than one table or sub-select in the FROM clause of
- ** this query, then it will not be possible to show that the DISTINCT
+ ** this query, then it will not be possible to show that the DISTINCT
** clause is redundant. */
if( pTabList->nSrc!=1 ) return 0;
iBase = pTabList->a[0].iCursor;
pTab = pTabList->a[0].pTab;
- /* If any of the expressions is an IPK column on table iBase, then return
+ /* If any of the expressions is an IPK column on table iBase, then return
** true. Note: The (p->iTable==iBase) part of this test may be false if the
** current SELECT is a correlated sub-query.
*/
#define TRACE_IDX_OUTPUTS(A)
#endif
-/*
-** Required because bestIndex() is called by bestOrClauseIndex()
+/*
+** Required because bestIndex() is called by bestOrClauseIndex()
*/
static void bestIndex(WhereBestIdx*);
/*
-** This routine attempts to find an scanning strategy that can be used
-** to optimize an 'OR' expression that is part of a WHERE clause.
+** This routine attempts to find an scanning strategy that can be used
+** to optimize an 'OR' expression that is part of a WHERE clause.
**
** The table associated with FROM clause term pSrc may be either a
** regular B-Tree table or a virtual table.
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( (pTerm->eOperator & WO_OR)!=0
&& ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
- && (pTerm->u.pOrInfo->indexable & maskSrc)!=0
+ && (pTerm->u.pOrInfo->indexable & maskSrc)!=0
){
WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
sBOI.pDistinct = 0;
sBOI.ppIdxInfo = 0;
for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
- WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
+ WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
(pOrTerm - pOrWC->a), (pTerm - pWC->a)
));
if( (pOrTerm->eOperator& WO_AND)!=0 ){
if( rTotal>=p->cost.rCost ) break;
}
- /* If there is an ORDER BY clause, increase the scan cost to account
+ /* If there is an ORDER BY clause, increase the scan cost to account
** for the cost of the sort. */
if( p->pOrderBy!=0 ){
WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
Vdbe *v; /* Prepared statement under construction */
int addrInit; /* Address of the initialization bypass jump */
Table *pTable; /* The table being indexed */
- KeyInfo *pKeyinfo; /* Key information for the index */
+ KeyInfo *pKeyinfo; /* Key information for the index */
int addrTop; /* Top of the index fill loop */
int regRecord; /* Register holding an index record */
int n; /* Column counter */
sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
sqlite3VdbeJumpHere(v, addrTop);
sqlite3ReleaseTempReg(pParse, regRecord);
-
+
/* Jump here when skipping the initialization */
sqlite3VdbeJumpHere(v, addrInit);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
-** Allocate and populate an sqlite3_index_info structure. It is the
+** Allocate and populate an sqlite3_index_info structure. It is the
** responsibility of the caller to eventually release the structure
** by passing the pointer returned by this function to sqlite3_free().
*/
static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
- Parse *pParse = p->pParse;
+ Parse *pParse = p->pParse;
WhereClause *pWC = p->pWC;
struct SrcList_item *pSrc = p->pSrc;
ExprList *pOrderBy = p->pOrderBy;
nTerm++;
}
- /* If the ORDER BY clause contains only columns in the current
+ /* If the ORDER BY clause contains only columns in the current
** virtual table then allocate space for the aOrderBy part of
** the sqlite3_index_info structure.
*/
for(i=0; i<p->nConstraint; i++){
if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"table %s: xBestIndex returned an invalid plan", pTab->zName);
}
}
** same virtual table. The sqlite3_index_info structure is created
** and initialized on the first invocation and reused on all subsequent
** invocations. The sqlite3_index_info structure is also used when
-** code is generated to access the virtual table. The whereInfoDelete()
+** code is generated to access the virtual table. The whereInfoDelete()
** routine takes care of freeing the sqlite3_index_info structure after
** everybody has finished with it.
*/
int bAllowIN; /* Allow IN optimizations */
double rCost;
- /* Make sure wsFlags is initialized to some sane value. Otherwise, if the
+ /* Make sure wsFlags is initialized to some sane value. Otherwise, if the
** malloc in allocateIndexInfo() fails and this function returns leaving
** wsFlags in an uninitialized state, the caller may behave unpredictably.
*/
/* The module name must be defined. Also, by this point there must
** be a pointer to an sqlite3_vtab structure. Otherwise
- ** sqlite3ViewGetColumnNames() would have picked up the error.
+ ** sqlite3ViewGetColumnNames() would have picked up the error.
*/
assert( pTab->azModuleArg && pTab->azModuleArg[0] );
assert( sqlite3GetVTable(pParse->db, pTab) );
for(bAllowIN=1; 1; bAllowIN--){
assert( bAllowIN==0 || bAllowIN==1 );
- /* Set the aConstraint[].usable fields and initialize all
+ /* Set the aConstraint[].usable fields and initialize all
** output variables to zero.
**
** aConstraint[].usable is true for constraints where the right-hand
**
** column = expr
**
- ** and we are evaluating a join, then the constraint on column is
+ ** and we are evaluating a join, then the constraint on column is
** only valid if all tables referenced in expr occur to the left
** of the table containing column.
**
if( !p->pOrderBy ){
pIdxInfo->nOrderBy = 0;
}
-
+
if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
return;
}
-
+
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
if( pUsage[i].argvIndex>0 ){
}
}
}
-
+
/* If there is an ORDER BY clause, and the selected virtual table index
** does not satisfy it, increase the cost of the scan accordingly. This
** matches the processing for non-virtual tables in bestBtreeIndex().
/* The cost is not allowed to be larger than SQLITE_BIG_DBL (the
** inital value of lowestCost in this loop. If it is, then the
** (cost<lowestCost) test below will never be true.
- **
- ** Use "(double)2" instead of "2.0" in case OMIT_FLOATING_POINT
+ **
+ ** Use "(double)2" instead of "2.0" in case OMIT_FLOATING_POINT
** is defined.
*/
if( (SQLITE_BIG_DBL/((double)2))<rCost ){
pIdxInfo->nOrderBy = nOrderBy;
/* Try to find a more efficient access pattern by using multiple indexes
- ** to optimize an OR expression within the WHERE clause.
+ ** to optimize an OR expression within the WHERE clause.
*/
bestOrClauseIndex(p);
}
break;
}
}
- if( i<pIdx->nSample ){
+ if( i<pIdx->nSample ){
sqlite3 *db = pParse->db;
CollSeq *pColl;
const u8 *z;
assert( z && pColl && pColl->xCmp );
}
n = sqlite3ValueBytes(pVal, pColl->enc);
-
+
for(; i<pIdx->nSample; i++){
int c;
int eSampletype = aSample[i].eType;
/*
** If expression pExpr represents a literal value, set *pp to point to
** an sqlite3_value structure containing the same value, with affinity
-** aff applied to it, before returning. It is the responsibility of the
-** caller to eventually release this structure by passing it to
+** aff applied to it, before returning. It is the responsibility of the
+** caller to eventually release this structure by passing it to
** sqlite3ValueFree().
**
** If the current parse is a recompile (sqlite3Reprepare()) and pExpr
*/
#ifdef SQLITE_ENABLE_STAT3
static int valueFromExpr(
- Parse *pParse,
- Expr *pExpr,
- u8 aff,
+ Parse *pParse,
+ Expr *pExpr,
+ u8 aff,
sqlite3_value **pp
){
if( pExpr->op==TK_VARIABLE
** for that index. When pExpr==NULL that means the constraint is
** "x IS NULL" instead of "x=VALUE".
**
-** Write the estimated row count into *pnRow and return SQLITE_OK.
+** Write the estimated row count into *pnRow and return SQLITE_OK.
** If unable to make an estimate, leave *pnRow unchanged and return
** non-zero.
**
**
** WHERE x IN (1,2,3,4)
**
-** Write the estimated row count into *pnRow and return SQLITE_OK.
+** Write the estimated row count into *pnRow and return SQLITE_OK.
** If unable to make an estimate, leave *pnRow unchanged and return
** non-zero.
**
/*
** This routine decides if pIdx can be used to satisfy the ORDER BY
-** clause, either in whole or in part. The return value is the
+** clause, either in whole or in part. The return value is the
** cumulative number of terms in the ORDER BY clause that are satisfied
** by the index pIdx and other indices in outer loops.
**
uniqueNotNull = pIdx->onError!=OE_None;
assert( nTerm>0 );
- /* Argument pIdx must either point to a 'real' named index structure,
+ /* Argument pIdx must either point to a 'real' named index structure,
** or an index structure allocated on the stack by bestBtreeIndex() to
** represent the rowid index that is part of every table. */
assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
}
/* termSortOrder is 0 or 1 for whether or not the access loop should
- ** run forward or backwards (respectively) in order to satisfy this
+ ** run forward or backwards (respectively) in order to satisfy this
** term of the ORDER BY clause. */
assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 );
assert( iSortOrder==0 || iSortOrder==1 );
** rows with the same values in all ORDER BY columns, or else this
** loop must generate just a single row of output. Example: Suppose
** the outer loops generate A=1 and A=1, and this loop generates B=3
- ** and B=4. Then without the following test, ORDER BY A,B would
+ ** and B=4. Then without the following test, ORDER BY A,B would
** generate the wrong order output: 1,3 1,4 1,3 1,4
*/
if( outerObUnique==0 && uniqueNotNull==0 ) return nPriorSat;
** index and in the main table.
**
** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in
-** the SQL statement, then this function only considers plans using the
+** the SQL statement, then this function only considers plans using the
** named index. If no such plan is found, then the returned cost is
-** SQLITE_BIG_DBL. If a plan is found that uses the named index,
+** SQLITE_BIG_DBL. If a plan is found that uses the named index,
** then the cost is calculated in the usual way.
**
-** If a NOT INDEXED clause was attached to the table
-** in the SELECT statement, then no indexes are considered. However, the
+** If a NOT INDEXED clause was attached to the table
+** in the SELECT statement, then no indexes are considered. However, the
** selected plan may still take advantage of the built-in rowid primary key
** index.
*/
** index being evaluated. They are then used to determine the expected
** cost and number of rows returned.
**
- ** pc.plan.nEq:
+ ** pc.plan.nEq:
** Number of equality terms that can be implemented using the index.
** In other words, the number of initial fields in the index that
** are used in == or IN or NOT NULL constraints of the WHERE clause.
**
- ** nInMul:
- ** The "in-multiplier". This is an estimate of how many seek operations
- ** SQLite must perform on the index in question. For example, if the
+ ** nInMul:
+ ** The "in-multiplier". This is an estimate of how many seek operations
+ ** SQLite must perform on the index in question. For example, if the
** WHERE clause is:
**
** WHERE a IN (1, 2, 3) AND b IN (4, 5, 6)
**
- ** SQLite must perform 9 lookups on an index on (a, b), so nInMul is
- ** set to 9. Given the same schema and either of the following WHERE
+ ** SQLite must perform 9 lookups on an index on (a, b), so nInMul is
+ ** set to 9. Given the same schema and either of the following WHERE
** clauses:
**
** WHERE a = 1
**
** nInMul is set to 1.
**
- ** If there exists a WHERE term of the form "x IN (SELECT ...)", then
- ** the sub-select is assumed to return 25 rows for the purposes of
+ ** If there exists a WHERE term of the form "x IN (SELECT ...)", then
+ ** the sub-select is assumed to return 25 rows for the purposes of
** determining nInMul.
**
- ** bInEst:
- ** Set to true if there was at least one "x IN (SELECT ...)" term used
+ ** bInEst:
+ ** Set to true if there was at least one "x IN (SELECT ...)" term used
** in determining the value of nInMul. Note that the RHS of the
** IN operator must be a SELECT, not a value list, for this variable
** to be true.
** original size (rangeDiv==4). Two inequalities reduce the search
** space to 1/16th of its original size (rangeDiv==16).
**
- ** bSort:
- ** Boolean. True if there is an ORDER BY clause that will require an
- ** external sort (i.e. scanning the index being evaluated will not
+ ** bSort:
+ ** Boolean. True if there is an ORDER BY clause that will require an
+ ** external sort (i.e. scanning the index being evaluated will not
** correctly order records).
**
** bDist:
- ** Boolean. True if there is a DISTINCT clause that will require an
+ ** Boolean. True if there is a DISTINCT clause that will require an
** external btree.
**
- ** bLookup:
+ ** bLookup:
** Boolean. True if a table lookup is required for each index entry
** visited. In other words, true if this is not a covering index.
** This is always false for the rowid primary key index of a table.
** For other indexes, it is true unless all the columns of the table
** used by the SELECT statement are present in the index (such an
** index is sometimes described as a covering index).
- ** For example, given the index on (a, b), the second of the following
+ ** For example, given the index on (a, b), the second of the following
** two queries requires table b-tree lookups in order to find the value
** of column c, but the first does not because columns a and b are
** both available in the index.
#endif
pc.used |= pTerm->prereqRight;
}
-
- /* If the index being considered is UNIQUE, and there is an equality
+
+ /* If the index being considered is UNIQUE, and there is an equality
** constraint for all columns in the index, then this search will find
- ** at most a single row. In this case set the WHERE_UNIQUE flag to
+ ** at most a single row. In this case set the WHERE_UNIQUE flag to
** indicate this to the caller.
**
** Otherwise, if the search may find more than one row, test to see if
** there is a range constraint on indexed column (pc.plan.nEq+1) that
- ** can be optimized using the index.
+ ** can be optimized using the index.
*/
if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
testcase( pc.plan.wsFlags & WHERE_COLUMN_IN );
}
/* If currently calculating the cost of using an index (not the IPK
- ** index), determine if all required column data may be obtained without
+ ** index), determine if all required column data may be obtained without
** using the main table (i.e. if the index is a covering
** index for this query). If it is, set the WHERE_IDX_ONLY flag in
** pc.plan.wsFlags. Otherwise, set the bLookup variable to true. */
pc.rCost += (nInMul + pc.plan.nRow)*log10N;
}else{
/* For a covering index:
- ** nInMul index searches to find the initial entry
+ ** nInMul index searches to find the initial entry
** + nRow steps through the index
*/
pc.rCost += nInMul*log10N;
/* Add in the estimated cost of sorting the result. Actual experimental
** measurements of sorting performance in SQLite show that sorting time
- ** adds C*N*log10(N) to the cost, where N is the number of rows to be
+ ** adds C*N*log10(N) to the cost, where N is the number of rows to be
** sorted and C is a factor between 1.95 and 4.3. We will split the
** difference and select C of 3.0.
*/
/* If there are additional constraints on this table that cannot
** be used with the current index, but which might lower the number
- ** of output rows, adjust the nRow value accordingly. This only
+ ** of output rows, adjust the nRow value accordingly. This only
** matters if the current index is the least costly, so do not bother
** with this step if we already know this index will not be chosen.
** Also, never reduce the output row count below 2 using this step.
/* Assume each additional range constraint reduces the result
** set size by a factor of 3. Indexed range constraints reduce
** the search space by a larger factor: 4. We make indexed range
- ** more selective intentionally because of the subjective
+ ** more selective intentionally because of the subjective
** observation that indexed range constraints really are more
** selective in practice, on average. */
pc.plan.nRow /= 3;
assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
- assert( pSrc->pIndex==0
- || p->cost.plan.u.pIdx==0
- || p->cost.plan.u.pIdx==pSrc->pIndex
+ assert( pSrc->pIndex==0
+ || p->cost.plan.u.pIdx==0
+ || p->cost.plan.u.pIdx==pSrc->pIndex
);
WHERETRACE((" best index is %s cost=%.1f\n",
p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
p->cost.rCost));
-
+
bestOrClauseIndex(p);
bestAutomaticIndex(p);
p->cost.plan.wsFlags |= eqTermMask;
/*
** Find the query plan for accessing table pSrc->pTab. Write the
-** best query plan and its cost into the WhereCost object supplied
+** best query plan and its cost into the WhereCost object supplied
** as the last parameter. This function may calculate the cost of
** both real and virtual table scans.
**
/*
** Code an OP_Affinity opcode to apply the column affinity string zAff
-** to the n registers starting at base.
+** to the n registers starting at base.
**
** As an optimization, SQLITE_AFF_NONE entries (which are no-ops) at the
** beginning and end of zAff are ignored. If all entries in zAff are
/*
** Generate code for a single equality term of the WHERE clause. An equality
-** term can be either X=expr or X IN (...). pTerm is the term to be
+** term can be either X=expr or X IN (...). pTerm is the term to be
** coded.
**
** The current value for the constraint is left in register iReg.
struct InLoop *pIn;
u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
- if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0
+ if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0
&& pLevel->plan.u.pIdx->aSortOrder[iEq]
){
testcase( iEq==0 );
** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10
** The index has as many as three equality constraints, but in this
-** example, the third "c" value is an inequality. So only two
+** example, the third "c" value is an inequality. So only two
** constraints are coded. This routine will generate code to evaluate
** a==5 and b IN (1,2,3). The current values for a and b will be stored
** in consecutive registers and the index of the first register is returned.
int k = pIdx->aiColumn[j];
pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx);
if( pTerm==0 ) break;
- /* The following true for indices with redundant columns.
+ /* The following true for indices with redundant columns.
** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
}
/*
-** Argument pLevel describes a strategy for scanning table pTab. This
+** Argument pLevel describes a strategy for scanning table pTab. This
** function returns a pointer to a string buffer containing a description
** of the subset of table rows scanned by the strategy in the form of an
** SQL expression. Or, if all rows are scanned, NULL is returned.
/*
** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
** command. If the query being compiled is an EXPLAIN QUERY PLAN, a single
-** record is added to the output to describe the table scan strategy in
+** record is added to the output to describe the table scan strategy in
** pLevel.
*/
static void explainOneScan(
}
if( (flags & WHERE_INDEXED)!=0 ){
char *zWhere = explainIndexRange(db, pLevel, pItem->pTab);
- zMsg = sqlite3MAppendf(db, zMsg, "%s USING %s%sINDEX%s%s%s", zMsg,
+ zMsg = sqlite3MAppendf(db, zMsg, "%s USING %s%sINDEX%s%s%s", zMsg,
((flags & WHERE_TEMP_INDEX)?"AUTOMATIC ":""),
((flags & WHERE_IDX_ONLY)?"COVERING ":""),
((flags & WHERE_TEMP_INDEX)?"":" "),
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
- omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0
+ omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0
&& (wctrlFlags & WHERE_FORCE_TABLE)==0;
VdbeNoopComment((v, "Begin Join Loop %d", iLevel));
Expr *pX; /* The expression that defines the start bound */
int r1, rTemp; /* Registers for holding the start boundary */
- /* The following constant maps TK_xx codes into corresponding
+ /* The following constant maps TK_xx codes into corresponding
** seek opcodes. It depends on a particular ordering of TK_xx
*/
const u8 aMoveOp[] = {
}else if( pLevel->plan.wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
/* Case 3: A scan using an index.
**
- ** The WHERE clause may contain zero or more equality
+ ** The WHERE clause may contain zero or more equality
** terms ("==" or "IN" operators) that refer to the N
** left-most columns of the index. It may also contain
** inequality constraints (>, <, >= or <=) on the indexed
- ** column that immediately follows the N equalities. Only
+ ** column that immediately follows the N equalities. Only
** the right-most column can be an inequality - the rest must
- ** use the "==" and "IN" operators. For example, if the
- ** index is on (x,y,z), then the following clauses are all
+ ** use the "==" and "IN" operators. For example, if the
+ ** index is on (x,y,z), then the following clauses are all
** optimized:
**
** x=5
** This case is also used when there are no WHERE clause
** constraints but an index is selected anyway, in order
** to force the output order to conform to an ORDER BY.
- */
+ */
static const u8 aStartOp[] = {
0,
0,
iIdxCur = pLevel->iIdxCur;
k = (nEq==pIdx->nColumn ? -1 : pIdx->aiColumn[nEq]);
- /* If this loop satisfies a sort order (pOrderBy) request that
- ** was passed to this function to implement a "SELECT min(x) ..."
+ /* If this loop satisfies a sort order (pOrderBy) request that
+ ** was passed to this function to implement a "SELECT min(x) ..."
** query, then the caller will only allow the loop to run for
** a single iteration. This means that the first row returned
** should not have a NULL value stored in 'x'. If column 'x' is
nExtraReg = 1;
}
- /* Find any inequality constraint terms for the start and end
- ** of the range.
+ /* Find any inequality constraint terms for the start and end
+ ** of the range.
*/
if( pLevel->plan.wsFlags & WHERE_TOP_LIMIT ){
pRangeEnd = findTerm(pWC, iCur, k, notReady, (WO_LT|WO_LE), pIdx);
addrNxt = pLevel->addrNxt;
/* If we are doing a reverse order scan on an ascending index, or
- ** a forward order scan on a descending index, interchange the
+ ** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
*/
if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
if( zStartAff ){
if( sqlite3CompareAffinity(pRight, zStartAff[nEq])==SQLITE_AFF_NONE){
/* Since the comparison is to be performed with no conversions
- ** applied to the operands, set the affinity to apply to pRight to
+ ** applied to the operands, set the affinity to apply to pRight to
** SQLITE_AFF_NONE. */
zStartAff[nEq] = SQLITE_AFF_NONE;
}
if( sqlite3ExprNeedsNoAffinityChange(pRight, zStartAff[nEq]) ){
zStartAff[nEq] = SQLITE_AFF_NONE;
}
- }
+ }
nConstraint++;
testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
}else if( isMinQuery ){
if( zEndAff ){
if( sqlite3CompareAffinity(pRight, zEndAff[nEq])==SQLITE_AFF_NONE){
/* Since the comparison is to be performed with no conversions
- ** applied to the operands, set the affinity to apply to pRight to
+ ** applied to the operands, set the affinity to apply to pRight to
** SQLITE_AFF_NONE. */
zEndAff[nEq] = SQLITE_AFF_NONE;
}
if( sqlite3ExprNeedsNoAffinityChange(pRight, zEndAff[nEq]) ){
zEndAff[nEq] = SQLITE_AFF_NONE;
}
- }
+ }
codeApplyAffinity(pParse, regBase, nEq+1, zEndAff);
nConstraint++;
testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */
}
- /* Record the instruction used to terminate the loop. Disable
+ /* Record the instruction used to terminate the loop. Disable
** WHERE clause terms made redundant by the index range scan.
*/
if( pLevel->plan.wsFlags & WHERE_UNIQUE ){
int untestedTerms = 0; /* Some terms not completely tested */
int ii; /* Loop counter */
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
-
+
pTerm = pLevel->plan.u.pTerm;
assert( pTerm!=0 );
assert( pTerm->eOperator & WO_OR );
pOrTab = pWInfo->pTabList;
}
- /* Initialize the rowset register to contain NULL. An SQL NULL is
+ /* Initialize the rowset register to contain NULL. An SQL NULL is
** equivalent to an empty rowset.
**
- ** Also initialize regReturn to contain the address of the instruction
+ ** Also initialize regReturn to contain the address of the instruction
** immediately following the OP_Return at the bottom of the loop. This
** is required in a few obscure LEFT JOIN cases where control jumps
- ** over the top of the loop into the body of it. In this case the
- ** correct response for the end-of-loop code (the OP_Return) is to
+ ** over the top of the loop into the body of it. In this case the
+ ** correct response for the end-of-loop code (the OP_Return) is to
** fall through to the next instruction, just as an OP_Next does if
** called on an uninitialized cursor.
*/
**
** Actually, each subexpression is converted to "xN AND w" where w is
** the "interesting" terms of z - terms that did not originate in the
- ** ON or USING clause of a LEFT JOIN, and terms that are usable as
+ ** ON or USING clause of a LEFT JOIN, and terms that are usable as
** indices.
**
** This optimization also only applies if the (x1 OR x2 OR ...) term
if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
int r;
- r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
+ r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
regRowid, 0);
sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
sqlite3VdbeCurrentAddr(v)+2, r, iSet);
** If the call to sqlite3WhereBegin() above resulted in a scan that
** uses an index, and this is either the first OR-connected term
** processed or the index is the same as that used by all previous
- ** terms, set pCov to the candidate covering index. Otherwise, set
- ** pCov to NULL to indicate that no candidate covering index will
+ ** terms, set pCov to the candidate covering index. Otherwise, set
+ ** pCov to NULL to indicate that no candidate covering index will
** be available.
*/
pLvl = &pSubWInfo->a[0];
}
/* For a LEFT OUTER JOIN, generate code that will record the fact that
- ** at least one row of the right table has matched the left table.
+ ** at least one row of the right table has matched the left table.
*/
if( pLevel->iLeftJoin ){
pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
sWBI.pParse = pParse;
/* The number of tables in the FROM clause is limited by the number of
- ** bits in a Bitmask
+ ** bits in a Bitmask
*/
testcase( pTabList->nSrc==BMS );
if( pTabList->nSrc>BMS ){
return 0;
}
- /* This function normally generates a nested loop for all tables in
+ /* This function normally generates a nested loop for all tables in
** pTabList. But if the WHERE_ONETABLE_ONLY flag is set, then we should
** only generate code for the first table in pTabList and assume that
** any cursors associated with subsequent tables are uninitialized.
*/
db = pParse->db;
nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
- pWInfo = sqlite3DbMallocZero(db,
- nByteWInfo +
+ pWInfo = sqlite3DbMallocZero(db,
+ nByteWInfo +
sizeof(WhereClause) +
sizeof(WhereMaskSet)
);
whereClauseInit(sWBI.pWC, pParse, pMaskSet, wctrlFlags);
sqlite3ExprCodeConstants(pParse, pWhere);
whereSplit(sWBI.pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */
-
+
/* Special case: a WHERE clause that is constant. Evaluate the
** expression and either jump over all of the code or fall thru.
*/
goto whereBeginError;
}
- /* Check if the DISTINCT qualifier, if there is one, is redundant.
+ /* Check if the DISTINCT qualifier, if there is one, is redundant.
** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
*/
/* Loop through the remaining entries in the FROM clause to find the
** next nested loop. The loop tests all FROM clause entries
- ** either once or twice.
+ ** either once or twice.
**
** The first test is always performed if there are two or more entries
** remaining and never performed if there is only one FROM clause entry
** not be as small as it would be if the table really were the innermost
** join. The nRow value can be reduced by WHERE clause constraints
** that do not use indices. But this nRow reduction only happens if the
- ** table really is the innermost join.
+ ** table really is the innermost join.
**
** The second loop iteration is only performed if no optimal scan
** strategies were found by the first iteration. This second iteration
**
** Without the optimal scan step (the first iteration) a suboptimal
** plan might be chosen for queries like this:
- **
- ** CREATE TABLE t1(a, b);
+ **
+ ** CREATE TABLE t1(a, b);
** CREATE TABLE t2(c, d);
** SELECT * FROM t2, t1 WHERE t2.rowid = t1.a;
**
** The best strategy is to iterate through table t1 first. However it
** is not possible to determine this with a simple greedy algorithm.
- ** Since the cost of a linear scan through table t2 is the same
- ** as the cost of a linear scan through table t1, a simple greedy
+ ** Since the cost of a linear scan through table t2 is the same
+ ** as the cost of a linear scan through table t1, a simple greedy
** algorithm may choose to use t2 for the outer loop, which is a much
** costlier approach.
*/
}
sWBI.notReady = (isOptimal ? m : sWBI.notValid);
if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
-
+
WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n",
j, sWBI.pSrc->pTab->zName, isOptimal));
assert( sWBI.pSrc->pTab );
if( IsVirtual(sWBI.pSrc->pTab) ){
sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo;
bestVirtualIndex(&sWBI);
- }else
+ }else
#endif
{
bestBtreeIndex(&sWBI);
/* If an INDEXED BY clause is present, then the plan must use that
** index if it uses any index at all */
- assert( sWBI.pSrc->pIndex==0
+ assert( sWBI.pSrc->pIndex==0
|| (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
|| sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex );
/* If two or more tables have nearly the same outer loop cost, but
** very different inner loop (optimal) cost, we want to choose
** for the outer loop that table which benefits the least from
- ** being in the inner loop. The following code scales the
+ ** being in the inner loop. The following code scales the
** outer loop cost estimate to accomplish that. */
WHERETRACE((" scaling cost from %.1f to %.1f\n",
sWBI.cost.rCost,
** An indexable full-table-scan from reaching rule (3).
**
** (4) The plan cost must be lower than prior plans, where "cost"
- ** is defined by the compareCost() function above.
+ ** is defined by the compareCost() function above.
*/
if( (sWBI.cost.used&sWBI.notValid)==0 /* (1) */
&& (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */
testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
- if( (wctrlFlags & WHERE_ONETABLE_ONLY)
- && (bestPlan.plan.wsFlags & WHERE_TEMP_INDEX)==0
+ if( (wctrlFlags & WHERE_ONETABLE_ONLY)
+ && (bestPlan.plan.wsFlags & WHERE_TEMP_INDEX)==0
){
pLevel->iIdxCur = iIdxCur;
}else{
Bitmask b = pTabItem->colUsed;
int n = 0;
for(; b; b=b>>1, n++){}
- sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1,
+ sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1,
SQLITE_INT_TO_PTR(n), P4_INT32);
assert( n<=pTab->nCol );
}
}
/*
-** Generate the end of the WHERE loop. See comments on
+** Generate the end of the WHERE loop. See comments on
** sqlite3WhereBegin() for additional information.
*/
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
** as the vdbe level waits until the table is read before actually
** seeking the table cursor to the record corresponding to the current
** position in the index.
- **
+ **
** Calls to the code generator in between sqlite3WhereBegin and
** sqlite3WhereEnd will have created code that references the table
** directly. This loop scans all that code looking for opcodes
pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0);
pOut->zStart = pOperand->zStart;
pOut->zEnd = &pPostOp->z[pPostOp->n];
- }
+ }
/* A routine to convert a binary TK_IS or TK_ISNOT expression into a
** unary TK_ISNULL or TK_NOTNULL expression. */
/* Next is all token values, in a form suitable for use by makeheaders.
** This section will be null unless lemon is run with the -m switch.
*/
-/*
+/*
** These constants (all generated automatically by the parser generator)
** specify the various kinds of tokens (terminals) that the parser
-** understands.
+** understands.
**
** Each symbol here is a terminal symbol in the grammar.
*/
** and nonterminals. "int" is used otherwise.
** YYNOCODE is a number of type YYCODETYPE which corresponds
** to no legal terminal or nonterminal number. This
-** number is used to fill in empty slots of the hash
+** number is used to fill in empty slots of the hash
** table.
** YYFALLBACK If defined, this indicates that one or more tokens
** have fall-back values which should be used if the
** and nonterminal numbers. "unsigned char" is
** used if there are fewer than 250 rules and
** states combined. "int" is used otherwise.
-** sqlite3ParserTOKENTYPE is the data type used for minor tokens given
+** sqlite3ParserTOKENTYPE is the data type used for minor tokens given
** directly to the parser from the tokenizer.
** YYMINORTYPE is the data type used for all minor tokens.
** This is typically a union of many types, one of
/* Next are the tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
** functions that take a state number and lookahead value and return an
-** action integer.
+** action integer.
**
** Suppose the action integer is N. Then the action is determined as
** follows
** If the index value yy_shift_ofst[S]+X is out of range or if the value
** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
-** and that yy_default[S] should be used instead.
+** and that yy_default[S] should be used instead.
**
** The formula above is for computing the action when the lookahead is
** a terminal symbol. If the lookahead is a non-terminal (as occurs after
/* The next table maps tokens into fallback tokens. If a construct
** like the following:
-**
+**
** %fallback ID X Y Z.
**
** appears in the grammar, then ID becomes a fallback token for X, Y,
#endif /* NDEBUG */
#ifndef NDEBUG
-/*
+/*
** Turn parser tracing on by giving a stream to which to write the trace
** and a prompt to preface each trace message. Tracing is turned off
-** by making either argument NULL
+** by making either argument NULL
**
** Inputs:
** <ul>
#ifndef NDEBUG
/* For tracing shifts, the names of all terminals and nonterminals
** are required. The following table supplies these names */
-static const char *const yyTokenName[] = {
- "$", "SEMI", "EXPLAIN", "QUERY",
- "PLAN", "BEGIN", "TRANSACTION", "DEFERRED",
- "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END",
- "ROLLBACK", "SAVEPOINT", "RELEASE", "TO",
- "TABLE", "CREATE", "IF", "NOT",
- "EXISTS", "TEMP", "LP", "RP",
- "AS", "COMMA", "ID", "INDEXED",
- "ABORT", "ACTION", "AFTER", "ANALYZE",
- "ASC", "ATTACH", "BEFORE", "BY",
- "CASCADE", "CAST", "COLUMNKW", "CONFLICT",
- "DATABASE", "DESC", "DETACH", "EACH",
- "FAIL", "FOR", "IGNORE", "INITIALLY",
- "INSTEAD", "LIKE_KW", "MATCH", "NO",
- "KEY", "OF", "OFFSET", "PRAGMA",
- "RAISE", "REPLACE", "RESTRICT", "ROW",
- "TRIGGER", "VACUUM", "VIEW", "VIRTUAL",
- "REINDEX", "RENAME", "CTIME_KW", "ANY",
- "OR", "AND", "IS", "BETWEEN",
- "IN", "ISNULL", "NOTNULL", "NE",
- "EQ", "GT", "LE", "LT",
- "GE", "ESCAPE", "BITAND", "BITOR",
- "LSHIFT", "RSHIFT", "PLUS", "MINUS",
- "STAR", "SLASH", "REM", "CONCAT",
- "COLLATE", "BITNOT", "STRING", "JOIN_KW",
- "CONSTRAINT", "DEFAULT", "NULL", "PRIMARY",
- "UNIQUE", "CHECK", "REFERENCES", "AUTOINCR",
- "ON", "INSERT", "DELETE", "UPDATE",
- "SET", "DEFERRABLE", "FOREIGN", "DROP",
- "UNION", "ALL", "EXCEPT", "INTERSECT",
- "SELECT", "DISTINCT", "DOT", "FROM",
- "JOIN", "USING", "ORDER", "GROUP",
- "HAVING", "LIMIT", "WHERE", "INTO",
- "VALUES", "INTEGER", "FLOAT", "BLOB",
- "REGISTER", "VARIABLE", "CASE", "WHEN",
- "THEN", "ELSE", "INDEX", "ALTER",
- "ADD", "error", "input", "cmdlist",
- "ecmd", "explain", "cmdx", "cmd",
+static const char *const yyTokenName[] = {
+ "$", "SEMI", "EXPLAIN", "QUERY",
+ "PLAN", "BEGIN", "TRANSACTION", "DEFERRED",
+ "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END",
+ "ROLLBACK", "SAVEPOINT", "RELEASE", "TO",
+ "TABLE", "CREATE", "IF", "NOT",
+ "EXISTS", "TEMP", "LP", "RP",
+ "AS", "COMMA", "ID", "INDEXED",
+ "ABORT", "ACTION", "AFTER", "ANALYZE",
+ "ASC", "ATTACH", "BEFORE", "BY",
+ "CASCADE", "CAST", "COLUMNKW", "CONFLICT",
+ "DATABASE", "DESC", "DETACH", "EACH",
+ "FAIL", "FOR", "IGNORE", "INITIALLY",
+ "INSTEAD", "LIKE_KW", "MATCH", "NO",
+ "KEY", "OF", "OFFSET", "PRAGMA",
+ "RAISE", "REPLACE", "RESTRICT", "ROW",
+ "TRIGGER", "VACUUM", "VIEW", "VIRTUAL",
+ "REINDEX", "RENAME", "CTIME_KW", "ANY",
+ "OR", "AND", "IS", "BETWEEN",
+ "IN", "ISNULL", "NOTNULL", "NE",
+ "EQ", "GT", "LE", "LT",
+ "GE", "ESCAPE", "BITAND", "BITOR",
+ "LSHIFT", "RSHIFT", "PLUS", "MINUS",
+ "STAR", "SLASH", "REM", "CONCAT",
+ "COLLATE", "BITNOT", "STRING", "JOIN_KW",
+ "CONSTRAINT", "DEFAULT", "NULL", "PRIMARY",
+ "UNIQUE", "CHECK", "REFERENCES", "AUTOINCR",
+ "ON", "INSERT", "DELETE", "UPDATE",
+ "SET", "DEFERRABLE", "FOREIGN", "DROP",
+ "UNION", "ALL", "EXCEPT", "INTERSECT",
+ "SELECT", "DISTINCT", "DOT", "FROM",
+ "JOIN", "USING", "ORDER", "GROUP",
+ "HAVING", "LIMIT", "WHERE", "INTO",
+ "VALUES", "INTEGER", "FLOAT", "BLOB",
+ "REGISTER", "VARIABLE", "CASE", "WHEN",
+ "THEN", "ELSE", "INDEX", "ALTER",
+ "ADD", "error", "input", "cmdlist",
+ "ecmd", "explain", "cmdx", "cmd",
"transtype", "trans_opt", "nm", "savepoint_opt",
- "create_table", "create_table_args", "createkw", "temp",
+ "create_table", "create_table_args", "createkw", "temp",
"ifnotexists", "dbnm", "columnlist", "conslist_opt",
- "select", "column", "columnid", "type",
- "carglist", "id", "ids", "typetoken",
- "typename", "signed", "plus_num", "minus_num",
- "ccons", "term", "expr", "onconf",
- "sortorder", "autoinc", "idxlist_opt", "refargs",
+ "select", "column", "columnid", "type",
+ "carglist", "id", "ids", "typetoken",
+ "typename", "signed", "plus_num", "minus_num",
+ "ccons", "term", "expr", "onconf",
+ "sortorder", "autoinc", "idxlist_opt", "refargs",
"defer_subclause", "refarg", "refact", "init_deferred_pred_opt",
- "conslist", "tconscomma", "tcons", "idxlist",
- "defer_subclause_opt", "orconf", "resolvetype", "raisetype",
+ "conslist", "tconscomma", "tcons", "idxlist",
+ "defer_subclause_opt", "orconf", "resolvetype", "raisetype",
"ifexists", "fullname", "oneselect", "multiselect_op",
- "distinct", "selcollist", "from", "where_opt",
- "groupby_opt", "having_opt", "orderby_opt", "limit_opt",
- "sclp", "as", "seltablist", "stl_prefix",
- "joinop", "indexed_opt", "on_opt", "using_opt",
- "joinop2", "inscollist", "sortlist", "nexprlist",
- "setlist", "insert_cmd", "inscollist_opt", "valuelist",
- "exprlist", "likeop", "between_op", "in_op",
- "case_operand", "case_exprlist", "case_else", "uniqueflag",
+ "distinct", "selcollist", "from", "where_opt",
+ "groupby_opt", "having_opt", "orderby_opt", "limit_opt",
+ "sclp", "as", "seltablist", "stl_prefix",
+ "joinop", "indexed_opt", "on_opt", "using_opt",
+ "joinop2", "inscollist", "sortlist", "nexprlist",
+ "setlist", "insert_cmd", "inscollist_opt", "valuelist",
+ "exprlist", "likeop", "between_op", "in_op",
+ "case_operand", "case_exprlist", "case_else", "uniqueflag",
"collate", "nmnum", "number", "trigger_decl",
"trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause",
- "when_clause", "trigger_cmd", "trnm", "tridxby",
+ "when_clause", "trigger_cmd", "trnm", "tridxby",
"database_kw_opt", "key_opt", "add_column_fullname", "kwcolumn_opt",
"create_vtab", "vtabarglist", "vtabarg", "vtabargtoken",
- "lp", "anylist",
+ "lp", "anylist",
};
#endif /* NDEBUG */
}
#endif
-/*
+/*
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
** malloc.
/* Here is inserted the actions which take place when a
** terminal or non-terminal is destroyed. This can happen
** when the symbol is popped from the stack during a
- ** reduce or during error processing or when a parser is
+ ** reduce or during error processing or when a parser is
** being destroyed before it is finished parsing.
**
** Note: during a reduce, the only symbols destroyed are those
return yymajor;
}
-/*
+/*
** Deallocate and destroy a parser. Destructors are all called for
** all stack elements before shutting the parser down.
**
){
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
-
+
if( stateno>YY_SHIFT_COUNT
|| (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
return yy_default[stateno];
#ifdef YYWILDCARD
{
int j = i - iLookAhead + YYWILDCARD;
- if(
+ if(
#if YY_SHIFT_MIN+YYWILDCARD<0
j>=0 &&
#endif
yypParser->yyidxMax = yypParser->yyidx;
}
#endif
-#if YYSTACKDEPTH>0
+#if YYSTACKDEPTH>0
if( yypParser->yyidx>=YYSTACKDEPTH ){
yyStackOverflow(yypParser, yypMinor);
return;
sqlite3ParserARG_FETCH;
yymsp = &yypParser->yystack[yypParser->yyidx];
#ifndef NDEBUG
- if( yyTraceFILE && yyruleno>=0
+ if( yyTraceFILE && yyruleno>=0
&& yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
yyRuleName[yyruleno]);
** not set the value of its left-hand side nonterminal. Leaving the
** value of the nonterminal uninitialized is utterly harmless as long
** as the value is never used. So really the only thing this code
- ** accomplishes is to quieten purify.
+ ** accomplishes is to quieten purify.
**
** 2007-01-16: The wireshark project (www.wireshark.org) reports that
** without this code, their parser segfaults. I'm not sure what there
case 169: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
{
sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy347, &yymsp[-3].minor.yy0);
- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list");
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list");
sqlite3Update(pParse,yymsp[-4].minor.yy347,yymsp[-1].minor.yy442,yymsp[0].minor.yy122,yymsp[-5].minor.yy258);
}
break;
** treated as functions that return constants */
yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
if( yygotominor.yy342.pExpr ){
- yygotominor.yy342.pExpr->op = TK_CONST_FUNC;
+ yygotominor.yy342.pExpr->op = TK_CONST_FUNC;
}
spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
yygotominor.yy342.pExpr->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
- }
+ }
if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
break;
case 242: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
{
- sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
+ sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy442, yymsp[-9].minor.yy392,
&yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy392);
}
}
break;
case 282: /* trigger_cmd_list ::= trigger_cmd SEMI */
-{
+{
assert( yymsp[-1].minor.yy327!=0 );
yymsp[-1].minor.yy327->pLast = yymsp[-1].minor.yy327;
yygotominor.yy327 = yymsp[-1].minor.yy327;
case 284: /* trnm ::= nm DOT nm */
{
yygotominor.yy0 = yymsp[0].minor.yy0;
- sqlite3ErrorMsg(pParse,
+ sqlite3ErrorMsg(pParse,
"qualified table names are not allowed on INSERT, UPDATE, and DELETE "
"statements within triggers");
}
break;
case 293: /* expr ::= RAISE LP IGNORE RP */
{
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
if( yygotominor.yy342.pExpr ){
yygotominor.yy342.pExpr->affinity = OE_Ignore;
}
break;
case 294: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
+ yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
if( yygotominor.yy342.pExpr ) {
yygotominor.yy342.pExpr->affinity = (char)yymsp[-3].minor.yy392;
}
#ifdef YYERRORSYMBOL
/* A syntax error has occurred.
** The response to an error depends upon whether or not the
- ** grammar defines an error token "ERROR".
+ ** grammar defines an error token "ERROR".
**
** This is what we do if the grammar does define ERROR:
**
yy_syntax_error(yypParser,yymajor,yyminorunion);
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
yymajor = YYNOCODE;
-
+
#else /* YYERRORSYMBOL is not defined */
/* This is what we do if the grammar does not define ERROR:
**
/*
** The sqlite3KeywordCode function looks up an identifier to determine if
-** it is a keyword. If it is a keyword, the token code of that keyword is
+** it is a keyword. If it is a keyword, the token code of that keyword is
** returned. If the input is not a keyword, TK_ID is returned.
**
** The implementation of this routine was generated by a program,
521, 527, 531, 536,
};
static const unsigned char aCode[121] = {
- TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
- TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN,
- TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
- TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE,
- TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE,
- TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW,
- TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT,
- TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO,
- TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP,
- TK_OR, TK_UNIQUE, TK_QUERY, TK_ATTACH, TK_HAVING,
- TK_GROUP, TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RELEASE,
- TK_BETWEEN, TK_NOTNULL, TK_NOT, TK_NO, TK_NULL,
- TK_LIKE_KW, TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE,
- TK_COLLATE, TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE,
- TK_JOIN, TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE,
- TK_PRAGMA, TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT,
- TK_WHEN, TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE,
- TK_AND, TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN,
- TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW,
- TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT,
- TK_IS, TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW,
- TK_LIKE_KW, TK_BY, TK_IF, TK_ISNULL, TK_ORDER,
- TK_RESTRICT, TK_JOIN_KW, TK_JOIN_KW, TK_ROLLBACK, TK_ROW,
- TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY,
- TK_ALL,
+ TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
+ TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN,
+ TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
+ TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE,
+ TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE,
+ TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW,
+ TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT,
+ TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO,
+ TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP,
+ TK_OR, TK_UNIQUE, TK_QUERY, TK_ATTACH, TK_HAVING,
+ TK_GROUP, TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RELEASE,
+ TK_BETWEEN, TK_NOTNULL, TK_NOT, TK_NO, TK_NULL,
+ TK_LIKE_KW, TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE,
+ TK_COLLATE, TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE,
+ TK_JOIN, TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE,
+ TK_PRAGMA, TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT,
+ TK_WHEN, TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE,
+ TK_AND, TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN,
+ TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW,
+ TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT,
+ TK_IS, TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW,
+ TK_LIKE_KW, TK_BY, TK_IF, TK_ISNULL, TK_ORDER,
+ TK_RESTRICT, TK_JOIN_KW, TK_JOIN_KW, TK_ROLLBACK, TK_ROW,
+ TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY,
+ TK_ALL,
};
int h, i;
if( n<2 ) return TK_ID;
** IdChar(X) will be true. Otherwise it is false.
**
** For ASCII, any character with the high-order bit set is
-** allowed in an identifier. For 7-bit characters,
+** allowed in an identifier. For 7-bit characters,
** sqlite3IsIdChar[X] must be 1.
**
** For EBCDIC, the rules are more complex but have the same
** end result.
**
** Ticket #1066. the SQL standard does not allow '$' in the
-** middle of identfiers. But many SQL implementations do.
+** middle of identfiers. But many SQL implementations do.
** SQLite will allow '$' in identifiers for compatibility.
** But the feature is undocumented.
*/
/*
-** Return the length of the token that begins at z[0].
+** Return the length of the token that begins at z[0].
** Store the token type in *tokenType before returning.
*/
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
*tokenType = TK_FLOAT;
}
if( (z[i]=='e' || z[i]=='E') &&
- ( sqlite3Isdigit(z[i+1])
+ ( sqlite3Isdigit(z[i+1])
|| ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2]))
)
){
/*
** Run the parser on the given SQL string. The parser structure is
** passed in. An SQLITE_ status code is returned. If an error occurs
-** then an and attempt is made to write an error message into
+** then an and attempt is made to write an error message into
** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that
** error message.
*/
#endif
if( !IN_DECLARE_VTAB ){
- /* If the pParse->declareVtab flag is set, do not delete any table
+ /* If the pParse->declareVtab flag is set, do not delete any table
** structure built up in pParse->pNewTable. The calling code (see vtab.c)
** will take responsibility for freeing the Table structure.
*/
** (2) NORMAL We are in the middle of statement which ends with a single
** semicolon.
**
-** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
+** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
** a statement.
**
** (4) CREATE The keyword CREATE has been seen at the beginning of a
#ifndef SQLITE_AMALGAMATION
/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant
-** contains the text of SQLITE_VERSION macro.
+** contains the text of SQLITE_VERSION macro.
*/
SQLITE_API const char sqlite3_version[] = SQLITE_VERSION;
#endif
/* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns
-** a pointer to the to the sqlite3_version[] string constant.
+** a pointer to the to the sqlite3_version[] string constant.
*/
SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; }
/* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a
** pointer to a string constant whose value is the same as the
-** SQLITE_SOURCE_ID C preprocessor macro.
+** SQLITE_SOURCE_ID C preprocessor macro.
*/
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
SQLITE_API char *sqlite3_data_directory = 0;
/*
-** Initialize SQLite.
+** Initialize SQLite.
**
** This routine must be called to initialize the memory allocation,
** VFS, and mutex subsystems prior to doing any serious work with
** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT
** this routine will be called automatically by key routines such as
-** sqlite3_open().
+** sqlite3_open().
**
** This routine is a no-op except on its very first call for the process,
** or for the first call after a call to sqlite3_shutdown.
}
#endif
- /* Make sure the mutex subsystem is initialized. If unable to
+ /* Make sure the mutex subsystem is initialized. If unable to
** initialize the mutex subsystem, return early with the error.
** If the system is so sick that we are unable to allocate a mutex,
** there is not much SQLite is going to be able to do.
rc = sqlite3OsInit();
}
if( rc==SQLITE_OK ){
- sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
+ sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
sqlite3GlobalConfig.isInit = 1;
}
switch( op ){
/* Mutex configuration options are only available in a threadsafe
- ** compile.
+ ** compile.
*/
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0
case SQLITE_CONFIG_SINGLETHREAD: {
sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
break;
}
-
+
/* Record a pointer to the logger funcction and its first argument.
** The default is NULL. Logging is disabled if the function pointer is
** NULL.
/*
** Set up the lookaside buffers for a database connection.
-** Return SQLITE_OK on success.
+** Return SQLITE_OK on success.
** If lookaside is already active, return SQLITE_BUSY.
**
** The sz parameter is the number of bytes in each lookaside slot.
return SQLITE_BUSY;
}
/* Free any existing lookaside buffer for this handle before
- ** allocating a new one so we don't have to have space for
+ ** allocating a new one so we don't have to have space for
** both at the same time.
*/
if( db->lookaside.bMalloced ){
}
/*
-** Another built-in collating sequence: NOCASE.
+** Another built-in collating sequence: NOCASE.
**
** This collating sequence is intended to be used for "case independant
** comparison". SQLite's knowledge of upper and lower case equivalents
/*
** Return TRUE if database connection db has unfinalized prepared
-** statements or unfinished sqlite3_backup objects.
+** statements or unfinished sqlite3_backup objects.
*/
static int connectionIsBusy(sqlite3 *db){
int j;
/* The temp-database schema is allocated differently from the other schema
** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
** So it needs to be freed here. Todo: Why not roll the temp schema into
- ** the same sqliteMalloc() as the one that allocates the database
+ ** the same sqliteMalloc() as the one that allocates the database
** structure?
*/
sqlite3DbFree(db, db->aDb[1].pSchema);
assert( sqlite3_mutex_held(db->mutex) );
sqlite3BeginBenignMalloc();
- /* Obtain all b-tree mutexes before making any calls to BtreeRollback().
+ /* Obtain all b-tree mutexes before making any calls to BtreeRollback().
** This is important in case the transaction being rolled back has
** modified the database schema. If the b-tree mutexes are not taken
** here, then another shared-cache connection might sneak in between
}else{
p->nBusy++;
}
- return rc;
+ return rc;
}
/*
** be invoked every nOps opcodes.
*/
SQLITE_API void sqlite3_progress_handler(
- sqlite3 *db,
+ sqlite3 *db,
int nOps,
- int (*xProgress)(void*),
+ int (*xProgress)(void*),
void *pArg
){
sqlite3_mutex_enter(db->mutex);
** This function is exactly the same as sqlite3_create_function(), except
** that it is designed to be called by internal code. The difference is
** that if a malloc() fails in sqlite3_create_function(), an error code
-** is returned and the mallocFailed flag cleared.
+** is returned and the mallocFailed flag cleared.
*/
SQLITE_PRIVATE int sqlite3CreateFunc(
sqlite3 *db,
assert( sqlite3_mutex_held(db->mutex) );
if( zFunctionName==0 ||
- (xFunc && (xFinal || xStep)) ||
+ (xFunc && (xFinal || xStep)) ||
(!xFunc && (xFinal && !xStep)) ||
(!xFunc && (!xFinal && xStep)) ||
(nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ||
(255<(nName = sqlite3Strlen30( zFunctionName))) ){
return SQLITE_MISUSE_BKPT;
}
-
+
#ifndef SQLITE_OMIT_UTF16
/* If SQLITE_UTF16 is specified as the encoding type, transform this
** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
#else
enc = SQLITE_UTF8;
#endif
-
+
/* Check if an existing function is being overridden or deleted. If so,
** and there are active VMs, then return SQLITE_BUSY. If a function
** is being overridden/deleted but there are no active VMs, allow the
p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0);
if( p && p->iPrefEnc==enc && p->nArg==nArg ){
if( db->activeVdbeCnt ){
- sqlite3Error(db, SQLITE_BUSY,
+ sqlite3Error(db, SQLITE_BUSY,
"unable to delete/modify user-function due to active statements");
assert( !db->mallocFailed );
return SQLITE_BUSY;
**
** If the function already exists as a regular global function, then
** this routine is a no-op. If the function does not exist, then create
-** a new one that always throws a run-time error.
+** a new one that always throws a run-time error.
**
** When virtual tables intend to provide an overloaded function, they
** should call this routine to make sure the global function exists.
#ifndef SQLITE_OMIT_TRACE
/*
** Register a trace function. The pArg from the previously registered trace
-** is returned.
+** is returned.
**
** A NULL trace function means that no tracing is executes. A non-NULL
** trace is a pointer to a function that is invoked at the start of each
return pOld;
}
/*
-** Register a profile function. The pArg from the previously registered
-** profile function is returned.
+** Register a profile function. The pArg from the previously registered
+** profile function is returned.
**
** A NULL profile function means that no profiling is executes. A non-NULL
** profile is a pointer to a function that is invoked at the conclusion of
** Invoke sqlite3_wal_checkpoint if the number of frames in the log file
** is greater than sqlite3.pWalArg cast to an integer (the value configured by
** wal_autocheckpoint()).
-*/
+*/
SQLITE_PRIVATE int sqlite3WalDefaultHook(
void *pClientData, /* Argument */
sqlite3 *db, /* Connection */
/*
** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points
-** to contains a zero-length string, all attached databases are
+** to contains a zero-length string, all attached databases are
** checkpointed.
*/
SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
** Run a checkpoint on database iDb. This is a no-op if database iDb is
** not currently open in WAL mode.
**
-** If a transaction is open on the database being checkpointed, this
-** function returns SQLITE_LOCKED and a checkpoint is not attempted. If
-** an error occurs while running the checkpoint, an SQLite error code is
+** If a transaction is open on the database being checkpointed, this
+** function returns SQLITE_LOCKED and a checkpoint is not attempted. If
+** an error occurs while running the checkpoint, an SQLite error code is
** returned (i.e. SQLITE_IOERR). Otherwise, SQLITE_OK.
**
** The mutex on database handle db should be held by the caller. The mutex
'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0
};
static const u16 misuse[] = {
- 'l', 'i', 'b', 'r', 'a', 'r', 'y', ' ',
- 'r', 'o', 'u', 't', 'i', 'n', 'e', ' ',
- 'c', 'a', 'l', 'l', 'e', 'd', ' ',
- 'o', 'u', 't', ' ',
- 'o', 'f', ' ',
+ 'l', 'i', 'b', 'r', 'a', 'r', 'y', ' ',
+ 'r', 'o', 'u', 't', 'i', 'n', 'e', ' ',
+ 'c', 'a', 'l', 'l', 'e', 'd', ' ',
+ 'o', 'u', 't', ' ',
+ 'o', 'f', ' ',
's', 'e', 'q', 'u', 'e', 'n', 'c', 'e', 0
};
*/
static int createCollation(
sqlite3* db,
- const char *zName,
+ const char *zName,
u8 enc,
void* pCtx,
int(*xCompare)(void*,int,const void*,int,const void*),
CollSeq *pColl;
int enc2;
int nName = sqlite3Strlen30(zName);
-
+
assert( sqlite3_mutex_held(db->mutex) );
/* If SQLITE_UTF16 is specified as the encoding type, transform this
return SQLITE_MISUSE_BKPT;
}
- /* Check if this call is removing or replacing an existing collation
+ /* Check if this call is removing or replacing an existing collation
** sequence. If so, and there are active VMs, return busy. If there
** are no active VMs, invalidate any pre-compiled statements.
*/
pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0);
if( pColl && pColl->xCmp ){
if( db->activeVdbeCnt ){
- sqlite3Error(db, SQLITE_BUSY,
+ sqlite3Error(db, SQLITE_BUSY,
"unable to delete/modify collation sequence due to active statements");
return SQLITE_BUSY;
}
** then any copies made by synthCollSeq() need to be invalidated.
** Also, collation destructor - CollSeq.xDel() - function may need
** to be called.
- */
+ */
if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){
CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName, nName);
int j;
** query parameter. The second argument contains the URI (or non-URI filename)
** itself. When this function is called the *pFlags variable should contain
** the default flags to open the database handle with. The value stored in
-** *pFlags may be updated before returning if the URI filename contains
+** *pFlags may be updated before returning if the URI filename contains
** "cache=xxx" or "mode=xxx" query parameters.
**
** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
** the VFS that should be used to open the database file. *pzFile is set to
-** point to a buffer containing the name of the file to open. It is the
+** point to a buffer containing the name of the file to open. It is the
** responsibility of the caller to eventually call sqlite3_free() to release
** this buffer.
**
** If an error occurs, then an SQLite error code is returned and *pzErrMsg
-** may be set to point to a buffer containing an English language error
+** may be set to point to a buffer containing an English language error
** message. It is the responsibility of the caller to eventually release
** this buffer by calling sqlite3_free().
*/
const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */
const char *zUri, /* Nul-terminated URI to parse */
unsigned int *pFlags, /* IN/OUT: SQLITE_OPEN_XXX flags */
- sqlite3_vfs **ppVfs, /* OUT: VFS to use */
+ sqlite3_vfs **ppVfs, /* OUT: VFS to use */
char **pzFile, /* OUT: Filename component of URI */
char **pzErrMsg /* OUT: Error message (if rc!=SQLITE_OK) */
){
assert( *pzErrMsg==0 );
- if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri)
- && nUri>=5 && memcmp(zUri, "file:", 5)==0
+ if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri)
+ && nUri>=5 && memcmp(zUri, "file:", 5)==0
){
char *zOpt;
int eState; /* Parser state when parsing URI */
int iOut = 0; /* Output character index */
int nByte = nUri+2; /* Bytes of space to allocate */
- /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
+ /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
** method that there may be extra parameters following the file-name. */
flags |= SQLITE_OPEN_URI;
while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
- *pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
+ *pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
iIn-7, &zUri[7]);
rc = SQLITE_ERROR;
goto parse_uri_out;
iIn = 5;
}
- /* Copy the filename and any query parameters into the zFile buffer.
- ** Decode %HH escape codes along the way.
+ /* Copy the filename and any query parameters into the zFile buffer.
+ ** Decode %HH escape codes along the way.
**
** Within this loop, variable eState may be set to 0, 1 or 2, depending
** on the parsing context. As follows:
eState = 0;
while( (c = zUri[iIn])!=0 && c!='#' ){
iIn++;
- if( c=='%'
- && sqlite3Isxdigit(zUri[iIn])
- && sqlite3Isxdigit(zUri[iIn+1])
+ if( c=='%'
+ && sqlite3Isxdigit(zUri[iIn])
+ && sqlite3Isxdigit(zUri[iIn+1])
){
int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
octet += sqlite3HexToInt(zUri[iIn++]);
** case we ignore all text in the remainder of the path, name or
** value currently being parsed. So ignore the current character
** and skip to the next "?", "=" or "&", as appropriate. */
- while( (c = zUri[iIn])!=0 && c!='#'
+ while( (c = zUri[iIn])!=0 && c!='#'
&& (eState!=0 || c!='?')
&& (eState!=1 || (c!='=' && c!='&'))
&& (eState!=2 || c!='&')
zFile[iOut++] = '\0';
zFile[iOut++] = '\0';
- /* Check if there were any options specified that should be interpreted
+ /* Check if there were any options specified that should be interpreted
** here. Options that are interpreted here include "vfs" and those that
** correspond to flags that may be passed to the sqlite3_open_v2()
** method. */
if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
static struct OpenMode aOpenMode[] = {
{ "ro", SQLITE_OPEN_READONLY },
- { "rw", SQLITE_OPEN_READWRITE },
+ { "rw", SQLITE_OPEN_READWRITE },
{ "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
{ "memory", SQLITE_OPEN_MEMORY },
{ 0, 0 }
/*
** This routine does the work of opening a database on behalf of
-** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
+** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
** is UTF-8 encoded.
*/
static int openDatabase(
if( rc ) return rc;
#endif
- /* Only allow sensible combinations of bits in the flags argument.
+ /* Only allow sensible combinations of bits in the flags argument.
** Throw an error if any non-sense combination is used. If we
** do not block illegal combinations here, it could trigger
** assert() statements in deeper layers. Sensible combinations
flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_EXCLUSIVE |
SQLITE_OPEN_MAIN_DB |
- SQLITE_OPEN_TEMP_DB |
- SQLITE_OPEN_TRANSIENT_DB |
- SQLITE_OPEN_MAIN_JOURNAL |
- SQLITE_OPEN_TEMP_JOURNAL |
- SQLITE_OPEN_SUBJOURNAL |
+ SQLITE_OPEN_TEMP_DB |
+ SQLITE_OPEN_TRANSIENT_DB |
+ SQLITE_OPEN_MAIN_JOURNAL |
+ SQLITE_OPEN_TEMP_JOURNAL |
+ SQLITE_OPEN_SUBJOURNAL |
SQLITE_OPEN_MASTER_JOURNAL |
SQLITE_OPEN_NOMUTEX |
SQLITE_OPEN_FULLMUTEX |
/* The default safety_level for the main database is 'full'; for the temp
- ** database it is 'NONE'. This matches the pager layer defaults.
+ ** database it is 'NONE'. This matches the pager layer defaults.
*/
db->aDb[0].zName = "main";
db->aDb[0].safety_level = 3;
** Open a new database handle.
*/
SQLITE_API int sqlite3_open(
- const char *zFilename,
- sqlite3 **ppDb
+ const char *zFilename,
+ sqlite3 **ppDb
){
return openDatabase(zFilename, ppDb,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
** Open a new database handle.
*/
SQLITE_API int sqlite3_open16(
- const void *zFilename,
+ const void *zFilename,
sqlite3 **ppDb
){
char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */
** Register a new collation sequence with the database handle db.
*/
SQLITE_API int sqlite3_create_collation(
- sqlite3* db,
- const char *zName,
- int enc,
+ sqlite3* db,
+ const char *zName,
+ int enc,
void* pCtx,
int(*xCompare)(void*,int,const void*,int,const void*)
){
** Register a new collation sequence with the database handle db.
*/
SQLITE_API int sqlite3_create_collation_v2(
- sqlite3* db,
- const char *zName,
- int enc,
+ sqlite3* db,
+ const char *zName,
+ int enc,
void* pCtx,
int(*xCompare)(void*,int,const void*,int,const void*),
void(*xDel)(void*)
** Register a new collation sequence with the database handle db.
*/
SQLITE_API int sqlite3_create_collation16(
- sqlite3* db,
+ sqlite3* db,
const void *zName,
- int enc,
+ int enc,
void* pCtx,
int(*xCompare)(void*,int,const void*,int,const void*)
){
** db. Replace any previously installed collation sequence factory.
*/
SQLITE_API int sqlite3_collation_needed(
- sqlite3 *db,
- void *pCollNeededArg,
+ sqlite3 *db,
+ void *pCollNeededArg,
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*)
){
sqlite3_mutex_enter(db->mutex);
** db. Replace any previously installed collation sequence factory.
*/
SQLITE_API int sqlite3_collation_needed16(
- sqlite3 *db,
- void *pCollNeededArg,
+ sqlite3 *db,
+ void *pCollNeededArg,
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*)
){
sqlite3_mutex_enter(db->mutex);
}
SQLITE_PRIVATE int sqlite3MisuseError(int lineno){
testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(SQLITE_MISUSE,
+ sqlite3_log(SQLITE_MISUSE,
"misuse at line %d of [%.10s]",
lineno, 20+sqlite3_sourceid());
return SQLITE_MISUSE;
}
SQLITE_PRIVATE int sqlite3CantopenError(int lineno){
testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(SQLITE_CANTOPEN,
+ sqlite3_log(SQLITE_CANTOPEN,
"cannot open file at line %d of [%.10s]",
lineno, 20+sqlite3_sourceid());
return SQLITE_CANTOPEN;
/* The following block stores the meta information that will be returned
** to the caller in local variables zDataType, zCollSeq, notnull, primarykey
** and autoinc. At this point there are two possibilities:
- **
- ** 1. The specified column name was rowid", "oid" or "_rowid_"
- ** and there is no explicitly declared IPK column.
**
- ** 2. The table is not a view and the column name identified an
+ ** 1. The specified column name was rowid", "oid" or "_rowid_"
+ ** and there is no explicitly declared IPK column.
+ **
+ ** 2. The table is not a view and the column name identified an
** explicitly declared column. Copy meta information from *pCol.
- */
+ */
if( pCol ){
zDataType = pCol->zType;
zCollSeq = pCol->zColl;
pVfs = sqlite3_vfs_find(0);
if( pVfs==0 ) return 0;
- /* This function works in milliseconds, but the underlying OsSleep()
+ /* This function works in milliseconds, but the underlying OsSleep()
** API uses microseconds. Hence the 1000's.
*/
rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000);
sqlite3BtreeLeave(pBtree);
}
sqlite3_mutex_leave(db->mutex);
- return rc;
+ return rc;
}
/*
/*
** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
**
- ** Register hooks to call to indicate which malloc() failures
+ ** Register hooks to call to indicate which malloc() failures
** are benign.
*/
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: {
** This action provides a run-time test to see how the ALWAYS and
** NEVER macros were defined at compile-time.
**
- ** The return value is ALWAYS(X).
+ ** The return value is ALWAYS(X).
**
** The recommended test is X==2. If the return value is 2, that means
** ALWAYS() and NEVER() are both no-op pass-through macros, which is the
/* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N)
**
- ** Enable or disable various optimizations for testing purposes. The
+ ** Enable or disable various optimizations for testing purposes. The
** argument N is a bitmask of optimizations to be disabled. For normal
** operation N should be 0. The idea is that a test program (like the
** SQL Logic Test or SLT test module) can run the same SQL multiple times
**
** If zWord is a keyword recognized by the parser, then return the
** number of keywords. Or if zWord is not a keyword, return 0.
- **
+ **
** This test feature is only available in the amalgamation since
** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite
** is built using separate source files.
rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0;
break;
}
-#endif
+#endif
/* sqlite3_test_control(SQLITE_TESTCTRL_SCRATCHMALLOC, sz, &pNew, pFree);
**
- ** Pass pFree into sqlite3ScratchFree().
- ** If sz>0 then allocate a scratch buffer into pNew.
+ ** Pass pFree into sqlite3ScratchFree().
+ ** If sz>0 then allocate a scratch buffer into pNew.
*/
case SQLITE_TESTCTRL_SCRATCHMALLOC: {
void *pFree, **ppNew;
/*
** This is a utility routine, useful to VFS implementations, that checks
-** to see if a database file was a URI that contained a specific query
+** to see if a database file was a URI that contained a specific query
** parameter, and if so obtains the value of the query parameter.
**
** The zFilename argument is the filename pointer passed into the xOpen()
#ifndef NDEBUG
/*
-** This function is a complex assert() that verifies the following
+** This function is a complex assert() that verifies the following
** properties of the blocked connections list:
**
-** 1) Each entry in the list has a non-NULL value for either
+** 1) Each entry in the list has a non-NULL value for either
** pUnlockConnection or pBlockingConnection, or both.
**
-** 2) All entries in the list that share a common value for
+** 2) All entries in the list that share a common value for
** xUnlockNotify are grouped together.
**
** 3) If the argument db is not NULL, then none of the entries in the
sqlite3 **pp;
assertMutexHeld();
for(
- pp=&sqlite3BlockedList;
- *pp && (*pp)->xUnlockNotify!=db->xUnlockNotify;
+ pp=&sqlite3BlockedList;
+ *pp && (*pp)->xUnlockNotify!=db->xUnlockNotify;
pp=&(*pp)->pNextBlocked
);
db->pNextBlocked = *pp;
db->xUnlockNotify = 0;
db->pUnlockArg = 0;
}else if( 0==db->pBlockingConnection ){
- /* The blocking transaction has been concluded. Or there never was a
+ /* The blocking transaction has been concluded. Or there never was a
** blocking transaction. In either case, invoke the notify callback
- ** immediately.
+ ** immediately.
*/
xNotify(&pArg, 1);
}else{
}
/*
-** This function is called while stepping or preparing a statement
+** This function is called while stepping or preparing a statement
** associated with connection db. The operation will return SQLITE_LOCKED
** to the user because it requires a lock that will not be available
** until connection pBlocker concludes its current transaction.
/*
** This function is called when
-** the transaction opened by database db has just finished. Locks held
+** the transaction opened by database db has just finished. Locks held
** by database connection db have been released.
**
** This function loops through each entry in the blocked connections
}else{
/* This occurs when the array of context pointers that need to
** be passed to the unlock-notify callback is larger than the
- ** aStatic[] array allocated on the stack and the attempt to
+ ** aStatic[] array allocated on the stack and the attempt to
** allocate a larger array from the heap has failed.
**
** This is a difficult situation to handle. Returning an error
** is returned the transaction on connection db will still be
** closed and the unlock-notify callbacks on blocked connections
** will go unissued. This might cause the application to wait
- ** indefinitely for an unlock-notify callback that will never
+ ** indefinitely for an unlock-notify callback that will never
** arrive.
**
** Instead, invoke the unlock-notify callback with the context
** array already accumulated. We can then clear the array and
- ** begin accumulating any further context pointers without
+ ** begin accumulating any further context pointers without
** requiring any dynamic allocation. This is sub-optimal because
** it means that instead of one callback with a large array of
** context pointers the application will receive two or more
** callbacks with smaller arrays of context pointers, which will
- ** reduce the applications ability to prioritize multiple
+ ** reduce the applications ability to prioritize multiple
** connections. But it is the best that can be done under the
** circumstances.
*/
}
/*
-** This is called when the database connection passed as an argument is
+** This is called when the database connection passed as an argument is
** being closed. The connection is removed from the blocked list.
*/
SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
** A doclist (document list) holds a docid-sorted list of hits for a
** given term. Doclists hold docids and associated token positions.
** A docid is the unique integer identifier for a single document.
-** A position is the index of a word within the document. The first
+** A position is the index of a word within the document. The first
** word of the document has a position of 0.
**
** FTS3 used to optionally store character offsets using a compile-time
**
** Here, array { X } means zero or more occurrences of X, adjacent in
** memory. A "position" is an index of a token in the token stream
-** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
+** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
** in the same logical place as the position element, and act as sentinals
** ending a position list array. POS_END is 0. POS_COLUMN is 1.
** The positions numbers are not stored literally but rather as two more
** a document record consists of a docid followed by a position-list and
** a doclist consists of one or more document records.
**
-** A bare doclist omits the position information, becoming an
+** A bare doclist omits the position information, becoming an
** array of varint-encoded docids.
**
**** Segment leaf nodes ****
#ifndef _FTSINT_H
#define _FTSINT_H
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
** When an fts3 table is created, it passes any arguments passed to
** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the
** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer
-** implementation. The xCreate() function in turn returns an
+** implementation. The xCreate() function in turn returns an
** sqlite3_tokenizer structure representing the specific tokenizer to
** be used for the fts3 table (customized by the tokenizer clause arguments).
**
** then argc is set to 2, and the argv[] array contains pointers
** to the strings "arg1" and "arg2".
**
- ** This method should return either SQLITE_OK (0), or an SQLite error
+ ** This method should return either SQLITE_OK (0), or an SQLite error
** code. If SQLITE_OK is returned, then *ppTokenizer should be set
** to point at the newly created tokenizer structure. The generic
** sqlite3_tokenizer.pModule variable should not be initialized by
/*
** Create a tokenizer cursor to tokenize an input buffer. The caller
** is responsible for ensuring that the input buffer remains valid
- ** until the cursor is closed (using the xClose() method).
+ ** until the cursor is closed (using the xClose() method).
*/
int (*xOpen)(
sqlite3_tokenizer *pTokenizer, /* Tokenizer object */
);
/*
- ** Destroy an existing tokenizer cursor. The fts3 module calls this
+ ** Destroy an existing tokenizer cursor. The fts3 module calls this
** method exactly once for each successful call to xOpen().
*/
int (*xClose)(sqlite3_tokenizer_cursor *pCursor);
** "OUT" variables identified below, or SQLITE_DONE to indicate that
** the end of the buffer has been reached, or an SQLite error code.
**
- ** *ppToken should be set to point at a buffer containing the
+ ** *ppToken should be set to point at a buffer containing the
** normalized version of the token (i.e. after any case-folding and/or
** stemming has been performed). *pnBytes should be set to the length
** of this buffer in bytes. The input text that generated the token is
**
** The buffer *ppToken is set to point at is managed by the tokenizer
** implementation. It is only required to be valid until the next call
- ** to xNext() or xClose().
+ ** to xNext() or xClose().
*/
/* TODO(shess) current implementation requires pInput to be
** nul-terminated. This should either be fixed, or pInput/nBytes
** Methods below this point are only available if iVersion>=1.
*/
- /*
+ /*
** Configure the language id of a tokenizer cursor.
*/
int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid);
} *ht;
};
-/* Each element in the hash table is an instance of the following
+/* Each element in the hash table is an instance of the following
** structure. All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
** (including the null-terminator, if any). Case
** is respected in comparisons.
**
-** FTS3_HASH_BINARY pKey points to binary data nKey bytes long.
+** FTS3_HASH_BINARY pKey points to binary data nKey bytes long.
** memcmp() is used to compare keys.
**
-** A copy of the key is made if the copyKey parameter to fts3HashInit is 1.
+** A copy of the key is made if the copyKey parameter to fts3HashInit is 1.
*/
#define FTS3_HASH_STRING 1
#define FTS3_HASH_BINARY 2
#define FTS3_MERGE_COUNT 16
/*
-** This is the maximum amount of data (in bytes) to store in the
+** This is the maximum amount of data (in bytes) to store in the
** Fts3Table.pendingTerms hash table. Normally, the hash table is
** populated as documents are inserted/updated/deleted in a transaction
** and used to create a new segment when the transaction is committed.
-** However if this limit is reached midway through a transaction, a new
+** However if this limit is reached midway through a transaction, a new
** segment is created and the hash table cleared immediately.
*/
#define FTS3_MAX_PENDING_DATA (1*1024*1024)
/*
** FTS4 virtual tables may maintain multiple indexes - one index of all terms
** in the document set and zero or more prefix indexes. All indexes are stored
-** as one or more b+-trees in the %_segments and %_segdir tables.
+** as one or more b+-trees in the %_segments and %_segdir tables.
**
** It is possible to determine which index a b+-tree belongs to based on the
** value stored in the "%_segdir.level" column. Given this value L, the index
** level values between 0 and 1023 (inclusive) belong to index 0, all levels
** between 1024 and 2047 to index 1, and so on.
**
-** It is considered impossible for an index to use more than 1024 levels. In
-** theory though this may happen, but only after at least
+** It is considered impossible for an index to use more than 1024 levels. In
+** theory though this may happen, but only after at least
** (FTS3_MERGE_COUNT^1024) separate flushes of the pending-terms tables.
*/
#define FTS3_SEGDIR_MAXLEVEL 1024
** Terminator values for position-lists and column-lists.
*/
#define POS_COLUMN (1) /* Column-list terminator */
-#define POS_END (0) /* Position-list terminator */
+#define POS_END (0) /* Position-list terminator */
/*
** This section provides definitions to allow the
-** FTS3 extension to be compiled outside of the
+** FTS3 extension to be compiled outside of the
** amalgamation.
*/
#ifndef SQLITE_AMALGAMATION
/*
** Activate assert() only if SQLITE_TEST is enabled.
*/
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
u8 bAutoincrmerge; /* True if automerge=1 */
u32 nLeafAdd; /* Number of leaf blocks added this trans */
- /* Precompiled statements used by the implementation. Each of these
- ** statements is run and reset within a single virtual table API call.
+ /* Precompiled statements used by the implementation. Each of these
+ ** statements is run and reset within a single virtual table API call.
*/
sqlite3_stmt *aStmt[37];
char *zSegmentsTbl; /* Name of %_segments table */
sqlite3_blob *pSegments; /* Blob handle open on %_segments table */
- /*
- ** The following array of hash tables is used to buffer pending index
+ /*
+ ** The following array of hash tables is used to buffer pending index
** updates during transactions. All pending updates buffered at any one
** time must share a common language-id (see the FTS4 langid= feature).
** The current language id is stored in variable iPrevLangid.
** terms that appear in the document set. Each subsequent index in aIndex[]
** is an index of prefixes of a specific length.
**
- ** Variable nPendingData contains an estimate the memory consumed by the
+ ** Variable nPendingData contains an estimate the memory consumed by the
** pending data structures, including hash table overhead, but not including
** malloc overhead. When nPendingData exceeds nMaxPendingData, all hash
- ** tables are flushed to disk. Variable iPrevDocid is the docid of the most
+ ** tables are flushed to disk. Variable iPrevDocid is the docid of the most
** recently inserted record.
*/
int nIndex; /* Size of aIndex[] */
**
** CREATE VIRTUAL TABLE ex1 USING fts3(a,b,c,d);
** SELECT docid FROM ex1 WHERE b MATCH 'one two three';
-**
+**
** Because the LHS of the MATCH operator is 2nd column "b",
** Fts3Cursor.eSearch will be set to FTS3_FULLTEXT_SEARCH+1. (+0 for a,
-** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1"
+** +1 for b, +2 for c, +3 for d.) If the LHS of MATCH were "ex1"
** indicating that all columns should be searched,
** then eSearch would be set to FTS3_FULLTEXT_SEARCH+4.
*/
int bIncr; /* True if doclist is loaded incrementally */
int iDoclistToken;
- /* Variables below this point are populated by fts3_expr.c when parsing
- ** a MATCH expression. Everything above is part of the evaluation phase.
+ /* Variables below this point are populated by fts3_expr.c when parsing
+ ** a MATCH expression. Everything above is part of the evaluation phase.
*/
int nToken; /* Number of tokens in the phrase */
int iColumn; /* Index of column this phrase must match */
/*
** A tree of these objects forms the RHS of a MATCH operator.
**
-** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist
-** points to a malloced buffer, size nDoclist bytes, containing the results
-** of this phrase query in FTS3 doclist format. As usual, the initial
-** "Length" field found in doclists stored on disk is omitted from this
+** If Fts3Expr.eType is FTSQUERY_PHRASE and isLoaded is true, then aDoclist
+** points to a malloced buffer, size nDoclist bytes, containing the results
+** of this phrase query in FTS3 doclist format. As usual, the initial
+** "Length" field found in doclists stored on disk is omitted from this
** buffer.
**
** Variable aMI is used only for FTSQUERY_NEAR nodes to store the global
** aMI[iCol*3 + 1] = Number of occurrences
** aMI[iCol*3 + 2] = Number of rows containing at least one instance
**
-** The aMI array is allocated using sqlite3_malloc(). It should be freed
+** The aMI array is allocated using sqlite3_malloc(). It should be freed
** when the expression node is.
*/
struct Fts3Expr {
/*
** Candidate values for Fts3Query.eType. Note that the order of the first
-** four values is in order of precedence when parsing expressions. For
+** four values is in order of precedence when parsing expressions. For
** example, the following:
**
** "a OR b AND c NOT d NEAR e"
SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *);
SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *);
-SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(Fts3Table *,
+SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(Fts3Table *,
int, int, int, const char *, int, int, int, Fts3MultiSegReader *);
/* Flags allowed as part of the 4th argument to SegmentReaderIterate() */
/* fts3_tokenizer.c */
SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
SQLITE_PRIVATE int sqlite3Fts3InitHashTable(sqlite3 *, Fts3Hash *, const char *);
-SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
+SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(Fts3Hash *pHash, const char *,
sqlite3_tokenizer **, char **
);
SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char);
Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
-SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **);
+SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **);
SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
/* #include <string.h> */
/* #include <stdarg.h> */
-#ifndef SQLITE_CORE
+#ifndef SQLITE_CORE
SQLITE_EXTENSION_INIT1
#endif
static int fts3TermSegReaderCursor(
Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
-/*
+/*
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
** The number of bytes written is returned.
return (int) (q - (unsigned char *)p);
}
-/*
+/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
int iOut = 0; /* Index of next byte to write to output */
/* If the first byte was a '[', then the close-quote character is a ']' */
- if( quote=='[' ) quote = ']';
+ if( quote=='[' ) quote = ']';
while( ALWAYS(z[iIn]) ){
if( z[iIn]==quote ){
** varint is part of.
*/
static void fts3GetReverseVarint(
- char **pp,
- char *pStart,
+ char **pp,
+ char *pStart,
sqlite3_int64 *pVal
){
sqlite3_int64 iVal;
char *p;
- /* Pointer p now points at the first byte past the varint we are
+ /* Pointer p now points at the first byte past the varint we are
** interested in. So, unless the doclist is corrupt, the 0x80 bit is
** clear on character p[-1]. */
for(p = (*pp)-2; p>=pStart && *p&0x80; p--);
** passed as the first argument. This is done as part of the xConnect()
** and xCreate() methods.
**
-** If *pRc is non-zero when this function is called, it is a no-op.
+** If *pRc is non-zero when this function is called, it is a no-op.
** Otherwise, if an error occurs, an SQLite error code is stored in *pRc
** before returning.
*/
/* Create the whole "CREATE TABLE" statement to pass to SQLite */
zSql = sqlite3_mprintf(
- "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)",
+ "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)",
zCols, p->zName, zLanguageid
);
if( !zCols || !zSql ){
** Create the %_stat table if it does not already exist.
*/
SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int *pRc, Fts3Table *p){
- fts3DbExec(pRc, p->db,
+ fts3DbExec(pRc, p->db,
"CREATE TABLE IF NOT EXISTS %Q.'%q_stat'"
"(id INTEGER PRIMARY KEY, value BLOB);",
p->zDb, p->zName
zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid);
}
if( zContentCols==0 ) rc = SQLITE_NOMEM;
-
+
/* Create the content table */
- fts3DbExec(&rc, db,
+ fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_content'(%s)",
p->zDb, p->zName, zContentCols
);
}
/* Create other tables */
- fts3DbExec(&rc, db,
+ fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_segments'(blockid INTEGER PRIMARY KEY, block BLOB);",
p->zDb, p->zName
);
- fts3DbExec(&rc, db,
+ fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_segdir'("
"level INTEGER,"
"idx INTEGER,"
p->zDb, p->zName
);
if( p->bHasDocsize ){
- fts3DbExec(&rc, db,
+ fts3DbExec(&rc, db,
"CREATE TABLE %Q.'%q_docsize'(docid INTEGER PRIMARY KEY, size BLOB);",
p->zDb, p->zName
);
/*
** Store the current database page-size in bytes in p->nPgsz.
**
-** If *pRc is non-zero when this function is called, it is a no-op.
+** If *pRc is non-zero when this function is called, it is a no-op.
** Otherwise, if an error occurs, an SQLite error code is stored in *pRc
** before returning.
*/
int rc; /* Return code */
char *zSql; /* SQL text "PRAGMA %Q.page_size" */
sqlite3_stmt *pStmt; /* Compiled "PRAGMA %Q.page_size" statement */
-
+
zSql = sqlite3_mprintf("PRAGMA %Q.page_size", p->zDb);
if( !zSql ){
rc = SQLITE_NOMEM;
**
** <key> = <value>
**
-** There may not be whitespace surrounding the "=" character. The <value>
+** There may not be whitespace surrounding the "=" character. The <value>
** term may be quoted, but the <key> may not.
*/
static int fts3IsSpecialColumn(
- const char *z,
+ const char *z,
int *pnKey,
char **pzValue
){
}
/*
-** Return a list of comma separated SQL expressions and a FROM clause that
+** Return a list of comma separated SQL expressions and a FROM clause that
** could be used in a SELECT statement such as the following:
**
** SELECT <list of expressions> FROM %_content AS x ...
fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid);
}
}
- fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x",
+ fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x",
p->zDb,
(p->zContentTbl ? p->zContentTbl : p->zName),
(p->zContentTbl ? "" : "_content")
**
** If argument zFunc is not NULL, then all but the first question mark
** is preceded by zFunc and an open bracket, and followed by a closed
-** bracket. For example, if zFunc is "zip" and the FTS3 table has three
+** bracket. For example, if zFunc is "zip" and the FTS3 table has three
** user-defined text columns, the following string is returned:
**
** "?, zip(?), zip(?), zip(?)"
/*
** This function interprets the string at (*pp) as a non-negative integer
-** value. It reads the integer and sets *pnOut to the value read, then
+** value. It reads the integer and sets *pnOut to the value read, then
** sets *pp to point to the byte immediately following the last byte of
** the integer value.
**
-** Only decimal digits ('0'..'9') may be part of an integer value.
+** Only decimal digits ('0'..'9') may be part of an integer value.
**
** If *pp does not being with a decimal digit SQLITE_ERROR is returned and
** the output value undefined. Otherwise SQLITE_OK is returned.
int *pnStr /* OUT: Bytes of string content */
){
int rc = SQLITE_OK; /* Return code */
- char *zSql; /* "SELECT *" statement on zTbl */
+ char *zSql; /* "SELECT *" statement on zTbl */
sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */
zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl);
char *zVal;
/* Check if this is a tokenizer specification */
- if( !pTokenizer
+ if( !pTokenizer
&& strlen(z)>8
- && 0==sqlite3_strnicmp(z, "tokenize", 8)
+ && 0==sqlite3_strnicmp(z, "tokenize", 8)
&& 0==sqlite3Fts3IsIdChar(z[8])
){
rc = sqlite3Fts3InitTokenizer(pHash, &z[9], &pTokenizer, pzErr);
break;
case 4: /* ORDER */
- if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
- && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
+ if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
+ && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
){
*pzErr = sqlite3_mprintf("unrecognized order: %s", zVal);
rc = SQLITE_ERROR;
** TABLE statement, use all columns from the content table.
*/
if( rc==SQLITE_OK && zContent ){
- sqlite3_free(zCompress);
- sqlite3_free(zUncompress);
+ sqlite3_free(zCompress);
+ sqlite3_free(zUncompress);
zCompress = 0;
zUncompress = 0;
if( nCol==0 ){
- sqlite3_free((void*)aCol);
+ sqlite3_free((void*)aCol);
aCol = 0;
rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
/* If a languageid= option was specified, remove the language id
- ** column from the aCol[] array. */
+ ** column from the aCol[] array. */
if( rc==SQLITE_OK && zLanguageid ){
int j;
for(j=0; j<nCol; j++){
/* Fill in the azColumn array */
for(iCol=0; iCol<nCol; iCol++){
- char *z;
+ char *z;
int n = 0;
z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
memcpy(zCsr, z, n);
p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc);
if( rc!=SQLITE_OK ) goto fts3_init_out;
- /* If this is an xCreate call, create the underlying tables in the
+ /* If this is an xCreate call, create the underlying tables in the
** database. TODO: For xConnect(), it could verify that said tables exist.
*/
if( isCreate ){
return fts3InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr);
}
-/*
+/*
** Implementation of the xBestIndex method for FTS3 tables. There
** are three possible strategies, in order of preference:
**
-** 1. Direct lookup by rowid or docid.
+** 1. Direct lookup by rowid or docid.
** 2. Full-text search using a MATCH operator on a non-docid column.
** 3. Linear scan of %_content table.
*/
int iLangidCons = -1; /* Index of langid=x constraint, if present */
/* By default use a full table scan. This is an expensive option,
- ** so search through the constraints to see if a more efficient
+ ** so search through the constraints to see if a more efficient
** strategy is possible.
*/
pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
if( pCons->usable==0 ) continue;
/* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
- if( iCons<0
- && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
+ if( iCons<0
+ && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
&& (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 )
){
pInfo->idxNum = FTS3_DOCID_SEARCH;
**
** If there is more than one MATCH constraint available, use the first
** one encountered. If there is both a MATCH constraint and a direct
- ** rowid/docid lookup, prefer the MATCH strategy. This is done even
+ ** rowid/docid lookup, prefer the MATCH strategy. This is done even
** though the rowid/docid lookup is faster than a MATCH query, selecting
- ** it would lead to an "unable to use function MATCH in the requested
+ ** it would lead to an "unable to use function MATCH in the requested
** context" error.
*/
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH
+ if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH
&& pCons->iColumn>=0 && pCons->iColumn<=p->nColumn
){
pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn;
}
/* Equality constraint on the langid column */
- if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
+ if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
&& pCons->iColumn==p->nColumn + 2
){
iLangidCons = i;
if( iCons>=0 ){
pInfo->aConstraintUsage[iCons].argvIndex = 1;
pInfo->aConstraintUsage[iCons].omit = 1;
- }
+ }
if( iLangidCons>=0 ){
pInfo->aConstraintUsage[iLangidCons].argvIndex = 2;
- }
+ }
/* Regardless of the strategy selected, FTS can deliver rows in rowid (or
- ** docid) order. Both ascending and descending are possible.
+ ** docid) order. Both ascending and descending are possible.
*/
if( pInfo->nOrderBy==1 ){
struct sqlite3_index_orderby *pOrder = &pInfo->aOrderBy[0];
UNUSED_PARAMETER(pVTab);
/* Allocate a buffer large enough for an Fts3Cursor structure. If the
- ** allocation succeeds, zero it and return SQLITE_OK. Otherwise,
+ ** allocation succeeds, zero it and return SQLITE_OK. Otherwise,
** if the allocation fails, return SQLITE_NOMEM.
*/
*ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor));
/*
** Position the pCsr->pStmt statement so that it is on the row
** of the %_content table that contains the last match. Return
-** SQLITE_OK on success.
+** SQLITE_OK on success.
*/
static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
int rc = SQLITE_OK;
/*
** This function is used to process a single interior node when searching
-** a b-tree for a term or term prefix. The node data is passed to this
+** a b-tree for a term or term prefix. The node data is passed to this
** function via the zNode/nNode parameters. The term to search for is
** passed in zTerm/nTerm.
**
int isFirstTerm = 1; /* True when processing first term on page */
sqlite3_int64 iChild; /* Block id of child node to descend to */
- /* Skip over the 'height' varint that occurs at the start of every
+ /* Skip over the 'height' varint that occurs at the start of every
** interior node. Then load the blockid of the left-child of the b-tree
- ** node into variable iChild.
+ ** node into variable iChild.
**
** Even if the data structure on disk is corrupted, this (reading two
** varints from the buffer) does not risk an overread. If zNode is a
if( zCsr>zEnd ){
return FTS_CORRUPT_VTAB;
}
-
+
while( zCsr<zEnd && (piFirst || piLast) ){
int cmp; /* memcmp() result */
int nSuffix; /* Size of term suffix */
int nPrefix = 0; /* Size of term prefix */
int nBuffer; /* Total term size */
-
+
/* Load the next term on the node into zBuffer. Use realloc() to expand
** the size of zBuffer if required. */
if( !isFirstTerm ){
}
isFirstTerm = 0;
zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
-
+
if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
rc = FTS_CORRUPT_VTAB;
goto finish_scan;
/* Compare the term we are searching for with the term just loaded from
** the interior node. If the specified term is greater than or equal
- ** to the term from the interior node, then all terms on the sub-tree
- ** headed by node iChild are smaller than zTerm. No need to search
+ ** to the term from the interior node, then all terms on the sub-tree
+ ** headed by node iChild are smaller than zTerm. No need to search
** iChild.
**
** If the interior node term is larger than the specified term, then
** node for the range of leaf nodes that may contain the specified term
** or terms for which the specified term is a prefix.
**
-** If piLeaf is not NULL, then *piLeaf is set to the blockid of the
+** If piLeaf is not NULL, then *piLeaf is set to the blockid of the
** left-most leaf node in the tree that may contain the specified term.
** If piLeaf2 is not NULL, then *piLeaf2 is set to the blockid of the
** right-most leaf node that may contain a term for which the specified
** term is a prefix.
**
-** It is possible that the range of returned leaf nodes does not contain
-** the specified term or any terms for which it is a prefix. However, if the
+** It is possible that the range of returned leaf nodes does not contain
+** the specified term or any terms for which it is a prefix. However, if the
** segment does contain any such terms, they are stored within the identified
** range. Because this function only inspects interior segment nodes (and
** never loads leaf nodes into memory), it is not possible to be sure.
**
** If an error occurs, an error code other than SQLITE_OK is returned.
-*/
+*/
static int fts3SelectLeaf(
Fts3Table *p, /* Virtual table handle */
const char *zTerm, /* Term to select leaves for */
}
/*
-** This function is used to create delta-encoded serialized lists of FTS3
+** This function is used to create delta-encoded serialized lists of FTS3
** varints. Each call to this function appends a single varint to a list.
*/
static void fts3PutDeltaVarint(
}
/*
-** When this function is called, *ppPoslist is assumed to point to the
+** When this function is called, *ppPoslist is assumed to point to the
** start of a position-list. After it returns, *ppPoslist points to the
** first byte after the position-list.
**
-** A position list is list of positions (delta encoded) and columns for
+** A position list is list of positions (delta encoded) and columns for
** a single document record of a doclist. So, in other words, this
** routine advances *ppPoslist so that it points to the next docid in
** the doclist, or to the first byte past the end of the doclist.
char *pEnd = *ppPoslist;
char c = 0;
- /* The end of a position list is marked by a zero encoded as an FTS3
+ /* The end of a position list is marked by a zero encoded as an FTS3
** varint. A single POS_END (0) byte. Except, if the 0 byte is preceded by
** a byte with the 0x80 bit set, then it is not a varint 0, but the tail
** of some other, multi-byte, value.
**
- ** The following while-loop moves pEnd to point to the first byte that is not
+ ** The following while-loop moves pEnd to point to the first byte that is not
** immediately preceded by a byte with the 0x80 bit set. Then increments
** pEnd once more so that it points to the byte immediately following the
** last byte in the position-list.
}
/*
-** When this function is called, *ppPoslist is assumed to point to the
+** When this function is called, *ppPoslist is assumed to point to the
** start of a column-list. After it returns, *ppPoslist points to the
** to the terminator (POS_COLUMN or POS_END) byte of the column-list.
**
** (in which case **pp will be a terminator bytes POS_END (0) or
** (1)).
**
-** If *pp points past the end of the current position-list, set *pi to
+** If *pp points past the end of the current position-list, set *pi to
** POSITION_LIST_END and return. Otherwise, read the next varint from *pp,
** increment the current value of *pi by the value read, and set *pp to
** point to the next value before returning.
** the value of iCol encoded as a varint to *pp. This will start a new
** column list.
**
-** Set *pp to point to the byte just after the last byte written before
+** Set *pp to point to the byte just after the last byte written before
** returning (do not modify it if iCol==0). Return the total number of bytes
** written (0 if iCol==0).
*/
/* At this point, both p1 and p2 point to the start of column-lists
** for the same column (the column with index iCol1 and iCol2).
- ** A column-list is a list of non-negative delta-encoded varints, each
+ ** A column-list is a list of non-negative delta-encoded varints, each
** incremented by 2 before being stored. Each list is terminated by a
** POS_END (0) or POS_COLUMN (1). The following block merges the two lists
** and writes the results to buffer p. p is left pointing to the byte
fts3GetDeltaVarint(&p1, &i1);
fts3GetDeltaVarint(&p2, &i2);
do {
- fts3PutDeltaVarint(&p, &iPrev, (i1<i2) ? i1 : i2);
+ fts3PutDeltaVarint(&p, &iPrev, (i1<i2) ? i1 : i2);
iPrev -= 2;
if( i1==i2 ){
fts3ReadNextPos(&p1, &i1);
** When this function returns, both *pp1 and *pp2 are left pointing to the
** byte following the 0x00 terminator of their respective position lists.
**
-** If isSaveLeft is 0, an entry is added to the output position list for
+** If isSaveLeft is 0, an entry is added to the output position list for
** each position in *pp2 for which there exists one or more positions in
** *pp1 so that (pos(*pp2)>pos(*pp1) && pos(*pp2)-pos(*pp1)<=nToken). i.e.
** when the *pp1 token appears before the *pp2 token, but not more than nToken
assert( isSaveLeft==0 || isExact==0 );
assert( p!=0 && *p1!=0 && *p2!=0 );
- if( *p1==POS_COLUMN ){
+ if( *p1==POS_COLUMN ){
p1++;
p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
}
- if( *p2==POS_COLUMN ){
+ if( *p2==POS_COLUMN ){
p2++;
p2 += sqlite3Fts3GetVarint32(p2, &iCol2);
}
fts3GetDeltaVarint(&p2, &iPos2); iPos2 -= 2;
while( 1 ){
- if( iPos2==iPos1+nToken
- || (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken)
+ if( iPos2==iPos1+nToken
+ || (isExact==0 && iPos2>iPos1 && iPos2<=iPos1+nToken)
){
sqlite3_int64 iSave;
iSave = isSaveLeft ? iPos1 : iPos2;
/* Advance pointer p1 or p2 (whichever corresponds to the smaller of
** iCol1 and iCol2) so that it points to either the 0x00 that marks the
- ** end of the position list, or the 0x01 that precedes the next
- ** column-number in the position list.
+ ** end of the position list, or the 0x01 that precedes the next
+ ** column-number in the position list.
*/
else if( iCol1<iCol2 ){
fts3ColumnlistCopy(0, &p1);
/*
** Merge two position-lists as required by the NEAR operator. The argument
-** position lists correspond to the left and right phrases of an expression
+** position lists correspond to the left and right phrases of an expression
** like:
**
** "phrase 1" NEAR "phrase number 2"
**
-** Position list *pp1 corresponds to the left-hand side of the NEAR
-** expression and *pp2 to the right. As usual, the indexes in the position
-** lists are the offsets of the last token in each phrase (tokens "1" and "2"
+** Position list *pp1 corresponds to the left-hand side of the NEAR
+** expression and *pp2 to the right. As usual, the indexes in the position
+** lists are the offsets of the last token in each phrase (tokens "1" and "2"
** in the example above).
**
** The output position list - written to *pp - is a copy of *pp2 with those
return res;
}
-/*
+/*
** An instance of this function is used to merge together the (potentially
** large number of) doclists for each term that matches a prefix query.
** See function fts3TermSelectMerge() for details.
** from *pp. *pp is then set to point 1 byte past the end of the read varint.
**
** If bDescIdx is false, the value read is added to *pVal before returning.
-** If it is true, the value read is subtracted from *pVal before this
+** If it is true, the value read is subtracted from *pVal before this
** function returns.
*/
static void fts3GetDeltaVarint3(
** end of the value written.
**
** If *pbFirst is zero when this function is called, the value written to
-** the buffer is that of parameter iVal.
+** the buffer is that of parameter iVal.
**
-** If *pbFirst is non-zero when this function is called, then the value
+** If *pbFirst is non-zero when this function is called, then the value
** written is either (iVal-*piPrev) (if bDescIdx is zero) or (*piPrev-iVal)
** (if bDescIdx is non-zero).
**
/*
** This macro is used by various functions that merge doclists. The two
** arguments are 64-bit docid values. If the value of the stack variable
-** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2).
+** bDescDoclist is 0 when this macro is invoked, then it returns (i1-i2).
** Otherwise, (i2-i1).
**
** Using this makes it easier to write code that can merge doclists that are
/*
** This function does an "OR" merge of two doclists (output contains all
-** positions contained in either argument doclist). If the docids in the
+** positions contained in either argument doclist). If the docids in the
** input doclists are sorted in ascending order, parameter bDescDoclist
** should be false. If they are sorted in ascending order, it should be
** passed a non-zero value.
** current and previous docid (a positive number - since the list is in
** ascending order).
**
- ** The first docid written to the output is therefore encoded using the
+ ** The first docid written to the output is therefore encoded using the
** same number of bytes as it is in whichever of the input lists it is
- ** read from. And each subsequent docid read from the same input list
+ ** read from. And each subsequent docid read from the same input list
** consumes either the same or less bytes as it did in the input (since
** the difference between it and the previous value in the output must
- ** be a positive value less than or equal to the delta value read from
+ ** be a positive value less than or equal to the delta value read from
** the input list). The same argument applies to all but the first docid
** read from the 'other' list. And to the contents of all position lists
** that will be copied and merged from the input to the output.
**
** The space required to store the output is therefore the sum of the
** sizes of the two inputs, plus enough space for exactly one of the input
- ** docids to grow.
+ ** docids to grow.
**
- ** A symetric argument may be made if the doclists are in descending
+ ** A symetric argument may be made if the doclists are in descending
** order.
*/
aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
** exactly nDist tokens before it.
**
** If the docids in the input doclists are sorted in ascending order,
-** parameter bDescDoclist should be false. If they are sorted in ascending
+** parameter bDescDoclist should be false. If they are sorted in ascending
** order, it should be passed a non-zero value.
**
** The right-hand input doclist is overwritten by this function.
int nNew;
char *aNew;
- int rc = fts3DoclistOrMerge(p->bDescIdx,
+ int rc = fts3DoclistOrMerge(p->bDescIdx,
pTS->aaOutput[i], pTS->anOutput[i], aOut, nOut, &aNew, &nNew
);
if( rc!=SQLITE_OK ){
char *aNew;
int nNew;
- int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge,
+ int rc = fts3DoclistOrMerge(p->bDescIdx, aMerge, nMerge,
pTS->aaOutput[iOut], pTS->anOutput[iOut], &aNew, &nNew
);
if( rc!=SQLITE_OK ){
if( aMerge!=aDoclist ) sqlite3_free(aMerge);
sqlite3_free(pTS->aaOutput[iOut]);
pTS->aaOutput[iOut] = 0;
-
+
aMerge = aNew;
nMerge = nNew;
if( (iOut+1)==SizeofArray(pTS->aaOutput) ){
** Append SegReader object pNew to the end of the pCsr->apSegment[] array.
*/
static int fts3SegReaderCursorAppend(
- Fts3MultiSegReader *pCsr,
+ Fts3MultiSegReader *pCsr,
Fts3SegReader *pNew
){
if( (pCsr->nSegment%16)==0 ){
sqlite3_stmt *pStmt = 0; /* Statement to iterate through segments */
int rc2; /* Result of sqlite3_reset() */
- /* If iLevel is less than 0 and this is not a scan, include a seg-reader
+ /* If iLevel is less than 0 and this is not a scan, include a seg-reader
** for the pending-terms. If this is a scan, then this call must be being
** made by an fts4aux module, not an FTS table. In this case calling
- ** Fts3SegReaderPending might segfault, as the data structures used by
+ ** Fts3SegReaderPending might segfault, as the data structures used by
** fts4aux are not completely populated. So it's easiest to filter these
** calls out here. */
if( iLevel<0 && p->aIndex ){
if( rc!=SQLITE_OK ) goto finished;
if( isPrefix==0 && isScan==0 ) iLeavesEndBlock = iStartBlock;
}
-
- rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1,
+
+ rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1,
(isPrefix==0 && isScan==0),
- iStartBlock, iLeavesEndBlock,
+ iStartBlock, iLeavesEndBlock,
iEndBlock, zRoot, nRoot, &pSeg
);
if( rc!=SQLITE_OK ) goto finished;
}
/*
-** Set up a cursor object for iterating through a full-text index or a
+** Set up a cursor object for iterating through a full-text index or a
** single level therein.
*/
SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(
){
assert( iIndex>=0 && iIndex<p->nIndex );
assert( iLevel==FTS3_SEGCURSOR_ALL
- || iLevel==FTS3_SEGCURSOR_PENDING
+ || iLevel==FTS3_SEGCURSOR_PENDING
|| iLevel>=0
);
assert( iLevel<FTS3_SEGDIR_MAXLEVEL );
int nTerm, /* Number of bytes in zTerm */
Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */
){
- return fts3SegReaderCursor(p,
+ return fts3SegReaderCursor(p,
iLangid, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr
);
}
/*
** Open an Fts3MultiSegReader to scan the doclist for term zTerm/nTerm. Or,
-** if isPrefix is true, to scan the doclist for all terms for which
+** if isPrefix is true, to scan the doclist for all terms for which
** zTerm/nTerm is a prefix. If successful, return SQLITE_OK and write
** a pointer to the new Fts3MultiSegReader to *ppSegcsr. Otherwise, return
** an SQLite error code.
**
** It is the responsibility of the caller to free this object by eventually
-** passing it to fts3SegReaderCursorFree()
+** passing it to fts3SegReaderCursorFree()
**
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
** Output parameter *ppSegcsr is set to 0 if an error occurs.
for(i=1; bFound==0 && i<p->nIndex; i++){
if( p->aIndex[i].nPrefix==nTerm ){
bFound = 1;
- rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
+ rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr
);
pSegcsr->bLookup = 1;
for(i=1; bFound==0 && i<p->nIndex; i++){
if( p->aIndex[i].nPrefix==nTerm+1 ){
bFound = 1;
- rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
+ rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr
);
if( rc==SQLITE_OK ){
}
if( bFound==0 ){
- rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
+ rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid,
0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr
);
pSegcsr->bLookup = !isPrefix;
rc = sqlite3Fts3SegReaderStart(p, pSegcsr, &filter);
while( SQLITE_OK==rc
- && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
+ && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pSegcsr))
){
rc = fts3TermSelectMerge(p, &tsc, pSegcsr->aDoclist, pSegcsr->nDoclist);
}
**
** If the isPoslist argument is true, then it is assumed that the doclist
** contains a position-list following each docid. Otherwise, it is assumed
-** that the doclist is simply a list of docids stored as delta encoded
+** that the doclist is simply a list of docids stored as delta encoded
** varints.
*/
static int fts3DoclistCountDocids(char *aList, int nList){
assert( p->base.zErrMsg==0 );
rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
- p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr,
+ p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr,
&p->base.zErrMsg
);
if( rc!=SQLITE_OK ){
return fts3NextMethod(pCursor);
}
-/*
-** This is the xEof method of the virtual table. SQLite calls this
+/*
+** This is the xEof method of the virtual table. SQLite calls this
** routine to find out if it has reached the end of a result set.
*/
static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
return ((Fts3Cursor *)pCursor)->isEof;
}
-/*
+/*
** This is the xRowid method. The SQLite core calls this routine to
** retrieve the rowid for the current row of the result set. fts3
** exposes %_content.docid as the rowid for the virtual table. The
return SQLITE_OK;
}
-/*
+/*
** This is the xColumn method, called by SQLite to request a value from
** the row that the supplied cursor currently points to.
**
assert( iCol>=0 && iCol<=p->nColumn+2 );
if( iCol==p->nColumn+1 ){
- /* This call is a request for the "docid" column. Since "docid" is an
+ /* This call is a request for the "docid" column. Since "docid" is an
** alias for "rowid", use the xRowid() method to obtain the value.
*/
sqlite3_result_int64(pCtx, pCsr->iPrevId);
}else if( iCol==p->nColumn+2 && pCsr->pExpr ){
sqlite3_result_int64(pCtx, pCsr->iLangid);
}else{
- /* The requested column is either a user column (one that contains
+ /* The requested column is either a user column (one that contains
** indexed data), or the language-id column. */
rc = fts3CursorSeek(0, pCsr);
return rc;
}
-/*
-** This function is the implementation of the xUpdate callback used by
+/*
+** This function is the implementation of the xUpdate callback used by
** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
** inserted, updated or deleted.
*/
**
** Of course, updating the input segments also involves deleting a bunch
** of blocks from the segments table. But this is not considered overhead
- ** as it would also be required by a crisis-merge that used the same input
+ ** as it would also be required by a crisis-merge that used the same input
** segments.
*/
const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
char c = 0;
while( p>pStart && (c=*p--)==0 );
- while( p>pStart && (*p & 0x80) | c ){
- c = *p--;
+ while( p>pStart && (*p & 0x80) | c ){
+ c = *p--;
}
if( p>pStart ){ p = &p[2]; }
while( *p++&0x80 );
** offsets() and optimize() SQL functions.
**
** If the value passed as the third argument is a blob of size
-** sizeof(Fts3Cursor*), then the blob contents are copied to the
+** sizeof(Fts3Cursor*), then the blob contents are copied to the
** output variable *ppCsr and SQLITE_OK is returned. Otherwise, an error
** message is written to context pContext and SQLITE_ERROR returned. The
** string passed via zFunc is used as part of the error message.
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
){
Fts3Cursor *pRet;
- if( sqlite3_value_type(pVal)!=SQLITE_BLOB
+ if( sqlite3_value_type(pVal)!=SQLITE_BLOB
|| sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
){
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
assert( nVal>=1 );
if( nVal>6 ){
- sqlite3_result_error(pContext,
+ sqlite3_result_error(pContext,
"wrong number of arguments to function snippet()", -1);
return;
}
}
}
-/*
-** Implementation of the special optimize() function for FTS3. This
+/*
+** Implementation of the special optimize() function for FTS3. This
** function merges all segments in the database to a single segment.
** Example usage is:
**
int rc; /* Return Code */
/* As it happens, the pending terms table is always empty here. This is
- ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction
- ** always opens a savepoint transaction. And the xSavepoint() method
+ ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction
+ ** always opens a savepoint transaction. And the xSavepoint() method
** flushes the pending terms table. But leave the (no-op) call to
** PendingTermsFlush() in in case that changes.
*/
}
/*
-** The fts3 built-in tokenizers - "simple", "porter" and "icu"- are
+** The fts3 built-in tokenizers - "simple", "porter" and "icu"- are
** implemented in files fts3_tokenizer1.c, fts3_porter.c and fts3_icu.c
** respectively. The following three forward declarations are for functions
** declared in these files used to retrieve the respective implementations.
/* Load the built-in tokenizers into the hash table */
if( rc==SQLITE_OK ){
if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
- || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
+ || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
#ifdef SQLITE_ENABLE_FTS4_UNICODE61
- || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
+ || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
#endif
#ifdef SQLITE_ENABLE_ICU
|| (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
}
#endif
- /* Create the virtual table wrapper around the hash-table and overload
+ /* Create the virtual table wrapper around the hash-table and overload
** the two scalar functions. If this is successful, register the
** module with sqlite.
*/
- if( SQLITE_OK==rc
+ if( SQLITE_OK==rc
&& SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
/*
** Allocate an Fts3MultiSegReader for each token in the expression headed
-** by pExpr.
+** by pExpr.
**
** An Fts3SegReader object is a cursor that can seek or scan a range of
** entries within a single segment b-tree. An Fts3MultiSegReader uses multiple
** If the allocated Fts3MultiSegReader just seeks to a single entry in a
** segment b-tree (if the term is not a prefix or it is a prefix for which
** there exists prefix b-tree of the right length) then it may be traversed
-** and merged incrementally. Otherwise, it has to be merged into an in-memory
+** and merged incrementally. Otherwise, it has to be merged into an in-memory
** doclist and then traversed.
*/
static void fts3EvalAllocateReaders(
*pnToken += nToken;
for(i=0; i<nToken; i++){
Fts3PhraseToken *pToken = &pExpr->pPhrase->aToken[i];
- int rc = fts3TermSegReaderCursor(pCsr,
+ int rc = fts3TermSegReaderCursor(pCsr,
pToken->z, pToken->n, pToken->isPrefix, &pToken->pSegcsr
);
if( rc!=SQLITE_OK ){
sqlite3_free(aPoslist);
return SQLITE_NOMEM;
}
-
+
pPhrase->doclist.pList = aOut;
if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
pPhrase->doclist.bFreeList = 1;
}
/*
-** This function is called for each Fts3Phrase in a full-text query
+** This function is called for each Fts3Phrase in a full-text query
** expression to initialize the mechanism for returning rows. Once this
** function has been called successfully on an Fts3Phrase, it may be
** used with fts3EvalPhraseNext() to iterate through the matching docids.
Fts3PhraseToken *pFirst = &p->aToken[0];
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
- if( pCsr->bDesc==pTab->bDescIdx
- && bOptOk==1
- && p->nToken==1
- && pFirst->pSegcsr
- && pFirst->pSegcsr->bLookup
+ if( pCsr->bDesc==pTab->bDescIdx
+ && bOptOk==1
+ && p->nToken==1
+ && pFirst->pSegcsr
+ && pFirst->pSegcsr->bLookup
&& pFirst->bFirst==0
){
/* Use the incremental approach. */
}
/*
-** This function is used to iterate backwards (from the end to start)
+** This function is used to iterate backwards (from the end to start)
** through doclists. It is used by this module to iterate through phrase
** doclists in reverse and by the fts3_write.c module to iterate through
** pending-terms lists when writing to databases with "order=desc".
**
-** The doclist may be sorted in ascending (parameter bDescIdx==0) or
+** The doclist may be sorted in ascending (parameter bDescIdx==0) or
** descending (parameter bDescIdx==1) order of docid. Regardless, this
** function iterates from the end of the doclist to the beginning.
*/
}
/*
-** Attempt to move the phrase iterator to point to the next matching docid.
-** If an error occurs, return an SQLite error code. Otherwise, return
+** Attempt to move the phrase iterator to point to the next matching docid.
+** If an error occurs, return an SQLite error code. Otherwise, return
** SQLITE_OK.
**
** If there is no "next" entry and no error occurs, then *pbEof is set to
if( p->bIncr ){
assert( p->nToken==1 );
assert( pDL->pNextDocid==0 );
- rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
+ rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
&pDL->iDocid, &pDL->pList, &pDL->nList
);
if( rc==SQLITE_OK && !pDL->pList ){
*pbEof = 1;
}
}else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
- sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
+ sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
&pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
);
pDL->pList = pDL->pNextDocid;
** Tokens are divided into AND/NEAR clusters. All tokens in a cluster belong
** to phrases that are connected only by AND and NEAR operators (not OR or
** NOT). When determining tokens to defer, each AND/NEAR cluster is considered
-** separately. The root of a tokens AND/NEAR cluster is stored in
+** separately. The root of a tokens AND/NEAR cluster is stored in
** Fts3TokenAndCost.pRoot.
*/
typedef struct Fts3TokenAndCost Fts3TokenAndCost;
** write this value to *pnPage and return SQLITE_OK. Otherwise, return
** an SQLite error code.
**
-** The average document size in pages is calculated by first calculating
+** The average document size in pages is calculated by first calculating
** determining the average size in bytes, B. If B is less than the amount
** of data that will fit on a single leaf page of an intkey table in
** this database, then the average docsize is 1. Otherwise, it is 1 plus
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
if( pCsr->nRowAvg==0 ){
/* The average document size, which is required to calculate the cost
- ** of each doclist, has not yet been determined. Read the required
+ ** of each doclist, has not yet been determined. Read the required
** data from the %_stat table to calculate it.
**
- ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
+ ** Entry 0 of the %_stat table is a blob containing (nCol+1) FTS3
** varints, where nCol is the number of columns in the FTS3 table.
** The first varint is the number of documents currently stored in
** the table. The following nCol varints contain the total amount of
pCsr->nDoc = nDoc;
pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
- assert( pCsr->nRowAvg>0 );
+ assert( pCsr->nRowAvg>0 );
rc = sqlite3_reset(pStmt);
if( rc!=SQLITE_OK ) return rc;
}
}
/*
-** This function is called to select the tokens (if any) that will be
+** This function is called to select the tokens (if any) that will be
** deferred. The array aTC[] has already been populated when this is
** called.
**
-** This function is called once for each AND/NEAR cluster in the
+** This function is called once for each AND/NEAR cluster in the
** expression. Each invocation determines which tokens to defer within
** the cluster with root node pRoot. See comments above the definition
** of struct Fts3TokenAndCost for more details.
assert( rc!=SQLITE_OK || nDocSize>0 );
- /* Iterate through all tokens in this AND/NEAR cluster, in ascending order
- ** of the number of overflow pages that will be loaded by the pager layer
+ /* Iterate through all tokens in this AND/NEAR cluster, in ascending order
+ ** of the number of overflow pages that will be loaded by the pager layer
** to retrieve the entire doclist for the token from the full-text index.
** Load the doclists for tokens that are either:
**
**
** After each token doclist is loaded, merge it with the others from the
** same phrase and count the number of documents that the merged doclist
- ** contains. Set variable "nMinEst" to the smallest number of documents in
+ ** contains. Set variable "nMinEst" to the smallest number of documents in
** any phrase doclist for which 1 or more token doclists have been loaded.
** Let nOther be the number of other phrases for which it is certain that
** one or more tokens will not be deferred.
/* Set pTC to point to the cheapest remaining token. */
for(iTC=0; iTC<nTC; iTC++){
- if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot
- && (!pTC || aTC[iTC].nOvfl<pTC->nOvfl)
+ if( aTC[iTC].pToken && aTC[iTC].pRoot==pRoot
+ && (!pTC || aTC[iTC].nOvfl<pTC->nOvfl)
){
pTC = &aTC[iTC];
}
if( ii && pTC->nOvfl>=((nMinEst+(nLoad4/4)-1)/(nLoad4/4))*nDocSize ){
/* The number of overflow pages to load for this (and therefore all
- ** subsequent) tokens is greater than the estimated number of pages
+ ** subsequent) tokens is greater than the estimated number of pages
** that will be loaded if all subsequent tokens are deferred.
*/
Fts3PhraseToken *pToken = pTC->pToken;
pToken->pSegcsr = 0;
}else{
/* Set nLoad4 to the value of (4^nOther) for the next iteration of the
- ** for-loop. Except, limit the value to 2^24 to prevent it from
+ ** for-loop. Except, limit the value to 2^24 to prevent it from
** overflowing the 32-bit integer it is stored in. */
if( ii<12 ) nLoad4 = nLoad4*4;
** close to a position in the *paPoslist position list are removed. If this
** leaves 0 positions, zero is returned. Otherwise, non-zero.
**
-** Before returning, *paPoslist is set to point to the position lsit
+** Before returning, *paPoslist is set to point to the position lsit
** associated with pPhrase. And *pnToken is set to the number of tokens in
** pPhrase.
*/
int nParam1 = nNear + pPhrase->nToken;
int nParam2 = nNear + *pnToken;
int nNew;
- char *p2;
- char *pOut;
+ char *p2;
+ char *pOut;
int res;
assert( pPhrase->doclist.pList );
**
** 1. Deferred tokens are not taken into account. If a phrase consists
** entirely of deferred tokens, it is assumed to match every row in
-** the db. In this case the position-list is not populated at all.
+** the db. In this case the position-list is not populated at all.
**
** Or, if a phrase contains one or more deferred tokens and one or
-** more non-deferred tokens, then the expression is advanced to the
+** more non-deferred tokens, then the expression is advanced to the
** next possible match, considering only non-deferred tokens. In other
** words, if the phrase is "A B C", and "B" is deferred, the expression
-** is advanced to the next row that contains an instance of "A * C",
+** is advanced to the next row that contains an instance of "A * C",
** where "*" may match any single token. The position list in this case
** is populated as for "A * C" before returning.
**
-** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is
+** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is
** advanced to point to the next row that matches "x AND y".
-**
+**
** See fts3EvalTestDeferredAndNear() for details on testing if a row is
** really a match, taking into account deferred tokens and NEAR operators.
*/
}
break;
}
-
+
case FTSQUERY_OR: {
Fts3Expr *pLeft = pExpr->pLeft;
Fts3Expr *pRight = pExpr->pRight;
fts3EvalNextRow(pCsr, pLeft, pRc);
if( pLeft->bEof==0 ){
- while( !*pRc
- && !pRight->bEof
- && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
+ while( !*pRc
+ && !pRight->bEof
+ && DOCID_CMP(pLeft->iDocid, pRight->iDocid)>0
){
fts3EvalNextRow(pCsr, pRight, pRc);
}
** If *pRc is not SQLITE_OK, or if pExpr is not the root node of a NEAR
** cluster, then this function returns 1 immediately.
**
-** Otherwise, it checks if the current row really does match the NEAR
-** expression, using the data currently stored in the position lists
-** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression.
+** Otherwise, it checks if the current row really does match the NEAR
+** expression, using the data currently stored in the position lists
+** (Fts3Expr->pPhrase.doclist.pList/nList) for each phrase in the expression.
**
** If the current row is a match, the position list associated with each
** phrase in the NEAR expression is edited in place to contain only those
** phrase instances sufficiently close to their peers to satisfy all NEAR
-** constraints. In this case it returns 1. If the NEAR expression does not
+** constraints. In this case it returns 1. If the NEAR expression does not
** match the current row, 0 is returned. The position lists may or may not
** be edited if 0 is returned.
*/
** | |
** "w" "x"
**
- ** The right-hand child of a NEAR node is always a phrase. The
+ ** The right-hand child of a NEAR node is always a phrase. The
** left-hand child may be either a phrase or a NEAR node. There are
** no exceptions to this - it's the way the parser in fts3_expr.c works.
*/
- if( *pRc==SQLITE_OK
- && pExpr->eType==FTSQUERY_NEAR
+ if( *pRc==SQLITE_OK
+ && pExpr->eType==FTSQUERY_NEAR
&& pExpr->bEof==0
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
){
- Fts3Expr *p;
+ Fts3Expr *p;
int nTmp = 0; /* Bytes of temp space */
char *aTmp; /* Temp space for PoslistNearMerge() */
/*
** This function is a helper function for fts3EvalTestDeferredAndNear().
** Assuming no error occurs or has occurred, It returns non-zero if the
-** expression passed as the second argument matches the row that pCsr
+** expression passed as the second argument matches the row that pCsr
** currently points to, or zero if it does not.
**
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
-** If an error occurs during execution of this function, *pRc is set to
-** the appropriate SQLite error code. In this case the returned value is
+** If an error occurs during execution of this function, *pRc is set to
+** the appropriate SQLite error code. In this case the returned value is
** undefined.
*/
static int fts3EvalTestExpr(
&& fts3EvalNearTest(pExpr, pRc)
);
- /* If the NEAR expression does not match any rows, zero the doclist for
+ /* If the NEAR expression does not match any rows, zero the doclist for
** all phrases involved in the NEAR. This is because the snippet(),
- ** offsets() and matchinfo() functions are not supposed to recognize
- ** any instances of phrases that are part of unmatched NEAR queries.
+ ** offsets() and matchinfo() functions are not supposed to recognize
+ ** any instances of phrases that are part of unmatched NEAR queries.
** For example if this expression:
**
** ... MATCH 'a OR (b NEAR c)'
** then any snippet() should ony highlight the "a" term, not the "b"
** (as "b" is part of a non-matching NEAR clause).
*/
- if( bHit==0
- && pExpr->eType==FTSQUERY_NEAR
+ if( bHit==0
+ && pExpr->eType==FTSQUERY_NEAR
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
){
Fts3Expr *p;
default: {
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
- if( pCsr->pDeferred
+ if( pCsr->pDeferred
&& (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
){
Fts3Phrase *pPhrase = pExpr->pPhrase;
** memory and scan it to determine the position list for each deferred
** token. Then, see if this row is really a match, considering deferred
** tokens and NEAR operators (neither of which were taken into account
- ** earlier, by fts3EvalNextRow()).
+ ** earlier, by fts3EvalNextRow()).
*/
if( pCsr->pDeferred ){
rc = fts3CursorSeek(0, pCsr);
/*
** Restart interation for expression pExpr so that the next call to
-** fts3EvalNext() visits the first row. Do not allow incremental
+** fts3EvalNext() visits the first row. Do not allow incremental
** loading or merging of phrase doclists for this iteration.
**
** If *pRc is other than SQLITE_OK when this function is called, it is
}
/*
-** After allocating the Fts3Expr.aMI[] array for each phrase in the
+** After allocating the Fts3Expr.aMI[] array for each phrase in the
** expression rooted at pExpr, the cursor iterates through all rows matched
** by pExpr, calling this function for each row. This function increments
** the values in Fts3Expr.aMI[] according to the position-list currently
-** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
+** found in Fts3Expr.pPhrase->doclist.pList for each of the phrase
** expression nodes.
*/
static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
pCsr->isRequireSeek = 1;
pCsr->isMatchinfoNeeded = 1;
pCsr->iPrevId = pRoot->iDocid;
- }while( pCsr->isEof==0
- && pRoot->eType==FTSQUERY_NEAR
- && fts3EvalTestDeferredAndNear(pCsr, &rc)
+ }while( pCsr->isEof==0
+ && pRoot->eType==FTSQUERY_NEAR
+ && fts3EvalTestDeferredAndNear(pCsr, &rc)
);
if( rc==SQLITE_OK && pCsr->isEof==0 ){
pRoot->bEof = bEof;
}else{
/* Caution: pRoot may iterate through docids in ascending or descending
- ** order. For this reason, even though it seems more defensive, the
+ ** order. For this reason, even though it seems more defensive, the
** do loop can not be written:
**
** do {...} while( pRoot->iDocid<iDocid && rc==SQLITE_OK );
}
/*
-** This function is used by the matchinfo() module to query a phrase
+** This function is used by the matchinfo() module to query a phrase
** expression node for the following information:
**
-** 1. The total number of occurrences of the phrase in each column of
+** 1. The total number of occurrences of the phrase in each column of
** the FTS table (considering all rows), and
**
** 2. For each column, the number of rows in the table for which the
**
** Caveats:
**
-** * If a phrase consists entirely of deferred tokens, then all output
+** * If a phrase consists entirely of deferred tokens, then all output
** values are set to the number of documents in the table. In other
-** words we assume that very common tokens occur exactly once in each
+** words we assume that very common tokens occur exactly once in each
** column of each row of the table.
**
-** * If a phrase contains some deferred tokens (and some non-deferred
+** * If a phrase contains some deferred tokens (and some non-deferred
** tokens), count the potential occurrence identified by considering
** the non-deferred tokens instead of actual phrase occurrences.
**
/*
** The expression pExpr passed as the second argument to this function
-** must be of type FTSQUERY_PHRASE.
+** must be of type FTSQUERY_PHRASE.
**
** The returned value is either NULL or a pointer to a buffer containing
** a position-list indicating the occurrences of the phrase in column iCol
-** of the current row.
+** of the current row.
**
-** More specifically, the returned buffer contains 1 varint for each
-** occurrence of the phrase in the column, stored using the normal (delta+2)
+** More specifically, the returned buffer contains 1 varint for each
+** occurrence of the phrase in the column, stored using the normal (delta+2)
** compression and is terminated by either an 0x01 or 0x00 byte. For example,
** if the requested column contains "a b X c d X X" and the position-list
** for 'X' is requested, the buffer returned may contain:
int iThis;
sqlite3_int64 iDocid;
- /* If this phrase is applies specifically to some column other than
+ /* If this phrase is applies specifically to some column other than
** column iCol, return a NULL pointer. */
*ppOut = 0;
assert( iCol>=0 && iCol<pTab->nColumn );
u8 bEof = 0;
Fts3Expr *p;
- /* Check if this phrase descends from an OR expression node. If not,
- ** return NULL. Otherwise, the entry that corresponds to docid
+ /* Check if this phrase descends from an OR expression node. If not,
+ ** return NULL. Otherwise, the entry that corresponds to docid
** pCsr->iPrevId may lie earlier in the doclist buffer. */
for(p=pExpr->pParent; p; p=p->pParent){
if( p->eType==FTSQUERY_OR ) bOr = 1;
int dummy;
while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
sqlite3Fts3DoclistPrev(
- bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
+ bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
&pIter, &iDocid, &dummy, &bEof
);
}
}else{
while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
sqlite3Fts3DoclistNext(
- bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
+ bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
&pIter, &iDocid, &bEof
);
}
** Initialize API pointer table, if required.
*/
SQLITE_API int sqlite3_extension_init(
- sqlite3 *db,
+ sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
*/
if( argc!=4 && argc!=5 ) goto bad_args;
- zDb = argv[1];
+ zDb = argv[1];
nDb = (int)strlen(zDb);
if( argc==5 ){
if( nDb==4 && 0==sqlite3_strnicmp("temp", zDb, 4) ){
- zDb = argv[3];
+ zDb = argv[3];
nDb = (int)strlen(zDb);
zFts3 = argv[4];
}else{
** xBestIndex - Analyze a WHERE and ORDER BY clause.
*/
static int fts3auxBestIndexMethod(
- sqlite3_vtab *pVTab,
+ sqlite3_vtab *pVTab,
sqlite3_index_info *pInfo
){
int i;
UNUSED_PARAMETER(pVTab);
/* This vtab delivers always results in "ORDER BY term ASC" order. */
- if( pInfo->nOrderBy==1
- && pInfo->aOrderBy[0].iColumn==0
+ if( pInfo->nOrderBy==1
+ && pInfo->aOrderBy[0].iColumn==0
&& pInfo->aOrderBy[0].desc==0
){
pInfo->orderByConsumed = 1;
static int fts3auxGrowStatArray(Fts3auxCursor *pCsr, int nSize){
if( nSize>pCsr->nStat ){
struct Fts3auxColstats *aNew;
- aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat,
+ aNew = (struct Fts3auxColstats *)sqlite3_realloc(pCsr->aStat,
sizeof(struct Fts3auxColstats) * nSize
);
if( aNew==0 ) return SQLITE_NOMEM;
- memset(&aNew[pCsr->nStat], 0,
+ memset(&aNew[pCsr->nStat], 0,
sizeof(struct Fts3auxColstats) * (nSize - pCsr->nStat)
);
pCsr->aStat = aNew;
/* State 1. In this state we are expecting either a 1, indicating
** that the following integer will be a column number, or the
- ** start of a position list for column 0.
- **
+ ** start of a position list for column 0.
+ **
** The only difference between state 1 and state 2 is that if the
** integer encountered in state 1 is not 0 or 1, then we need to
** increment the column 0 "nDoc" count for this term.
******************************************************************************
**
** This module contains code that implements a parser for fts3 query strings
-** (the right-hand argument to the MATCH operator). Because the supported
+** (the right-hand argument to the MATCH operator). Because the supported
** syntax is relatively simple, the whole tokenizer/parser system is
-** hand-coded.
+** hand-coded.
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
/*
-** By default, this module parses the legacy syntax that has been
+** By default, this module parses the legacy syntax that has been
** traditionally used by fts3. Or, if SQLITE_ENABLE_FTS3_PARENTHESIS
** is defined, then it uses the new syntax. The differences between
** the new and the old syntaxes are:
**
** b) The new syntax supports the AND and NOT operators. The old does not.
**
-** c) The old syntax supports the "-" token qualifier. This is not
+** c) The old syntax supports the "-" token qualifier. This is not
** supported by the new syntax (it is replaced by the NOT operator).
**
** d) When using the old syntax, the OR operator has a greater precedence
**
** If compiled with SQLITE_TEST defined, then this module exports the
** symbol "int sqlite3_fts3_enable_parentheses". Setting this variable
-** to zero causes the module to use the old syntax. If it is set to
+** to zero causes the module to use the old syntax. If it is set to
** non-zero the new syntax is activated. This is so both syntaxes can
** be tested using a single build of testfixture.
**
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_fts3_enable_parentheses = 0;
#else
-# ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
+# ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
# define sqlite3_fts3_enable_parentheses 1
# else
# define sqlite3_fts3_enable_parentheses 0
/*
** isNot:
** This variable is used by function getNextNode(). When getNextNode() is
-** called, it sets ParseContext.isNot to true if the 'next node' is a
+** called, it sets ParseContext.isNot to true if the 'next node' is a
** FTSQUERY_PHRASE with a unary "-" attached to it. i.e. "mysql" in the
** FTS3 query "sqlite -mysql". Otherwise, ParseContext.isNot is set to
** zero.
};
/*
-** This function is equivalent to the standard isspace() function.
+** This function is equivalent to the standard isspace() function.
**
** The standard isspace() can be awkward to use safely, because although it
** is defined to accept an argument of type int, its behavior when passed
/*
** Allocate nByte bytes of memory using sqlite3_malloc(). If successful,
-** zero the memory before returning a pointer to it. If unsuccessful,
+** zero the memory before returning a pointer to it. If unsuccessful,
** return NULL.
*/
static void *fts3MallocZero(int nByte){
** structure of type FTSQUERY_PHRASE containing a phrase consisting of this
** single token and set *ppExpr to point to it. If the end of the buffer is
** reached before a token is found, set *ppExpr to zero. It is the
-** responsibility of the caller to eventually deallocate the allocated
+** responsibility of the caller to eventually deallocate the allocated
** Fts3Expr structure (if any) by passing it to sqlite3_free().
**
** Return SQLITE_OK if successful, or SQLITE_NOMEM if a memory allocation
}
while( 1 ){
- if( !sqlite3_fts3_enable_parentheses
- && iStart>0 && z[iStart-1]=='-'
+ if( !sqlite3_fts3_enable_parentheses
+ && iStart>0 && z[iStart-1]=='-'
){
pParse->isNot = 1;
iStart--;
pModule->xClose(pCursor);
}
-
+
*pnConsumed = nConsumed;
*ppExpr = pRet;
return rc;
** Buffer zInput, length nInput, contains the contents of a quoted string
** that appeared as part of an fts3 query expression. Neither quote character
** is included in the buffer. This function attempts to tokenize the entire
-** input buffer and create an Fts3Expr structure of type FTSQUERY_PHRASE
+** input buffer and create an Fts3Expr structure of type FTSQUERY_PHRASE
** containing the results.
**
** If successful, SQLITE_OK is returned and *ppExpr set to point at the
int nToken = 0;
/* The final Fts3Expr data structure, including the Fts3Phrase,
- ** Fts3PhraseToken structures token buffers are all stored as a single
+ ** Fts3PhraseToken structures token buffers are all stored as a single
** allocation so that the expression can be freed with a single call to
** sqlite3_free(). Setting this up requires a two pass approach.
**
** to assemble data in two dynamic buffers:
**
** Buffer p: Points to the Fts3Expr structure, followed by the Fts3Phrase
- ** structure, followed by the array of Fts3PhraseToken
+ ** structure, followed by the array of Fts3PhraseToken
** structures. This pass only populates the Fts3PhraseToken array.
**
** Buffer zTemp: Contains copies of all tokens.
static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
/*
-** The output variable *ppExpr is populated with an allocated Fts3Expr
+** The output variable *ppExpr is populated with an allocated Fts3Expr
** structure, or set to 0 if the end of the input buffer is reached.
**
** Returns an SQLite error code. SQLITE_OK if everything works, SQLITE_NOMEM
pParse->isNot = 0;
/* Skip over any whitespace before checking for a keyword, an open or
- ** close bracket, or a quoted string.
+ ** close bracket, or a quoted string.
*/
while( nInput>0 && fts3isspace(*zInput) ){
nInput--;
/* At this point this is probably a keyword. But for that to be true,
** the next byte must contain either whitespace, an open or close
- ** parenthesis, a quote character, or EOF.
+ ** parenthesis, a quote character, or EOF.
*/
cNext = zInput[nKey];
- if( fts3isspace(cNext)
+ if( fts3isspace(cNext)
|| cNext=='"' || cNext=='(' || cNext==')' || cNext==0
){
pRet = (Fts3Expr *)fts3MallocZero(sizeof(Fts3Expr));
*pnConsumed = (int)((zInput - z) + 1 + nConsumed);
return rc;
}
-
+
/* Check for a close bracket. */
if( *zInput==')' ){
pParse->nNest--;
}
- /* If control flows to this point, this must be a regular token, or
+ /* If control flows to this point, this must be a regular token, or
** the end of the input. Read a regular token using the sqlite3_tokenizer
** interface. Before doing so, figure out if there is an explicit
- ** column specifier for the token.
+ ** column specifier for the token.
**
** TODO: Strangely, it is not possible to associate a column specifier
** with a quoted phrase, only with a single token. Not sure if this was
** an implementation artifact or an intentional decision when fts3 was
- ** first implemented. Whichever it was, this module duplicates the
+ ** first implemented. Whichever it was, this module duplicates the
** limitation.
*/
iCol = pParse->iDefaultCol;
for(ii=0; ii<pParse->nCol; ii++){
const char *zStr = pParse->azCol[ii];
int nStr = (int)strlen(zStr);
- if( nInput>nStr && zInput[nStr]==':'
- && sqlite3_strnicmp(zStr, zInput, nStr)==0
+ if( nInput>nStr && zInput[nStr]==':'
+ && sqlite3_strnicmp(zStr, zInput, nStr)==0
){
iCol = ii;
iColLen = (int)((zInput - z) + nStr + 1);
}
/*
-** Argument ppHead contains a pointer to the current head of a query
+** Argument ppHead contains a pointer to the current head of a query
** expression tree being parsed. pPrev is the expression node most recently
** inserted into the tree. This function adds pNew, which is always a binary
** operator node, into the expression tree based on the relative precedence
/*
** Parse the fts3 query expression found in buffer z, length n. This function
-** returns either when the end of the buffer is reached or an unmatched
+** returns either when the end of the buffer is reached or an unmatched
** closing bracket - ')' - is encountered.
**
** If successful, SQLITE_OK is returned, *ppExpr is set to point to the
if( rc==SQLITE_OK ){
int isPhrase;
- if( !sqlite3_fts3_enable_parentheses
- && p->eType==FTSQUERY_PHRASE && pParse->isNot
+ if( !sqlite3_fts3_enable_parentheses
+ && p->eType==FTSQUERY_PHRASE && pParse->isNot
){
/* Create an implicit NOT operator. */
Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
rc = SQLITE_ERROR;
goto exprparse_out;
}
-
+
if( isPhrase && !isRequirePhrase ){
/* Insert an implicit AND operator. */
Fts3Expr *pAnd;
rc = SQLITE_ERROR;
goto exprparse_out;
}
-
+
if( isPhrase ){
if( pRet ){
assert( pPrev && pPrev->pLeft && pPrev->pRight==0 );
}
/*
-** Return SQLITE_ERROR if the maximum depth of the expression tree passed
+** Return SQLITE_ERROR if the maximum depth of the expression tree passed
** as the only argument is more than nMaxDepth.
*/
static int fts3ExprCheckDepth(Fts3Expr *p, int nMaxDepth){
int rc = SQLITE_OK;
if( p ){
- if( nMaxDepth<0 ){
+ if( nMaxDepth<0 ){
rc = SQLITE_TOOBIG;
}else{
rc = fts3ExprCheckDepth(p->pLeft, nMaxDepth-1);
/*
** This function attempts to transform the expression tree at (*pp) to
** an equivalent but more balanced form. The tree is modified in place.
-** If successful, SQLITE_OK is returned and (*pp) set to point to the
-** new root expression node.
+** If successful, SQLITE_OK is returned and (*pp) set to point to the
+** new root expression node.
**
** nMaxDepth is the maximum allowable depth of the balanced sub-tree.
**
-** Otherwise, if an error occurs, an SQLite error code is returned and
+** Otherwise, if an error occurs, an SQLite error code is returned and
** expression (*pp) freed.
*/
static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){
}
pRoot = p;
}else{
- /* An error occurred. Delete the contents of the apLeaf[] array
+ /* An error occurred. Delete the contents of the apLeaf[] array
** and pFree list. Everything else is cleaned up by the call to
** sqlite3Fts3ExprFree(pRoot) below. */
Fts3Expr *pDel;
** differences:
**
** 1. It does not do expression rebalancing.
-** 2. It does not check that the expression does not exceed the
+** 2. It does not check that the expression does not exceed the
** maximum allowable depth.
-** 3. Even if it fails, *ppExpr may still be set to point to an
+** 3. Even if it fails, *ppExpr may still be set to point to an
** expression tree. It should be deleted using sqlite3Fts3ExprFree()
** in this case.
*/
if( rc==SQLITE_OK && sParse.nNest ){
rc = SQLITE_ERROR;
}
-
+
return rc;
}
** The first parameter, pTokenizer, is passed the fts3 tokenizer module to
** use to normalize query tokens while parsing the expression. The azCol[]
** array, which is assumed to contain nCol entries, should contain the names
-** of each column in the target fts3 table, in order from left to right.
+** of each column in the target fts3 table, in order from left to right.
** Column names must be nul-terminated strings.
**
** The iDefaultCol parameter should be passed the index of the table column
int rc = fts3ExprParseUnbalanced(
pTokenizer, iLangid, azCol, bFts4, nCol, iDefaultCol, z, n, ppExpr
);
-
+
/* Rebalance the expression. And check that its depth does not exceed
** MAX_EXPR_DEPTH. */
if( rc==SQLITE_OK && *ppExpr ){
** Function to query the hash-table of tokenizers (see README.tokenizers).
*/
static int queryTestTokenizer(
- sqlite3 *db,
- const char *zName,
+ sqlite3 *db,
+ const char *zName,
const sqlite3_tokenizer_module **pp
){
int rc;
/*
** Return a pointer to a buffer containing a text representation of the
** expression passed as the first argument. The buffer is obtained from
-** sqlite3_malloc(). It is the responsibility of the caller to use
+** sqlite3_malloc(). It is the responsibility of the caller to use
** sqlite3_free() to release the memory. If an OOM condition is encountered,
** NULL is returned.
**
-** If the second argument is not NULL, then its contents are prepended to
+** If the second argument is not NULL, then its contents are prepended to
** the returned expression text and then freed using sqlite3_free().
*/
static char *exprToString(Fts3Expr *pExpr, char *zBuf){
zBuf = sqlite3_mprintf(
"%zPHRASE %d 0", zBuf, pPhrase->iColumn);
for(i=0; zBuf && i<pPhrase->nToken; i++){
- zBuf = sqlite3_mprintf("%z %.*s%s", zBuf,
+ zBuf = sqlite3_mprintf("%z %.*s%s", zBuf,
pPhrase->aToken[i].n, pPhrase->aToken[i].z,
(pPhrase->aToken[i].isPrefix?"+":"")
);
}
/*
-** This is the implementation of a scalar SQL function used to test the
+** This is the implementation of a scalar SQL function used to test the
** expression parser. It should be called as follows:
**
** fts3_exprtest(<tokenizer>, <expr>, <column 1>, ...);
sqlite3 *db = sqlite3_context_db_handle(context);
if( argc<3 ){
- sqlite3_result_error(context,
+ sqlite3_result_error(context,
"Usage: fts3_exprtest(tokenizer, expr, col1, ...", -1
);
return;
}
/*
-** Register the query expression parser test function fts3_exprtest()
-** with database connection db.
+** Register the query expression parser test function fts3_exprtest()
+** with database connection db.
*/
SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3* db){
int rc = sqlite3_create_function(
db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0
);
if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "fts3_exprtest_rebalance",
+ rc = sqlite3_create_function(db, "fts3_exprtest_rebalance",
-1, SQLITE_UTF8, (void *)1, fts3ExprTest, 0, 0
);
}
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
-** keyClass is one of the constants
-** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass
+** keyClass is one of the constants
+** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass
** determines what kind of key the hash table will use. "copyKey" is
** true if the hash table should make its own private copy of keys and
** false if it should just use the supplied pointer.
/*
** Return a pointer to the appropriate hash function given the key class.
**
-** The C syntax in this function definition may be unfamilar to some
+** The C syntax in this function definition may be unfamilar to some
** programmers, so we provide the following additional explanation:
**
** The name of the function is "ftsHashFunction". The function takes a
/* Resize the hash table so that it cantains "new_size" buckets.
-** "new_size" must be a power of 2. The hash table might fail
+** "new_size" must be a power of 2. The hash table might fail
** to resize if sqliteMalloc() fails.
**
** Return non-zero if a memory allocation error occurs.
count = pEntry->count;
xCompare = ftsCompareFunction(pH->keyClass);
while( count-- && elem ){
- if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
+ if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
return elem;
}
elem = elem->next;
){
struct _fts3ht *pEntry;
if( elem->prev ){
- elem->prev->next = elem->next;
+ elem->prev->next = elem->next;
}else{
pH->first = elem->next;
}
}
SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(
- const Fts3Hash *pH,
- const void *pKey,
+ const Fts3Hash *pH,
+ const void *pKey,
int nKey
){
int h; /* A hash on key */
return fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1));
}
-/*
+/*
** Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey. Return the data for this element if it is
** found, or NULL if there is no match.
/*
** Prepare to begin tokenizing a particular string. The input
** string to be tokenized is zInput[0..nInput-1]. A cursor
-** used to incrementally tokenize this string is returned in
+** used to incrementally tokenize this string is returned in
** *ppCursor.
*/
static int porterOpen(
/*
** isConsonant() and isVowel() determine if their first character in
** the string they point to is a consonant or a vowel, according
-** to Porter ruls.
+** to Porter ruls.
**
** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'.
** 'Y' is a consonant unless it follows another consonant,
/*
** If the word ends with zFrom and xCond() is true for the stem
-** of the word that preceeds the zFrom ending, then change the
+** of the word that preceeds the zFrom ending, then change the
** ending to zTo.
**
** The input word *pz and zFrom are both in reverse order. zTo
-** is in normal order.
+** is in normal order.
**
** Return TRUE if zFrom matches. Return FALSE if zFrom does not
** match. Not that TRUE is returned even if xCond() fails and
** word contains digits, 3 bytes are taken from the beginning and
** 3 bytes from the end. For long words without digits, 10 bytes
** are taken from each end. US-ASCII case folding still applies.
-**
-** If the input word contains not digits but does characters not
-** in [a-zA-Z] then no stemming is attempted and this routine just
+**
+** If the input word contains not digits but does characters not
+** in [a-zA-Z] then no stemming is attempted and this routine just
** copies the input into the input into the output with US-ASCII
** case folding.
**
}
}
- /* Step 1b */
+ /* Step 1b */
z2 = z;
if( stem(&z, "dee", "ee", m_gt_0) ){
/* Do nothing. The work was all in the test */
- }else if(
+ }else if(
(stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel))
&& z!=z2
){
/* #include <string.h> */
/*
-** Implementation of the SQL scalar function for accessing the underlying
+** Implementation of the SQL scalar function for accessing the underlying
** hash table. This function may be called as follows:
**
** SELECT <function-name>(<key-name>);
if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("unknown tokenizer");
}else{
- (*ppTok)->pModule = m;
+ (*ppTok)->pModule = m;
}
sqlite3_free((void *)aArg);
}
/* #include <string.h> */
/*
-** Implementation of a special SQL scalar function for testing tokenizers
+** Implementation of a special SQL scalar function for testing tokenizers
** designed to be used in concert with the Tcl testing framework. This
** function must be called with two or more arguments:
**
**
** The return value is a string that may be interpreted as a Tcl
** list. For each token in the <input-string>, three elements are
-** added to the returned list. The first is the token position, the
+** added to the returned list. The first is the token position, the
** second is the token text (folded, stemmed, etc.) and the third is the
-** substring of <input-string> associated with the token. For example,
+** substring of <input-string> associated with the token. For example,
** using the built-in "simple" tokenizer:
**
** SELECT fts_tokenizer_test('simple', 'I don't see how');
** will return the string:
**
** "{0 i I 1 dont don't 2 see see 3 how how}"
-**
+**
*/
static void testFunc(
sqlite3_context *context,
static
int registerTokenizer(
- sqlite3 *db,
- char *zName,
+ sqlite3 *db,
+ char *zName,
const sqlite3_tokenizer_module *p
){
int rc;
static
int queryTokenizer(
- sqlite3 *db,
- char *zName,
+ sqlite3 *db,
+ char *zName,
const sqlite3_tokenizer_module **pp
){
int rc;
/*
** Set up SQL objects in database db used to access the contents of
** the hash table pointed to by argument pHash. The hash table must
-** been initialized to use string keys, and to take a private copy
+** been initialized to use string keys, and to take a private copy
** of the key when a value is inserted. i.e. by a call similar to:
**
** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
**
** This function adds a scalar function (see header comment above
** scalarFunc() in this file for details) and, if ENABLE_TABLE is
-** defined at compilation time, a temporary virtual table (see header
-** comment above struct HashTableVtab) to the database schema. Both
+** defined at compilation time, a temporary virtual table (see header
+** comment above struct HashTableVtab) to the database schema. Both
** provide read/write access to the contents of *pHash.
**
** The third argument to this function, zName, is used as the name
** of both the scalar and, if created, the virtual table.
*/
SQLITE_PRIVATE int sqlite3Fts3InitHashTable(
- sqlite3 *db,
- Fts3Hash *pHash,
+ sqlite3 *db,
+ Fts3Hash *pHash,
const char *zName
){
int rc = SQLITE_OK;
/*
** Prepare to begin tokenizing a particular string. The input
** string to be tokenized is pInput[0..nBytes-1]. A cursor
-** used to incrementally tokenize this string is returned in
+** used to incrementally tokenize this string is returned in
** *ppCursor.
*/
static int simpleOpen(
**
** input = <string>
**
-** The virtual table module tokenizes this <string>, using the FTS3
-** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE
+** The virtual table module tokenizes this <string>, using the FTS3
+** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE
** statement and returns one row for each token in the result. With
** fields set as follows:
**
/*
** The second argument, argv[], is an array of pointers to nul-terminated
-** strings. This function makes a copy of the array and strings into a
+** strings. This function makes a copy of the array and strings into a
** single block of memory. It then dequotes any of the strings that appear
** to be quoted.
**
** and xCreate are identical operations.
**
** argv[0]: module name
-** argv[1]: database name
+** argv[1]: database name
** argv[2]: table name
** argv[3]: first argument (tokenizer name)
*/
** xBestIndex - Analyze a WHERE and ORDER BY clause.
*/
static int fts3tokBestIndexMethod(
- sqlite3_vtab *pVTab,
+ sqlite3_vtab *pVTab,
sqlite3_index_info *pInfo
){
int i;
UNUSED_PARAMETER(pVTab);
for(i=0; i<pInfo->nConstraint; i++){
- if( pInfo->aConstraint[i].usable
- && pInfo->aConstraint[i].iColumn==0
- && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ
+ if( pInfo->aConstraint[i].usable
+ && pInfo->aConstraint[i].iColumn==0
+ && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ
){
pInfo->idxNum = 1;
pInfo->aConstraintUsage[i].argvIndex = 1;
** This file is part of the SQLite FTS3 extension module. Specifically,
** this file contains code to insert, update and delete rows from FTS3
** tables. It also contains code to merge FTS3 b-tree segments. Some
-** of the sub-routines used to merge segments are also used by the query
+** of the sub-routines used to merge segments are also used by the query
** code in fts3.c.
*/
/*
** When full-text index nodes are loaded from disk, the buffer that they
-** are loaded into has the following number of bytes of padding at the end
+** are loaded into has the following number of bytes of padding at the end
** of it. i.e. if a full-text index node is 900 bytes in size, then a buffer
** of 920 bytes is allocated for it.
**
** method before retrieving all query results (as may happen, for example,
** if a query has a LIMIT clause).
**
-** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD
+** Incremental loading is used for b-tree nodes FTS3_NODE_CHUNK_THRESHOLD
** bytes and larger. Nodes are loaded in chunks of FTS3_NODE_CHUNKSIZE bytes.
-** The code is written so that the hard lower-limit for each of these values
-** is 1. Clearly such small values would be inefficient, but can be useful
+** The code is written so that the hard lower-limit for each of these values
+** is 1. Clearly such small values would be inefficient, but can be useful
** for testing purposes.
**
** If this module is built with SQLITE_TEST defined, these constants may
# define FTS3_NODE_CHUNKSIZE test_fts3_node_chunksize
# define FTS3_NODE_CHUNK_THRESHOLD test_fts3_node_chunk_threshold
#else
-# define FTS3_NODE_CHUNKSIZE (4*1024)
+# define FTS3_NODE_CHUNKSIZE (4*1024)
# define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4)
#endif
/*
** If FTS_LOG_MERGES is defined, call sqlite3_log() to report each automatic
-** and incremental merge operation that takes place. This is used for
+** and incremental merge operation that takes place. This is used for
** debugging FTS only, it should not usually be turned on in production
** systems.
*/
char *aDoclist; /* Pointer to doclist of current entry */
int nDoclist; /* Size of doclist in current entry */
- /* The following variables are used by fts3SegReaderNextDocid() to iterate
+ /* The following variables are used by fts3SegReaderNextDocid() to iterate
** through the current doclist (aDoclist/nDoclist).
*/
char *pOffsetList;
** fts3NodeFree()
**
** When a b+tree is written to the database (either as a result of a merge
-** or the pending-terms table being flushed), leaves are written into the
+** or the pending-terms table being flushed), leaves are written into the
** database file as soon as they are completely populated. The interior of
** the tree is assembled in memory and written out only once all leaves have
** been populated and stored. This is Ok, as the b+-tree fanout is usually
-** very large, meaning that the interior of the tree consumes relatively
+** very large, meaning that the interior of the tree consumes relatively
** little memory.
*/
struct SegmentNode {
*/
#define SQL_DELETE_CONTENT 0
#define SQL_IS_EMPTY 1
-#define SQL_DELETE_ALL_CONTENT 2
+#define SQL_DELETE_ALL_CONTENT 2
#define SQL_DELETE_ALL_SEGMENTS 3
#define SQL_DELETE_ALL_SEGDIR 4
#define SQL_DELETE_ALL_DOCSIZE 5
** Otherwise, an SQLite error code is returned and *pp is set to 0.
**
** If argument apVal is not NULL, then it must point to an array with
-** at least as many entries as the requested statement has bound
+** at least as many entries as the requested statement has bound
** parameters. The values are bound to the statements parameters before
** returning.
*/
/* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)",
/* 11 */ "REPLACE INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)",
- /* Return segments in order from oldest to newest.*/
+ /* Return segments in order from oldest to newest.*/
/* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
"FROM %Q.'%q_segdir' WHERE level = ? ORDER BY idx ASC",
/* 13 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
" ORDER BY (level %% 1024) ASC LIMIT 1",
/* Estimate the upper limit on the number of leaf nodes in a new segment
-** created by merging the oldest :2 segments from absolute level :1. See
+** created by merging the oldest :2 segments from absolute level :1. See
** function sqlite3Fts3Incrmerge() for details. */
/* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) "
" FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?",
/* 31 */ "UPDATE %Q.'%q_segdir' SET idx = ? WHERE level=? AND idx=?",
/* SQL_SELECT_SEGDIR
-** Read a single entry from the %_segdir table. The entry from absolute
+** Read a single entry from the %_segdir table. The entry from absolute
** level :1 with index value :2. */
/* 32 */ "SELECT idx, start_block, leaves_end_block, end_block, root "
"FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?",
assert( SizeofArray(azSql)==SizeofArray(p->aStmt) );
assert( eStmt<SizeofArray(azSql) && eStmt>=0 );
-
+
pStmt = p->aStmt[eStmt];
if( !pStmt ){
char *zSql;
sqlite3_stmt *pStmt;
int rc;
if( *pRC ) return;
- rc = fts3SqlStmt(p, eStmt, &pStmt, apVal);
+ rc = fts3SqlStmt(p, eStmt, &pStmt, apVal);
if( rc==SQLITE_OK ){
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
** table-lock on the %_content table. This is required before reading
** data from the fts3 table. If this lock is not acquired first, then
** the caller may end up holding read-locks on the %_segments and %_segdir
-** tables, but no read-lock on the %_content table. If this happens
+** tables, but no read-lock on the %_content table. If this happens
** a second connection will be able to write to the fts3 table, but
** attempting to commit those writes might return SQLITE_LOCKED or
-** SQLITE_LOCKED_SHAREDCACHE (because the commit attempts to obtain
-** write-locks on the %_segments and %_segdir ** tables).
+** SQLITE_LOCKED_SHAREDCACHE (because the commit attempts to obtain
+** write-locks on the %_segments and %_segdir ** tables).
**
** We try to avoid this because if FTS3 returns any error when committing
** a transaction, the whole transaction will be rolled back. And this is
/*
** FTS maintains a separate indexes for each language-id (a 32-bit integer).
** Within each language id, a separate index is maintained to store the
-** document terms, and each configured prefix size (configured the FTS
+** document terms, and each configured prefix size (configured the FTS
** "prefix=" option). And each index consists of multiple levels ("relative
** levels").
**
** separate component values into the single 64-bit integer value that
** can be used to query the %_segdir table.
**
-** Specifically, each language-id/index combination is allocated 1024
+** Specifically, each language-id/index combination is allocated 1024
** 64-bit integer level values ("absolute levels"). The main terms index
** for language-id 0 is allocate values 0-1023. The first prefix index
** (if any) for language-id 0 is allocated values 1024-2047. And so on.
** Language 1 indexes are allocated immediately following language 0.
**
** So, for a system with nPrefix prefix indexes configured, the block of
-** absolute levels that corresponds to language-id iLangid and index
+** absolute levels that corresponds to language-id iLangid and index
** iIndex starts at absolute level ((iLangid * (nPrefix+1) + iIndex) * 1024).
*/
static sqlite3_int64 getAbsoluteLevel(
/*
** Set *ppStmt to a statement handle that may be used to iterate through
** all rows in the %_segdir table, from oldest to newest. If successful,
-** return SQLITE_OK. If an error occurs while preparing the statement,
+** return SQLITE_OK. If an error occurs while preparing the statement,
** return an SQLite error code.
**
** There is only ever one instance of this SQL statement compiled for
if( iLevel<0 ){
/* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */
rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0);
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK ){
sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
- sqlite3_bind_int64(pStmt, 2,
+ sqlite3_bind_int64(pStmt, 2,
getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
);
}
}else{
/* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */
rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0);
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK ){
sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel));
}
}
}
if( fts3PendingListAppend(&pList, p->iPrevDocid, iCol, iPos, &rc) ){
if( pList==fts3HashInsert(pHash, zToken, nToken, pList) ){
- /* Malloc failed while inserting the new entry. This can only
+ /* Malloc failed while inserting the new entry. This can only
** happen if there was no previous entry for this token.
*/
assert( 0==fts3HashFind(pHash, zToken, nToken) );
assert( pTokenizer && pModule );
/* If the user has inserted a NULL value, this function may be called with
- ** zText==0. In this case, add zero token entries to the hash table and
+ ** zText==0. In this case, add zero token entries to the hash table and
** return early. */
if( zText==0 ){
*pnWord = 0;
rc = fts3PendingTermsAddOne(
p, iCol, iPos, &p->aIndex[0].hPending, zToken, nToken
);
-
- /* Add the term to each of the prefix indexes that it is not too
+
+ /* Add the term to each of the prefix indexes that it is not too
** short for. */
for(i=1; rc==SQLITE_OK && i<p->nIndex; i++){
struct Fts3Index *pIndex = &p->aIndex[i];
return (rc==SQLITE_DONE ? SQLITE_OK : rc);
}
-/*
-** Calling this function indicates that subsequent calls to
+/*
+** Calling this function indicates that subsequent calls to
** fts3PendingTermsAdd() are to add term/position-list pairs for the
** contents of the document with docid iDocid.
*/
** buffer was half empty, that would let the less frequent terms
** generate longer doclists.
*/
- if( iDocid<=p->iPrevDocid
+ if( iDocid<=p->iPrevDocid
|| p->iPrevLangid!=iLangid
- || p->nPendingData>p->nMaxPendingData
+ || p->nPendingData>p->nMaxPendingData
){
int rc = sqlite3Fts3PendingTermsFlush(p);
if( rc!=SQLITE_OK ) return rc;
}
/*
-** Discard the contents of the pending-terms hash tables.
+** Discard the contents of the pending-terms hash tables.
*/
SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *p){
int i;
** fts3InsertData(). Parameter iDocid is the docid of the new row.
*/
static int fts3InsertTerms(
- Fts3Table *p,
- int iLangid,
- sqlite3_value **apVal,
+ Fts3Table *p,
+ int iLangid,
+ sqlite3_value **apVal,
u32 *aSz
){
int i; /* Iterator variable */
rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]);
if( rc==SQLITE_OK && p->zLanguageid ){
rc = sqlite3_bind_int(
- pContentInsert, p->nColumn+2,
+ pContentInsert, p->nColumn+2,
sqlite3_value_int(apVal[p->nColumn+4])
);
}
if( rc!=SQLITE_OK ) return rc;
}
- /* Execute the statement to insert the record. Set *piDocid to the
- ** new docid value.
+ /* Execute the statement to insert the record. Set *piDocid to the
+ ** new docid value.
*/
sqlite3_step(pContentInsert);
rc = sqlite3_reset(pContentInsert);
** (an integer) of a row about to be deleted. Remove all terms from the
** full-text index.
*/
-static void fts3DeleteTerms(
+static void fts3DeleteTerms(
int *pRC, /* Result code */
Fts3Table *p, /* The FTS table to delete from */
sqlite3_value *pRowid, /* The docid to be deleted */
*/
static int fts3SegmentMerge(Fts3Table *, int, int, int);
-/*
+/*
** This function allocates a new level iLevel index in the segdir table.
** Usually, indexes are allocated within a level sequentially starting
** with 0, so the allocated index is one greater than the value returned
** SELECT max(idx) FROM %_segdir WHERE level = :iLevel
**
** However, if there are already FTS3_MERGE_COUNT indexes at the requested
-** level, they are merged into a single level (iLevel+1) segment and the
+** level, they are merged into a single level (iLevel+1) segment and the
** allocated index is 0.
**
** If successful, *piIdx is set to the allocated index slot and SQLITE_OK
** returned. Otherwise, an SQLite error code is returned.
*/
static int fts3AllocateSegdirIdx(
- Fts3Table *p,
+ Fts3Table *p,
int iLangid, /* Language id */
int iIndex, /* Index for p->aIndex */
- int iLevel,
+ int iLevel,
int *piIdx
){
int rc; /* Return Code */
** This function reads data from a single row of the %_segments table. The
** specific row is identified by the iBlockid parameter. If paBlob is not
** NULL, then a buffer is allocated using sqlite3_malloc() and populated
-** with the contents of the blob stored in the "block" column of the
+** with the contents of the blob stored in the "block" column of the
** identified table row is. Whether or not paBlob is NULL, *pnBlob is set
** to the size of the blob in bytes before returning.
**
sqlite3_blob_close(p->pSegments);
p->pSegments = 0;
}
-
+
static int fts3SegReaderIncrRead(Fts3SegReader *pReader){
int nRead; /* Number of bytes to read */
int rc; /* Return code */
nRead = MIN(pReader->nNode - pReader->nPopulate, FTS3_NODE_CHUNKSIZE);
rc = sqlite3_blob_read(
- pReader->pBlob,
+ pReader->pBlob,
&pReader->aNode[pReader->nPopulate],
nRead,
pReader->nPopulate
static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){
int rc = SQLITE_OK;
- assert( !pReader->pBlob
+ assert( !pReader->pBlob
|| (pFrom>=pReader->aNode && pFrom<&pReader->aNode[pReader->nNode])
);
- while( pReader->pBlob && rc==SQLITE_OK
+ while( pReader->pBlob && rc==SQLITE_OK
&& (pFrom - pReader->aNode + nByte)>pReader->nPopulate
){
rc = fts3SegReaderIncrRead(pReader);
** SQLITE_DONE. Otherwise, an SQLite error code.
*/
static int fts3SegReaderNext(
- Fts3Table *p,
+ Fts3Table *p,
Fts3SegReader *pReader,
int bIncr
){
fts3SegReaderSetEof(pReader);
- /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
+ /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf
** blocks have already been traversed. */
assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );
if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
}
rc = sqlite3Fts3ReadBlock(
- p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode,
+ p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode,
(bIncr ? &pReader->nPopulate : 0)
);
if( rc!=SQLITE_OK ) return rc;
rc = fts3SegReaderRequire(pReader, pNext, FTS3_VARINT_MAX*2);
if( rc!=SQLITE_OK ) return rc;
-
- /* Because of the FTS3_NODE_PADDING bytes of padding, the following is
+
+ /* Because of the FTS3_NODE_PADDING bytes of padding, the following is
** safe (no risk of overread) even if the node data is corrupted. */
pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
- if( nPrefix<0 || nSuffix<=0
- || &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
+ if( nPrefix<0 || nSuffix<=0
+ || &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
){
return FTS_CORRUPT_VTAB;
}
pReader->pOffsetList = 0;
/* Check that the doclist does not appear to extend past the end of the
- ** b-tree node. And that the final byte of the doclist is 0x00. If either
+ ** b-tree node. And that the final byte of the doclist is 0x00. If either
** of these statements is untrue, then the data structure is corrupt.
*/
- if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
+ if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
|| (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
){
return FTS_CORRUPT_VTAB;
pReader->iDocid = 0;
pReader->nOffsetList = 0;
sqlite3Fts3DoclistPrev(0,
- pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList,
+ pReader->aDoclist, pReader->nDoclist, &pReader->pOffsetList,
&pReader->iDocid, &pReader->nOffsetList, &bEof
);
}else{
/*
** Advance the SegReader to point to the next docid in the doclist
** associated with the current term.
-**
-** If arguments ppOffsetList and pnOffsetList are not NULL, then
+**
+** If arguments ppOffsetList and pnOffsetList are not NULL, then
** *ppOffsetList is set to point to the first column-offset list
** in the doclist entry (i.e. immediately past the docid varint).
** *pnOffsetList is set to the length of the set of column-offset
** following block advances it to point one byte past the end of
** the same offset list. */
while( 1 ){
-
+
/* The following line of code (and the "p++" below the while() loop) is
- ** normally all that is required to move pointer p to the desired
+ ** normally all that is required to move pointer p to the desired
** position. The exception is if this node is being loaded from disk
** incrementally and pointer "p" now points to the first byte passed
** the populated part of pReader->aNode[].
*/
while( *p | c ) c = *p++ & 0x80;
assert( *p==0 );
-
+
if( pReader->pBlob==0 || p<&pReader->aNode[pReader->nPopulate] ) break;
rc = fts3SegReaderIncrRead(pReader);
if( rc!=SQLITE_OK ) return rc;
}
p++;
-
+
/* If required, populate the output variables with a pointer to and the
** size of the previous offset-list.
*/
/* List may have been edited in place by fts3EvalNearTrim() */
while( p<pEnd && *p==0 ) p++;
-
+
/* If there are no more entries in the doclist, set pOffsetList to
** NULL. Otherwise, set Fts3SegReader.iDocid to the next docid and
** Fts3SegReader.pOffsetList to point to the next offset list before
SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(
- Fts3Cursor *pCsr,
+ Fts3Cursor *pCsr,
Fts3MultiSegReader *pMsr,
int *pnOvfl
){
for(ii=0; rc==SQLITE_OK && ii<pMsr->nSegment; ii++){
Fts3SegReader *pReader = pMsr->apSegment[ii];
- if( !fts3SegReaderIsPending(pReader)
- && !fts3SegReaderIsRootOnly(pReader)
+ if( !fts3SegReaderIsPending(pReader)
+ && !fts3SegReaderIsRootOnly(pReader)
){
sqlite3_int64 jj;
for(jj=pReader->iStartBlock; jj<=pReader->iLeafEndBlock; jj++){
}
/*
-** Free all allocations associated with the iterator passed as the
+** Free all allocations associated with the iterator passed as the
** second argument.
*/
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
}else{
/* The query is a simple term lookup that matches at most one term in
- ** the index. All that is required is a straight hash-lookup.
+ ** the index. All that is required is a straight hash-lookup.
**
** Because the stack address of pE may be accessed via the aElem pointer
** below, the "Fts3HashElem *pE" must be declared so that it is valid
}
/*
-** Compare the entries pointed to by two Fts3SegReader structures.
+** Compare the entries pointed to by two Fts3SegReader structures.
** Comparison is as follows:
**
** 1) EOF is greater than not EOF.
/*
** Compare the term that the Fts3SegReader object passed as the first argument
-** points to with the term specified by arguments zTerm and nTerm.
+** points to with the term specified by arguments zTerm and nTerm.
**
** If the pSeg iterator is already at EOF, return 0. Otherwise, return
** -ve if the pSeg term is less than zTerm/nTerm, 0 if the two terms are
#endif
}
-/*
+/*
** Insert a record into the %_segments table.
*/
static int fts3WriteSegment(
return rc;
}
-/*
+/*
** Insert a record into the %_segdir table.
*/
static int fts3WriteSegdir(
/*
** Return the size of the common prefix (if any) shared by zPrev and
-** zNext, in bytes. For example,
+** zNext, in bytes. For example,
**
** fts3PrefixCompress("abc", 3, "abcdef", 6) // returns 3
** fts3PrefixCompress("abX", 3, "abcdef", 6) // returns 2
*/
static int fts3NodeAddTerm(
Fts3Table *p, /* Virtual table handle */
- SegmentNode **ppTree, /* IN/OUT: SegmentNode handle */
+ SegmentNode **ppTree, /* IN/OUT: SegmentNode handle */
int isCopyTerm, /* True if zTerm/nTerm is transient */
const char *zTerm, /* Pointer to buffer containing term */
int nTerm /* Size of term in bytes */
int rc;
SegmentNode *pNew;
- /* First try to append the term to the current node. Return early if
+ /* First try to append the term to the current node. Return early if
** this is possible.
*/
if( pTree ){
** and the static node buffer (p->nNodeSize bytes) is not large
** enough. Use a separately malloced buffer instead This wastes
** p->nNodeSize bytes, but since this scenario only comes about when
- ** the database contain two terms that share a prefix of almost 2KB,
- ** this is not expected to be a serious problem.
+ ** the database contain two terms that share a prefix of almost 2KB,
+ ** this is not expected to be a serious problem.
*/
assert( pTree->aData==(char *)&pTree[1] );
pTree->aData = (char *)sqlite3_malloc(nReq);
** If this is the first node in the tree, the term is added to it.
**
** Otherwise, the term is not added to the new node, it is left empty for
- ** now. Instead, the term is inserted into the parent of pTree. If pTree
+ ** now. Instead, the term is inserted into the parent of pTree. If pTree
** has no parent, one is created here.
*/
pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize);
pTree->zMalloc = 0;
}else{
pNew->pLeftmost = pNew;
- rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm);
+ rc = fts3NodeAddTerm(p, &pNew, isCopyTerm, zTerm, nTerm);
}
*ppTree = pNew;
** Helper function for fts3NodeWrite().
*/
static int fts3TreeFinishNode(
- SegmentNode *pTree,
- int iHeight,
+ SegmentNode *pTree,
+ int iHeight,
sqlite3_int64 iLeftChild
){
int nStart;
/*
** Write the buffer for the segment node pTree and all of its peers to the
-** database. Then call this function recursively to write the parent of
-** pTree and its peers to the database.
+** database. Then call this function recursively to write the parent of
+** pTree and its peers to the database.
**
** Except, if pTree is a root node, do not write it to the database. Instead,
** set output variables *paRoot and *pnRoot to contain the root node.
**
** If successful, SQLITE_OK is returned and output variable *piLast is
** set to the largest blockid written to the database (or zero if no
-** blocks were written to the db). Otherwise, an SQLite error code is
+** blocks were written to the db). Otherwise, an SQLite error code is
** returned.
*/
static int fts3NodeWrite(
for(pIter=pTree->pLeftmost; pIter && rc==SQLITE_OK; pIter=pIter->pRight){
int nStart = fts3TreeFinishNode(pIter, iHeight, iNextLeaf);
int nWrite = pIter->nData - nStart;
-
+
rc = fts3WriteSegment(p, iNextFree, &pIter->aData[nStart], nWrite);
iNextFree++;
iNextLeaf += (pIter->nEntry+1);
*/
static int fts3SegWriterAdd(
Fts3Table *p, /* Virtual table handle */
- SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */
+ SegmentWriter **ppWriter, /* IN/OUT: SegmentWriter handle */
int isCopyTerm, /* True if buffer zTerm must be copied */
const char *zTerm, /* Pointer to buffer containing term */
int nTerm, /* Size of term in bytes */
}
/*
-** Release all memory held by the SegmentWriter object passed as the
+** Release all memory held by the SegmentWriter object passed as the
** first argument.
*/
static void fts3SegWriterFree(SegmentWriter *pWriter){
** Return SQLITE_OK if successful, or an SQLite error code if not.
*/
static int fts3SegmentMaxLevel(
- Fts3Table *p,
+ Fts3Table *p,
int iLangid,
- int iIndex,
+ int iIndex,
sqlite3_int64 *pnMax
){
sqlite3_stmt *pStmt;
rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
if( rc!=SQLITE_OK ) return rc;
sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
- sqlite3_bind_int64(pStmt, 2,
+ sqlite3_bind_int64(pStmt, 2,
getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
);
if( SQLITE_ROW==sqlite3_step(pStmt) ){
** This function is used after merging multiple segments into a single large
** segment to delete the old, now redundant, segment b-trees. Specifically,
** it:
-**
-** 1) Deletes all %_segments entries for the segments associated with
-** each of the SegReader objects in the array passed as the third
+**
+** 1) Deletes all %_segments entries for the segments associated with
+** each of the SegReader objects in the array passed as the third
** argument, and
**
** 2) deletes all %_segdir entries with level iLevel, or all %_segdir
rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0));
- sqlite3_bind_int64(pDelete, 2,
+ sqlite3_bind_int64(pDelete, 2,
getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1)
);
}
}
/*
-** When this function is called, buffer *ppList (size *pnList bytes) contains
+** When this function is called, buffer *ppList (size *pnList bytes) contains
** a position list that may (or may not) feature multiple columns. This
** function adjusts the pointer *ppList and the length *pnList so that they
** identify the subset of the position list that corresponds to column iCol.
while( 1 ){
char c = 0;
while( p<pEnd && (c | *p)&0xFE ) c = *p++ & 0x80;
-
+
if( iCol==iCurrent ){
nList = (int)(p - pList);
break;
rc = fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
j = 1;
- while( rc==SQLITE_OK
+ while( rc==SQLITE_OK
&& j<nMerge
&& apSegment[j]->pOffsetList
&& apSegment[j]->iDocid==iDocid
int i;
int nSeg = pCsr->nSegment;
- /* If the Fts3SegFilter defines a specific term (or term prefix) to search
+ /* If the Fts3SegFilter defines a specific term (or term prefix) to search
** for, then advance each segment iterator until it points to a term of
** equal or greater value than the specified term. This prevents many
** unnecessary merge/sort operations for the case where single segment
** sqlite3Fts3SegReaderStart()
** sqlite3Fts3SegReaderStep()
**
-** then the entire doclist for the term is available in
+** then the entire doclist for the term is available in
** MultiSegReader.aDoclist/nDoclist.
*/
SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
do {
int nMerge;
int i;
-
+
/* Advance the first pCsr->nAdvance entries in the apSegment[] array
- ** forward. Then sort the list in order of current term again.
+ ** forward. Then sort the list in order of current term again.
*/
for(i=0; i<pCsr->nAdvance; i++){
Fts3SegReader *pSeg = apSegment[i];
pCsr->zTerm = apSegment[0]->zTerm;
/* If this is a prefix-search, and if the term that apSegment[0] points
- ** to does not share a suffix with pFilter->zTerm/nTerm, then all
+ ** to does not share a suffix with pFilter->zTerm/nTerm, then all
** required callbacks have been made. In this case exit early.
**
** Similarly, if this is a search for an exact match, and the first term
** of segment apSegment[0] is not a match, exit early.
*/
if( pFilter->zTerm && !isScan ){
- if( pCsr->nTerm<pFilter->nTerm
+ if( pCsr->nTerm<pFilter->nTerm
|| (!isPrefix && pCsr->nTerm>pFilter->nTerm)
- || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm)
+ || memcmp(pCsr->zTerm, pFilter->zTerm, pFilter->nTerm)
){
break;
}
}
nMerge = 1;
- while( nMerge<nSegment
+ while( nMerge<nSegment
&& apSegment[nMerge]->aNode
- && apSegment[nMerge]->nTerm==pCsr->nTerm
+ && apSegment[nMerge]->nTerm==pCsr->nTerm
&& 0==memcmp(pCsr->zTerm, apSegment[nMerge]->zTerm, pCsr->nTerm)
){
nMerge++;
}
assert( isIgnoreEmpty || (isRequirePos && !isColFilter) );
- if( nMerge==1
- && !isIgnoreEmpty
- && !isFirst
+ if( nMerge==1
+ && !isIgnoreEmpty
+ && !isFirst
&& (p->bDescIdx==0 || fts3SegReaderIsPending(apSegment[0])==0)
){
pCsr->nDoclist = apSegment[0]->nDoclist;
if( !isIgnoreEmpty || nList>0 ){
- /* Calculate the 'docid' delta value to write into the merged
+ /* Calculate the 'docid' delta value to write into the merged
** doclist. */
sqlite3_int64 iDelta;
if( p->bDescIdx && nDoclist>0 ){
if( isFirst ){
char *a = &pCsr->aBuffer[nDoclist];
int nWrite;
-
+
nWrite = sqlite3Fts3FirstFilter(iDelta, pList, nList, a);
if( nWrite ){
iPrev = iDocid;
}
/*
-** Merge all level iLevel segments in the database into a single
+** Merge all level iLevel segments in the database into a single
** iLevel+1 segment. Or, if iLevel<0, merge all segments into a
-** single segment with a level equal to the numerically largest level
+** single segment with a level equal to the numerically largest level
** currently present in the database.
**
** If this function is called with iLevel<0, but there is only one
-** segment in the database, SQLITE_DONE is returned immediately.
-** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
+** segment in the database, SQLITE_DONE is returned immediately.
+** Otherwise, if successful, SQLITE_OK is returned. If an error occurs,
** an SQLite error code is returned.
*/
static int fts3SegmentMerge(
- Fts3Table *p,
+ Fts3Table *p,
int iLangid, /* Language id to merge */
int iIndex, /* Index in p->aIndex[] to merge */
int iLevel /* Level to merge */
}else{
/* This call is to merge all segments at level iLevel. find the next
** available segment index at level iLevel+1. The call to
- ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
+ ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
** a single iLevel+2 segment if necessary. */
rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
while( SQLITE_OK==rc ){
rc = sqlite3Fts3SegReaderStep(p, &csr);
if( rc!=SQLITE_ROW ) break;
- rc = fts3SegWriterAdd(p, &pWriter, 1,
+ rc = fts3SegWriterAdd(p, &pWriter, 1,
csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
}
if( rc!=SQLITE_OK ) goto finished;
}
-/*
+/*
** Flush the contents of pendingTerms to level 0 segments.
*/
SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
int rc = SQLITE_OK;
int i;
-
+
for(i=0; rc==SQLITE_OK && i<p->nIndex; i++){
rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING);
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
/*
** Record 0 of the %_stat table contains a blob consisting of N varints,
** where N is the number of user defined columns in the fts3 table plus
-** two. If nCol is the number of user defined columns, then values of the
+** two. If nCol is the number of user defined columns, then values of the
** varints are set as follows:
**
** Varint 0: Total number of rows in the table.
}
/*
-** Merge the entire database so that there is one segment for each
+** Merge the entire database so that there is one segment for each
** iIndex/iLangid combination.
*/
static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
**
** INSERT INTO <tbl>(<tbl>) VALUES('rebuild');
**
-** The entire FTS index is discarded and rebuilt. If the table is one
+** The entire FTS index is discarded and rebuilt. If the table is one
** created using the content=xxx option, then the new index is based on
** the current contents of the xxx table. Otherwise, it is rebuilt based
** on the contents of the %_content table.
/*
-** This function opens a cursor used to read the input data for an
+** This function opens a cursor used to read the input data for an
** incremental merge operation. Specifically, it opens a cursor to scan
-** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute
+** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute
** level iAbsLevel.
*/
static int fts3IncrmergeCsr(
Fts3MultiSegReader *pCsr /* Cursor object to populate */
){
int rc; /* Return Code */
- sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */
+ sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */
int nByte; /* Bytes allocated at pCsr->apSegment[] */
/* Allocate space for the Fts3MultiSegReader.aCsr[] array */
};
/*
-** This structure is used to build up buffers containing segment b-tree
+** This structure is used to build up buffers containing segment b-tree
** nodes (blocks).
*/
struct NodeWriter {
/*
** Attempt to advance the node-reader object passed as the first argument to
-** the next entry on the node.
+** the next entry on the node.
**
-** Return an error code if an error occurs (SQLITE_NOMEM is possible).
+** Return an error code if an error occurs (SQLITE_NOMEM is possible).
** Otherwise return SQLITE_OK. If there is no next entry on the node
** (e.g. because the current entry is the last) set NodeReader->aNode to
-** NULL to indicate EOF. Otherwise, populate the NodeReader structure output
+** NULL to indicate EOF. Otherwise, populate the NodeReader structure output
** variables for the new entry.
*/
static int nodeReaderNext(NodeReader *p){
/*
** Initialize a node-reader object to read the node in buffer aNode/nNode.
**
-** If successful, SQLITE_OK is returned and the NodeReader object set to
+** If successful, SQLITE_OK is returned and the NodeReader object set to
** point to the first entry on the node (if any). Otherwise, an SQLite
** error code is returned.
*/
int nSpace;
/* Figure out how much space the key will consume if it is written to
- ** the current node of layer iLayer. Due to the prefix compression,
+ ** the current node of layer iLayer. Due to the prefix compression,
** the space required changes depending on which node the key is to
** be added to. */
nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm);
nSpace = sqlite3Fts3VarintLen(nPrefix);
nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
- if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){
+ if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){
/* If the current node of layer iLayer contains zero keys, or if adding
- ** the key to it will not cause it to grow to larger than nNodeSize
+ ** the key to it will not cause it to grow to larger than nNodeSize
** bytes in size, write the key here. */
Blob *pBlk = &pNode->block;
** A node header is a single 0x00 byte for a leaf node, or a height varint
** followed by the left-hand-child varint for an internal node.
**
-** The term to be appended is passed via arguments zTerm/nTerm. For a
+** The term to be appended is passed via arguments zTerm/nTerm. For a
** leaf node, the doclist is passed as aDoclist/nDoclist. For an internal
** node, both aDoclist and nDoclist must be passed 0.
**
** If the size of the value in blob pPrev is zero, then this is the first
-** term written to the node. Otherwise, pPrev contains a copy of the
+** term written to the node. Otherwise, pPrev contains a copy of the
** previous term. Before this function returns, it is updated to contain a
** copy of zTerm/nTerm.
**
const char *zTerm, /* New term to write */
int nTerm, /* Size of zTerm in bytes */
const char *aDoclist, /* Doclist (or NULL) to write */
- int nDoclist /* Size of aDoclist in bytes */
+ int nDoclist /* Size of aDoclist in bytes */
){
int rc = SQLITE_OK; /* Return code */
int bFirst = (pPrev->n==0); /* True if this is the first term written */
rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n);
pWriter->nWork++;
- /* Add the current term to the parent node. The term added to the
+ /* Add the current term to the parent node. The term added to the
** parent must:
**
** a) be greater than the largest term on the leaf node just written
NodeWriter *pRoot; /* NodeWriter for root node */
int rc = *pRc; /* Error code */
- /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment
+ /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment
** root node. If the segment fits entirely on a single leaf node, iRoot
** will be set to 0. If the root node is the parent of the leaves, iRoot
** will be 1. And so on. */
/* The entire output segment fits on a single node. Normally, this means
** the node would be stored as a blob in the "root" column of the %_segdir
- ** table. However, this is not permitted in this case. The problem is that
- ** space has already been reserved in the %_segments table, and so the
- ** start_block and end_block fields of the %_segdir table must be populated.
- ** And, by design or by accident, released versions of FTS cannot handle
+ ** table. However, this is not permitted in this case. The problem is that
+ ** space has already been reserved in the %_segments table, and so the
+ ** start_block and end_block fields of the %_segdir table must be populated.
+ ** And, by design or by accident, released versions of FTS cannot handle
** segments that fit entirely on the root node with start_block!=0.
**
- ** Instead, create a synthetic root node that contains nothing but a
+ ** Instead, create a synthetic root node that contains nothing but a
** pointer to the single content node. So that the segment consists of a
** single leaf and a single interior (root) node.
**
- ** Todo: Better might be to defer allocating space in the %_segments
+ ** Todo: Better might be to defer allocating space in the %_segments
** table until we are sure it is needed.
*/
if( iRoot==0 ){
/* Write the %_segdir record. */
if( rc==SQLITE_OK ){
- rc = fts3WriteSegdir(p,
+ rc = fts3WriteSegdir(p,
pWriter->iAbsLevel+1, /* level */
pWriter->iIdx, /* idx */
pWriter->iStart, /* start_block */
/*
-** Query to see if the entry in the %_segments table with blockid iEnd is
+** Query to see if the entry in the %_segments table with blockid iEnd is
** NULL. If no error occurs and the entry is NULL, set *pbRes 1 before
-** returning. Otherwise, set *pbRes to 0.
+** returning. Otherwise, set *pbRes to 0.
**
-** Or, if an error occurs while querying the database, return an SQLite
+** Or, if an error occurs while querying the database, return an SQLite
** error code. The final value of *pbRes is undefined in this case.
**
** This is used to test if a segment is an "appendable" segment. If it
if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1;
rc = sqlite3_reset(pCheck);
}
-
+
*pbRes = bRes;
return rc;
}
/*
** This function is called when initializing an incremental-merge operation.
-** It checks if the existing segment with index value iIdx at absolute level
+** It checks if the existing segment with index value iIdx at absolute level
** (iAbsLevel+1) can be appended to by the incremental merge. If it can, the
** merge-writer object *pWriter is initialized to write to it.
**
** * It was initially created as an appendable segment (with all required
** space pre-allocated), and
**
-** * The first key read from the input (arguments zKey and nKey) is
+** * The first key read from the input (arguments zKey and nKey) is
** greater than the largest key currently stored in the potential
** output segment.
*/
/*
** Determine the largest segment index value that exists within absolute
** level iAbsLevel+1. If no error occurs, set *piIdx to this value plus
-** one before returning SQLITE_OK. Or, if there are no segments at all
+** one before returning SQLITE_OK. Or, if there are no segments at all
** within level iAbsLevel, set *piIdx to zero.
**
** If an error occurs, return an SQLite error code. The final value of
** *piIdx is undefined in this case.
*/
-static int fts3IncrmergeOutputIdx(
+static int fts3IncrmergeOutputIdx(
Fts3Table *p, /* FTS Table handle */
sqlite3_int64 iAbsLevel, /* Absolute index of input segments */
int *piIdx /* OUT: Next free index at iAbsLevel+1 */
return rc;
}
-/*
+/*
** Allocate an appendable output segment on absolute level iAbsLevel+1
** with idx value iIdx.
**
** When an appendable segment is allocated, it is estimated that the
** maximum number of leaf blocks that may be required is the sum of the
** number of leaf blocks consumed by the input segments, plus the number
-** of input segments, multiplied by two. This value is stored in stack
+** of input segments, multiplied by two. This value is stored in stack
** variable nLeafEst.
**
** A total of 16*nLeafEst blocks are allocated when an appendable segment
** of interior nodes that are parents of the leaf nodes start at block
** (start_block + (1 + end_block - start_block) / 16). And so on.
**
-** In the actual code below, the value "16" is replaced with the
+** In the actual code below, the value "16" is replaced with the
** pre-processor macro FTS_MAX_APPENDABLE_HEIGHT.
*/
-static int fts3IncrmergeWriter(
+static int fts3IncrmergeWriter(
Fts3Table *p, /* Fts3 table handle */
sqlite3_int64 iAbsLevel, /* Absolute level of input segments */
int iIdx, /* Index of new output segment */
if( rc!=SQLITE_OK ) return rc;
/* Insert the marker in the %_segments table to make sure nobody tries
- ** to steal the space just allocated. This is also used to identify
+ ** to steal the space just allocated. This is also used to identify
** appendable segments. */
rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0);
if( rc!=SQLITE_OK ) return rc;
}
/*
-** Remove an entry from the %_segdir table. This involves running the
+** Remove an entry from the %_segdir table. This involves running the
** following two statements:
**
** DELETE FROM %_segdir WHERE level = :iAbsLevel AND idx = :iIdx
** UPDATE %_segdir SET idx = idx - 1 WHERE level = :iAbsLevel AND idx > :iIdx
**
-** The DELETE statement removes the specific %_segdir level. The UPDATE
+** The DELETE statement removes the specific %_segdir level. The UPDATE
** statement ensures that the remaining segments have contiguously allocated
** idx values.
*/
pNew->n = 0;
/* Populate new node buffer */
- for(rc = nodeReaderInit(&reader, aNode, nNode);
- rc==SQLITE_OK && reader.aNode;
+ for(rc = nodeReaderInit(&reader, aNode, nNode);
+ rc==SQLITE_OK && reader.aNode;
rc = nodeReaderNext(&reader)
){
if( pNew->n==0 ){
}
/*
-** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute
+** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute
** level iAbsLevel. This may involve deleting entries from the %_segments
** table, and modifying existing entries in both the %_segments and %_segdir
** tables.
}
*pnRem = 0;
}else{
- /* The incremental merge did not copy all the data from this
+ /* The incremental merge did not copy all the data from this
** segment to the upper level. The segment is modified in place
- ** so that it contains no keys smaller than zTerm/nTerm. */
+ ** so that it contains no keys smaller than zTerm/nTerm. */
const char *zTerm = pSeg->zTerm;
int nTerm = pSeg->nTerm;
rc = fts3TruncateSegment(p, iAbsLevel, pSeg->iIdx, zTerm, nTerm);
}
/*
-** Load an incr-merge hint from the database. The incr-merge hint, if one
+** Load an incr-merge hint from the database. The incr-merge hint, if one
** exists, is stored in the rowid==1 row of the %_stat table.
**
** If successful, populate blob *pHint with the value read from the %_stat
/*
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
** Otherwise, append an entry to the hint stored in blob *pHint. Each entry
-** consists of two varints, the absolute level number of the input segments
+** consists of two varints, the absolute level number of the input segments
** and the number of input segments.
**
** If successful, leave *pRc set to SQLITE_OK and return. If an error occurs,
/*
** Read the last entry (most recently pushed) from the hint blob *pHint
-** and then remove the entry. Write the two values read to *piAbsLevel and
+** and then remove the entry. Write the two values read to *piAbsLevel and
** *pnInput before returning.
**
** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does
** Incremental merges happen nMin segments at a time. The two
** segments to be merged are the nMin oldest segments (the ones with
** the smallest indexes) in the highest level that contains at least
-** nMin segments. Multiple merges might occur in an attempt to write the
+** nMin segments. Multiple merges might occur in an attempt to write the
** quota of nMerge leaf blocks.
*/
SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
/* Search the %_segdir table for the absolute level with the smallest
** relative level number that contains at least nMin segments, if any.
** If one is found, set iAbsLevel to the absolute level number and
- ** nSeg to nMin. If no level with at least nMin segments can be found,
+ ** nSeg to nMin. If no level with at least nMin segments can be found,
** set nSeg to -1.
*/
rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0);
/* If the hint read from the %_stat table is not empty, check if the
** last entry in it specifies a relative level smaller than or equal
- ** to the level identified by the block above (if any). If so, this
+ ** to the level identified by the block above (if any). If so, this
** iteration of the loop will work on merging at the hinted level.
*/
if( rc==SQLITE_OK && hint.n ){
** Exit early in this case. */
if( nSeg<0 ) break;
- /* Open a cursor to iterate through the contents of the oldest nSeg
- ** indexes of absolute level iAbsLevel. If this cursor is opened using
+ /* Open a cursor to iterate through the contents of the oldest nSeg
+ ** indexes of absolute level iAbsLevel. If this cursor is opened using
** the 'hint' parameters, it is possible that there are less than nSeg
** segments available in level iAbsLevel. In this case, no work is
- ** done on iAbsLevel - fall through to the next iteration of the loop
+ ** done on iAbsLevel - fall through to the next iteration of the loop
** to start work on some other level. */
memset(pWriter, 0, nAlloc);
pFilter->flags = FTS3_SEGMENT_REQUIRE_POS;
** to true and return SQLITE_OK. Or if the contents do not match, set *pbOk
** to false before returning.
**
-** If an error occurs (e.g. an OOM or IO error), return an SQLite error
+** If an error occurs (e.g. an OOM or IO error), return an SQLite error
** code. The final value of *pbOk is undefined in this case.
*/
static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
sqlite3_stmt *pStmt = 0;
char *zSql;
-
+
zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist);
if( !zSql ){
rc = SQLITE_NOMEM;
** the FTS index are correct, return SQLITE_OK. Or, if the contents of the
** FTS index are incorrect, return SQLITE_CORRUPT_VTAB.
**
-** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite
+** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite
** error code.
**
** The integrity-check works as follows. For each token and indexed token
**
** + The index number (0 for the main index, 1 for the first prefix
** index etc.),
-** + The token (or token prefix) text itself,
+** + The token (or token prefix) text itself,
** + The language-id of the row it appears in,
** + The docid of the row it appears in,
** + The column it appears in, and
**
** The integrity-check code calculates the same checksum in two ways:
**
-** 1. By scanning the contents of the FTS index, and
+** 1. By scanning the contents of the FTS index, and
** 2. By scanning and tokenizing the content table.
**
** If the two checksums are identical, the integrity-check is deemed to have
**
** "INSERT INTO tbl(tbl) VALUES(<expr>)"
**
-** Argument pVal contains the result of <expr>. Currently the only
+** Argument pVal contains the result of <expr>. Currently the only
** meaningful value to insert is the text 'optimize'.
*/
static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
}
/*
-** Free all entries in the pCsr->pDeffered list. Entries are added to
+** Free all entries in the pCsr->pDeffered list. Entries are added to
** this list using sqlite3Fts3DeferToken().
*/
SQLITE_PRIVATE void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *pCsr){
int i; /* Used to iterate through table columns */
sqlite3_int64 iDocid; /* Docid of the row pCsr points to */
Fts3DeferredToken *pDef; /* Used to iterate through deferred tokens */
-
+
Fts3Table *p = (Fts3Table *)pCsr->base.pVtab;
sqlite3_tokenizer *pT = p->pTokenizer;
sqlite3_tokenizer_module const *pModule = pT->pModule;
-
+
assert( pCsr->isRequireSeek==0 );
iDocid = sqlite3_column_int64(pCsr->pStmt, 0);
-
+
for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
sqlite3_tokenizer_cursor *pTC = 0;
-
+
rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
while( rc==SQLITE_OK ){
char const *zToken; /* Buffer containing token */
int nToken = 0; /* Number of bytes in token */
int iDum1 = 0, iDum2 = 0; /* Dummy variables */
int iPos = 0; /* Position of token in zText */
-
+
rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
Fts3PhraseToken *pPT = pDef->pToken;
if( pTC ) pModule->xClose(pTC);
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
}
-
+
for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
if( pDef->pList ){
rc = fts3PendingListAppendVarint(&pDef->pList, 0);
}
SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(
- Fts3DeferredToken *p,
- char **ppData,
+ Fts3DeferredToken *p,
+ char **ppData,
int *pnData
){
char *pRet;
nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy);
*pnData = p->pList->nData - nSkip;
*ppData = pRet;
-
+
memcpy(pRet, &p->pList->aData[nSkip], *pnData);
return SQLITE_OK;
}
}
memset(pDeferred, 0, sizeof(*pDeferred));
pDeferred->pToken = pToken;
- pDeferred->pNext = pCsr->pDeferred;
+ pDeferred->pNext = pCsr->pDeferred;
pDeferred->iCol = iCol;
pCsr->pDeferred = pDeferred;
** of subsiduary data structures accordingly.
*/
static int fts3DeleteByRowid(
- Fts3Table *p,
- sqlite3_value *pRowid,
+ Fts3Table *p,
+ sqlite3_value *pRowid,
int *pnChng, /* IN/OUT: Decrement if row is deleted */
u32 *aSzDel
){
** This function does the work for the xUpdate method of FTS3 virtual
** tables. The schema of the virtual table being:
**
-** CREATE TABLE <table name>(
+** CREATE TABLE <table name>(
** <user columns>,
-** <table name> HIDDEN,
-** docid HIDDEN,
+** <table name> HIDDEN,
+** docid HIDDEN,
** <langid> HIDDEN
** );
**
-**
+**
*/
SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
sqlite3_vtab *pVtab, /* FTS3 vtab object */
int bInsertDone = 0;
assert( p->pSegments==0 );
- assert(
+ assert(
nArg==1 /* DELETE operations */
|| nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */
);
**
** INSERT INTO xyz(xyz) VALUES('command');
*/
- if( nArg>1
- && sqlite3_value_type(apVal[0])==SQLITE_NULL
- && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
+ if( nArg>1
+ && sqlite3_value_type(apVal[0])==SQLITE_NULL
+ && sqlite3_value_type(apVal[p->nColumn+2])!=SQLITE_NULL
){
rc = fts3SpecialInsert(p, apVal[p->nColumn+2]);
goto update_out;
pNewRowid = apVal[1];
}
- if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && (
+ if( sqlite3_value_type(pNewRowid)!=SQLITE_NULL && (
sqlite3_value_type(apVal[0])==SQLITE_NULL
|| sqlite3_value_int64(apVal[0])!=sqlite3_value_int64(pNewRowid)
)){
/* The new rowid is not NULL (in this case the rowid will be
- ** automatically assigned and there is no chance of a conflict), and
+ ** automatically assigned and there is no chance of a conflict), and
** the statement is either an INSERT or an UPDATE that modifies the
** rowid column. So if the conflict mode is REPLACE, then delete any
- ** existing row with rowid=pNewRowid.
+ ** existing row with rowid=pNewRowid.
**
- ** Or, if the conflict mode is not REPLACE, insert the new record into
+ ** Or, if the conflict mode is not REPLACE, insert the new record into
** the %_content table. If we hit the duplicate rowid constraint (or any
** other error) while doing so, return immediately.
**
** This branch may also run if pNewRowid contains a value that cannot
- ** be losslessly converted to an integer. In this case, the eventual
+ ** be losslessly converted to an integer. In this case, the eventual
** call to fts3InsertData() (either just below or further on in this
- ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is
+ ** function) will return SQLITE_MISMATCH. If fts3DeleteByRowid is
** invoked, it will delete zero rows (since no row will have
** docid=$pNewRowid if $pNewRowid is not an integer value).
*/
rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel);
isRemove = 1;
}
-
+
/* If this is an INSERT or UPDATE operation, insert the new record. */
if( nArg>1 && rc==SQLITE_OK ){
int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]);
return rc;
}
-/*
+/*
** Flush any data in the pending-terms hash table to disk. If successful,
-** merge all segments in the database (including the new segment, if
-** there was any data to flush) into a single segment.
+** merge all segments in the database (including the new segment, if
+** there was any data to flush) into a single segment.
*/
SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){
int rc;
#define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */
/*
-** The default value for the second argument to matchinfo().
+** The default value for the second argument to matchinfo().
*/
#define FTS3_MATCHINFO_DEFAULT "pcx"
};
/*
-** The following types are used as part of the implementation of the
+** The following types are used as part of the implementation of the
** fts3BestSnippet() routine.
*/
typedef struct SnippetIter SnippetIter;
};
/*
-** This type is used as an fts3ExprIterate() context object while
+** This type is used as an fts3ExprIterate() context object while
** accumulating the data returned by the matchinfo() function.
*/
typedef struct MatchInfo MatchInfo;
** are part of a sub-tree that is the right-hand-side of a NOT operator.
** For each phrase node found, the supplied callback function is invoked.
**
-** If the callback function returns anything other than SQLITE_OK,
+** If the callback function returns anything other than SQLITE_OK,
** the iteration is abandoned and the error code returned immediately.
** Otherwise, SQLITE_OK is returned after a callback has been made for
** all eligible phrase nodes.
/*
** Load the doclists for each phrase in the query associated with FTS3 cursor
-** pCsr.
+** pCsr.
**
-** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable
-** phrases in the expression (all phrases except those directly or
-** indirectly descended from the right-hand-side of a NOT operator). If
+** If pnPhrase is not NULL, then *pnPhrase is set to the number of matchable
+** phrases in the expression (all phrases except those directly or
+** indirectly descended from the right-hand-side of a NOT operator). If
** pnToken is not NULL, then it is set to the number of tokens in all
** matchable phrases of the expression.
*/
}
/*
-** Advance the position list iterator specified by the first two
+** Advance the position list iterator specified by the first two
** arguments so that it points to the first element with a value greater
** than or equal to parameter iNext.
*/
}
/*
-** Retrieve information about the current candidate snippet of snippet
+** Retrieve information about the current candidate snippet of snippet
** iterator pIter.
*/
static void fts3SnippetDetails(
pPhrase->iTail = iFirst;
}else{
assert( rc!=SQLITE_OK || (
- pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0
+ pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0
));
}
}
/*
-** Select the fragment of text consisting of nFragment contiguous tokens
+** Select the fragment of text consisting of nFragment contiguous tokens
** from column iCol that represent the "best" snippet. The best snippet
** is the snippet with the highest score, where scores are calculated
** by adding:
**
** (a) +1 point for each occurrence of a matchable phrase in the snippet.
**
-** (b) +1000 points for the first occurrence of each matchable phrase in
+** (b) +1000 points for the first occurrence of each matchable phrase in
** the snippet for which the corresponding mCovered bit is not set.
**
** The selected snippet parameters are stored in structure *pFragment before
}
}
- /* Loop through all candidate snippets. Store the best snippet in
+ /* Loop through all candidate snippets. Store the best snippet in
** *pFragment. Store its associated 'score' in iBestScore.
*/
pFragment->iCol = iCol;
**
** ........X.....X
**
-** This function "shifts" the beginning of the snippet forward in the
-** document so that there are approximately the same number of
+** This function "shifts" the beginning of the snippet forward in the
+** document so that there are approximately the same number of
** non-highlighted terms to the right of the final highlighted term as there
** are to the left of the first highlighted term. For example, to this:
**
**
** This is done as part of extracting the snippet text, not when selecting
** the snippet. Snippet selection is done based on doclists only, so there
-** is no way for fts3BestSnippet() to know whether or not the document
-** actually contains terms that follow the final highlighted term.
+** is no way for fts3BestSnippet() to know whether or not the document
+** actually contains terms that follow the final highlighted term.
*/
static int fts3SnippetShift(
Fts3Table *pTab, /* FTS3 table snippet comes from */
int iCol = pFragment->iCol+1; /* Query column to extract text from */
sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */
sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */
-
+
zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol);
if( zDoc==0 ){
if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){
if( rc==SQLITE_DONE ){
/* Special case - the last token of the snippet is also the last token
** of the column. Append any punctuation that occurred between the end
- ** of the previous token and the end of the document to the output.
+ ** of the previous token and the end of the document to the output.
** Then break out of the loop. */
rc = fts3StringAppend(pOut, &zDoc[iEnd], -1);
}
/* Now that the shift has been done, check if the initial "..." are
** required. They are required if (a) this is not the first fragment,
- ** or (b) this fragment does not begin at position 0 of its column.
+ ** or (b) this fragment does not begin at position 0 of its column.
*/
if( rc==SQLITE_OK && (iPos>0 || iFragment>0) ){
rc = fts3StringAppend(pOut, zEllipsis, -1);
/*
-** This function is used to count the entries in a column-list (a
-** delta-encoded list of term offsets within a single column of a single
+** This function is used to count the entries in a column-list (a
+** delta-encoded list of term offsets within a single column of a single
** row). When this function is called, *ppCollist should point to the
** beginning of the first varint in the column-list (the varint that
** contains the position of the first matching term in the column data).
/*
** fts3ExprIterate() callback used to collect the "global" matchinfo stats
-** for a single query.
+** for a single query.
**
** fts3ExprIterate() callback to load the 'global' elements of a
-** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements
-** of the matchinfo array that are constant for all rows returned by the
+** FTS3_MATCHINFO_HITS matchinfo array. The global stats are those elements
+** of the matchinfo array that are constant for all rows returned by the
** current query.
**
** Argument pCtx is actually a pointer to a struct of type MatchInfo. This
** at least one instance of phrase iPhrase.
**
** If the phrase pExpr consists entirely of deferred tokens, then all X and
-** Y values are set to nDoc, where nDoc is the number of documents in the
+** Y values are set to nDoc, where nDoc is the number of documents in the
** file system. This is done because the full-text index doclist is required
** to calculate these values properly, and the full-text index doclist is
** not available for deferred tokens.
/*
** fts3ExprIterate() callback used to collect the "local" part of the
-** FTS3_MATCHINFO_HITS array. The local stats are those elements of the
+** FTS3_MATCHINFO_HITS array. The local stats are those elements of the
** array that are different for each row returned by the query.
*/
static int fts3ExprLocalHitsCb(
}
static int fts3MatchinfoCheck(
- Fts3Table *pTab,
+ Fts3Table *pTab,
char cArg,
char **pzErr
){
switch( cArg ){
case FTS3_MATCHINFO_NDOC:
- case FTS3_MATCHINFO_NPHRASE:
- case FTS3_MATCHINFO_NCOL:
+ case FTS3_MATCHINFO_NPHRASE:
+ case FTS3_MATCHINFO_NCOL:
nVal = 1;
break;
}
/*
-** An instance of the following structure is used to store state while
+** An instance of the following structure is used to store state while
** iterating through a multi-column position-list corresponding to the
** hits for a single phrase on a single row in order to calculate the
** values for a matchinfo() FTS3_MATCHINFO_LCS request.
int iPos; /* Current position */
};
-/*
+/*
** If LcsIterator.iCol is set to the following value, the iterator has
** finished iterating through all offsets for all columns.
*/
pIter->pRead = pRead;
return rc;
}
-
+
/*
-** This function implements the FTS3_MATCHINFO_LCS matchinfo() flag.
+** This function implements the FTS3_MATCHINFO_LCS matchinfo() flag.
**
** If the call is successful, the longest-common-substring lengths for each
-** column are written into the first nCol elements of the pInfo->aMatchinfo[]
+** column are written into the first nCol elements of the pInfo->aMatchinfo[]
** array before returning. SQLITE_OK is returned in this case.
**
** Otherwise, if an error occurs, an SQLite error code is returned and the
-** data written to the first nCol elements of pInfo->aMatchinfo[] is
+** data written to the first nCol elements of pInfo->aMatchinfo[] is
** undefined.
*/
static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
/*
** Populate the buffer pInfo->aMatchinfo[] with an array of integers to
-** be returned by the matchinfo() function. Argument zArg contains the
+** be returned by the matchinfo() function. Argument zArg contains the
** format string passed as the second argument to matchinfo (or the
** default value "pcx" if no second argument was specified). The format
** string has already been validated and the pInfo->aMatchinfo[] array
** rows (i.e. FTS3_MATCHINFO_NPHRASE, NCOL, NDOC, AVGLENGTH and part of HITS)
** have already been populated.
**
-** Return SQLITE_OK if successful, or an SQLite error code if an error
+** Return SQLITE_OK if successful, or an SQLite error code if an error
** occurs. If a value other than SQLITE_OK is returned, the state the
** pInfo->aMatchinfo[] buffer is left in is undefined.
*/
case FTS3_MATCHINFO_NCOL:
if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nCol;
break;
-
+
case FTS3_MATCHINFO_NDOC:
if( bGlobal ){
sqlite3_int64 nDoc = 0;
}
break;
- case FTS3_MATCHINFO_AVGLENGTH:
+ case FTS3_MATCHINFO_AVGLENGTH:
if( bGlobal ){
sqlite3_int64 nDoc; /* Number of rows in table */
const char *a; /* Aggregate column length array */
/*
-** Populate pCsr->aMatchinfo[] with data for the current row. The
+** Populate pCsr->aMatchinfo[] with data for the current row. The
** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32).
*/
static int fts3GetMatchinfo(
sInfo.pCursor = pCsr;
sInfo.nCol = pTab->nColumn;
- /* If there is cached matchinfo() data, but the format string for the
- ** cache does not match the format string for this request, discard
+ /* If there is cached matchinfo() data, but the format string for the
+ ** cache does not match the format string for this request, discard
** the cached data. */
if( pCsr->zMatchinfo && strcmp(pCsr->zMatchinfo, zArg) ){
assert( pCsr->aMatchinfo );
}
/* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the
- ** matchinfo function has been called for this query. In this case
+ ** matchinfo function has been called for this query. In this case
** allocate the array used to accumulate the matchinfo data and
** initialize those elements that are constant for every row.
*/
/* The returned text includes up to four fragments of text extracted from
** the data in the current row. The first iteration of the for(...) loop
- ** below attempts to locate a single fragment of text nToken tokens in
+ ** below attempts to locate a single fragment of text nToken tokens in
** size that contains at least one instance of all phrases in the query
** expression that appear in the current row. If such a fragment of text
** cannot be found, the second iteration of the loop attempts to locate
assert( nFToken>0 );
for(i=0; i<nSnippet && rc==SQLITE_OK; i++){
- rc = fts3SnippetText(pCsr, &aSnippet[i],
+ rc = fts3SnippetText(pCsr, &aSnippet[i],
i, (i==nSnippet-1), nFToken, zStart, zEnd, zEllipsis, &res
);
}
sCtx.iDocid = pCsr->iPrevId;
sCtx.pCsr = pCsr;
- /* Loop through the table columns, appending offset information to
+ /* Loop through the table columns, appending offset information to
** string-buffer res for each column.
*/
for(iCol=0; iCol<pTab->nColumn; iCol++){
const char *zDoc;
int nDoc;
- /* Initialize the contents of sCtx.aTerm[] for column iCol. There is
+ /* Initialize the contents of sCtx.aTerm[] for column iCol. There is
** no way that this operation can fail, so the return code from
** fts3ExprIterate() can be discarded.
*/
sCtx.iTerm = 0;
(void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void *)&sCtx);
- /* Retreive the text stored in column iCol. If an SQL NULL is stored
+ /* Retreive the text stored in column iCol. If an SQL NULL is stored
** in column iCol, jump immediately to the next iteration of the loop.
** If an OOM occurs while retrieving the data (this can happen if SQLite
- ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM
- ** to the caller.
+ ** needs to transform the data from utf-16 to utf-8), return SQLITE_NOMEM
+ ** to the caller.
*/
zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol+1);
nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
}
if( rc==SQLITE_OK ){
char aBuffer[64];
- sqlite3_snprintf(sizeof(aBuffer), aBuffer,
+ sqlite3_snprintf(sizeof(aBuffer), aBuffer,
"%d %d %d %d ", iCol, pTerm-sCtx.aTerm, iStart, iEnd-iStart
);
rc = fts3StringAppend(&res, aBuffer, -1);
**
** For each codepoint in the zIn/nIn string, this function checks if the
** sqlite3FtsUnicodeIsalnum() function already returns the desired result.
-** If so, no action is taken. Otherwise, the codepoint is added to the
+** If so, no action is taken. Otherwise, the codepoint is added to the
** unicode_tokenizer.aiException[] array. For the purposes of tokenization,
** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all
** codepoints in the aiException[] array.
while( z<zTerm ){
READ_UTF8(z, zTerm, iCode);
assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
- if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
- && sqlite3FtsUnicodeIsdiacritic(iCode)==0
+ if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
+ && sqlite3FtsUnicodeIsdiacritic(iCode)==0
){
nEntry++;
}
z = (const unsigned char *)zIn;
while( z<zTerm ){
READ_UTF8(z, zTerm, iCode);
- if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
+ if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
){
int i, j;
/*
** Prepare to begin tokenizing a particular string. The input
** string to be tokenized is pInput[0..nBytes-1]. A cursor
-** used to incrementally tokenize this string is returned in
+** used to incrementally tokenize this string is returned in
** *ppCursor.
*/
static int unicodeOpen(
const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput];
/* Scan past any delimiter characters before the start of the next token.
- ** Return SQLITE_DONE early if this takes us all the way to the end of
+ ** Return SQLITE_DONE early if this takes us all the way to the end of
** the input. */
while( z<zTerm ){
READ_UTF8(z, zTerm, iCode);
/* If the cursor is not at EOF, read the next character */
if( z>=zTerm ) break;
READ_UTF8(z, zTerm, iCode);
- }while( unicodeIsAlnum(p, iCode)
+ }while( unicodeIsAlnum(p, iCode)
|| sqlite3FtsUnicodeIsdiacritic(iCode)
);
}
/*
-** Set *ppModule to a pointer to the sqlite3_tokenizer_module
+** Set *ppModule to a pointer to the sqlite3_tokenizer_module
** structure for the unicode tokenizer.
*/
SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const **ppModule){
** range of unicode codepoints that are not either letters or numbers (i.e.
** codepoints for which this function should return 0).
**
- ** The most significant 22 bits in each 32-bit value contain the first
+ ** The most significant 22 bits in each 32-bit value contain the first
** codepoint in the range. The least significant 10 bits are used to store
- ** the size of the range (always at least 1). In other words, the value
- ** ((C<<22) + N) represents a range of N codepoints starting with codepoint
- ** C. It is not possible to represent a range larger than 1023 codepoints
+ ** the size of the range (always at least 1). In other words, the value
+ ** ((C<<22) + N) represents a range of N codepoints starting with codepoint
+ ** C. It is not possible to represent a range larger than 1023 codepoints
** using this format.
*/
const static unsigned int aEntry[] = {
*/
static int remove_diacritic(int c){
unsigned short aDia[] = {
- 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
- 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
- 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
- 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
- 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
- 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
- 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
- 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
- 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
- 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
- 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
- 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
- 62924, 63050, 63082, 63274, 63390,
+ 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
+ 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
+ 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
+ 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
+ 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
+ 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
+ 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
+ 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
+ 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
+ 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
+ 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
+ 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
+ 62924, 63050, 63082, 63274, 63390,
};
char aChar[] = {
- '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
- 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
- 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
- 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
- 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
- '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
- 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
- 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
- 'e', 'i', 'o', 'u', 'y',
+ '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
+ 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
+ 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
+ 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
+ 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
+ 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
+ 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
+ 'e', 'i', 'o', 'u', 'y',
};
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
{42802, 1, 62}, {42873, 1, 4}, {42877, 76, 1},
{42878, 1, 10}, {42891, 0, 1}, {42893, 74, 1},
{42896, 1, 4}, {42912, 1, 10}, {42922, 72, 1},
- {65313, 14, 26},
+ {65313, 14, 26},
};
static const unsigned short aiOff[] = {
- 1, 2, 8, 15, 16, 26, 28, 32,
- 37, 38, 40, 48, 63, 64, 69, 71,
- 79, 80, 116, 202, 203, 205, 206, 207,
- 209, 210, 211, 213, 214, 217, 218, 219,
- 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721,
- 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274,
- 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406,
- 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462,
- 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511,
- 65514, 65521, 65527, 65528, 65529,
+ 1, 2, 8, 15, 16, 26, 28, 32,
+ 37, 38, 40, 48, 63, 64, 69, 71,
+ 79, 80, 116, 202, 203, 205, 206, 207,
+ 209, 210, 211, 213, 214, 217, 218, 219,
+ 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721,
+ 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274,
+ 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406,
+ 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462,
+ 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511,
+ 65514, 65521, 65527, 65528, 65529,
};
int ret = c;
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
}
-
+
else if( c>=66560 && c<66600 ){
ret = c + 40;
}
** Database Format of R-Tree Tables
** --------------------------------
**
-** The data structure for a single virtual r-tree table is stored in three
+** The data structure for a single virtual r-tree table is stored in three
** native SQLite tables declared as follows. In each case, the '%' character
** in the table name is replaced with the user-supplied name of the r-tree
** table.
** of the node contain the tree depth as a big-endian integer.
** For non-root nodes, the first 2 bytes are left unused.
**
-** 2. The next 2 bytes contain the number of entries currently
+** 2. The next 2 bytes contain the number of entries currently
** stored in the node.
**
** 3. The remainder of the node contains the node entries. Each entry
/*
** This file contains an implementation of a couple of different variants
-** of the r-tree algorithm. See the README file for further details. The
+** of the r-tree algorithm. See the README file for further details. The
** same data-structure is used for all, but the algorithms for insert and
-** delete operations vary. The variants used are selected at compile time
+** delete operations vary. The variants used are selected at compile time
** by defining the following symbols:
*/
-/* Either, both or none of the following may be set to activate
+/* Either, both or none of the following may be set to activate
** r*tree variant algorithms.
*/
#define VARIANT_RSTARTREE_CHOOSESUBTREE 0
#define VARIANT_RSTARTREE_REINSERT 1
-/*
+/*
** Exactly one of the following must be set to 1.
*/
#define VARIANT_GUTTMAN_QUADRATIC_SPLIT 0
#define AssignCells splitNodeStartree
#endif
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
#define RTREE_MAX_DIMENSIONS 5
/* Size of hash table Rtree.aHash. This hash table is not expected to
-** ever contain very many entries, so a fixed number of buckets is
+** ever contain very many entries, so a fixed number of buckets is
** used.
*/
#define HASHSIZE 128
-/*
+/*
** An rtree virtual-table object.
*/
struct Rtree {
int nBytesPerCell; /* Bytes consumed per cell */
int iDepth; /* Current depth of the r-tree structure */
char *zDb; /* Name of database containing r-tree table */
- char *zName; /* Name of r-tree table */
- RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
+ char *zName; /* Name of r-tree table */
+ RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
int nBusy; /* Current number of users of this structure */
/* List of nodes removed during a CondenseTree operation. List is
** linked together via the pointer normally used for hash chains -
- ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree
+ ** RtreeNode.pNext. RtreeNode.iNode stores the depth of the sub-tree
** headed by the node (leaf nodes have RtreeNode.iNode==0).
*/
RtreeNode *pDeleted;
#endif
/*
-** The minimum number of cells allowed for a node is a third of the
+** The minimum number of cells allowed for a node is a third of the
** maximum. In Gutman's notation:
**
** m = M/3
/*
** The smallest possible node-size is (512-64)==448 bytes. And the largest
** supported cell size is 48 bytes (8 byte rowid + ten 4 byte coordinates).
-** Therefore all non-root nodes must contain at least 3 entries. Since
+** Therefore all non-root nodes must contain at least 3 entries. Since
** 2^40 is greater than 2^64, an r-tree structure always has a depth of
** 40 or less.
*/
#define RTREE_MAX_DEPTH 40
-/*
+/*
** An rtree cursor object.
*/
struct RtreeCursor {
#define RTREE_GT 0x45
#define RTREE_MATCH 0x46
-/*
+/*
** An rtree structure node.
*/
struct RtreeNode {
};
#define NCELL(pNode) readInt16(&(pNode)->zData[2])
-/*
+/*
** Structure to store a deserialized rtree record.
*/
struct RtreeCell {
}
static void readCoord(u8 *p, RtreeCoord *pCoord){
u32 i = (
- (((u32)p[0]) << 24) +
- (((u32)p[1]) << 16) +
- (((u32)p[2]) << 8) +
+ (((u32)p[0]) << 24) +
+ (((u32)p[1]) << 16) +
+ (((u32)p[2]) << 8) +
(((u32)p[3]) << 0)
);
*(u32 *)pCoord = i;
}
static i64 readInt64(u8 *p){
return (
- (((i64)p[0]) << 56) +
- (((i64)p[1]) << 48) +
- (((i64)p[2]) << 40) +
- (((i64)p[3]) << 32) +
- (((i64)p[4]) << 24) +
- (((i64)p[5]) << 16) +
- (((i64)p[6]) << 8) +
+ (((i64)p[0]) << 56) +
+ (((i64)p[1]) << 48) +
+ (((i64)p[2]) << 40) +
+ (((i64)p[3]) << 32) +
+ (((i64)p[4]) << 24) +
+ (((i64)p[5]) << 16) +
+ (((i64)p[6]) << 8) +
(((i64)p[7]) << 0)
);
}
*/
static int nodeHash(i64 iNode){
return (
- (iNode>>56) ^ (iNode>>48) ^ (iNode>>40) ^ (iNode>>32) ^
+ (iNode>>56) ^ (iNode>>48) ^ (iNode>>40) ^ (iNode>>32) ^
(iNode>>24) ^ (iNode>>16) ^ (iNode>> 8) ^ (iNode>> 0)
) % HASHSIZE;
}
}
/* If no error has occurred so far, check if the "number of entries"
- ** field on the node is too large. If so, set the return code to
+ ** field on the node is too large. If so, set the return code to
** SQLITE_CORRUPT_VTAB.
*/
if( pNode && rc==SQLITE_OK ){
** Overwrite cell iCell of node pNode with the contents of pCell.
*/
static void nodeOverwriteCell(
- Rtree *pRtree,
- RtreeNode *pNode,
- RtreeCell *pCell,
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ RtreeCell *pCell,
int iCell
){
int ii;
*/
static int
nodeInsertCell(
- Rtree *pRtree,
- RtreeNode *pNode,
- RtreeCell *pCell
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ RtreeCell *pCell
){
int nCell; /* Current number of cells in pNode */
int nMaxCell; /* Maximum number of cells for pNode */
** an internal node, then the 64-bit integer is a child page number.
*/
static i64 nodeGetRowid(
- Rtree *pRtree,
- RtreeNode *pNode,
+ Rtree *pRtree,
+ RtreeNode *pNode,
int iCell
){
assert( iCell<NCELL(pNode) );
** Return coordinate iCoord from cell iCell in node pNode.
*/
static void nodeGetCoord(
- Rtree *pRtree,
- RtreeNode *pNode,
+ Rtree *pRtree,
+ RtreeNode *pNode,
int iCell,
int iCoord,
RtreeCoord *pCoord /* Space to write result to */
** to by pCell with the results.
*/
static void nodeGetCell(
- Rtree *pRtree,
- RtreeNode *pNode,
+ Rtree *pRtree,
+ RtreeNode *pNode,
int iCell,
RtreeCell *pCell
){
sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int
);
-/*
+/*
** Rtree virtual table module xCreate method.
*/
static int rtreeCreate(
return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1);
}
-/*
+/*
** Rtree virtual table module xConnect method.
*/
static int rtreeConnect(
}
}
-/*
+/*
** Rtree virtual table module xDisconnect method.
*/
static int rtreeDisconnect(sqlite3_vtab *pVtab){
return SQLITE_OK;
}
-/*
+/*
** Rtree virtual table module xDestroy method.
*/
static int rtreeDestroy(sqlite3_vtab *pVtab){
"DROP TABLE '%q'.'%q_node';"
"DROP TABLE '%q'.'%q_rowid';"
"DROP TABLE '%q'.'%q_parent';",
- pRtree->zDb, pRtree->zName,
+ pRtree->zDb, pRtree->zName,
pRtree->zDb, pRtree->zName,
pRtree->zDb, pRtree->zName
);
return rc;
}
-/*
+/*
** Rtree virtual table module xOpen method.
*/
static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
}
}
-/*
+/*
** Rtree virtual table module xClose method.
*/
static int rtreeClose(sqlite3_vtab_cursor *cur){
/*
** Rtree virtual table module xEof method.
**
-** Return non-zero if the cursor does not currently point to a valid
+** Return non-zero if the cursor does not currently point to a valid
** record (i.e if the scan has finished), or zero otherwise.
*/
static int rtreeEof(sqlite3_vtab_cursor *cur){
return pConstraint->xGeom(pConstraint->pGeom, nCoord, aCoord, pbRes);
}
-/*
+/*
** Cursor pCursor currently points to a cell in a non-leaf page.
** Set *pbEof to true if the sub-tree headed by the cell is filtered
-** (excluded) by the constraints in the pCursor->aConstraint[]
+** (excluded) by the constraints in the pCursor->aConstraint[]
** array, or false otherwise.
**
** Return SQLITE_OK if successful or an SQLite error code if an error
RtreeDValue cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]);
RtreeDValue cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]);
- assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
+ assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|| p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH
);
switch( p->op ){
- case RTREE_LE: case RTREE_LT:
- bRes = p->rValue<cell_min;
+ case RTREE_LE: case RTREE_LT:
+ bRes = p->rValue<cell_min;
break;
- case RTREE_GE: case RTREE_GT:
- bRes = p->rValue>cell_max;
+ case RTREE_GE: case RTREE_GT:
+ bRes = p->rValue>cell_max;
break;
case RTREE_EQ:
return rc;
}
-/*
+/*
** Test if the cell that cursor pCursor currently points to
-** would be filtered (excluded) by the constraints in the
+** would be filtered (excluded) by the constraints in the
** pCursor->aConstraint[] array. If so, set *pbEof to true before
** returning. If the cell is not filtered (excluded) by the constraints,
** set pbEof to zero.
RtreeConstraint *p = &pCursor->aConstraint[ii];
RtreeDValue coord = DCOORD(cell.aCoord[p->iCoord]);
int res;
- assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
+ assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|| p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH
);
switch( p->op ){
/*
** Cursor pCursor currently points at a node that heads a sub-tree of
** height iHeight (if iHeight==0, then the node is a leaf). Descend
-** to point to the left-most cell of the sub-tree that matches the
+** to point to the left-most cell of the sub-tree that matches the
** configured constraints.
*/
static int descendToCell(
- Rtree *pRtree,
- RtreeCursor *pCursor,
+ Rtree *pRtree,
+ RtreeCursor *pCursor,
int iHeight,
int *pEof /* OUT: Set to true if cannot descend */
){
}
/*
-** One of the cells in node pNode is guaranteed to have a 64-bit
+** One of the cells in node pNode is guaranteed to have a 64-bit
** integer value equal to iRowid. Return the index of this cell.
*/
static int nodeRowidIndex(
- Rtree *pRtree,
- RtreeNode *pNode,
+ Rtree *pRtree,
+ RtreeNode *pNode,
i64 iRowid,
int *piIndex
){
return SQLITE_OK;
}
-/*
+/*
** Rtree virtual table module xNext method.
*/
static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
return rc;
}
-/*
+/*
** Rtree virtual table module xRowid method.
*/
static int rtreeRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
return SQLITE_OK;
}
-/*
+/*
** Rtree virtual table module xColumn method.
*/
static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
return SQLITE_OK;
}
-/*
-** Use nodeAcquire() to obtain the leaf node containing the record with
+/*
+** Use nodeAcquire() to obtain the leaf node containing the record with
** rowid iRowid. If successful, set *ppLeaf to point to the node and
** return SQLITE_OK. If there is no such record in the table, set
** *ppLeaf to 0 and return SQLITE_OK. If an error occurs, set *ppLeaf
/* Check that the blob is roughly the right size. */
nBlob = sqlite3_value_bytes(pValue);
- if( nBlob<(int)sizeof(RtreeMatchArg)
+ if( nBlob<(int)sizeof(RtreeMatchArg)
|| ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0
){
return SQLITE_ERROR;
p = (RtreeMatchArg *)&pGeom[1];
memcpy(p, sqlite3_value_blob(pValue), nBlob);
- if( p->magic!=RTREE_GEOMETRY_MAGIC
+ if( p->magic!=RTREE_GEOMETRY_MAGIC
|| nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(RtreeDValue))
){
sqlite3_free(pGeom);
return SQLITE_OK;
}
-/*
+/*
** Rtree virtual table module xFilter method.
*/
static int rtreeFilter(
- sqlite3_vtab_cursor *pVtabCursor,
+ sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
RtreeNode *pLeaf; /* Leaf on which the required cell resides */
i64 iRowid = sqlite3_value_int64(argv[0]);
rc = findLeafNode(pRtree, iRowid, &pLeaf);
- pCsr->pNode = pLeaf;
+ pCsr->pNode = pLeaf;
if( pLeaf ){
assert( rc==SQLITE_OK );
rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &pCsr->iCell);
}
}else{
- /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array
- ** with the configured constraints.
+ /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array
+ ** with the configured constraints.
*/
if( argc>0 ){
pCsr->aConstraint = sqlite3_malloc(sizeof(RtreeConstraint)*argc);
}
}
}
-
+
if( rc==SQLITE_OK ){
pCsr->pNode = 0;
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
/*
** Rtree virtual table module xBestIndex method. There are three
-** table scan strategies to choose from (in order from most to
+** table scan strategies to choose from (in order from most to
** least desirable):
**
** idxNum idxStr Strategy
** ------------------------------------------------
**
** If strategy 1 is used, then idxStr is not meaningful. If strategy
-** 2 is used, idxStr is formatted to contain 2 bytes for each
-** constraint used. The first two bytes of idxStr correspond to
+** 2 is used, idxStr is formatted to contain 2 bytes for each
+** constraint used. The first two bytes of idxStr correspond to
** the constraint in sqlite3_index_info.aConstraintUsage[] with
** (argvIndex==1) etc.
**
pIdxInfo->aConstraintUsage[jj].omit = 1;
/* This strategy involves a two rowid lookups on an B-Tree structures
- ** and then a linear search of an R-Tree node. This should be
- ** considered almost as quick as a direct rowid lookup (for which
+ ** and then a linear search of an R-Tree node. This should be
+ ** considered almost as quick as a direct rowid lookup (for which
** sqlite uses an internal cost of 0.0).
- */
+ */
pIdxInfo->estimatedCost = 10.0;
return SQLITE_OK;
}
case SQLITE_INDEX_CONSTRAINT_GE: op = RTREE_GE; break;
default:
assert( p->op==SQLITE_INDEX_CONSTRAINT_MATCH );
- op = RTREE_MATCH;
+ op = RTREE_MATCH;
break;
}
zIdxStr[iIdx++] = op;
for(ii=0; ii<(pRtree->nDim*2); ii+=2){
RtreeCoord *a1 = &p1->aCoord[ii];
RtreeCoord *a2 = &p2->aCoord[ii];
- if( (!isInt && (a2[0].f<a1[0].f || a2[1].f>a1[1].f))
- || ( isInt && (a2[0].i<a1[0].i || a2[1].i>a1[1].i))
+ if( (!isInt && (a2[0].f<a1[0].f || a2[1].f>a1[1].f))
+ || ( isInt && (a2[0].i<a1[0].i || a2[1].i>a1[1].i))
){
return 0;
}
#if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT
static RtreeDValue cellOverlap(
- Rtree *pRtree,
- RtreeCell *p,
- RtreeCell *aCell,
- int nCell,
+ Rtree *pRtree,
+ RtreeCell *p,
+ RtreeCell *aCell,
+ int nCell,
int iExclude
){
int ii;
#if VARIANT_RSTARTREE_CHOOSESUBTREE
static RtreeDValue cellOverlapEnlargement(
- Rtree *pRtree,
- RtreeCell *p,
- RtreeCell *pInsert,
- RtreeCell *aCell,
- int nCell,
+ Rtree *pRtree,
+ RtreeCell *p,
+ RtreeCell *pInsert,
+ RtreeCell *aCell,
+ int nCell,
int iExclude
){
RtreeDValue before, after;
}else{
overlap = 0.0;
}
- if( (iCell==0)
- || (overlap<fMinOverlap)
+ if( (iCell==0)
+ || (overlap<fMinOverlap)
|| (overlap==fMinOverlap && growth<fMinGrowth)
|| (overlap==fMinOverlap && growth==fMinGrowth && area<fMinArea)
){
cellUnion(pRtree, &cell, pCell);
nodeOverwriteCell(pRtree, pParent, &cell, iCell);
}
-
+
p = pParent;
}
return SQLITE_OK;
*/
static RtreeCell *LinearPickNext(
Rtree *pRtree,
- RtreeCell *aCell,
- int nCell,
- RtreeCell *pLeftBox,
+ RtreeCell *aCell,
+ int nCell,
+ RtreeCell *pLeftBox,
RtreeCell *pRightBox,
int *aiUsed
){
*/
static void LinearPickSeeds(
Rtree *pRtree,
- RtreeCell *aCell,
- int nCell,
- int *piLeftSeed,
+ RtreeCell *aCell,
+ int nCell,
+ int *piLeftSeed,
int *piRightSeed
){
int i;
RtreeDValue maxNormalInnerWidth = (RtreeDValue)0;
/* Pick two "seed" cells from the array of cells. The algorithm used
- ** here is the LinearPickSeeds algorithm from Gutman[1984]. The
+ ** here is the LinearPickSeeds algorithm from Gutman[1984]. The
** indices of the two seed cells in the array are stored in local
** variables iLeftSeek and iRightSeed.
*/
*/
static RtreeCell *QuadraticPickNext(
Rtree *pRtree,
- RtreeCell *aCell,
- int nCell,
- RtreeCell *pLeftBox,
+ RtreeCell *aCell,
+ int nCell,
+ RtreeCell *pLeftBox,
RtreeCell *pRightBox,
int *aiUsed
){
*/
static void QuadraticPickSeeds(
Rtree *pRtree,
- RtreeCell *aCell,
- int nCell,
- int *piLeftSeed,
+ RtreeCell *aCell,
+ int nCell,
+ int *piLeftSeed,
int *piRightSeed
){
int ii;
/*
** Arguments aIdx, aDistance and aSpare all point to arrays of size
-** nIdx. The aIdx array contains the set of integers from 0 to
+** nIdx. The aIdx array contains the set of integers from 0 to
** (nIdx-1) in no particular order. This function sorts the values
** in aIdx according to the indexed values in aDistance. For
** example, assuming the inputs:
** sorting algorithm.
*/
static void SortByDistance(
- int *aIdx,
- int nIdx,
- RtreeDValue *aDistance,
+ int *aIdx,
+ int nIdx,
+ RtreeDValue *aDistance,
int *aSpare
){
if( nIdx>1 ){
/*
** Arguments aIdx, aCell and aSpare all point to arrays of size
-** nIdx. The aIdx array contains the set of integers from 0 to
+** nIdx. The aIdx array contains the set of integers from 0 to
** (nIdx-1) in no particular order. This function sorts the values
** in aIdx according to dimension iDim of the cells in aCell. The
** minimum value of dimension iDim is considered first, the
*/
static void SortByDimension(
Rtree *pRtree,
- int *aIdx,
- int nIdx,
- int iDim,
- RtreeCell *aCell,
+ int *aIdx,
+ int nIdx,
+ int iDim,
+ RtreeCell *aCell,
int *aSpare
){
if( nIdx>1 ){
int nLeft;
for(
- nLeft=RTREE_MINCELLS(pRtree);
- nLeft<=(nCell-RTREE_MINCELLS(pRtree));
+ nLeft=RTREE_MINCELLS(pRtree);
+ nLeft<=(nCell-RTREE_MINCELLS(pRtree));
nLeft++
){
RtreeCell left;
for(i=nCell-2; i>0; i--){
RtreeCell *pNext;
pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed);
- RtreeDValue diff =
- cellGrowth(pRtree, pBboxLeft, pNext) -
+ RtreeDValue diff =
+ cellGrowth(pRtree, pBboxLeft, pNext) -
cellGrowth(pRtree, pBboxRight, pNext)
;
if( (RTREE_MINCELLS(pRtree)-NCELL(pRight)==i)
#endif
static int updateMapping(
- Rtree *pRtree,
- i64 iRowid,
- RtreeNode *pNode,
+ Rtree *pRtree,
+ i64 iRowid,
+ RtreeNode *pNode,
int iHeight
){
int (*xSetMapping)(Rtree *, sqlite3_int64, sqlite3_int64);
RtreeCell leftbbox;
RtreeCell rightbbox;
- /* Allocate an array and populate it with a copy of pCell and
+ /* Allocate an array and populate it with a copy of pCell and
** all cells from node pLeft. Then zero the original node.
*/
aCell = sqlite3_malloc((sizeof(RtreeCell)+sizeof(int))*(nCell+1));
}
/*
-** If node pLeaf is not the root of the r-tree and its pParent pointer is
+** If node pLeaf is not the root of the r-tree and its pParent pointer is
** still NULL, load all ancestor nodes of pLeaf into memory and populate
** the pLeaf->pParent chain all the way up to the root node.
**
** This operation is required when a row is deleted (or updated - an update
** is implemented as a delete followed by an insert). SQLite provides the
** rowid of the row to delete, which can be used to find the leaf on which
-** the entry resides (argument pLeaf). Once the leaf is located, this
+** the entry resides (argument pLeaf). Once the leaf is located, this
** function is called to determine its ancestry.
*/
static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
if( SQLITE_OK!=(rc = sqlite3_reset(pRtree->pDeleteParent)) ){
return rc;
}
-
+
/* Remove the node from the in-memory hash table and link it into
** the Rtree.pDeleted list. Its contents will be re-inserted later on.
*/
static int fixBoundingBox(Rtree *pRtree, RtreeNode *pNode){
RtreeNode *pParent = pNode->pParent;
- int rc = SQLITE_OK;
+ int rc = SQLITE_OK;
if( pParent ){
- int ii;
+ int ii;
int nCell = NCELL(pNode);
RtreeCell box; /* Bounding box for pNode */
nodeGetCell(pRtree, pNode, 0, &box);
}
static int Reinsert(
- Rtree *pRtree,
- RtreeNode *pNode,
- RtreeCell *pCell,
+ Rtree *pRtree,
+ RtreeNode *pNode,
+ RtreeCell *pCell,
int iHeight
){
int *aOrder;
for(ii=0; ii<nCell; ii++){
aDistance[ii] = 0.0;
for(iDim=0; iDim<pRtree->nDim; iDim++){
- RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) -
+ RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) -
DCOORD(aCell[ii].aCoord[iDim*2]));
aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]);
}
}
/*
-** Insert cell pCell into node pNode. Node pNode is the head of a
+** Insert cell pCell into node pNode. Node pNode is the head of a
** subtree iHeight high (leaf nodes have iHeight==0).
*/
static int rtreeInsertCell(
/* Obtain a reference to the root node to initialize Rtree.iDepth */
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
- /* Obtain a reference to the leaf node that contains the entry
- ** about to be deleted.
+ /* Obtain a reference to the leaf node that contains the entry
+ ** about to be deleted.
*/
if( rc==SQLITE_OK ){
rc = findLeafNode(pRtree, iDelete, &pLeaf);
}
/* Check if the root node now has exactly one child. If so, remove
- ** it, schedule the contents of the child for reinsertion and
+ ** it, schedule the contents of the child for reinsertion and
** reduce the tree height by one.
**
** This is equivalent to copying the contents of the child into
- ** the root node (the operation that Gutman's paper says to perform
+ ** the root node (the operation that Gutman's paper says to perform
** in this scenario).
*/
if( rc==SQLITE_OK && pRtree->iDepth>0 && NCELL(pRoot)==1 ){
** The xUpdate method for rtree module virtual tables.
*/
static int rtreeUpdate(
- sqlite3_vtab *pVtab,
- int nData,
- sqlite3_value **azData,
+ sqlite3_vtab *pVtab,
+ int nData,
+ sqlite3_value **azData,
sqlite_int64 *pRowid
){
Rtree *pRtree = (Rtree *)pVtab;
}
}
- /* If a rowid value was supplied, check if it is already present in
+ /* If a rowid value was supplied, check if it is already present in
** the table. If so, the constraint has failed. */
if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){
cell.iRowid = sqlite3_value_int64(azData[2]);
"ALTER TABLE %Q.'%q_node' RENAME TO \"%w_node\";"
"ALTER TABLE %Q.'%q_parent' RENAME TO \"%w_parent\";"
"ALTER TABLE %Q.'%q_rowid' RENAME TO \"%w_rowid\";"
- , pRtree->zDb, pRtree->zName, zNewName
- , pRtree->zDb, pRtree->zName, zNewName
+ , pRtree->zDb, pRtree->zName, zNewName
+ , pRtree->zDb, pRtree->zName, zNewName
, pRtree->zDb, pRtree->zName, zNewName
);
if( zSql ){
};
static int rtreeSqlInit(
- Rtree *pRtree,
- sqlite3 *db,
- const char *zDb,
- const char *zPrefix,
+ Rtree *pRtree,
+ sqlite3 *db,
+ const char *zDb,
+ const char *zPrefix,
int isCreate
){
int rc = SQLITE_OK;
for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){
char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix);
if( zSql ){
- rc = sqlite3_prepare_v2(db, zSql, -1, appStmt[i], 0);
+ rc = sqlite3_prepare_v2(db, zSql, -1, appStmt[i], 0);
}else{
rc = SQLITE_NOMEM;
}
** table already exists. In this case the node-size is determined by inspecting
** the root node of the tree.
**
-** Otherwise, for an xCreate(), use 64 bytes less than the database page-size.
-** This ensures that each node is stored on a single database page. If the
-** database page-size is so large that more than RTREE_MAXCELLS entries
+** Otherwise, for an xCreate(), use 64 bytes less than the database page-size.
+** This ensures that each node is stored on a single database page. If the
+** database page-size is so large that more than RTREE_MAXCELLS entries
** would fit in a single node, use a smaller node-size.
*/
static int getNodeSize(
return rc;
}
-/*
+/*
** This function is the implementation of both the xConnect and xCreate
** methods of the r-tree virtual table.
**
**
** The human readable string takes the form of a Tcl list with one
** entry for each cell in the r-tree node. Each entry is itself a
-** list, containing the 8-byte rowid/pageno followed by the
+** list, containing the 8-byte rowid/pageno followed by the
** <num-dimension>*2 coordinates.
*/
static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
zText = sqlite3_mprintf("{%s}", zCell);
}
}
-
+
sqlite3_result_text(ctx, zText, -1, sqlite3_free);
}
static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
UNUSED_PARAMETER(nArg);
- if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
+ if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB
|| sqlite3_value_bytes(apArg[0])<2
){
- sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
+ sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
}else{
u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
sqlite3_result_int(ctx, readInt16(zBlob));
/*
** Register the r-tree module with database handle db. This creates the
-** virtual table module "rtree" and the debugging/analysis scalar
+** virtual table module "rtree" and the debugging/analysis scalar
** function "rtreenode".
*/
SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db){
/* Create the new user-function. Register a destructor function to delete
** the context object when it is no longer required. */
- return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY,
+ return sqlite3_create_function_v2(db, zGeom, -1, SQLITE_ANY,
(void *)pGeomCtx, geomCallback, 0, 0, doSqlite3Free
);
}
*************************************************************************
** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $
**
-** This file implements an integration between the ICU library
-** ("International Components for Unicode", an open-source library
-** for handling unicode data) and SQLite. The integration uses
+** This file implements an integration between the ICU library
+** ("International Components for Unicode", an open-source library
+** for handling unicode data) and SQLite. The integration uses
** ICU to provide the following to SQLite:
**
** * An implementation of the SQL regexp() function (and hence REGEXP
**
** * Integration of ICU and SQLite collation seqences.
**
-** * An implementation of the LIKE operator that uses ICU to
+** * An implementation of the LIKE operator that uses ICU to
** provide case-independent matching.
*/
/*
** Compare two UTF-8 strings for equality where the first string is
-** a "LIKE" expression. Return true (1) if they are the same and
+** a "LIKE" expression. Return true (1) if they are the same and
** false (0) if they are different.
*/
static int icuLikeCompare(
uint8_t c;
/* Skip any MATCH_ALL or MATCH_ONE characters that follow a
- ** MATCH_ALL. For each MATCH_ONE, skip one character in the
+ ** MATCH_ALL. For each MATCH_ONE, skip one character in the
** test string.
*/
while( (c=zPattern[iPattern]) == MATCH_ALL || c == MATCH_ONE ){
**
** A LIKE B
**
-** is implemented as like(B, A). If there is an escape character E,
+** is implemented as like(B, A). If there is an escape character E,
**
** A LIKE B ESCAPE E
**
** is mapped to like(B, A, E).
*/
static void icuLikeFunc(
- sqlite3_context *context,
- int argc,
+ sqlite3_context *context,
+ int argc,
sqlite3_value **argv
){
const unsigned char *zA = sqlite3_value_text(argv[0]);
if( zE==0 ) return;
U8_NEXT(zE, i, nE, uEsc);
if( i!=nE){
- sqlite3_result_error(context,
+ sqlite3_result_error(context,
"ESCAPE expression must be a single character", -1);
return;
}
** This function is called when an ICU function called from within
** the implementation of an SQL scalar function returns an error.
**
-** The scalar function context passed as the first argument is
+** The scalar function context passed as the first argument is
** loaded with an error message based on the following two args.
*/
static void icuFunctionError(
/*
** Implementation of SQLite REGEXP operator. This scalar function takes
** two arguments. The first is a regular expression pattern to compile
-** the second is a string to match against that pattern. If either
+** the second is a string to match against that pattern. If either
** argument is an SQL NULL, then NULL Is returned. Otherwise, the result
** is 1 if the string matches the pattern, or 0 otherwise.
**
(void)nArg; /* Unused parameter */
- /* If the left hand side of the regexp operator is NULL,
- ** then the result is also NULL.
+ /* If the left hand side of the regexp operator is NULL,
+ ** then the result is also NULL.
*/
if( !zString ){
return;
}
/* Set the text that the regular expression operates on to a NULL
- ** pointer. This is not really necessary, but it is tidier than
+ ** pointer. This is not really necessary, but it is tidier than
** leaving the regular expression object configured with an invalid
** pointer after this function returns.
*/
}
/*
-** Implementations of scalar functions for case mapping - upper() and
+** Implementations of scalar functions for case mapping - upper() and
** lower(). Function upper() converts its input to upper-case (ABC).
** Function lower() converts to lower-case (abc).
**
** "language specific". Refer to ICU documentation for the differences
** between the two.
**
-** To utilise "general" case mapping, the upper() or lower() scalar
+** To utilise "general" case mapping, the upper() or lower() scalar
** functions are invoked with one argument:
**
** upper('ABC') -> 'abc'
/*
** Implementation of the scalar function icu_load_collation().
**
-** This scalar function is used to add ICU collation based collation
+** This scalar function is used to add ICU collation based collation
** types to an SQLite database connection. It is intended to be called
** as follows:
**
** collation sequence to create.
*/
static void icuLoadCollation(
- sqlite3_context *p,
- int nArg,
+ sqlite3_context *p,
+ int nArg,
sqlite3_value **apArg
){
sqlite3 *db = (sqlite3 *)sqlite3_user_data(p);
}
assert(p);
- rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
+ rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
icuCollationColl, icuCollationDel
);
if( rc!=SQLITE_OK ){
#if !SQLITE_CORE
SQLITE_API int sqlite3_extension_init(
- sqlite3 *db,
+ sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
/*
** Prepare to begin tokenizing a particular string. The input
** string to be tokenized is pInput[0..nBytes-1]. A cursor
-** used to incrementally tokenize this string is returned in
+** used to incrementally tokenize this string is returned in
** *ppCursor.
*/
static int icuOpen(
pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3];
pCsr->aOffset[iOut] = iInput;
- U8_NEXT(zInput, iInput, nInput, c);
+ U8_NEXT(zInput, iInput, nInput, c);
while( c>0 ){
int isError = 0;
c = u_foldCase(c, opt);
env->GetMethodID(g_ClassQueryEngineEvent, "onQueryEngineEvent",
"(ILorg/iotivity/service/ssm/DataReader;)V");
- jmethodID cid_DataReader = env->GetMethodID(g_ClassDataReader, "<init>", "(I)V");
+ jmethodID cid_DataReader = env->GetMethodID(g_ClassDataReader, "<init>", "(J)V");
if (cid_DataReader == NULL)
return SSM_E_FAIL;
- env->CallVoidMethod(m_objQueryEngineEvent, midQueryEngineEvent,
+ env->CallVoidMethod(m_objQueryEngineEvent,
+ midQueryEngineEvent,
(jint)cqid,
- env->NewObject(g_ClassDataReader, cid_DataReader, (jint)pResult));
+ env->NewObject(
+ g_ClassDataReader,
+ cid_DataReader,
+ reinterpret_cast<jlong>(pResult)));
DETACH_CURRENT_THREAD(g_JVM);
return NULL;
}
- jmethodID cid_QueryEngine = env->GetMethodID(g_ClassQueryEngine, "<init>", "(I)V");
+ jmethodID cid_QueryEngine = env->GetMethodID(g_ClassQueryEngine, "<init>", "(J)V");
if (cid_QueryEngine == NULL)
return NULL;
- return env->NewObject(g_ClassQueryEngine, cid_QueryEngine, (jint)pQueryEngine);
+ return env->NewObject(g_ClassQueryEngine, cid_QueryEngine, reinterpret_cast<jlong>(pQueryEngine));
}
JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_releaseQueryEngine
}
JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_executeContextQuery
-(JNIEnv *env, jclass clz, jint pQueryEngineInstance, jstring jstrContextQuery)
+(JNIEnv *env, jclass clz, jlong pQueryEngineInstance, jstring jstrContextQuery)
{
int cqid = -1;
if (jstrContextQuery == NULL)
}
JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_registerQueryEvent
-(JNIEnv *env, jclass clz, jint pQueryEngineInstance, jobject queryEngineEvent)
+(JNIEnv *env, jclass clz, jlong pQueryEngineInstance, jobject queryEngineEvent)
{
IQueryEngine *pQueryEngine = (IQueryEngine *)pQueryEngineInstance;
}
JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_killContextQuery
-(JNIEnv *env, jclass clz, jint pQueryEngineInstance, jint cqid)
+(JNIEnv *env, jclass clz, jlong pQueryEngineInstance, jint cqid)
{
IQueryEngine *pQueryEngine = (IQueryEngine *)pQueryEngineInstance;
}
JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getDataId
-(JNIEnv *env, jclass clz, jint pDataReaderInstance)
+(JNIEnv *env, jclass clz, jlong pDataReaderInstance)
{
IModelData *pDataReader = (IModelData *)pDataReaderInstance;
}
JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyCount
-(JNIEnv *env, jclass clz, jint pIModelDataInstance )
+(JNIEnv *env, jclass clz, jlong pIModelDataInstance )
{
IModelData *pModelData = (IModelData *)pIModelDataInstance;
}
JNIEXPORT jstring JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyName
-(JNIEnv *env, jclass clz, jint pIModelDataInstance, jint propertyIndex )
+(JNIEnv *env, jclass clz, jlong pIModelDataInstance, jint propertyIndex )
{
IModelData *pModelData = (IModelData *)pIModelDataInstance;
}
JNIEXPORT jstring JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyValue
-(JNIEnv *env, jclass clz, jint pIModelDataInstance, jint propertyIndex )
+(JNIEnv *env, jclass clz, jlong pIModelDataInstance, jint propertyIndex )
{
IModelData *pModelData = (IModelData *)pIModelDataInstance;
}
JNIEXPORT jobject JNICALL Java_org_iotivity_service_ssm_CoreController_getAffectedModels
-(JNIEnv *env, jclass clz, jint pDataReaderInstance)
+(JNIEnv *env, jclass clz, jlong pDataReaderInstance)
{
IDataReader *pDataReader = (IDataReader *)pDataReaderInstance;
std::vector<std::string> affectedModels;
}
JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getModelDataCount
-(JNIEnv *env, jclass clz, jint pDataReaderInstance, jstring jstrModelName)
+(JNIEnv *env, jclass clz, jlong pDataReaderInstance, jstring jstrModelName)
{
IDataReader *pDataReader = (IDataReader *)pDataReaderInstance;
int modelCount = 0;
}
//return IModelData
JNIEXPORT jobject JNICALL Java_org_iotivity_service_ssm_CoreController_getModelData
-(JNIEnv *env, jclass clz, jint pDataReaderInstance, jstring jstrModelName, jint jintDataIndex )
+(JNIEnv *env, jclass clz, jlong pDataReaderInstance, jstring jstrModelName, jint jintDataIndex )
{
IDataReader *pDataReader = (IDataReader *)pDataReaderInstance;
IModelData *pModelData = NULL;
return NULL;
}
- jmethodID cid_ModelData = env->GetMethodID(g_ClassModelData, "<init>", "(I)V");
+ jmethodID cid_ModelData = env->GetMethodID(g_ClassModelData, "<init>", "(J)V");
if (cid_ModelData == NULL)
return NULL;
- return env->NewObject(g_ClassModelData, cid_ModelData, (jint)pModelData);
+ return env->NewObject(g_ClassModelData, cid_ModelData, reinterpret_cast<jlong>(pModelData));
}
JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_registerReportReceiver
(JNIEnv *env, jclass clz, jobject queryEngine);
JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_executeContextQuery
-(JNIEnv *env, jclass clz, jint pQueryEngineInstance, jstring jstrContextQuery);
+(JNIEnv *env, jclass clz, jlong pQueryEngineInstance, jstring jstrContextQuery);
JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_registerQueryEvent
-(JNIEnv *env, jclass clz, jint pQueryEngineInstance, jobject queryEngineEvent);
+(JNIEnv *env, jclass clz, jlong pQueryEngineInstance, jobject queryEngineEvent);
JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_killContextQuery
-(JNIEnv *env, jclass clz, jint pQueryEngineInstance, jint cqid);
+(JNIEnv *env, jclass clz, jlong pQueryEngineInstance, jint cqid);
JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getDataId
-(JNIEnv *env, jclass clz, jint pDataReaderInstance);
+(JNIEnv *env, jclass clz, jlong pDataReaderInstance);
JNIEXPORT jobject JNICALL Java_org_iotivity_service_ssm_CoreController_getAffectedModels
-(JNIEnv *env, jclass clz, jint pDataReaderInstance);
+(JNIEnv *env, jclass clz, jlong pDataReaderInstance);
JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getModelDataCount
-(JNIEnv *env, jclass clz, jint pDataReaderInstance, jstring jstrModelName);
+(JNIEnv *env, jclass clz, jlong pDataReaderInstance, jstring jstrModelName);
JNIEXPORT jobject JNICALL Java_org_iotivity_service_ssm_CoreController_getModelData
-(JNIEnv *env, jclass clz, jint pDataReaderInstance, jstring jstrModelName, jint jintDataIndex );
+(JNIEnv *env, jclass clz, jlong pDataReaderInstance, jstring jstrModelName, jint jintDataIndex );
JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyCount
-(JNIEnv *env, jclass clz, jint pIModelDataInstance );
+(JNIEnv *env, jclass clz, jlong pIModelDataInstance );
JNIEXPORT jstring JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyName
-(JNIEnv *env, jclass clz, jint pIModelDataInstance, jint propertyIndex );
+(JNIEnv *env, jclass clz, jlong pIModelDataInstance, jint propertyIndex );
JNIEXPORT jstring JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyValue
-(JNIEnv *env, jclass clz, jint pIModelDataInstance, jint propertyIndex );
+(JNIEnv *env, jclass clz, jlong pIModelDataInstance, jint propertyIndex );
JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_registerReportReceiver
(JNIEnv *env, jclass clz, jobject reportReceiver );
}
#endif
-#endif
\ No newline at end of file
+#endif
which should working as signal beacon.
-2. Indoor Trajectory Sensor is the soft sensor for tizen platform that
-
+2. Indoor Trajectory Sensor is the soft sensor for tizen platform that
+
checks the RSSI signal between reference thing and tizen platform using
tizen BLE api.
3. Trackee_Thing is sub sensor which almost same behavior as Indoor Trajector Sensor
-
- which not only belongs to tizen platform. This also can check the RSSI for
+
+ which not only belongs to tizen platform. This also can check the RSSI for
checking distance and send its measurements to other device using iotivity protocol.
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD)
{
- OC_LOG(ERROR, TAG, PCF("WiFi shield not present"));
+ OC_LOG(ERROR, TAG, ("WiFi shield not present"));
return -1;
}
OC_LOG_V(INFO, TAG, "WiFi Shield Firmware version %s", fwVersion);
if ( strncmp(fwVersion, INTEL_WIFI_SHIELD_FW_VER, sizeof(INTEL_WIFI_SHIELD_FW_VER)) != 0 )
{
- OC_LOG(DEBUG, TAG, PCF("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
+ OC_LOG(DEBUG, TAG, ("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
return -1;
}
// wait 10 seconds for connection:
delay(10000);
}
- OC_LOG(DEBUG, TAG, PCF("Connected to wifi"));
+ OC_LOG(DEBUG, TAG, ("Connected to wifi"));
IPAddress ip = WiFi.localIP();
OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
-Followings should be done befor building Arudno applications
+Followings should be done befor building Arudno applications
1. Applications on arduino conform the Iotivity Base released on 22-Aug-2014.
(Ver. 22th Aug(oic-resource: commit: cdeeed62bd9b11beb2cdd340168e766088c18dac [cdeeed6]))
Makefile path: / oic-resource / csdk / libcoap-4.1.1 / makefile
- path to be modified:
-
+ path to be modified:
+
- INCD_ARD_TIME = -I$(ARDUINO_DIR)/libraries/Time ---> for Time.h
- SDIR_ARD_TIME = $(ARDUINO_DIR)/libraries/Time ---> for Time.c
\ No newline at end of file
if (entityHandlerRequest && (flag & OC_REQUEST_FLAG))
{
- OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+ OC_LOG (INFO, TAG, ("Flag includes OC_REQUEST_FLAG"));
if (OC_REST_GET == entityHandlerRequest->method)
{
if (JsonGenerator( REFER, (char *)entityHandlerRequest->resJSONPayload, \
{
if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
{
- OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
+ OC_LOG (INFO, TAG, ("Received OC_OBSERVE_REGISTER from client"));
g_REFERUnderObservation = 1;
}
else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
{
- OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
+ OC_LOG (INFO, TAG, ("Received OC_OBSERVE_DEREGISTER from client"));
}
}
// Add your initialization code here
OC_LOG_INIT();
- OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
+ OC_LOG(DEBUG, TAG, ("OCServer is starting..."));
// Connect to Ethernet or WiFi network
if (ConnectToNetwork() != 0)
// Initialize the OC Stack in Server mode
if (OCInit(NULL, OC_WELL_KNOWN_PORT, OC_SERVER) != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCStack init error"));
+ OC_LOG(ERROR, TAG, ("OCStack init error"));
return;
}
delay(5000);
if (OCProcess() != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCStack process error"));
+ OC_LOG(ERROR, TAG, ("OCStack process error"));
return;
}
ChangeREFERRepresentation(NULL);
{
if (flag & OC_REQUEST_FLAG)
{
- OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+ OC_LOG (INFO, TAG, ("Flag includes OC_REQUEST_FLAG"));
if (OC_REST_GET == entityHandlerRequest->method)
{
if ( JsonGenerator( (char *)entityHandlerRequest->resJSONPayload,
ehRet = OC_EH_ERROR;
}
}
-
+
}
else if (flag & OC_OBSERVE_FLAG)
{
- OC_LOG (INFO, TAG, PCF("Flag includes OC_OBSERVE_FLAG"));
+ OC_LOG (INFO, TAG, ("Flag includes OC_OBSERVE_FLAG"));
if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
{
- OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
+ OC_LOG (INFO, TAG, ("Received OC_OBSERVE_REGISTER from client"));
g_PROXIUnderObservation = 1;
}
else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
{
- OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
+ OC_LOG (INFO, TAG, ("Received OC_OBSERVE_DEREGISTER from client"));
}
}
// Add your initialization code here
OC_LOG_INIT();
- OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
+ OC_LOG(DEBUG, TAG, ("OCServer is starting..."));
// uint16_t port = OC_WELL_KNOWN_PORT;
// Connect to Ethernet or WiFi network
// Initialize the OC Stack in Server mode
if (OCInit(NULL, OC_WELL_KNOWN_PORT, OC_SERVER) != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCStack init error"));
+ OC_LOG(ERROR, TAG, ("OCStack init error"));
return;
}
// of Arduino microcontroller. Modify it as per specfic application needs.
if (OCProcess() != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCStack process error"));
+ OC_LOG(ERROR, TAG, ("OCStack process error"));
return;
}
-Followings should be done befor building Arudno applications
+Followings should be done befor building Arudno applications
1. Applications on arduino conform the Iotivity Base released on 22-Aug-2014.
(Ver. 22th Aug(oic-resource: commit: cdeeed62bd9b11beb2cdd340168e766088c18dac [cdeeed6]))
Makefile path: / oic-resource / csdk / libcoap-4.1.1 / makefile
- path to be modified:
-
+ path to be modified:
+
- INCD_ARD_TIME = -I$(ARDUINO_DIR)/libraries/Time ---> for Time.h
- SDIR_ARD_TIME = $(ARDUINO_DIR)/libraries/Time ---> for Time.c
\ No newline at end of file
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD)
{
- OC_LOG(ERROR, TAG, PCF("WiFi shield not present"));
+ OC_LOG(ERROR, TAG, ("WiFi shield not present"));
return -1;
}
OC_LOG_V(INFO, TAG, "WiFi Shield Firmware version %s", fwVersion);
if ( strncmp(fwVersion, INTEL_WIFI_SHIELD_FW_VER, sizeof(INTEL_WIFI_SHIELD_FW_VER)) != 0 )
{
- OC_LOG(DEBUG, TAG, PCF("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
+ OC_LOG(DEBUG, TAG, ("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
return -1;
}
// wait 10 seconds for connection:
delay(10000);
}
- OC_LOG(DEBUG, TAG, PCF("Connected to wifi"));
+ OC_LOG(DEBUG, TAG, ("Connected to wifi"));
IPAddress ip = WiFi.localIP();
OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
if (entityHandlerRequest && (flag & OC_REQUEST_FLAG))
{
- OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+ OC_LOG (INFO, TAG, ("Flag includes OC_REQUEST_FLAG"));
if (OC_REST_GET == entityHandlerRequest->method)
{
if (JsonGenerator( TH, payload, MAX_RESPONSE_LENGTH))
{
if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
{
- OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
+ OC_LOG (INFO, TAG, ("Received OC_OBSERVE_REGISTER from client"));
g_THUnderObservation = 1;
}
else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
{
- OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
+ OC_LOG (INFO, TAG, ("Received OC_OBSERVE_DEREGISTER from client"));
}
}
// Add your initialization code here
OC_LOG_INIT();
- OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
+ OC_LOG(DEBUG, TAG, ("OCServer is starting..."));
uint16_t port = OC_WELL_KNOWN_PORT;
// Connect to Ethernet or WiFi network
// Initialize the OC Stack in Server mode
if (OCInit(NULL, port, OC_SERVER) != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCStack init error"));
+ OC_LOG(ERROR, TAG, ("OCStack init error"));
return;
}
OCStartPresence(60);
if (OCProcess() != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCStack process error"));
+ OC_LOG(ERROR, TAG, ("OCStack process error"));
return;
}
ChangeTHRepresentation(NULL);
-Followings should be done befor building Arudno applications
+Followings should be done befor building Arudno applications
1. Applications on arduino conform the Iotivity Base released on 22-Aug-2014.
(Ver. 22th Aug(oic-resource: commit: cdeeed62bd9b11beb2cdd340168e766088c18dac [cdeeed6]))
Makefile path: / oic-resource / csdk / libcoap-4.1.1 / makefile
- path to be modified:
-
+ path to be modified:
+
- INCD_ARD_TIME = -I$(ARDUINO_DIR)/libraries/Time ---> for Time.h
- SDIR_ARD_TIME = $(ARDUINO_DIR)/libraries/Time ---> for Time.c
\ No newline at end of file
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD)
{
- OC_LOG(ERROR, TAG, PCF("WiFi shield not present"));
+ OC_LOG(ERROR, TAG, ("WiFi shield not present"));
return -1;
}
OC_LOG_V(INFO, TAG, "WiFi Shield Firmware version %s", fwVersion);
if ( strncmp(fwVersion, INTEL_WIFI_SHIELD_FW_VER, sizeof(INTEL_WIFI_SHIELD_FW_VER)) != 0 )
{
- OC_LOG(DEBUG, TAG, PCF("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
+ OC_LOG(DEBUG, TAG, ("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
return -1;
}
// wait 10 seconds for connection:
delay(10000);
}
- OC_LOG(DEBUG, TAG, PCF("Connected to wifi"));
+ OC_LOG(DEBUG, TAG, ("Connected to wifi"));
IPAddress ip = WiFi.localIP();
OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
if (entityHandlerRequest && (flag & OC_REQUEST_FLAG))
{
- OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+ OC_LOG (INFO, TAG, ("Flag includes OC_REQUEST_FLAG"));
if (OC_REST_GET == entityHandlerRequest->method)
{
if (JsonGenerator( TH, payload, MAX_RESPONSE_LENGTH))
{
if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
{
- OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
+ OC_LOG (INFO, TAG, ("Received OC_OBSERVE_REGISTER from client"));
g_THUnderObservation = 1;
}
else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
{
- OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
+ OC_LOG (INFO, TAG, ("Received OC_OBSERVE_DEREGISTER from client"));
}
}
// Add your initialization code here
OC_LOG_INIT();
- OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
+ OC_LOG(DEBUG, TAG, ("OCServer is starting..."));
uint16_t port = OC_WELL_KNOWN_PORT;
// Connect to Ethernet or WiFi network
// Initialize the OC Stack in Server mode
if (OCInit(NULL, port, OC_SERVER) != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCStack init error"));
+ OC_LOG(ERROR, TAG, ("OCStack init error"));
return;
}
OCStartPresence(60);
if (OCProcess() != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCStack process error"));
+ OC_LOG(ERROR, TAG, ("OCStack process error"));
return;
}
ChangeTHRepresentation(NULL);
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD)
{
- OC_LOG(ERROR, TAG, PCF("WiFi shield not present"));
+ OC_LOG(ERROR, TAG, ("WiFi shield not present"));
return -1;
}
OC_LOG_V(INFO, TAG, "WiFi Shield Firmware version %s", fwVersion);
if ( strncmp(fwVersion, INTEL_WIFI_SHIELD_FW_VER, sizeof(INTEL_WIFI_SHIELD_FW_VER)) != 0 )
{
- OC_LOG(DEBUG, TAG, PCF("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
+ OC_LOG(DEBUG, TAG, ("!!!!! Upgrade WiFi Shield Firmware version !!!!!!"));
return -1;
}
// wait 10 seconds for connection:
delay(10000);
}
- OC_LOG(DEBUG, TAG, PCF("Connected to wifi"));
+ OC_LOG(DEBUG, TAG, ("Connected to wifi"));
IPAddress ip = WiFi.localIP();
OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
-Followings should be done befor building Arudno applications
+Followings should be done befor building Arudno applications
1. Applications on arduino conform the Iotivity Base released on 22-Aug-2014.
(Ver. 22th Aug(oic-resource: commit: cdeeed62bd9b11beb2cdd340168e766088c18dac [cdeeed6]))
Makefile path: / oic-resource / csdk / libcoap-4.1.1 / makefile
- path to be modified:
-
+ path to be modified:
+
- INCD_ARD_TIME = -I$(ARDUINO_DIR)/libraries/Time ---> for Time.h
- SDIR_ARD_TIME = $(ARDUINO_DIR)/libraries/Time ---> for Time.c
\ No newline at end of file
if (entityHandlerRequest && (flag & OC_REQUEST_FLAG))
{
- OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+ OC_LOG (INFO, TAG, ("Flag includes OC_REQUEST_FLAG"));
if (OC_REST_GET == entityHandlerRequest->method)
{
if (JsonGenerator((char *)entityHandlerRequest->resJSONPayload, \
{
if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
{
- OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
+ OC_LOG (INFO, TAG, ("Received OC_OBSERVE_REGISTER from client"));
g_PROXIUnderObservation = 1;
}
else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
{
- OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
+ OC_LOG (INFO, TAG, ("Received OC_OBSERVE_DEREGISTER from client"));
}
}
// Add your initialization code here
OC_LOG_INIT();
- OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
+ OC_LOG(DEBUG, TAG, ("OCServer is starting..."));
// uint16_t port = OC_WELL_KNOWN_PORT;
// Connect to Ethernet or WiFi network
// Initialize the OC Stack in Server mode
if (OCInit(NULL, OC_WELL_KNOWN_PORT, OC_SERVER) != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCStack init error"));
+ OC_LOG(ERROR, TAG, ("OCStack init error"));
return;
}
if (OCProcess() != OC_STACK_OK)
{
- OC_LOG(ERROR, TAG, PCF("OCStack process error"));
+ OC_LOG(ERROR, TAG, ("OCStack process error"));
return;
}
#if (ARDUINO == 0)
Release notes
-Release date: Aug 5th, 2014.
+Release date: Aug 5th, 2014.
OS: Ubuntu 12.0.4 and above
-Requires boost version 1.55 to build.
-NOTE: Boost is not distributed but should be installed in the Ubuntu machine.
+Requires boost version 1.55 to build.
+NOTE: Boost is not distributed but should be installed in the Ubuntu machine.
What\92s new?
Class OCPlatform (Header file: OCPlatform.h)
registerResource API (signature update)
\95This API provides the ability to register the resource with its name, type and list of properties
-\95Signature of this API has changed. The API takes reference to resource handle which will be filled upon successful registration. Other parameters include resource URI, resource Type, resource interface, entity handler address and resource property (whether discoverable, observable etc.).
-\95NOTE: This applies to server side functionality.
+\95Signature of this API has changed. The API takes reference to resource handle which will be filled upon successful registration. Other parameters include resource URI, resource Type, resource interface, entity handler address and resource property (whether discoverable, observable etc.).
+\95NOTE: This applies to server side functionality.
\95NOTE: This API might get modified to accommodate for resource collection in future.
notifyObservers API
\95This new API provides the ability to notify core that resource\92s attributes have changed. When entity handler is ready to indicate core that a resource has changed, notifyObservers API needs to be invoked.
-\95This API takes resource handle as the only parameter.
-\95NOTE: This applies to server side functionality.
+\95This API takes resource handle as the only parameter.
+\95NOTE: This applies to server side functionality.
\95NOTE: This API might get modified to accommodate for resource collection in future.
Class OCResource (Header file: OCResource.h)
get API
-\95This new API provides the ability to get the attributes of a resource. This API takes a callback as parameter. Callback will be invoked with Attribute map which will provide representation of the resource. Callback will also include error code for GET operation.
-\95NOTE: This applies to client side functionality.
+\95This new API provides the ability to get the attributes of a resource. This API takes a callback as parameter. Callback will be invoked with Attribute map which will provide representation of the resource. Callback will also include error code for GET operation.
+\95NOTE: This applies to client side functionality.
\95NOTE: This API might get modified to accommodate for resource collection in future.
put API
-\95This new API provides the ability to set the attributes of a resource via PUT.
-\95This API takes Attribute map, query parameter map and a callback as parameters. Callback will be invoked with Attribute map which will provide current representation of the resource. Callback will also include error code for PUT operation.
-\95NOTE: This applies to client side functionality.
+\95This new API provides the ability to set the attributes of a resource via PUT.
+\95This API takes Attribute map, query parameter map and a callback as parameters. Callback will be invoked with Attribute map which will provide current representation of the resource. Callback will also include error code for PUT operation.
+\95NOTE: This applies to client side functionality.
\95NOTE: This API might get modified to accommodate for resource collection in future.
Observe API
\95This new API provides the ability for the client to set observation on a resource
-\95This API provides callback as a parameter. Callback will be invoked with attribute map and with an error code for this operation.
-\95NOTE: This applies to client side functionality.
+\95This API provides callback as a parameter. Callback will be invoked with attribute map and with an error code for this operation.
+\95NOTE: This applies to client side functionality.
cancelObserve API
\95This new API provides the ability for the client to cancel observation on a resource
-\95This API provides callback as a parameter. Callback will be invoked with error code for this operation.
-\95NOTE: This applies to client side functionality.
+\95This API provides callback as a parameter. Callback will be invoked with error code for this operation.
+\95NOTE: This applies to client side functionality.
Class OCResourceRequest (Header file: OCResourceRequest.h)
-NOTE: This applies to server side functionality.
+NOTE: This applies to server side functionality.
getRequestType API
\95This new API provides the ability to retrieve the type of request. This could be GET, PUT (and in future POST and DELETE).
getQueryParams API
-\95This new API provides the ability to retrieve the query parameters from the URL request.
+\95This new API provides the ability to retrieve the query parameters from the URL request.
getRequestHandlerFlag API
-\95This new API provides the ability to retrieve the request handler flag on the URL request. This could be either INIT, REQUEST or OBSERVE flag.
+\95This new API provides the ability to retrieve the request handler flag on the URL request. This could be either INIT, REQUEST or OBSERVE flag.
getResourceRepresentation API
-\95This new API provides the ability to retrieve attribute representation of the resource.
+\95This new API provides the ability to retrieve attribute representation of the resource.
Class OCResourceResponse (Header file: OCResourceResponse.h)
-NOTE: This applies to server side functionality.
+NOTE: This applies to server side functionality.
setErrorCode API
\95This new API provides the ability to set the error code
setResourceRepresentation API
-\95This new API provides the ability to set the attribute representation of a resource.
+\95This new API provides the ability to set the attribute representation of a resource.
Other Notes:
-1. Security model is still open.
-2. APIs have OCStackResult as return type. This is will indicate success or failure for the API operation.
-3. Resource collection/hierarchy APIs are not checked into the code base. They will be given as separate header files.
+1. Security model is still open.
+2. APIs have OCStackResult as return type. This is will indicate success or failure for the API operation.
+3. Resource collection/hierarchy APIs are not checked into the code base. They will be given as separate header files.
4. Query parameters are not used in this deliverable.
5. Only single client observer has been tested.
6. Maximum length of URI supported is 64 bytes
How to build:
-1. Root folder oic-resource consists of \91OIC\92 folder. Inside OIC folder there is a Makefile.
-2. Before building, make sure to have contents from oic-utilities repo at the folder level where oic-resource is.
-3. Use \91make\92 to build the entire OIC code. This would build the C++ SDK, stack and samples.
+1. Root folder oic-resource consists of \91OIC\92 folder. Inside OIC folder there is a Makefile.
+2. Before building, make sure to have contents from oic-utilities repo at the folder level where oic-resource is.
+3. Use \91make\92 to build the entire OIC code. This would build the C++ SDK, stack and samples.
Samples:
-1. We have a sample for hosting a resource on a server and a sample for client which will be able to discover resources.
+1. We have a sample for hosting a resource on a server and a sample for client which will be able to discover resources.
2. Server sample location: OIC/examples/simpleserver.cpp
3. Client sample location: OIC/examples/simpleclient.cpp
-4. In simpleserver.cpp, inside main,
+4. In simpleserver.cpp, inside main,
PlatformConfig cfg;
cfg.ipAddress = "134.134.161.33";
-Modify the above IP address to the IP address of the machine where this server is running.
+Modify the above IP address to the IP address of the machine where this server is running.
-Similarly, in simpleclient.cpp, inside main, modify the IP address to the IP address of the machine where the client is running.
+Similarly, in simpleclient.cpp, inside main, modify the IP address to the IP address of the machine where the client is running.
The server and client can run in same machine or in different machines.
void InitializeContext(ICtxDelegate *pDelegate)
{
-
+
std::cout << "[BMISensor] Sensor::" << __func__ << " is called."
<< std::endl;
}
} // for
- delete avg;
+ delete[] avg;
}
bool CProximity::set_threadFunc(workfunc func)
}
is_first = false;
-}
\ No newline at end of file
+}
-Sensor application for arduino conforms the Iotivity Base released on 22-Aug-2014.
+Sensor application for arduino conforms the Iotivity Base released on 22-Aug-2014.
For successful execution, you have to copy the file, local.properties, into the following pathes:
- oic-resource/csdk/
- oic-resource/csdk/libcoap-4.1.1
######################################################################
# Source files and Targets
######################################################################
-tgm_src = env.Glob('sdk/src/*.cpp', '../../extlibs/timer/timer.c')
-tgmsdk_static = things_manager_env.StaticLibrary('TGMSDKLibrary', tgm_src)
-tgmsdk_shared = things_manager_env.SharedLibrary('TGMSDKLibrary', tgm_src)
-things_manager_env.InstallTarget([tgmsdk_static,tgmsdk_shared], 'libTGMSDK')
-things_manager_env.UserInstallTargetLib([tgmsdk_static,tgmsdk_shared], 'libTGMSDK')
-# Build JNI layer
-#if target_os == 'android':
-# SConscript(os.path.join('sdk', 'java', 'jni', 'SConscript'))
+# Remove it if the conversion for Android and Tizen platform is done
+if target_os in ['linux', 'tizen']:
+ tgm_src = env.Glob('sdk/src/*.cpp', '../../extlibs/timer/timer.c')
+ tgmsdk_static = things_manager_env.StaticLibrary('TGMSDKLibrary', tgm_src)
+ tgmsdk_shared = things_manager_env.SharedLibrary('TGMSDKLibrary', tgm_src)
-#Go to build sample apps
-SConscript('sampleapp/SConscript')
+ things_manager_env.InstallTarget([tgmsdk_static,tgmsdk_shared], 'libTGMSDK')
+ things_manager_env.UserInstallTargetLib([tgmsdk_static,tgmsdk_shared], 'libTGMSDK')
+
+ # Build JNI layer
+ #if target_os == 'android':
+ # SConscript(os.path.join('sdk', 'java', 'jni', 'SConscript'))
+
+ #Go to build sample apps
+ SConscript('sampleapp/SConscript')
import org.iotivity.service.tm.Action;
import org.iotivity.service.tm.ActionSet;
import org.iotivity.service.tm.Capability;
-import org.iotivity.service.tm.IActionListener;
+import org.iotivity.service.tm.GroupManager.*;
import android.os.Message;
import android.util.Log;
*/
public class ActionListener implements IActionListener {
- private final String LOG_TAG = "[TMSample] " + this.getClass()
- .getSimpleName();
+ private final String LOG_TAG = "[TMSample] "
+ + this.getClass()
+ .getSimpleName();
private static Message msg;
private String logMessage;
private GroupApiActivity groupApiActivityObj = null;
groupApiActivityObj = GroupApiActivity.getGroupApiActivityObj();
logMessage = "API Result : SUCCESS" + "\n";
- logMessage = logMessage
- + "Recieved Callback for called API (OnPostCallback)" + "\n";
+ logMessage += "Recieved Callback for called API (OnPostCallback)"
+ + "\n";
// sending message to handler of GroupApiActivity to Update the UI
GroupApiActivity.setMessageLog(logMessage);
msg = Message.obtain();
msg.what = 1;
groupApiActivityObj.getHandler().sendMessage(msg);
-
}
@Override
msg = Message.obtain();
msg.what = 1;
groupApiActivityObj.getHandler().sendMessage(msg);
-
}
@Override
groupApiActivityObj = GroupApiActivity.getGroupApiActivityObj();
logMessage = "API Result : SUCCESS" + "\n";
- logMessage = logMessage
- + "Recieved Callback for called API (onPutResponseCallback)"
+ logMessage += "Recieved Callback for called API (onPutResponseCallback)"
+ "\n";
GroupApiActivity.setMessageLog(logMessage);
// sending message to handler of GroupApiActivity to Update the UI
msg = Message.obtain();
msg.what = 1;
groupApiActivityObj.getHandler().sendMessage(msg);
-
}
-
}
import org.iotivity.base.OcRepresentation;
import org.iotivity.base.OcResource;
import org.iotivity.base.OcResourceHandle;
-import org.iotivity.service.tm.IConfigurationListener;
-import org.iotivity.service.tm.IDiagnosticsListener;
-import org.iotivity.service.tm.IFindCandidateResourceListener;
+import org.iotivity.service.tm.GroupSynchronization;
import org.iotivity.service.tm.OCStackResult;
-import org.iotivity.service.tm.ThingsManager;
+import org.iotivity.service.tm.GroupManager;
+import org.iotivity.service.tm.ThingsMaintenance;
+import org.iotivity.service.tm.GroupManager.*;
+import org.iotivity.service.tm.ThingsConfiguration;
+import org.iotivity.service.tm.ThingsConfiguration.*;
+import org.iotivity.service.tm.ThingsMaintenance.*;
import android.app.Activity;
import android.app.Dialog;
private final String CONFIGURATION_COLLECTION_RESOURCE_URI = "/core/configuration/resourceset";
private final String CONFIGURATION_COLLECTION_RESOURCE_TYPE = "core.configuration.resourceset";
- private final String DIAGNOSTIC_COLLECTION_RESOURCE_URI = "/core/diagnostics/resourceset";
- private final String DIAGNOSTIC_COLLECTION_RESOURCE_TYPE = "core.diagnostics.resourceset";
+ private final String MAINTENANCE_COLLECTION_RESOURCE_URI = "/core/maintenance/resourceset";
+ private final String MAINTENANCE_COLLECTION_RESOURCE_TYPE = "core.maintenance.resourceset";
private final String FACTORYSET_COLLECTION_RESOURCE_URI = "/core/factoryset/resourceset";
private final String FACTORYSET_COLLECTION_RESOURCE_TYPE = "core.factoryset.resourceset";
private final String CONFIGURATION_RESOURCE_URI = "/oic/con";
- private final String DIAGNOSTIC_RESOURCE_URI = "/oic/diag";
+ private final String MAINTENANCE_RESOURCE_URI = "/oic/mnt";
private final String FACTORYSET_RESOURCE_URI = "/factorySet";
private ListView list;
private static Handler mHandler;
private static Message msg;
- private ThingsManager thingsManager = null;
+ private GroupManager groupManager = null;
+ private GroupSynchronization groupSyn = null;
+ private ThingsConfiguration thingsConfiguration = null;
+ private ThingsMaintenance thingsMaintenance = null;
private Map<String, ResourceInformation> resourceList = null;
private Map<String, ResourceInformation> collectionList = null;
public boolean configurationResourceFlag = false;
public boolean factorySetResourceFlag = false;
- public boolean diagnosticsResourceFlag = false;
+ public boolean maintenanceResourceFlag = false;
public static Context mcontext;
public String region = "";
setContentView(R.layout.configapis);
mcontext = this;
- thingsManager = new ThingsManager();
+ groupManager = new GroupManager();
+ groupSyn = new GroupSynchronization();
+ thingsConfiguration = ThingsConfiguration.getInstance();
+ thingsMaintenance = ThingsMaintenance.getInstance();
// set the listeners
setResourceListener();
displayToastMessage("Configuration collection resource does not exist!");
} else {
Vector<String> resourceTypes = new Vector<String>();
- resourceTypes.add("oic.con");
+ resourceTypes.add("oic.wk.con");
findCandidateResources(resourceTypes);
logMessage = "";
messageCount++;
resourceTypes.clear();
- resourceTypes.add("oic.diag");
+ resourceTypes.add("oic.wk.mnt");
findCandidateResources(resourceTypes);
messageCount++;
try {
createResourceCollection(CONFIGURATION_COLLECTION_RESOURCE_URI,
CONFIGURATION_COLLECTION_RESOURCE_TYPE);
- createResourceCollection(DIAGNOSTIC_COLLECTION_RESOURCE_URI,
- DIAGNOSTIC_COLLECTION_RESOURCE_TYPE);
+ createResourceCollection(MAINTENANCE_COLLECTION_RESOURCE_URI,
+ MAINTENANCE_COLLECTION_RESOURCE_TYPE);
createResourceCollection(FACTORYSET_COLLECTION_RESOURCE_URI,
FACTORYSET_COLLECTION_RESOURCE_TYPE);
} catch (OcException e) {
}
private void setResourceListener() {
- thingsManager
+ groupManager
.setFindCandidateResourceListener(new IFindCandidateResourceListener() {
@Override
- synchronized public void onResourceCallback(
+ public void onResourceFoundCallback(
Vector<OcResource> resources) {
+ // TODO Auto-generated method stub
Log.i(LOG_TAG, "onResourceCallback: enter");
for (int i = 0; i < resources.size(); i++) {
OcResource resource = resources.get(i);
Log.i(LOG_TAG, "Resource URI:" + uri);
Log.i(LOG_TAG, "Resource HOST: " + host);
Log.i(LOG_TAG, "Resource types: ");
- logMessage = logMessage + "Resource URI : " + uri
- + "\n";
- logMessage = logMessage + "Resource Host : " + host
- + "\n";
+ logMessage += "Resource URI : " + uri + "\n";
+ logMessage += "Resource Host : " + host + "\n";
List<String> resourcetypes = resource
.getResourceTypes();
for (int j = 0; j < resourcetypes.size(); j++) {
Log.i(LOG_TAG, resourcetypes.get(j));
- logMessage = logMessage + "ResourceType "
- + (j + 1) + " : "
+ logMessage += "ResourceType " + (j + 1) + " : "
+ resourcetypes.get(j) + "\n";
}
.getResourceInterfaces();
for (int j = 0; j < interfacetypes.size(); j++) {
Log.i(LOG_TAG, interfacetypes.get(j));
- logMessage = logMessage + "interfacetype "
- + (j + 1) + " : "
- + interfacetypes.get(j) + "\n";
+ logMessage += "interfacetype " + (j + 1)
+ + " : " + interfacetypes.get(j) + "\n";
}
try {
}
private void setConfigurationListener() {
- thingsManager.setConfigurationListener(new IConfigurationListener() {
- @Override
- public void onBootStrapCallback(
- Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
- int errorValue) {
- Log.i(LOG_TAG, "onBootStrapCallback: enter");
- }
-
- @Override
- public void onUpdateConfigurationsCallback(
- Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
- int errorValue) {
- Log.i(LOG_TAG, "onUpdateConfigurationsCallback: enter");
- Log.i(LOG_TAG, "Resource URI: " + rep.getUri());
- if (rep.hasAttribute("loc")) {
- logMessage = logMessage + "Location : "
- + rep.getValueString("loc") + "\n";
- }
- if (rep.hasAttribute("st")) {
- logMessage = logMessage + "System Time : "
- + rep.getValueString("loc") + "\n";
- }
- if (rep.hasAttribute("c")) {
- logMessage = logMessage + "Currency : "
- + rep.getValueString("c") + "\n";
- }
- if (rep.hasAttribute("r")) {
- logMessage = logMessage + "Region : "
- + rep.getValueString("r") + "\n";
- }
+ thingsConfiguration
+ .setConfigurationListener(new IConfigurationListener() {
+ @Override
+ public void onBootStrapCallback(
+ Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue) {
+ Log.i(LOG_TAG, "onBootStrapCallback: enter");
+ }
- }
+ @Override
+ public void onUpdateConfigurationsCallback(
+ Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue) {
+ Log.i(LOG_TAG, "onUpdateConfigurationsCallback: enter");
+ Log.i(LOG_TAG, "Resource URI: " + rep.getUri());
+ if (rep.hasAttribute("n")) {
+ logMessage += "Device Name : "
+ + rep.getValueString("n") + "\n";
+ }
+ if (rep.hasAttribute("loc")) {
+ logMessage += "Location : "
+ + rep.getValueString("loc") + "\n";
+ }
+ if (rep.hasAttribute("locn")) {
+ logMessage += "Location Name : "
+ + rep.getValueString("locn") + "\n";
+ }
+ if (rep.hasAttribute("r")) {
+ logMessage += "Region : " + rep.getValueString("r")
+ + "\n";
+ }
+ if (rep.hasAttribute("c")) {
+ logMessage += "Currency : "
+ + rep.getValueString("c") + "\n";
+ }
+ }
- @Override
- public void onGetConfigurationsCallback(
- Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
- int errorValue) {
- Log.i(LOG_TAG, "onGetConfigurationsCallback: enter");
- Log.i(LOG_TAG, "Resource URI: " + rep.getUri());
- logMessage = logMessage + "Resource URI : " + rep.getUri()
- + "\n";
-
- if (rep.hasAttribute("loc")) {
- logMessage = logMessage + "Location : "
- + rep.getValueString("loc") + "\n";
- }
- if (rep.hasAttribute("st")) {
- logMessage = logMessage + "System Time : "
- + rep.getValueString("st") + "\n";
- }
- if (rep.hasAttribute("c")) {
- logMessage = logMessage + "Currency : "
- + rep.getValueString("c") + "\n";
- }
- if (rep.hasAttribute("r")) {
- logMessage = logMessage + "Region : "
- + rep.getValueString("r") + "\n";
- }
+ @Override
+ public void onGetConfigurationsCallback(
+ Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue) {
+ Log.i(LOG_TAG, "onGetConfigurationsCallback: enter");
+ Log.i(LOG_TAG, "Resource URI: " + rep.getUri());
+ logMessage += "Resource URI : " + rep.getUri() + "\n";
+
+ if (rep.hasAttribute("n")) {
+ logMessage += "Device Name : "
+ + rep.getValueString("n") + "\n";
+ }
+ if (rep.hasAttribute("loc")) {
+ logMessage += "Location : "
+ + rep.getValueString("loc") + "\n";
+ }
+ if (rep.hasAttribute("locn")) {
+ logMessage += "Location Name : "
+ + rep.getValueString("locn") + "\n";
+ }
+ if (rep.hasAttribute("r")) {
+ logMessage += "Region : " + rep.getValueString("r")
+ + "\n";
+ }
+ if (rep.hasAttribute("c")) {
+ logMessage += "Currency : "
+ + rep.getValueString("c") + "\n";
+ }
- msg = Message.obtain();
- msg.what = 0;
- mHandler.sendMessage(msg);
- }
- });
+ msg = Message.obtain();
+ msg.what = 0;
+ mHandler.sendMessage(msg);
+ }
+ });
}
private void setDiagnosticsListener() {
- thingsManager.setDiagnosticsListener(new IDiagnosticsListener() {
+ thingsMaintenance
+ .setThingsMaintenanceListener(new IThingsMaintenanceListener() {
- @Override
- public void onRebootCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue) {
- Log.i(LOG_TAG, "onRebootCallback: enter");
- }
+ @Override
+ public void onRebootCallback(
+ Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue) {
+ // TODO Auto-generated method stu
+ }
- @Override
- public void onFactoryResetCallback(
- Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
- int errorValue) {
- Log.i(LOG_TAG, "onFactoryResetCallback: enter");
- }
- });
+ @Override
+ public void onFactoryResetCallback(
+ Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue) {
+ // TODO Auto-generated method stub
+
+ }
+ });
}
/**
* This method find the resources available in network.
*/
private void findCandidateResources(Vector<String> resourceTypes) {
- OCStackResult result = thingsManager.findCandidateResources(
+ OCStackResult result = groupManager.findCandidateResources(
resourceTypes, 5);
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG, "Error while calling findCandidateResources");
displayToastMessage(toastmessage);
}
if (messageCount == 1)
- logMessage = logMessage + "API RESULT : " + result.toString()
- + "\n";
+ logMessage += "API RESULT : " + result.toString() + "\n";
}
/**
OCStackResult result = OCStackResult.OC_STACK_ERROR;
try {
- result = thingsManager.getConfigurations(
+ result = thingsConfiguration.getConfigurations(
configurationCollection.resource, configs);
} catch (OcException e) {
e.printStackTrace();
OCStackResult result = OCStackResult.OC_STACK_ERROR;
try {
- result = thingsManager.updateConfigurations(
+ result = thingsConfiguration.updateConfigurations(
configurationCollection.resource, configurations);
} catch (OcException e) {
e.printStackTrace();
displayToastMessage(toastmessage);
}
logMessage = "API RESULT : " + result.toString() + "\n";
- logMessage = logMessage + "Updating region to " + region;
+ logMessage += "Updating region to " + region;
msg = Message.obtain();
msg.what = 0;
mHandler.sendMessage(msg);
*/
private void factoryReset() {
ResourceInformation diagnosticsCollection = collectionList
- .get(DIAGNOSTIC_COLLECTION_RESOURCE_URI);
+ .get(MAINTENANCE_COLLECTION_RESOURCE_URI);
if (null == diagnosticsCollection
|| null == diagnosticsCollection.resource) {
displayToastMessage("Diagnostic collection does not exist!");
return;
}
- if (false == diagnosticsResourceFlag) {
+ if (false == maintenanceResourceFlag) {
displayToastMessage("Diagnostic resource does not exist!");
return;
}
OCStackResult result = OCStackResult.values()[30];
try {
- result = thingsManager.factoryReset(diagnosticsCollection.resource);
+ result = thingsMaintenance
+ .factoryReset(diagnosticsCollection.resource);
} catch (OcException e) {
e.printStackTrace();
}
*/
private void reboot() {
ResourceInformation diagnosticsCollection = collectionList
- .get(DIAGNOSTIC_COLLECTION_RESOURCE_URI);
+ .get(MAINTENANCE_COLLECTION_RESOURCE_URI);
if (null == diagnosticsCollection
|| null == diagnosticsCollection.resource) {
displayToastMessage("Diagnostic collection does not exist!");
return;
}
- if (false == diagnosticsResourceFlag) {
+ if (false == maintenanceResourceFlag) {
displayToastMessage("Diagnostic resource does not exist!");
return;
}
OCStackResult result = OCStackResult.OC_STACK_ERROR;
try {
- result = thingsManager.reboot(diagnosticsCollection.resource);
+ result = thingsMaintenance.reboot(diagnosticsCollection.resource);
} catch (OcException e) {
e.printStackTrace();
}
* Response will be in JSON format (key-value pair).
*/
private String getListOfSupportedConfigurationUnits() {
- return thingsManager.getListOfSupportedConfigurationUnits();
+ return thingsConfiguration.getListOfSupportedConfigurationUnits();
}
private void displayToastMessage(String message) {
OcResourceHandle handle;
handle = resourceInfoCollection.resourceHandle;
resourceInfo.resourceHandle = handle;
- resourceInfo.resourceHandle = thingsManager.bindResourceToGroup(
+ resourceInfo.resourceHandle = groupManager.bindResourceToGroup(
resource, handle);
resourceList.put(uri + host, resourceInfo);
configurationResourceFlag = true;
- } else if (uri.equalsIgnoreCase("/oic/diag")) {
+ } else if (uri.equalsIgnoreCase("/oic/mnt")) {
ResourceInformation diagnosticResource = collectionList
- .get(DIAGNOSTIC_COLLECTION_RESOURCE_URI);
+ .get(MAINTENANCE_COLLECTION_RESOURCE_URI);
if (null == diagnosticResource
|| null == diagnosticResource.resourceHandle) {
Log.e(LOG_TAG, "Invalid Configuration collection!");
ResourceInformation resourceInfoCollection;
resourceInfoCollection = collectionList
- .get(DIAGNOSTIC_COLLECTION_RESOURCE_URI);
+ .get(MAINTENANCE_COLLECTION_RESOURCE_URI);
OcResourceHandle handle;
handle = resourceInfoCollection.resourceHandle;
resourceInfo.resourceHandle = handle;
- resourceInfo.resourceHandle = thingsManager.bindResourceToGroup(
+ resourceInfo.resourceHandle = groupManager.bindResourceToGroup(
resource, handle);
resourceList.put(uri + host, resourceInfo);
- diagnosticsResourceFlag = true;
+ maintenanceResourceFlag = true;
} else if (uri.equalsIgnoreCase("/factorySet")) {
ResourceInformation factorysetResource = collectionList
.get(FACTORYSET_COLLECTION_RESOURCE_URI);
OcResourceHandle handle;
handle = resourceInfoCollection.resourceHandle;
resourceInfo.resourceHandle = handle;
- resourceInfo.resourceHandle = thingsManager.bindResourceToGroup(
+ resourceInfo.resourceHandle = groupManager.bindResourceToGroup(
resource, handle);
resourceList.put(uri + host, resourceInfo);
OcResourceHandle resourceHandle = null;
// Crate group
- OCStackResult result = thingsManager.createGroup(typename);
+ OCStackResult result = groupSyn.createGroup(typename);
if ((OCStackResult.OC_STACK_OK != result)) {
Log.e(LOG_TAG, "createGroup returned error: " + result.name());
return;
} else {
Log.e(LOG_TAG, "createGroup returned: " + result.name());
}
- groupList = thingsManager.getGroupList();
+ groupList = groupSyn.getGroupList();
if (groupList.containsKey(typename)) {
resourceHandle = groupList.get(typename);
} else {
}
} else if (resource.resource.getUri().equalsIgnoreCase(
- DIAGNOSTIC_RESOURCE_URI)) {
+ MAINTENANCE_RESOURCE_URI)) {
ResourceInformation diagnosticResource = collectionList
- .get(DIAGNOSTIC_COLLECTION_RESOURCE_URI);
+ .get(MAINTENANCE_COLLECTION_RESOURCE_URI);
if (null != diagnosticResource
&& null != diagnosticResource.resourceHandle) {
OcPlatform
.unregisterResource(resource.resourceHandle);
Log.i(LOG_TAG, "unregistered resource"
+ CONFIGURATION_COLLECTION_RESOURCE_URI);
-
}
}
}
}
// delete all the groups
- thingsManager.deleteGroup(CONFIGURATION_COLLECTION_RESOURCE_TYPE);
- thingsManager.deleteGroup(DIAGNOSTIC_COLLECTION_RESOURCE_TYPE);
- thingsManager.deleteGroup(FACTORYSET_COLLECTION_RESOURCE_TYPE);
+ groupSyn.deleteGroup(CONFIGURATION_COLLECTION_RESOURCE_TYPE);
+ groupSyn.deleteGroup(MAINTENANCE_COLLECTION_RESOURCE_TYPE);
+ groupSyn.deleteGroup(FACTORYSET_COLLECTION_RESOURCE_TYPE);
} catch (OcException e) {
Log.e(LOG_TAG, "OcException occured! " + e.toString());
}
import org.iotivity.base.OcHeaderOption;
import org.iotivity.base.OcRepresentation;
-import org.iotivity.service.tm.IConfigurationListener;
+import org.iotivity.service.tm.ThingsConfiguration;
+import org.iotivity.service.tm.ThingsConfiguration.*;
import android.util.Log;
*/
public class ConfigurationListener implements IConfigurationListener {
- private final String LOG_TAG = "[TMSample] " + this.getClass().getSimpleName();
+ private final String LOG_TAG = "[TMSample] "
+ + this.getClass().getSimpleName();
@Override
public void onBootStrapCallback(Vector<OcHeaderOption> headerOptions,
Log.i(LOG_TAG, "Got Callback : onGetConfigurationsCallback");
}
-
}
+++ /dev/null
-/******************************************************************
- *
- * 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.
- *
- ******************************************************************/
-package com.tm.sample;
-
-import java.util.Vector;
-
-import org.iotivity.base.OcHeaderOption;
-import org.iotivity.base.OcRepresentation;
-import org.iotivity.service.tm.IDiagnosticsListener;
-
-import android.util.Log;
-
-/**
- * For receiving Diagnostic APIs callback : BootStrap,Reboot & FactoryReset
- */
-public class DiagnosticListener implements IDiagnosticsListener {
-
- private final String LOG_TAG = "[TMSample] " + this.getClass().getSimpleName();
-
- @Override
- public void onRebootCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue) {
- Log.i(LOG_TAG, "Got Callback : onRebootCallback");
-
- }
-
- @Override
- public void onFactoryResetCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue) {
- Log.i(LOG_TAG, "Got Callback : onFactoryResetCallback");
-
- }
-
-}
// For Scheduled ActionSet
public static Context mcontext;
public static Calendar scheduleTime;
-
- private final String LOG_TAG = "[TMSample] " + this.getClass()
- .getSimpleName();;
+
+ private final String LOG_TAG = "[TMSample] "
+ + this.getClass()
+ .getSimpleName(); ;
@Override
protected void onCreate(Bundle savedInstanceState) {
import org.iotivity.service.tm.Action;
import org.iotivity.service.tm.ActionSet;
import org.iotivity.service.tm.Capability;
-import org.iotivity.service.tm.IFindCandidateResourceListener;
-import org.iotivity.service.tm.IFindGroupListener;
+import org.iotivity.service.tm.GroupSynchronization;
+import org.iotivity.service.tm.GroupSynchronization.*;
import org.iotivity.service.tm.OCStackResult;
-import org.iotivity.service.tm.ThingsManager;
+import org.iotivity.service.tm.GroupManager;
+import org.iotivity.service.tm.GroupManager.*;
import org.iotivity.service.tm.Time.ActionSetType;
import android.os.Message;
*/
public class GroupClient {
- private static final String LOG_TAG = "[TMSample] GroupClient";
- private static Message msg;
- public String logMessage;
+ private static final String LOG_TAG = "[TMSample] GroupClient";
+ private static Message msg;
+ public String logMessage;
- private final String groupResourceType = "b.collection";
+ private final String groupResourceType = "b.collection";
- private final ThingsManager thingsManagerObj;
- private final ActionListener actionListener;
- private final ObserveListener observeListener;
- private OcResource groupResource;
- private OcResourceHandle groupResourceHandle;
- private OcResourceHandle foundLightHandle;
- private static GroupApiActivity groupApiActivityObj = null;
- public static Vector<String> lights = new Vector<String>();
- public static Vector<String> bookmarks = new Vector<String>();
+ private final GroupManager groupManagerObj;
+ private final GroupSynchronization groupSynObj;
+ private final ActionListener actionListener;
+ private final ObserveListener observeListener;
+ private OcResource groupResource;
+ private OcResourceHandle groupResourceHandle;
+ private OcResourceHandle foundLightHandle;
+ private static GroupApiActivity groupApiActivityObj = null;
+ public static Vector<String> lights = new Vector<String>();
+ public static Vector<String> bookmarks = new Vector<String>();
/**
* Listener for receiving observe notifications.
groupApiActivityObj.getHandler().sendMessage(msg);
logMessage = "onGroupFind" + "\n";
- logMessage = logMessage + "URI : " + uri + "\n";
- logMessage = logMessage + "Host :" + hostAddress;
+ logMessage += "URI : " + uri + "\n";
+ logMessage += "Host :" + hostAddress;
GroupApiActivity.setMessageLog(logMessage);
msg = Message.obtain();
msg.what = 1;
*/
private class FindCadidateResourceListener implements
IFindCandidateResourceListener {
+
@Override
- public void onResourceCallback(Vector<OcResource> resources) {
+ public void onResourceFoundCallback(Vector<OcResource> resources) {
+ // TODO Auto-generated method stub
Log.i(LOG_TAG, "onResourceCallback invoked");
if (resources != null) {
String hostAddress = ocResource.getHost();
logMessage = "API RESULT : " + "OC_STACK_OK" + "\n";
- logMessage = logMessage + "URI: " + resourceURI + "\n";
- logMessage = logMessage + "Host:" + hostAddress;
+ logMessage += "URI: " + resourceURI + "\n";
+ logMessage += "Host:" + hostAddress;
GroupApiActivity.setMessageLog(logMessage);
msg = Message.obtain();
msg.what = 1;
logMessage = "API RESULT : " + "OC_STACK_OK"
+ "\n";
- logMessage = logMessage + "URI: " + resourceURI
- + "\n";
- logMessage = logMessage + "Host:" + hostAddress;
+ logMessage += "URI: " + resourceURI + "\n";
+ logMessage += "Host:" + hostAddress;
GroupApiActivity.setMessageLog(logMessage);
msg = Message.obtain();
msg.what = 1;
groupApiActivityObj.getHandler().sendMessage(
msg);
try {
- foundLightHandle = thingsManagerObj
+ foundLightHandle = groupManagerObj
.bindResourceToGroup(ocResource,
groupResourceHandle);
if (groupApiActivityObj != null) {
logMessage = "API RESULT : " + "OC_STACK_OK"
+ "\n";
- logMessage = logMessage + "URI: " + resourceURI
- + "\n";
- logMessage = logMessage + "Host:" + hostAddress;
+ logMessage += "URI: " + resourceURI + "\n";
+ logMessage += "Host:" + hostAddress;
GroupApiActivity.setMessageLog(logMessage);
msg = Message.obtain();
msg.what = 1;
}
}
}
+
}
};
private final FindGroupListener findGroupListener;
public GroupClient() {
- thingsManagerObj = new ThingsManager();
+ groupManagerObj = new GroupManager();
+ groupSynObj = GroupSynchronization.getInstance();
findGroupListener = new FindGroupListener();
actionListener = new ActionListener();
observeListener = new ObserveListener();
findCandidateResourceListener = new FindCadidateResourceListener();
- thingsManagerObj.setGroupListener(findGroupListener);
- thingsManagerObj
+ groupSynObj.setGroupListener(findGroupListener);
+ groupManagerObj
.setFindCandidateResourceListener(findCandidateResourceListener);
- thingsManagerObj.setActionListener(actionListener);
+ groupManagerObj.setActionListener(actionListener);
groupApiActivityObj = GroupApiActivity.getGroupApiActivityObj();
}
Map<String, OcResourceHandle> groupList = new HashMap<String, OcResourceHandle>();
// creating group of type b.collection
- OCStackResult result = thingsManagerObj.createGroup(groupResourceType);
+ // OcPlatform.registerResource(ocResource);
+ OCStackResult result = groupSynObj.createGroup(groupResourceType);
if ((OCStackResult.OC_STACK_OK != result)) {
Log.e(LOG_TAG, "createGroup returned error: " + result.name());
return;
}
// getting the Created group Handle
- groupList = thingsManagerObj.getGroupList();
+ groupList = groupSynObj.getGroupList();
if (groupList.containsKey(groupResourceType)) {
groupResourceHandle = groupList.get(groupResourceType);
} else {
Vector<String> resourceTypes = new Vector<String>();
resourceTypes.add(groupResourceType);
- OCStackResult result = thingsManagerObj.findGroup(resourceTypes);
+ OCStackResult result = groupSynObj.findGroup(resourceTypes);
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG, "findGroup returned error: " + result.name());
return;
Vector<String> types = new Vector<String>();
types.add("core.light");
- OCStackResult result = thingsManagerObj
- .findCandidateResources(types, 5);
+ OCStackResult result = groupManagerObj.findCandidateResources(types, 5);
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG,
"findCandidateResources returned error: " + result.name());
Vector<String> types = new Vector<String>();
types.add("core.bookmark");
- OCStackResult result = thingsManagerObj
- .findCandidateResources(types, 5);
+ OCStackResult result = groupManagerObj.findCandidateResources(types, 5);
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG,
"findCandidateResources returned error: " + result.name());
}
try {
- OCStackResult result = thingsManagerObj.addActionSet(groupResource,
+ OCStackResult result = groupManagerObj.addActionSet(groupResource,
actionSet);
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG, "addActionSet returned error: " + result.name());
}
try {
- OCStackResult result = thingsManagerObj.addActionSet(groupResource,
+ OCStackResult result = groupManagerObj.addActionSet(groupResource,
actionSet);
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG, "addActionSet returned error: " + result.name());
}
try {
- OCStackResult result = thingsManagerObj.addActionSet(groupResource,
+ OCStackResult result = groupManagerObj.addActionSet(groupResource,
actionSet);
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG, "addActionSet returned error: " + result.name());
}
try {
- OCStackResult result = thingsManagerObj.addActionSet(groupResource,
+ OCStackResult result = groupManagerObj.addActionSet(groupResource,
actionSet);
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG, "addActionSet returned error: " + result.name());
Log.i(LOG_TAG, "getting the action set of bulb on action");
try {
- OCStackResult result = thingsManagerObj.getActionSet(groupResource,
+ OCStackResult result = groupManagerObj.getActionSet(groupResource,
"AllBulbOn");
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG,
Log.i(LOG_TAG, "getting the action set of bulb off action");
try {
- OCStackResult result = thingsManagerObj.getActionSet(groupResource,
+ OCStackResult result = groupManagerObj.getActionSet(groupResource,
"AllBulbOff");
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG,
Log.i(LOG_TAG, "deleting the action set of bulb on action");
try {
- OCStackResult result = thingsManagerObj.deleteActionSet(
+ OCStackResult result = groupManagerObj.deleteActionSet(
groupResource, "AllBulbOn");
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG,
Log.i(LOG_TAG, "deleting the action set of bulb off action");
try {
- OCStackResult result = thingsManagerObj.deleteActionSet(
+ OCStackResult result = groupManagerObj.deleteActionSet(
groupResource, "AllBulbOff");
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG,
* groups.
*/
public void leaveGroup() {
- thingsManagerObj.setGroupListener(null);
- thingsManagerObj.setFindCandidateResourceListener(null);
- thingsManagerObj.setActionListener(null);
+ groupSynObj.setGroupListener(null);
+ groupManagerObj.setFindCandidateResourceListener(null);
+ groupManagerObj.setActionListener(null);
if (null != foundLightHandle) {
try {
}
if (null != groupResourceHandle) {
- thingsManagerObj.deleteGroup(groupResourceType);
+ groupSynObj.deleteGroup(groupResourceType);
} else {
Log.i(LOG_TAG, "groupResourceHandle is NULL");
}
private void executeActionSet(String actonSetName, long delay) {
try {
- OCStackResult result = thingsManagerObj.executeActionSet(
+ OCStackResult result = groupManagerObj.executeActionSet(
groupResource, actonSetName, delay);
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG,
private void cancelActionSet(String actionSetName) {
try {
- OCStackResult result = thingsManagerObj.cancelActionSet(
+ OCStackResult result = groupManagerObj.cancelActionSet(
groupResource, actionSetName);
if (OCStackResult.OC_STACK_OK != result) {
Log.e(LOG_TAG,
import org.iotivity.base.PlatformConfig;
import org.iotivity.base.QualityOfService;
import org.iotivity.base.ServiceType;
-import org.iotivity.service.tm.ThingsManager;
+import org.iotivity.service.tm.GroupManager;
+import org.iotivity.service.tm.GroupManager.*;
import android.app.Activity;
import android.app.AlertDialog;
private ArrayAdapter<String> apis;
private ArrayList<String> apisList;
private ListView list;
- private final String LOG_TAG = "[TMSample] " + this.getClass()
- .getSimpleName();
- public ThingsManager thingsManagerObj = new ThingsManager();
+ private final String LOG_TAG = "[TMSample] "
+ + this.getClass()
+ .getSimpleName();
+ public GroupManager groupManagerObj = new GroupManager();
@Override
protected void onCreate(Bundle savedInstanceState) {
dialog = dialogBuilder.create();
dialog.show();
- Log.i(LOG_TAG, "WiFi is not enabled/connected! Please connect the WiFi and start application again...");
+ Log.i(LOG_TAG,
+ "WiFi is not enabled/connected! Please connect the WiFi and start application again...");
return;
}
// If wifi is connected calling the configure method for configuring the
// OcPlatform
- platformConfigObj = new PlatformConfig(getApplicationContext(),ServiceType.IN_PROC,
- ModeType.CLIENT_SERVER, "0.0.0.0", 0, QualityOfService.LOW);
+ platformConfigObj = new PlatformConfig(getApplicationContext(),
+ ServiceType.IN_PROC, ModeType.CLIENT_SERVER, "0.0.0.0", 0,
+ QualityOfService.LOW);
Log.i(LOG_TAG, "Before Calling Configure of ocPlatform");
OcPlatform.Configure(platformConfigObj);
.getSimpleName();
// Configuration resource members
protected String configurationUri;
+ protected String deviceName;
protected String location;
- protected String systemTime;
+ protected String locationName;
protected String currency;
protected String region;
protected Vector<String> configurationTypes = new Vector<String>();
public ConfigurationResource() {
Log.i(LOG_TAG, "ConfigurationResource: enter");
+ deviceName = ConfigurationDefaultValues.defaultDeviceName;
location = ConfigurationDefaultValues.defaultLocation;
- systemTime = ConfigurationDefaultValues.defaultSystemTime;
+ locationName = ConfigurationDefaultValues.defaultLocationName;
currency = ConfigurationDefaultValues.defaultCurrency;
region = ConfigurationDefaultValues.defaultRegion;
.add(ConfigurationDefaultValues.ConResourceTypePrefix);
configurationInterfaces.add(OcPlatform.DEFAULT_INTERFACE);
+ configurationRep.setValueString("n", deviceName);
configurationRep.setValueString("loc", location);
- configurationRep.setValueString("st", systemTime);
+ configurationRep.setValueString("locn", locationName);
configurationRep.setValueString("c", currency);
configurationRep.setValueString("r", region);
+
configurationRep.setUri(configurationUri);
configurationRep.setResourceTypes(configurationTypes);
configurationRep.setResourceInterfaces(configurationInterfaces);
public void setConfigurationRepresentation(OcRepresentation rep) {
Log.i(LOG_TAG, "setConfigurationRepresentation: enter");
- String loc;
- String st;
- String cur;
- String reg;
- loc = rep.getValueString("loc");
- st = rep.getValueString("st");
- cur = rep.getValueString("c");
- reg = rep.getValueString("r");
+ String dName = rep.getValueString("n");
+ String loc = rep.getValueString("loc");
+ String locn = rep.getValueString("locn");
+ String cur = rep.getValueString("c");
+ String reg = rep.getValueString("r");
+
+ if (!(dName.equalsIgnoreCase(""))) {
+ deviceName = dName;
+ Log.i(LOG_TAG,
+ "setConfigurationRepresentation: New value(deviceName): "
+ + deviceName);
+ }
if (!(loc.equalsIgnoreCase(""))) {
location = loc;
Log.i(LOG_TAG,
"setConfigurationRepresentation: New value(location): "
+ location);
}
- if (!(st.equalsIgnoreCase(""))) {
- systemTime = st;
+ if (!(locn.equalsIgnoreCase(""))) {
+ locationName = locn;
Log.i(LOG_TAG,
- "setConfigurationRepresentation: New value(system time): "
- + systemTime);
+ "setConfigurationRepresentation: New value(locationName): "
+ + locationName);
}
if (!(cur.equalsIgnoreCase(""))) {
currency = cur;
public OcRepresentation getConfigurationRepresentation() {
+ configurationRep.setValueString("n", deviceName);
configurationRep.setValueString("loc", location);
- configurationRep.setValueString("st", systemTime);
+ configurationRep.setValueString("locn", locationName);
configurationRep.setValueString("c", currency);
configurationRep.setValueString("r", region);
return configurationRep;
// For resetting the default values to configuration Resource
public void factoryReset() {
+ deviceName = ConfigurationDefaultValues.defaultDeviceName;
location = ConfigurationDefaultValues.defaultLocation;
- systemTime = ConfigurationDefaultValues.defaultSystemTime;
+ locationName = ConfigurationDefaultValues.defaultLocationName;
currency = ConfigurationDefaultValues.defaultCurrency;
region = ConfigurationDefaultValues.defaultRegion;
Log.i(LOG_TAG, "ConfiguartionResource: factoryReset done");
-
}
// Deleting all the resources, that we have created using createResources()
import org.iotivity.base.OcResourceResponse;
import org.iotivity.base.RequestHandlerFlag;
import org.iotivity.base.RequestType;
-import org.iotivity.service.tm.IConfigurationListener;
-import org.iotivity.service.tm.IDiagnosticsListener;
import org.iotivity.service.tm.OCStackResult;
-import org.iotivity.service.tm.ThingsManager;
+import org.iotivity.service.tm.GroupManager;
+import org.iotivity.service.tm.ThingsConfiguration;
+import org.iotivity.service.tm.ThingsConfiguration.*;
+import org.iotivity.service.tm.ThingsMaintenance;
+import org.iotivity.service.tm.ThingsMaintenance.*;
import android.os.Message;
import android.util.Log;
/*
- * For Creating the Resources [configurtion, Diagnostic & FactoryRest] &
+ * For Creating the Resources [configuration, Maintenance & FactoryRest] &
* for Handling of the Client's Request
*/
-public class ConfigurationServer implements IDiagnosticsListener,
- IConfigurationListener, OcPlatform.EntityHandler {
- private final String LOG_TAG = "[CON-SERVER]"
- + this.getClass()
- .getSimpleName();
- private ThingsManager thingsmanager = null;
- private ConfigurationResource conResource = null;
- private DiagnosticsResource diagResource = null;
- private FactorySetResource factorySetResource = null;
+public class ConfigurationServer {
+ private final String LOG_TAG = "[CON-SERVER]"
+ + this.getClass()
+ .getSimpleName();
+ private GroupManager groupmanager = null;
+ private ThingsConfiguration thingsconfig = null;
+ private ThingsMaintenance thingsmnt = null;
+ private ConfigurationResource conResource = null;
+ private MaintenanceResource mntResource = null;
+ private FactorySetResource factorySetResource = null;
+
+ private final ThingsConfigurationListener thingConfigurationListener;
+ private final ThingsMaintenanceListener thingsMaintenanceListener;
+ private final RequestHandler requestHandler;
// constructor
public ConfigurationServer() {
- thingsmanager = new ThingsManager();
- thingsmanager.setDiagnosticsListener(this);
- thingsmanager.setConfigurationListener(this);
- }
+ groupmanager = new GroupManager();
+ thingsconfig = ThingsConfiguration.getInstance();
+ thingsmnt = ThingsMaintenance.getInstance();
+ thingConfigurationListener = new ThingsConfigurationListener();
+ thingsMaintenanceListener = new ThingsMaintenanceListener();
+ requestHandler = new RequestHandler();
- public void DoBootStrap() {
- Log.i(LOG_TAG, "DoBootStrap: enter");
+ thingsconfig.setConfigurationListener(thingConfigurationListener);
+ thingsmnt.setThingsMaintenanceListener(thingsMaintenanceListener);
- OCStackResult result = thingsmanager.doBootstrap();
- if (OCStackResult.OC_STACK_ERROR == result) {
- Log.e(LOG_TAG, "doBootStrap returned error: "
- + OCStackResult.OC_STACK_ERROR.name());
- }
- Log.i(LOG_TAG, "DoBootStrap: exit");
}
- // Creating resources : configuration, diagnostics, factoryReset
+ // Creating resources : configuration, maintenance, factoryReset
public void CreateConfigurationResource() {
Log.i(LOG_TAG, "CreateConfigurationResource: enter");
try {
conResource = new ConfigurationResource();
- conResource.createResource(this);
+ conResource.createResource(requestHandler);
- diagResource = new DiagnosticsResource();
- diagResource.createResource(this);
+ mntResource = new MaintenanceResource();
+ mntResource.createResource(requestHandler);
factorySetResource = new FactorySetResource();
- factorySetResource.createResource(this);
+ factorySetResource.createResource(requestHandler);
} catch (OcException e) {
Log.e(LOG_TAG, "OcException occured: " + e.toString());
}
MainActivity mainActivityObj = MainActivity.getMainActivityObject();
MainActivity.setmessage(message);
mainActivityObj.getmHandler().sendMessage(msg);
+ }
+
+ public void DoBootStrap() {
+ Log.i(LOG_TAG, "DoBootStrap: enter");
+
+ OCStackResult result = thingsconfig.doBootstrap();
+ if (OCStackResult.OC_STACK_ERROR == result) {
+ Log.e(LOG_TAG, "doBootStrap returned error: "
+ + OCStackResult.OC_STACK_ERROR.name());
+ }
+ Log.i(LOG_TAG, "DoBootStrap: exit");
+ }
+
+ private class ThingsConfigurationListener implements IConfigurationListener {
+
+ @Override
+ public void onBootStrapCallback(Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue) {
+
+ String message;
+ Log.i(LOG_TAG, "onBootStrapCallback");
+
+ // setting the default values received from bootstrap Server
+ ConfigurationDefaultValues.defaultDeviceName = rep
+ .getValueString("n");
+ ConfigurationDefaultValues.defaultLocation = rep
+ .getValueString("loc");
+ ConfigurationDefaultValues.defaultLocationName = rep
+ .getValueString("locn");
+ ConfigurationDefaultValues.defaultCurrency = rep
+ .getValueString("c");
+ ConfigurationDefaultValues.defaultRegion = rep.getValueString("r");
+
+ // forming the message to display on UI
+ message = "URI : " + rep.getUri() + "\n";
+ message += "Device Name : "
+ + ConfigurationDefaultValues.defaultDeviceName + "\n";
+ message += "Location : "
+ + ConfigurationDefaultValues.defaultLocation + "\n";
+ message += "Location Name : "
+ + ConfigurationDefaultValues.defaultLocationName + "\n";
+ message += "Currency : "
+ + ConfigurationDefaultValues.defaultCurrency + "\n";
+ message += "Region : " + ConfigurationDefaultValues.defaultRegion
+ + "\n";
+
+ Log.i(LOG_TAG, "Resource URI: " + rep.getUri());
+ Log.i(LOG_TAG, "Region: "
+ + ConfigurationDefaultValues.defaultRegion);
+ Log.i(LOG_TAG, "Device Name: "
+ + ConfigurationDefaultValues.defaultDeviceName);
+ Log.i(LOG_TAG, "Location: "
+ + ConfigurationDefaultValues.defaultLocation);
+ Log.i(LOG_TAG, "Location Name: "
+ + ConfigurationDefaultValues.defaultLocationName);
+ Log.i(LOG_TAG, "Currency: "
+ + ConfigurationDefaultValues.defaultCurrency);
+
+ // showing the formed message on the UI
+ Message msg = Message.obtain();
+ msg.what = 0;
+ MainActivity mainActivityObj = MainActivity.getMainActivityObject();
+ MainActivity.setmessage(message);
+ mainActivityObj.getmHandler().sendMessage(msg);
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void onUpdateConfigurationsCallback(
+ Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
+ int errorValue) {
+ Log.i(LOG_TAG, "onUpdateConfigurationsCallback");
+ }
+ @Override
+ public void onGetConfigurationsCallback(
+ Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
+ int errorValue) {
+ Log.i(LOG_TAG, "onGetConfigurationsCallback");
+ }
+ }
+
+ private class ThingsMaintenanceListener implements
+ IThingsMaintenanceListener {
+
+ // Callback Function for Reboot
+ @Override
+ public void onRebootCallback(Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue) {
+ Log.i(LOG_TAG, "onRebootCallback");
+ }
+
+ // Callback Function for FactoryReset
+ @Override
+ public void onFactoryResetCallback(
+ Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
+ int errorValue) {
+ Log.i(LOG_TAG, "onFactoryResetCallback");
+ }
}
// For deleting all the resources
public void deleteResources() {
if (null != conResource)
conResource.deleteResource();
- if (null != diagResource)
- diagResource.deleteResource();
+ if (null != mntResource)
+ mntResource.deleteResource();
if (null != factorySetResource)
factorySetResource.deleteResource();
}
- // Callback Function for doBootStrap
- @Override
- public void onBootStrapCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue) {
- String message;
- Log.i(LOG_TAG, "onBootStrapCallback");
-
- // setting the default values received from bootstrap Server
-
- ConfigurationDefaultValues.defaultRegion = rep.getValueString("r");
- ConfigurationDefaultValues.defaultSystemTime = rep.getValueString("st");
- ConfigurationDefaultValues.defaultCurrency = rep.getValueString("c");
- ConfigurationDefaultValues.defaultLocation = rep.getValueString("loc");
-
- // forming the message to display on UI
- message = "URI : " + rep.getUri() + "\n";
- message = message + "Region : "
- + ConfigurationDefaultValues.defaultRegion + "\n";
- message = message + "System Time : "
- + ConfigurationDefaultValues.defaultSystemTime + "\n";
- message = message + "Currency : "
- + ConfigurationDefaultValues.defaultCurrency + "\n";
- message = message + "Location : "
- + ConfigurationDefaultValues.defaultLocation + "\n";
-
- Log.i(LOG_TAG, "Resource URI: " + rep.getUri());
- Log.i(LOG_TAG, "Region: " + ConfigurationDefaultValues.defaultRegion);
- Log.i(LOG_TAG, "System Time: "
- + ConfigurationDefaultValues.defaultSystemTime);
- Log.i(LOG_TAG, "Currency: "
- + ConfigurationDefaultValues.defaultCurrency);
- Log.i(LOG_TAG, "Location: "
- + ConfigurationDefaultValues.defaultLocation);
-
- // showing the formed message on the UI
- Message msg = Message.obtain();
- msg.what = 0;
- MainActivity mainActivityObj = MainActivity.getMainActivityObject();
- MainActivity.setmessage(message);
- mainActivityObj.getmHandler().sendMessage(msg);
- }
+ private class RequestHandler implements OcPlatform.EntityHandler {
- // Callback Function for Reboot
- @Override
- public void onRebootCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue) {
- Log.i(LOG_TAG, "onRebootCallback");
- }
+ @Override
+ public EntityHandlerResult handleEntity(OcResourceRequest request) {
+ Log.i(LOG_TAG, "handleEntity: enter");
- // Callback Function for FactoryReset
- @Override
- public void onFactoryResetCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue) {
- Log.i(LOG_TAG, "onFactoryResetCallback");
- }
-
- // For Handling the Client's Request
- @Override
- public EntityHandlerResult handleEntity(OcResourceRequest request) {
- Log.i(LOG_TAG, "handleEntity: enter");
-
- EntityHandlerResult result = EntityHandlerResult.ERROR;
- if (null == request) {
- Log.e(LOG_TAG, "handleEntity: Invalid OcResourceRequest!");
- return result;
- }
-
- RequestType requestType = request.getRequestType();
- EnumSet<RequestHandlerFlag> requestHandlerFlag = request
- .getRequestHandlerFlagSet();
- Log.i(LOG_TAG, "prepareResponseForResource: request type: "
- + requestType.name());
- Log.i(LOG_TAG, "prepareResponseForResource: request for resource: "
- + request.getResourceUri());
-
- if (requestHandlerFlag.contains(RequestHandlerFlag.REQUEST)) {
- if (RequestType.GET == requestType) {
- sendResponse(request);
- } else if (RequestType.PUT == requestType) {
- OcRepresentation rep = request.getResourceRepresentation();
- if (null == rep) {
- Log.e(LOG_TAG,
- "handleEntity: Invalid resource representation!");
- return result;
- }
+ EntityHandlerResult result = EntityHandlerResult.ERROR;
+ if (null == request) {
+ Log.e(LOG_TAG, "handleEntity: Invalid OcResourceRequest!");
+ return result;
+ }
- if (request.getResourceUri().equalsIgnoreCase(
- conResource.getUri())) {
- conResource.setConfigurationRepresentation(rep);
- } else if (request.getResourceUri().equalsIgnoreCase(
- diagResource.getUri())) {
+ RequestType requestType = request.getRequestType();
+ EnumSet<RequestHandlerFlag> requestHandlerFlag = request
+ .getRequestHandlerFlagSet();
+ Log.i(LOG_TAG, "prepareResponseForResource: request type: "
+ + requestType.name());
+ Log.i(LOG_TAG, "prepareResponseForResource: request for resource: "
+ + request.getResourceUri());
+
+ if (requestHandlerFlag.contains(RequestHandlerFlag.REQUEST)) {
+ if (RequestType.GET == requestType) {
+ sendResponse(request);
+ } else if (RequestType.PUT == requestType) {
+ OcRepresentation rep = request.getResourceRepresentation();
+ if (null == rep) {
+ Log.e(LOG_TAG,
+ "handleEntity: Invalid resource representation!");
+ return result;
+ }
- String factorySetAtt = rep.getValueString("fr");
- if (factorySetAtt.equalsIgnoreCase("true")) {
- conResource.factoryReset();
+ if (request.getResourceUri().equalsIgnoreCase(
+ conResource.getUri())) {
+ conResource.setConfigurationRepresentation(rep);
+ } else if (request.getResourceUri().equalsIgnoreCase(
+ mntResource.getUri())) {
+
+ String factorySetAtt = rep.getValueString("fr");
+ if (factorySetAtt.equalsIgnoreCase("true")) {
+ conResource.factoryReset();
+ }
+ mntResource.setDiagnosticsRepresentation(rep);
}
- diagResource.setDiagnosticsRepresentation(rep);
+ sendResponse(request);
}
- sendResponse(request);
}
- }
- Log.i(LOG_TAG, "handleEntity: exit");
- return result;
+ Log.i(LOG_TAG, "handleEntity: exit");
+ return result;
+ }
}
// For sending response to the client
if (request.getResourceUri().equalsIgnoreCase(conResource.getUri())) {
rep = conResource.getConfigurationRepresentation();
} else if (request.getResourceUri().equalsIgnoreCase(
- diagResource.getUri())) {
- rep = diagResource.getDiagnosticsRepresentation();
+ mntResource.getUri())) {
+ rep = mntResource.getDiagnosticsRepresentation();
}
response.setResourceRepresentation(rep, OcPlatform.DEFAULT_INTERFACE);
response.setErrorCode(200);
}
Log.i(LOG_TAG, "sendResponse: exit");
}
-
- @Override
- public void onUpdateConfigurationsCallback(
- Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
- int errorValue) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void onGetConfigurationsCallback(
- Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
- int errorValue) {
- // TODO Auto-generated method stub
-
- }
}
// Default values for Resources
class ConfigurationDefaultValues {
// configuration Resource default values
+
+ public static String defaultDeviceName = new String();
public static String defaultLocation = new String();
- public static String defaultRegion = new String();
- public static String defaultSystemTime = new String();
+ public static String defaultLocationName = new String();
public static String defaultCurrency = new String();
+ public static String defaultRegion = new String();
+
public static String ConURIPrefix = "/oic/con";
- public static String ConResourceTypePrefix = "oic.con";
+ public static String ConResourceTypePrefix = "oic.wk.con";
// Diagnostics Resource default values
- public static String diagURIPrefix = "/oic/diag";
- public static String diagResourceTypePrefix = "oic.diag";
+ public static String diagURIPrefix = "/oic/mnt";
+ public static String diagResourceTypePrefix = "oic.wk.mnt";
public static String diagnosticsValue = "false";
public static String defaultFactoryReset = "false";
public static String defaultReboot = "false";
public void setFactorySetRepresentation(OcRepresentation rep) {
Log.i(LOG_TAG, "setFactorySetRepresentation: enter");
- String loc;
- String st;
- String cur;
- String reg;
- loc = rep.getValueString("loc");
- st = rep.getValueString("st");
- cur = rep.getValueString("c");
- reg = rep.getValueString("r");
- if (null != loc) {
+ String dName = rep.getValueString("n");
+ String loc = rep.getValueString("loc");
+ String locn = rep.getValueString("locn");
+ String cur = rep.getValueString("c");
+ String reg = rep.getValueString("r");
+
+ if (!(dName.equalsIgnoreCase(""))) {
+ deviceName = dName;
+ Log.i(LOG_TAG,
+ "setConfigurationRepresentation: New value(deviceName): "
+ + deviceName);
+ }
+ if (!(loc.equalsIgnoreCase(""))) {
location = loc;
- Log.i(LOG_TAG, "setConfigurationRepresentation: New value: "
- + location);
+ Log.i(LOG_TAG,
+ "setConfigurationRepresentation: New value(location): "
+ + location);
}
- if (null != st) {
- // systemTime = st;
- Log.i(LOG_TAG, "setConfigurationRepresentation: New value: "
- + systemTime);
+ if (!(locn.equalsIgnoreCase(""))) {
+ locationName = locn;
+ Log.i(LOG_TAG,
+ "setConfigurationRepresentation: New value(locationName): "
+ + locationName);
}
- if (null != cur) {
+ if (!(cur.equalsIgnoreCase(""))) {
currency = cur;
- Log.i(LOG_TAG, "setConfigurationRepresentation: New value: "
- + currency);
+ Log.i(LOG_TAG,
+ "setConfigurationRepresentation: New value(currency): "
+ + currency);
}
- if (null != reg) {
+ if (!(reg.equalsIgnoreCase(""))) {
region = reg;
- Log.i(LOG_TAG, "setConfigurationRepresentation: New value: "
- + region);
+ Log.i(LOG_TAG,
+ "setConfigurationRepresentation: New value(region): "
+ + region);
}
Log.i(LOG_TAG, "setFactorySetRepresentation: exit");
}
OcRepresentation getFactorySetRepresentation() {
+ configurationRep.setValueString("n", deviceName);
configurationRep.setValueString("loc", location);
- configurationRep.setValueString("st", systemTime);
+ configurationRep.setValueString("locn", locationName);
configurationRep.setValueString("c", currency);
configurationRep.setValueString("r", region);
return configurationRep;
*/
public class MainActivity extends Activity {
- private final String LOG_TAG = "[CON-SERVER]" + this.getClass().getSimpleName();
+ private final String LOG_TAG = "[CON-SERVER]"
+ + this.getClass()
+ .getSimpleName();
private Handler mHandler;
private static MainActivity mainActivityObj;
private ConfigurationServer conServerObj;
AlertDialog dialog = dialogBuilder.create();
dialog.show();
- Log.i(LOG_TAG, "WiFi is not enabled/connected! Please connect the WiFi and start application again...");
+ Log.i(LOG_TAG,
+ "WiFi is not enabled/connected! Please connect the WiFi and start application again...");
return;
}
// If wifi is connected calling the configure method for configuring the
// ocPlatform
- PlatformConfig cfg = new PlatformConfig(getApplicationContext(),ServiceType.IN_PROC,
- ModeType.CLIENT_SERVER, "0.0.0.0", 0, QualityOfService.LOW);
+ PlatformConfig cfg = new PlatformConfig(getApplicationContext(),
+ ServiceType.IN_PROC, ModeType.CLIENT_SERVER, "0.0.0.0", 0,
+ QualityOfService.LOW);
OcPlatform.Configure(cfg);
Log.i(LOG_TAG, "Configuration done Successfully");
}
dialog.setProgress(0);
dialog.setMax(100);
dialog.show();
- Log.i(LOG_TAG, "Rebooting.. Please wait ...");
+ // Log.i(LOG_TAG, "Rebooting.. Please wait ...");
Thread thread = new Thread() {
@Override
public void run() {
import android.util.Log;
//For creating/deleting the Diagnostics Resource
-public class DiagnosticsResource {
- private final String LOG_TAG = "[CON-SERVER]"
- + this.getClass()
- .getSimpleName();
- // diagnostics members
- private String diagnosticsUri;
- private String factoryReset;
- private String reboot;
- private String startCollection;
- private Vector<String> diagnosticsTypes = new Vector<String>();
- private Vector<String> diagnosticsInterfaces = new Vector<String>();
- private OcResourceHandle diagnosticsHandle;
- private OcRepresentation diagnosticsRep = new OcRepresentation();
+public class MaintenanceResource {
+ private final String LOG_TAG = "[CON-SERVER]"
+ + this.getClass()
+ .getSimpleName();
+ // maintenance members
+ private String m_maintenanceUri;
+ private String m_factoryReset;
+ private String m_reboot;
+ private String m_startCollection;
+ private Vector<String> m_maintenanceTypes = new Vector<String>();
+ private Vector<String> m_maintenanceInterfaces = new Vector<String>();
+ private OcResourceHandle m_maintenanceHandle = null;
+ private OcRepresentation m_maintenanceRep = new OcRepresentation();
// constructor
- public DiagnosticsResource() {
- Log.i(LOG_TAG, "DiagnosticsCollection: enter");
-
- factoryReset = ConfigurationDefaultValues.defaultFactoryReset;
- reboot = ConfigurationDefaultValues.defaultReboot;
- startCollection = ConfigurationDefaultValues.defaultStartCollection;
-
- diagnosticsUri = ConfigurationDefaultValues.diagURIPrefix;
- diagnosticsTypes.add(ConfigurationDefaultValues.diagResourceTypePrefix);
- diagnosticsInterfaces.add(OcPlatform.DEFAULT_INTERFACE);
- diagnosticsRep.setValueString("fr", factoryReset);
- diagnosticsRep.setValueString("rb", reboot);
- diagnosticsRep.setValueString("ssc", startCollection);
- diagnosticsRep.setUri(diagnosticsUri);
- diagnosticsRep.setResourceTypes(diagnosticsTypes);
- diagnosticsRep.setResourceInterfaces(diagnosticsInterfaces);
-
+ public MaintenanceResource() {
+ Log.i(LOG_TAG, "MaintenanceResource: enter");
+
+ m_factoryReset = ConfigurationDefaultValues.defaultFactoryReset;
+ m_reboot = ConfigurationDefaultValues.defaultReboot;
+ m_startCollection = ConfigurationDefaultValues.defaultStartCollection;
+
+ m_maintenanceUri = ConfigurationDefaultValues.diagURIPrefix;
+ m_maintenanceTypes
+ .add(ConfigurationDefaultValues.diagResourceTypePrefix);
+ m_maintenanceInterfaces.add(OcPlatform.DEFAULT_INTERFACE);
+ m_maintenanceRep.setValueString("fr", m_factoryReset);
+ m_maintenanceRep.setValueString("rb", m_reboot);
+ m_maintenanceRep.setValueString("ssc", m_startCollection);
+ m_maintenanceRep.setUri(m_maintenanceUri);
+ m_maintenanceRep.setResourceTypes(m_maintenanceTypes);
+ m_maintenanceRep.setResourceInterfaces(m_maintenanceInterfaces);
}
// for creating Diagnostic Resource
public void createResource(OcPlatform.EntityHandler listener)
throws OcException {
- Log.i(LOG_TAG, "createResource(Diagnostics): enter");
+ Log.i(LOG_TAG, "createResource(Maintenance): enter");
EnumSet<ResourceProperty> propertySet = EnumSet.of(
ResourceProperty.DISCOVERABLE, ResourceProperty.OBSERVABLE);
if (null == listener) {
}
// Register diagnostic resource
- diagnosticsHandle = OcPlatform.registerResource(diagnosticsUri,
- diagnosticsTypes.get(0), diagnosticsInterfaces.get(0),
+ m_maintenanceHandle = OcPlatform.registerResource(m_maintenanceUri,
+ m_maintenanceTypes.get(0), m_maintenanceInterfaces.get(0),
listener, propertySet);
- if (null == diagnosticsHandle) {
+ if (null == m_maintenanceHandle) {
Log.e(LOG_TAG, "registerResource failed!");
return;
}
// Sleep value can be changed as per the developer
// convenience.
Thread.sleep(1000);
- if (reboot.equalsIgnoreCase("true")) {
+ if (m_reboot.equalsIgnoreCase("true")) {
Log.i(LOG_TAG, "Reboot will be soon...");
MainActivity mainActivityObj = MainActivity
.getMainActivityObject();
+ e.toString());
continue;
}
- reboot = ConfigurationDefaultValues.defaultReboot;
+ m_reboot = ConfigurationDefaultValues.defaultReboot;
}
- if (factoryReset.equalsIgnoreCase("true")) {
- factoryReset = ConfigurationDefaultValues.defaultFactoryReset;
+ if (m_factoryReset.equalsIgnoreCase("true")) {
+ m_factoryReset = ConfigurationDefaultValues.defaultFactoryReset;
factoryReset();
}
}
String ssc = rep.getValueString("ssc");
if (!(fr.equalsIgnoreCase(""))) {
- factoryReset = fr;
+ m_factoryReset = fr;
Log.i(LOG_TAG,
"setConfigurationRepresentation: New value(FactoryReset): "
+ fr);
}
if (!(rb.equalsIgnoreCase(""))) {
- reboot = rb;
+ m_reboot = rb;
Log.i(LOG_TAG, "setDiagnosticsRepresentation: new value:(reboot) "
+ rb);
}
if (!(ssc.equalsIgnoreCase(""))) {
- startCollection = ssc;
+ m_startCollection = ssc;
Log.i(LOG_TAG,
"setDiagnosticsRepresentation: new value:(startcollection) "
+ ssc);
}
-
Log.i(LOG_TAG, "setDiagnosticsRepresentation: exit");
}
OcRepresentation getDiagnosticsRepresentation() {
- diagnosticsRep.setValueString("fr", factoryReset);
- diagnosticsRep.setValueString("rb", reboot);
- diagnosticsRep.setValueString("ssc", startCollection);
- return diagnosticsRep;
+ m_maintenanceRep.setValueString("fr", m_factoryReset);
+ m_maintenanceRep.setValueString("rb", m_reboot);
+ m_maintenanceRep.setValueString("ssc", m_startCollection);
+ return m_maintenanceRep;
}
public String getUri() {
- return diagnosticsUri;
+ return m_maintenanceUri;
}
// For Resetting diagnostics Resource attributes to their default values
public void factoryReset() {
- factoryReset = ConfigurationDefaultValues.defaultFactoryReset;
- reboot = ConfigurationDefaultValues.defaultReboot;
- startCollection = ConfigurationDefaultValues.defaultStartCollection;
+ m_factoryReset = ConfigurationDefaultValues.defaultFactoryReset;
+ m_reboot = ConfigurationDefaultValues.defaultReboot;
+ m_startCollection = ConfigurationDefaultValues.defaultStartCollection;
}
// For Deleting diagnostic resource
public void deleteResource() {
try {
- if (null != diagnosticsHandle) {
+ if (null != m_maintenanceHandle) {
// Unregister the collection resource
- OcPlatform.unregisterResource(diagnosticsHandle);
+ OcPlatform.unregisterResource(m_maintenanceHandle);
}
} catch (OcException e) {
Log.e(LOG_TAG, "OcException occured! " + e.toString());
#include <functional>
#include <thread>
+#include <string.h>
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
#include "ConfigurationCollection.h"
using namespace OC;
+using namespace std;
/// This function internally calls registerResource API.
void ConfigurationResource::createResources(ResourceEntityHandler callback)
{
string value;
+ if (rep.getValue("n", value))
+ {
+ m_deviceName = value;
+ std::cout << "\t\t\t\t" << "m_deviceName: " << m_deviceName << std::endl;
+ }
+
if (rep.getValue("loc", value))
{
m_location = value;
std::cout << "\t\t\t\t" << "m_location: " << m_location << std::endl;
}
- if (rep.getValue("st", value))
+ if (rep.getValue("locn", value))
{
- std::cout << "\t\t\t\t" << "SystemTime is not allowed to be written." << std::endl;
+ m_locationName = value;
+ std::cout << "\t\t\t\t" << "m_locationName: " << m_locationName << std::endl;
}
if (rep.getValue("c", value))
OCRepresentation ConfigurationResource::getConfigurationRepresentation()
{
+ m_configurationRep.setValue("n", m_deviceName);
m_configurationRep.setValue("loc", m_location);
- m_configurationRep.setValue("st", m_systemTime);
+ m_configurationRep.setValue("locn", m_locationName);
m_configurationRep.setValue("c", m_currency);
m_configurationRep.setValue("r", m_region);
void ConfigurationResource::factoryReset()
{
+ m_deviceName = defaultDeviceName;
m_location = defaultLocation;
- m_systemTime = defaultSystemTime;
+ m_locationName = defaultLocationName;
m_currency = defaultCurrency;
m_region = defaultRegion;
}
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
#pragma once
typedef std::function<
OCEntityHandlerResult(std::shared_ptr< OCResourceRequest > request) > ResourceEntityHandler;
-static std::string defaultURIPrefix = "/oic/con";
-static std::string defaultResourceTypePrefix = "oic.con";
+static std::string defaultConURI = "/oic/con";
+static std::string defaultConResourceType = "oic.wk.con";
+extern std::string defaultDeviceName;
extern std::string defaultLocation;
-extern std::string defaultSystemTime;
+extern std::string defaultLocationName;
extern std::string defaultCurrency;
extern std::string defaultRegion;
public:
// Configuration members
std::string m_configurationUri;
+ std::string m_deviceName;
std::string m_location;
- std::string m_systemTime;
+ std::string m_locationName;
std::string m_currency;
std::string m_region;
std::vector< std::string > m_configurationTypes;
public:
/// Constructor
ConfigurationResource() :
- m_location(defaultLocation), m_systemTime(defaultSystemTime), m_currency(
- defaultCurrency), m_region(defaultRegion)
+ m_deviceName(defaultDeviceName), m_location(defaultLocation),
+ m_locationName(defaultLocationName), m_currency(defaultCurrency),
+ m_region(defaultRegion)
{
- m_configurationUri = "/oic/con"; // URI of the resource
- m_configurationTypes.push_back("oic.con"); // resource type name.
+ m_configurationUri = defaultConURI; // URI of the resource
+ m_configurationTypes.push_back(defaultConResourceType); // resource type name.
m_configurationInterfaces.push_back(DEFAULT_INTERFACE); // resource interface.
- //m_configurationInterfaces.push_back(BATCH_INTERFACE); // resource interface.
- //m_configurationInterfaces.push_back(LINK_INTERFACE); // resource interface.
+ m_configurationRep.setValue("st", m_deviceName);
m_configurationRep.setValue("loc", m_location);
- m_configurationRep.setValue("st", m_systemTime);
+ m_configurationRep.setValue("locn", m_locationName);
m_configurationRep.setValue("c", m_currency);
m_configurationRep.setValue("r", m_region);
m_configurationRep.setUri(m_configurationUri);
#include <functional>
#include <thread>
+#include <string.h>
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
#include "FactorySetCollection.h"
using namespace OC;
+using namespace std;
FactorySetResource::FactorySetResource()
{
{
string value;
+ if (rep.getValue("n", value))
+ {
+ m_deviceName = value;
+ std::cout << "\t\t\t\t" << "m_deviceName: " << m_deviceName << std::endl;
+ }
+
if (rep.getValue("loc", value))
{
m_location = value;
std::cout << "\t\t\t\t" << "m_location: " << m_location << std::endl;
}
- if (rep.getValue("st", value))
+ if (rep.getValue("locn", value))
{
- std::cout << "\t\t\t\t" << "SystemTime is not allowed to be written." << std::endl;
+ m_locationName = value;
+ std::cout << "\t\t\t\t" << "m_locationName: " << m_locationName << std::endl;
}
if (rep.getValue("c", value))
OCRepresentation FactorySetResource::getFactorySetRepresentation()
{
+ m_configurationRep.setValue("n", m_deviceName);
m_configurationRep.setValue("loc", m_location);
- m_configurationRep.setValue("st", m_systemTime);
+ m_configurationRep.setValue("locn", m_locationName);
m_configurationRep.setValue("c", m_currency);
m_configurationRep.setValue("r", m_region);
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
+//#include "ThingsManager.h"
#include "ConfigurationCollection.h"
#pragma once
#include <functional>
#include <thread>
+#include <string.h>
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
-#include "DiagnosticsCollection.h"
+#include "MaintenanceCollection.h"
using namespace OC;
+using namespace std;
/// This function internally calls registerResource API.
-void DiagnosticsResource::createResources(ResourceEntityHandler callback)
+void MaintenanceResource::createResources(ResourceEntityHandler callback)
{
using namespace OC::OCPlatform;
}
// This will internally create and register the resource.
- OCStackResult result = registerResource(m_diagnosticsHandle, m_diagnosticsUri,
- m_diagnosticsTypes[0], m_diagnosticsInterfaces[0], callback,
+ OCStackResult result = registerResource(m_maintenanceHandle, m_maintenanceUri,
+ m_maintenanceTypes[0], m_maintenanceInterfaces[0], callback,
OC_DISCOVERABLE | OC_OBSERVABLE);
if (OC_STACK_OK != result)
{
- std::cout << "Resource creation (diagnostics) was unsuccessful\n";
+ std::cout << "Resource creation (maintenance) was unsuccessful\n";
}
thread exec(
std::function< void(int second) >(
- std::bind(&DiagnosticsResource::diagnosticsMonitor, this,
+ std::bind(&MaintenanceResource::maintenanceMonitor, this,
std::placeholders::_1)), 10); // every 10 seconds
exec.detach();
- std::cout << "Diagnostics Resource is Created!\n";
+ std::cout << "maintenance Resource is Created!\n";
}
-void DiagnosticsResource::setDiagnosticsRepresentation(OCRepresentation& rep)
+void MaintenanceResource::setMaintenanceRepresentation(OCRepresentation& rep)
{
string value;
}
}
-OCRepresentation DiagnosticsResource::getDiagnosticsRepresentation()
+OCRepresentation MaintenanceResource::getMaintenanceRepresentation()
{
- m_diagnosticsRep.setValue("fr", m_factoryReset);
- m_diagnosticsRep.setValue("rb", m_reboot);
- m_diagnosticsRep.setValue("ssc", m_startStatCollection);
+ m_maintenanceRep.setValue("fr", m_factoryReset);
+ m_maintenanceRep.setValue("rb", m_reboot);
+ m_maintenanceRep.setValue("ssc", m_startStatCollection);
- return m_diagnosticsRep;
+ return m_maintenanceRep;
}
-std::string DiagnosticsResource::getUri()
+std::string MaintenanceResource::getUri()
{
- return m_diagnosticsUri;
+ return m_maintenanceUri;
}
-void DiagnosticsResource::diagnosticsMonitor(int second)
+void MaintenanceResource::maintenanceMonitor(int second)
{
while (1)
{
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
#pragma once
typedef std::function<
OCEntityHandlerResult(std::shared_ptr< OCResourceRequest > request) > ResourceEntityHandler;
+static std::string defaultMntURI = "/oic/mnt";
+static std::string defaultMntResourceType = "oic.wk.mnt";
+
static std::string defaultFactoryReset = "false";
static std::string defaultReboot = "false";
static std::string defaultStartStatCollection = "false";
-class DiagnosticsResource
+class MaintenanceResource
{
public:
- // diagnostics members
- std::string m_diagnosticsUri;
+ // Maintenance members
+ std::string m_maintenanceUri;
std::string m_factoryReset;
std::string m_reboot;
std::string m_startStatCollection;
- std::vector< std::string > m_diagnosticsTypes;
- std::vector< std::string > m_diagnosticsInterfaces;
- OCResourceHandle m_diagnosticsHandle;
- OCRepresentation m_diagnosticsRep;
+ std::vector< std::string > m_maintenanceTypes;
+ std::vector< std::string > m_maintenanceInterfaces;
+ OCResourceHandle m_maintenanceHandle;
+ OCRepresentation m_maintenanceRep;
public:
/// Constructor
- DiagnosticsResource() :
+ MaintenanceResource() :
m_factoryReset(defaultFactoryReset), m_reboot(defaultReboot),
m_startStatCollection(defaultStartStatCollection)
{
- m_diagnosticsUri = "/oic/diag"; // URI of the resource
- m_diagnosticsTypes.push_back("oic.diag"); // resource type name.
- m_diagnosticsInterfaces.push_back(DEFAULT_INTERFACE); // resource interface.
- m_diagnosticsRep.setValue("fr", m_factoryReset);
- m_diagnosticsRep.setValue("rb", m_reboot);
- m_diagnosticsRep.setValue("ssc", m_startStatCollection);
- m_diagnosticsRep.setUri(m_diagnosticsUri);
- m_diagnosticsRep.setResourceTypes(m_diagnosticsTypes);
- m_diagnosticsRep.setResourceInterfaces(m_diagnosticsInterfaces);
- m_diagnosticsHandle = NULL;
+ m_maintenanceUri = defaultMntURI; // URI of the resource
+ m_maintenanceTypes.push_back(defaultMntResourceType); // resource type name.
+ m_maintenanceInterfaces.push_back(DEFAULT_INTERFACE); // resource interface.
+ m_maintenanceRep.setValue("fr", m_factoryReset);
+ m_maintenanceRep.setValue("rb", m_reboot);
+ m_maintenanceRep.setValue("ssc", m_startStatCollection);
+ m_maintenanceRep.setUri(m_maintenanceUri);
+ m_maintenanceRep.setResourceTypes(m_maintenanceTypes);
+ m_maintenanceRep.setResourceInterfaces(m_maintenanceInterfaces);
+ m_maintenanceHandle = NULL;
}
;
/// This function internally calls registerResource API.
void createResources(ResourceEntityHandler callback);
- void setDiagnosticsRepresentation(OCRepresentation& rep);
+ void setMaintenanceRepresentation(OCRepresentation& rep);
- OCRepresentation getDiagnosticsRepresentation();
+ OCRepresentation getMaintenanceRepresentation();
std::string getUri();
- void diagnosticsMonitor(int second);
+ void maintenanceMonitor(int second);
std::function< void() > factoryReset;
};
######################################################################
#build sampleapp
######################################################################
-conserver = linux_sample_env.Program('con-server', ['ConfigurationCollection.cpp', 'DiagnosticsCollection.cpp', 'FactorySetCollection.cpp', 'con-server.cpp'])
+conserver = linux_sample_env.Program('con-server', ['ConfigurationCollection.cpp', 'MaintenanceCollection.cpp', 'FactorySetCollection.cpp', 'con-server.cpp'])
conclient = linux_sample_env.Program('con-client', 'con-client.cpp')
bootstrapserver = linux_sample_env.Program('bootstrapserver', 'bootstrapserver.cpp')
Alias("ConServerApp", conserver)
OCStackResult sendResponse(std::shared_ptr< OCResourceRequest > pRequest);
OCEntityHandlerResult entityHandlerBootstrap(std::shared_ptr< OCResourceRequest > request);
-#define DefaultRegion "Seoul, Korea"
-#define DefaultSystemTime "00:00:00"
+#define DefaultDeviceName "Legacy Device"
#define DefaultLocation "37.256616, 127.052806"
+#define DefaultLocationName "Living Room"
#define DefaultCurrency "Won"
-
+#define DefaultRegion "Seoul, Korea"
class BootstrapResource
{
OCRepresentation getBootstrapRepresentation()
{
- m_bootstrapRep.setValue< std::string >("r", DefaultRegion);
- m_bootstrapRep.setValue< std::string >("st", DefaultSystemTime);
+ m_bootstrapRep.setValue< std::string >("n", DefaultDeviceName);
m_bootstrapRep.setValue< std::string >("loc", DefaultLocation);
+ m_bootstrapRep.setValue< std::string >("locn", DefaultLocationName);
m_bootstrapRep.setValue< std::string >("c", DefaultCurrency);
+ m_bootstrapRep.setValue< std::string >("r", DefaultRegion);
return m_bootstrapRep;
}
#include <vector>
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
+#include "ThingsConfiguration.h"
+#include "ThingsMaintenance.h"
+#include "GroupManager.h"
using namespace OC;
using namespace OIC;
const int SUCCESS_RESPONSE = 0;
-static ThingsManager* g_thingsmanager;
+static GroupManager* g_groupmanager;
+static ThingsConfiguration* g_thingsConf;
+static ThingsMaintenance* g_thingsMnt;
OCResourceHandle configurationCollectionHandle;
std::shared_ptr< OCResource > g_configurationCollection; // for a group of multiple resources
std::shared_ptr< OCResource > g_configurationResource; // For a single resource
-OCResourceHandle diagnosticsCollectionHandle;
-std::shared_ptr< OCResource > g_diagnosticsCollection; // for a group of multiple resources
-std::shared_ptr< OCResource > g_diagnosticsResource; // For a single resource
+OCResourceHandle maintenanceCollectionHandle;
+std::shared_ptr< OCResource > g_maintenanceCollection; // for a group of multiple resources
+std::shared_ptr< OCResource > g_maintenanceResource; // For a single resource
OCResourceHandle setCollectionHandle;
std::shared_ptr< OCResource > g_setCollection; // for a group of multiple resources
std::map< std::string, std::shared_ptr< OCResource > > resourceTable;
std::vector< OCResourceHandle > resourceHandleVector;
-typedef std::function<
- void(const HeaderOptions& headerOptions,
- const OCRepresentation& rep, const int eCode) > ConfigurationCallback;
-typedef std::function<
- void(const HeaderOptions& headerOptions,
- const OCRepresentation& rep, const int eCode) > DiagnosticsCallback;
-
typedef std::string ConfigurationName;
typedef std::string ConfigurationValue;
std::cout << "\tResource URI: " << rep.getUri() << std::endl;
+ if (rep.hasAttribute("n"))
+ std::cout << "\t\tDeviceName:" << rep.getValue< std::string >("n") << std::endl;
if (rep.hasAttribute("loc"))
std::cout << "\t\tLocation:" << rep.getValue< std::string >("loc") << std::endl;
- if (rep.hasAttribute("st"))
- std::cout << "\t\tSystemTime:" << rep.getValue< std::string >("st") << std::endl;
+ if (rep.hasAttribute("locn"))
+ std::cout << "\t\tLocationName:" << rep.getValue< std::string >("locn") << std::endl;
if (rep.hasAttribute("c"))
std::cout << "\t\tCurrency:" << rep.getValue< std::string >("c") << std::endl;
if (rep.hasAttribute("r"))
std::cout << "\tResource URI: " << rep.getUri() << std::endl;
+ if (rep.hasAttribute("n"))
+ std::cout << "\t\tDeviceName:" << rep.getValue< std::string >("n") << std::endl;
if (rep.hasAttribute("loc"))
std::cout << "\t\tLocation:" << rep.getValue< std::string >("loc") << std::endl;
- if (rep.hasAttribute("st"))
- std::cout << "\t\tSystemTime:" << rep.getValue< std::string >("st") << std::endl;
+ if (rep.hasAttribute("locn"))
+ std::cout << "\t\tLocationName:" << rep.getValue< std::string >("locn") << std::endl;
if (rep.hasAttribute("c"))
std::cout << "\t\tCurrency:" << rep.getValue< std::string >("c") << std::endl;
if (rep.hasAttribute("r"))
{
if (resource->uri() == "/core/a/configuration/resourceset")
g_configurationCollection = resource;
- else if (resource->uri() == "/core/a/diagnostics/resourceset")
- g_diagnosticsCollection = resource;
+ else if (resource->uri() == "/core/a/maintenance/resourceset")
+ g_maintenanceCollection = resource;
else if (resource->uri() == "/core/a/factoryset/resourceset")
g_setCollection = resource;
else
if (g_configurationResource == NULL)
g_configurationResource = resource;
}
- else if (resource->uri() == "/oic/diag")
+ else if (resource->uri() == "/oic/mnt")
{
- OCPlatform::bindResource(diagnosticsCollectionHandle,
+ OCPlatform::bindResource(maintenanceCollectionHandle,
foundResourceHandle);
- if (g_diagnosticsResource == NULL)
- g_diagnosticsResource = resource;
+ if (g_maintenanceResource == NULL)
+ g_maintenanceResource = resource;
}
else if (resource->uri() == "/factorySet")
{
{ OC::ServiceType::InProc, OC::ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos };
OCPlatform::Configure(cfg);
- g_thingsmanager = new ThingsManager();
+ //g_thingsmanager = new ThingsManager();
+ g_thingsConf = new ThingsConfiguration();
+ g_thingsMnt = new ThingsMaintenance();
+ g_groupmanager = new GroupManager();
//**************************************************************
pthread_mutex_unlock(&mutex_lock);
cout << endl << endl << "(0) Quit" << std::endl;
- cout << "(1) Find all resources(URI: /oic/con, /oic/diag, /factoryset)" << std::endl;
+ cout << "(1) Find all resources(URI: /oic/con, /oic/mnt, /factoryset)" << std::endl;
cout << "(2) Find all groups" << std::endl;
cout << "(3) Get a Configuration resource" << std::endl;
- cout << "(4) Update a region attribute value" << std::endl;
+ cout << "(4) Update a device name attribute value" << std::endl;
cout << "(5) FactoryReset (for the group)" << std::endl;
cout << "(6) Reboot (for the group)" << std::endl;
cout << "(10) Show Configuration Units" << std::endl;
DEFAULT_INTERFACE);
}
- // For Registering a collection resource for diagnostics resources
- if (diagnosticsCollectionHandle == NULL)
+ // For Registering a collection resource for maintenance resources
+ if (maintenanceCollectionHandle == NULL)
{
- string resourceURI = "/core/a/diagnostics/resourceset";
- string resourceTypeName = "core.diagnostics.resourceset";
+ string resourceURI = "/core/a/maintenance/resourceset";
+ string resourceTypeName = "core.maintenance.resourceset";
string resourceInterface = BATCH_INTERFACE;
- OCPlatform::registerResource(diagnosticsCollectionHandle, resourceURI,
+ OCPlatform::registerResource(maintenanceCollectionHandle, resourceURI,
resourceTypeName, resourceInterface, NULL,
//&entityHandler, // entityHandler
OC_DISCOVERABLE);
- OCPlatform::bindInterfaceToResource(diagnosticsCollectionHandle, GROUP_INTERFACE);
- OCPlatform::bindInterfaceToResource(diagnosticsCollectionHandle, DEFAULT_INTERFACE);
+ OCPlatform::bindInterfaceToResource(maintenanceCollectionHandle, GROUP_INTERFACE);
+ OCPlatform::bindInterfaceToResource(maintenanceCollectionHandle, DEFAULT_INTERFACE);
}
// For Registering a collection resource for set resources
OCPlatform::bindInterfaceToResource(setCollectionHandle, DEFAULT_INTERFACE);
}
- types.push_back("oic.con");
- types.push_back("oic.diag");
+ types.push_back("oic.wk.con");
+ types.push_back("oic.wk.mnt");
types.push_back("factorySet");
std::cout << "Finding Configuration Resource... " << std::endl;
- std::cout << "Finding Diagnostics Resource... " << std::endl;
+ std::cout << "Finding Maintenance Resource... " << std::endl;
std::cout << "Finding Set Resource... " << std::endl;
- g_thingsmanager->findCandidateResources(types, &onFoundCandidateResource, 5);
+ g_groupmanager->findCandidateResources(types, &onFoundCandidateResource, 5);
pthread_mutex_lock(&mutex_lock);
isWaiting = 1;
{
std::vector< std::string > types;
types.push_back("core.configuration.resourceset");
- types.push_back("core.diagnostics.resourceset");
+ types.push_back("core.maintenance.resourceset");
types.push_back("core.factoryset.resourceset");
- g_thingsmanager->findCandidateResources(types, &onFoundCollectionResource, 5);
+ g_groupmanager->findCandidateResources(types, &onFoundCollectionResource, 5);
std::cout << "Finding Collection resource... " << std::endl;
-
+
pthread_mutex_lock(&mutex_lock);
isWaiting = 1;
pthread_mutex_unlock(&mutex_lock);
configurations.push_back(name);
- if (g_thingsmanager->getConfigurations(g_configurationCollection, configurations, &onGet)
+ if (g_thingsConf->getConfigurations(g_configurationCollection, configurations, &onGet)
!= OC_STACK_ERROR)
{
pthread_mutex_lock(&mutex_lock);
}
else if (g_Steps == 4)
{
- ConfigurationName name = "r";
- ConfigurationValue value = "U.S.A (new region)";
+ ConfigurationName name = "n";
+ ConfigurationValue value = "OIC Device";
if(g_configurationCollection == NULL)
{
continue;
}
- std::cout << "For example, change region resource's value" << std::endl;
+ std::cout << "For example, change a device name" << std::endl;
std::cout << g_configurationCollection->uri() << std::endl;
std::map< ConfigurationName, ConfigurationValue > configurations;
configurations.insert(std::make_pair(name, value));
- if (g_thingsmanager->updateConfigurations(g_configurationCollection, configurations,
+ if (g_thingsConf->updateConfigurations(g_configurationCollection, configurations,
&onUpdate) != OC_STACK_ERROR)
{
pthread_mutex_lock(&mutex_lock);
else if (g_Steps == 5)
{
// factory reset
- if(g_diagnosticsCollection == NULL)
+ if(g_maintenanceCollection == NULL)
{
std::cout<<"Note that you first create a group to use this command." << std::endl;
continue;
}
- if (g_thingsmanager->factoryReset(g_diagnosticsCollection, &onFactoryReset)
+ if (g_thingsMnt->factoryReset(g_maintenanceCollection, &onFactoryReset)
!= OC_STACK_ERROR)
{
pthread_mutex_lock(&mutex_lock);
else if (g_Steps == 6)
{
// reboot
- if(g_diagnosticsCollection == NULL)
+ if(g_maintenanceCollection == NULL)
{
std::cout<<"Note that you first create a group to use this command." << std::endl;
continue;
}
- if (g_thingsmanager->reboot(g_diagnosticsCollection, &onReboot) != OC_STACK_ERROR)
+ if (g_thingsMnt->reboot(g_maintenanceCollection, &onReboot) != OC_STACK_ERROR)
{
pthread_mutex_lock(&mutex_lock);
isWaiting = 0;
}
else if (g_Steps == 10)
{
- std::cout << g_thingsmanager->getListOfSupportedConfigurationUnits() << std::endl;
+ std::cout << g_thingsConf->getListOfSupportedConfigurationUnits() << std::endl;
}
}
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
+#include "ThingsConfiguration.h"
+#include "ThingsMaintenance.h"
#include "ConfigurationCollection.h"
-#include "DiagnosticsCollection.h"
+#include "MaintenanceCollection.h"
#include "FactorySetCollection.h"
using namespace OC;
// Default system configuration value's variables
// The variable's names should be same as the names of "extern" variables defined in
// "ConfigurationResource.h"
+
+std::string defaultDeviceName;
std::string defaultLocation;
+std::string defaultLocationName;
std::string defaultRegion;
-std::string defaultSystemTime;
std::string defaultCurrency;
-static ThingsManager* g_thingsmanager;
+static ThingsConfiguration* g_thingsConf;
// Forward declaring the entityHandler (Configuration)
bool prepareResponseForResource(std::shared_ptr< OCResourceRequest > request);
OCEntityHandlerResult entityHandlerForResource(std::shared_ptr< OCResourceRequest > request);
ConfigurationResource *myConfigurationResource;
-DiagnosticsResource *myDiagnosticsResource;
+MaintenanceResource *myMaintenanceResource;
FactorySetResource *myFactorySetResource;
typedef std::function< void(OCRepresentation&) > putFunc;
res = std::bind(&ConfigurationResource::getConfigurationRepresentation,
myConfigurationResource);
}
- else if (uri == myDiagnosticsResource->getUri())
+ else if (uri == myMaintenanceResource->getUri())
{
- res = std::bind(&DiagnosticsResource::getDiagnosticsRepresentation,
- myDiagnosticsResource);
+ res = std::bind(&MaintenanceResource::getMaintenanceRepresentation,
+ myMaintenanceResource);
}
return res;
res = std::bind(&ConfigurationResource::setConfigurationRepresentation,
myConfigurationResource, std::placeholders::_1);
}
- else if (uri == myDiagnosticsResource->getUri())
+ else if (uri == myMaintenanceResource->getUri())
{
- res = std::bind(&DiagnosticsResource::setDiagnosticsRepresentation,
- myDiagnosticsResource, std::placeholders::_1);
+ res = std::bind(&MaintenanceResource::setMaintenanceRepresentation,
+ myMaintenanceResource, std::placeholders::_1);
}
return res;
std::cout << "\n\nGET request was successful" << std::endl;
std::cout << "\tResource URI: " << rep.getUri() << std::endl;
+ defaultDeviceName = rep.getValue< std::string >("n");
+ defaultLocation = rep.getValue< std::string >("loc");
+ defaultLocationName = rep.getValue< std::string >("locn");
defaultRegion = rep.getValue< std::string >("r");
- defaultSystemTime = rep.getValue< std::string >("st");
defaultCurrency = rep.getValue< std::string >("c");
- defaultLocation = rep.getValue< std::string >("loc");
+ std::cout << "\DeviceName : " << defaultDeviceName << std::endl;
std::cout << "\tLocation : " << defaultLocation << std::endl;
- std::cout << "\tSystemTime : " << defaultSystemTime << std::endl;
+ std::cout << "\tLocationName : " << defaultLocationName << std::endl;
std::cout << "\tCurrency : " << defaultCurrency << std::endl;
std::cout << "\tRegion : " << defaultRegion << std::endl;
{ OC::ServiceType::InProc, OC::ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos };
OCPlatform::Configure(cfg);
- g_thingsmanager = new ThingsManager();
+ g_thingsConf = new ThingsConfiguration();
//**************************************************************
if (getuid() != 0)
std::cout << endl << endl << "(0) Quit" << std::endl;
std::cout << "(1) Bootstrap" << std::endl;
- std::cout << "(2) Create Configuration Resources" << std::endl;
+ std::cout << "(2) Create Configuration/Maintenance Resources" << std::endl;
cin >> g_Steps;
}
else if (g_Steps == 1)
{
- if( g_thingsmanager->doBootstrap(&onBootstrap) == OC_STACK_OK)
+ if( g_thingsConf->doBootstrap(&onBootstrap) == OC_STACK_OK)
{
pthread_mutex_lock(&mutex_lock);
isWaiting = 1;
myConfigurationResource = new ConfigurationResource();
myConfigurationResource->createResources(&entityHandlerForResource);
- myDiagnosticsResource = new DiagnosticsResource();
- myDiagnosticsResource->createResources(&entityHandlerForResource);
-
+ myMaintenanceResource = new MaintenanceResource();
+ myMaintenanceResource->createResources(&entityHandlerForResource);
myFactorySetResource = new FactorySetResource();
myFactorySetResource->createResources(&entityHandlerForResource);
- myDiagnosticsResource->factoryReset = std::function < void()
+ myMaintenanceResource->factoryReset = std::function < void()
> (std::bind(&ConfigurationResource::factoryReset,
myConfigurationResource));
#include "timer.h"
-#include <ThingsManager.h>
+#include <GroupManager.h>
using namespace std;
using namespace OC;
shared_ptr<OCResource> g_resource;
vector<string> lights;
-ThingsManager *thingsMgr = new ThingsManager();
+GroupManager *groupMgr = new GroupManager();
void onGet(const HeaderOptions& opt, const OCRepresentation &rep,
const int eCode);
if (rep.getValue("ActionSet", plainText))
{
- ActionSet *actionset = thingsMgr->getActionSetfromString(plainText);
+ ActionSet *actionset = groupMgr->getActionSetfromString(plainText);
if (actionset != NULL)
{
cout << endl << "\tACTIONSET NAME :: "
void Scheduled_AllbulbOff()
{
- thingsMgr->executeActionSet(g_resource, "AllBulbOffScheduledCall", &onPost);
+ groupMgr->executeActionSet(g_resource, "AllBulbOffScheduledCall", &onPost);
}
void Scheduled_AllbulbOffEx()
{
- thingsMgr->executeActionSet(g_resource, "AllBulbOffScheduledCall", 10, &onPost);
+ groupMgr->executeActionSet(g_resource, "AllBulbOffScheduledCall", 10, &onPost);
}
void CancelScheduled_AllBulbOff()
{
- thingsMgr->cancelActionSet(g_resource, "AllBulbOffScheduledCall", &onPost);
+ groupMgr->cancelActionSet(g_resource, "AllBulbOffScheduledCall", &onPost);
}
void Recursive_allBulbOn()
{
- thingsMgr->executeActionSet(g_resource, "AllBulbOnRecursiveCall", &onPost);
+ groupMgr->executeActionSet(g_resource, "AllBulbOnRecursiveCall", &onPost);
}
void Recursive_allBulbOnEx()
{
- thingsMgr->executeActionSet(g_resource, "AllBulbOnRecursiveCall", 10, &onPost);
+ groupMgr->executeActionSet(g_resource, "AllBulbOnRecursiveCall", 10, &onPost);
}
void CancelRecursive_allBulbOn()
{
- thingsMgr->cancelActionSet(g_resource, "AllBulbOnRecursiveCall", &onPost);
+ groupMgr->cancelActionSet(g_resource, "AllBulbOnRecursiveCall", &onPost);
}
void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep,
}
if (g_resource)
{
- thingsMgr->addActionSet(g_resource, allBulbOff, onPut);
+ groupMgr->addActionSet(g_resource, allBulbOff, onPut);
}
delete allBulbOff;
}
if (g_resource)
{
- thingsMgr->addActionSet(g_resource, allBulbOff, onPut);
+ groupMgr->addActionSet(g_resource, allBulbOff, onPut);
}
delete allBulbOff;
}
if (g_resource)
{
- thingsMgr->addActionSet(g_resource, allBulbOff, onPut);
+ groupMgr->addActionSet(g_resource, allBulbOff, onPut);
}
delete allBulbOff;
}
if (g_resource)
{
- thingsMgr->addActionSet(g_resource, allBulbOn, onPut);
+ groupMgr->addActionSet(g_resource, allBulbOn, onPut);
}
delete allBulbOn;
// Find lights for group creation.
vector<string> types;
types.push_back("core.light");
- thingsMgr->findCandidateResources(types, &foundResources, 5);
+ groupMgr->findCandidateResources(types, &foundResources, 5);
OCStackResult res = OCPlatform::registerResource(resourceHandle, resourceURI,
resourceTypeName, resourceInterface, NULL, OC_DISCOVERABLE);
}
else if (n == 6)
{
- thingsMgr->getActionSet(g_resource, "AllBulbOff", onPost);
+ groupMgr->getActionSet(g_resource, "AllBulbOff", onPost);
}
else if (n == 7)
{
- thingsMgr->deleteActionSet(g_resource, "AllBulbOff", onPut);
+ groupMgr->deleteActionSet(g_resource, "AllBulbOff", onPut);
}
else if (n == 8)
{
+++ /dev/null
-##
-# linux sample app build script
-##
-
-Import('env')
-
-# Add third party libraries
-lib_env = env.Clone()
-SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
-linux_sample_env = lib_env.Clone()
-
-######################################################################
-# Build flags
-######################################################################
-linux_sample_env.AppendUnique(CPPPATH = ['include'])
-linux_sample_env.AppendUnique(CPPPATH = ['../../../../../extlibs/timer'])
-linux_sample_env.AppendUnique(CPPPATH = ['../../../sdk/inc'])
-linux_sample_env.AppendUnique(CPPPATH = ['../../../sdk/src'])
-linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-DLINUX', '-pthread'])
-linux_sample_env.AppendUnique(CPPDEFINES = ['LINUX'])
-linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
-linux_sample_env.AppendUnique(LIBS = ['libTGMSDKLibrary', 'oc', 'octbstack',
- 'connectivity_abstraction',
- 'libcoap', 'liboc_logger', 'dl', 'pthread'])
-if env.get('SECURED') == '1':
- linux_sample_env.AppendUnique(LIBS = ['tinydtls'])
-
-# On some platforms link order can miss functions so librt needs to be
-# re-scanned at the end if present. gcc 4.6 is one with this issue.
-if 'rt' in linux_sample_env.get('LIBS'):
- linux_sample_env.Append(LIBS = ['rt'])
-
-######################################################################
-#build sampleapp
-######################################################################
-group = linux_sample_env.Program('group', 'group.cpp')
-musicplayer = linux_sample_env.Program('musicplayer', 'musicplayer.cpp')
-phone = linux_sample_env.Program('phone', 'phone.cpp')
-speaker = linux_sample_env.Program('speaker', 'speaker.cpp')
-Alias("GroupApp", group)
-Alias("MusicplayerApp", musicplayer)
-Alias("PhoneApp", phone)
-Alias("SpeakerApp", speaker)
-env.AppendTarget('GroupApp')
-env.AppendTarget('MusicplayerApp')
-env.AppendTarget('PhoneApp')
-env.AppendTarget('SpeakerApp')
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-#include <string>
-#include <cstdlib>
-#include <pthread.h>
-#include "OCPlatform.h"
-#include "OCApi.h"
-#include "ThingsManager.h"
-
-using namespace OC;
-using namespace OIC;
-
-static ThingsManager* gThingManager = NULL;
-
-static std::vector< OCResourceHandle > gResourceHandleList;
-
-static std::string collectionResourceType = "core.group";
-
-void onFindResource(std::shared_ptr< OCResource > resource)
-{
- cout << "onFindResource" << endl;
-
- try
- {
- if (resource)
- {
- OCResourceHandle resourceHandle;
- OCStackResult result = OCPlatform::registerResource(resourceHandle, resource);
- if (OC_STACK_OK == result)
- {
- cout << "onFindResource : Resource creation was successful\n";
- }
- else
- {
- cout << "onFindResource : Resource creation was unsuccessful\n";
- return;
- }
-
- result = gThingManager->joinGroup(collectionResourceType, resourceHandle);
- if (OC_STACK_OK == result)
- {
- cout << "onFindResource : Joining group was successful\n";
- }
- else
- {
- cout << "onFindResource : Joining group was unsuccessful\n";
-
- OCPlatform::unregisterResource(resourceHandle);
- return;
- }
-
- gResourceHandleList.push_back(resourceHandle);
- }
- else
- {
- cout << "onFindResource : There is no found resource." << endl;
- }
- }catch (std::exception& e)
- {
- std::cout << "Exception: " << e.what() << std::endl;
- }
-}
-
-int main(int argc, char* argv[])
-{
- // Create PlatformConfig object
- PlatformConfig cfg
- { OC::ServiceType::InProc, OC::ModeType::Both/*OC::ModeType::Server*/, "0.0.0.0", 0,
- OC::QualityOfService::LowQos };
-
- OCPlatform::Configure(cfg);
- gThingManager = new ThingsManager();
-
- int selectedMenu;
- OCStackResult result;
-
- try
- {
- while (true)
- {
- // some operations
- cout << "(1) CREATE GROUP " << endl;
- cout << "(11) FIND MUSIC PLAYER & JOIN GROUP | (12) FIND SPEAKER & JOIN GROUP" << endl;
- cout << "(21) LEAVE GROUP - MUSIC PLAYER | (22) LEAVE GROUP - SPEAKER" << endl;
- cout << "(31) DELETE GROUP " << endl;
-
- std::cin >> selectedMenu;
-
- if (selectedMenu == 1)
- {
- result = gThingManager->createGroup(collectionResourceType);
- if (OC_STACK_OK == result)
- {
- cout << "Group creation was successful\n";
- }
- else
- {
- cout << "Group creation was unsuccessful\n";
- }
- }
- else if (selectedMenu == 11)
- {
- ostringstream query;
- query << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.musicplayer";
-
- cout << query.str() << endl;
- result = OCPlatform::findResource("",
- query.str(),
- CT_DEFAULT,
- onFindResource);
-
- if (OC_STACK_OK == result)
- {
- cout << "Finding music player was successful\n";
- }
- else
- {
- cout << "Finding music player was unsuccessful\n";
- }
- }
- else if (selectedMenu == 12)
- {
- ostringstream query;
- query << OC_RSRVD_WELL_KNOWN_URI << "?rt=core.speaker";
- result = OCPlatform::findResource("",
- query.str(),
- CT_DEFAULT,
- onFindResource);
-
- if (OC_STACK_OK == result)
- {
- cout << "Finding speaker was successful\n";
- }
- else
- {
- cout << "Finding speaker was unsuccessful\n";
- }
- }
- else if (selectedMenu == 21)
- {
- std::vector< OCResourceHandle >::iterator It;
- OCResourceHandle resourceHandle;
- for (It = gResourceHandleList.begin(); It != gResourceHandleList.end(); ++It)
- {
- resourceHandle = (*It);
- std::string mpType = "core.musicplayer";
- std::string type = OCGetResourceTypeName(resourceHandle, 0);
- if (0 == mpType.compare(type))
- {
- result = gThingManager->leaveGroup(collectionResourceType, resourceHandle);
- if (OC_STACK_OK == result)
- {
- cout << "Leaving group of music player was successful\n";
- }
- else
- {
- cout << "Leaving group of music player was unsuccessful\n";
- }
- break;
- }
- }
-
- if(It == gResourceHandleList.end())
- continue;
-
- gResourceHandleList.erase(It);
- result = OCPlatform::unregisterResource(resourceHandle);
- if (OC_STACK_OK == result)
- {
- cout << "Unregistering music player was successful\n";
- }
- else
- {
- cout << "Unregistering music player was unsuccessful\n";
- }
- }
- else if (selectedMenu == 22)
- {
- std::vector< OCResourceHandle >::iterator It;
- OCResourceHandle resourceHandle;
- for (It = gResourceHandleList.begin(); It != gResourceHandleList.end(); ++It)
- {
- resourceHandle = (*It);
- std::string mpType = "core.speaker";
- std::string type = OCGetResourceTypeName(resourceHandle, 0);
- if (0 == mpType.compare(type))
- {
- result = gThingManager->leaveGroup(collectionResourceType, resourceHandle);
- if (OC_STACK_OK == result)
- {
- cout << "Leaving group of speaker was successful\n";
- }
- else
- {
- cout << "Leaving group of speaker was unsuccessful\n";
- }
- break;
- }
- }
-
- if(It == gResourceHandleList.end())
- continue;
-
- gResourceHandleList.erase(It);
- result = OCPlatform::unregisterResource(resourceHandle);
- if (OC_STACK_OK == result)
- {
- cout << "Unregistering speaker was successful\n";
- }
- else
- {
- cout << "Unregistering speaker was unsuccessful\n";
- }
- }
- else if (selectedMenu == 31)
- {
- gThingManager->deleteGroup(collectionResourceType);
- }
- }
- }
- catch (OCException& e)
- {
- std::cout << "Exception: " << e.what() << std::endl;
- }
-
- return 0;
-}
-
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-#include <string>
-#include <cstdlib>
-#include <pthread.h>
-#include "OCPlatform.h"
-#include "OCApi.h"
-#include "ThingsManager.h"
-
-using namespace OC;
-
-OCEntityHandlerResult mpEntityHandler(const std::shared_ptr< OCResourceRequest > request)
-{
- cout << "mpEntityHandler:\n";
-
- if (request)
- {
- // Get the request type and request flag
- std::string requestType = request->getRequestType();
- int requestFlag = request->getRequestHandlerFlag();
- std::string action;
-
- if (requestFlag == RequestHandlerFlag::RequestFlag)
- {
- cout << "\trequestFlag : Request\n";
-
- OCRepresentation rp = request->getResourceRepresentation();
-
- // If the request type is GET
- if (requestType == "GET")
- {
- cout << "\t\trequestType : GET\n";
- }
- else if (requestType == "PUT")
- {
- cout << "\t\trequestType : PUT\n";
-
- action = rp.getValue< std::string >("play");
- cout << "\t\t\tplay : " << action << endl;
- }
- else if (requestType == "POST")
- {
- cout << "\t\trequestType : POST\n";
- }
- else if (requestType == "DELETE")
- {
- cout << "\t\trequestType : DELETE\n";
- }
- }
- else if (requestFlag == RequestHandlerFlag::ObserverFlag)
- {
- cout << "\trequestFlag : Observer\n";
- }
- }
- else
- {
- cout << "Request invalid" << endl;
- }
-
- return OC_EH_OK;
-}
-
-int main(int argc, char* argv[])
-{
- // Create PlatformConfig object
- PlatformConfig cfg
- { OC::ServiceType::InProc, OC::ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos };
-
- OCPlatform::Configure(cfg);
-
- OCPlatform::startPresence(30);
-
- int selectedMenu;
- OCStackResult result;
- OCResourceHandle mpResourceHandle = NULL;
-
- try
- {
- while (true)
- {
- // some operations
- cout << "(1) CREATE MUSIC PLAYER | (2) DELETE MUSIC PLAYER" << endl;
-
- std::cin >> selectedMenu;
-
- if (selectedMenu == 1)
- {
- if (mpResourceHandle)
- {
- cout << "Music player resource is registered already." << endl;
- continue;
- }
-
- std::string resourceURi = "/core/musicplayer";
- std::string resourceTypeName = "core.musicplayer";
- std::string resourceInterface = DEFAULT_INTERFACE;
-
- result = OCPlatform::registerResource(mpResourceHandle, resourceURi,
- resourceTypeName, resourceInterface, mpEntityHandler,
- OC_DISCOVERABLE | OC_OBSERVABLE);
- if (OC_STACK_OK == result)
- {
- cout << "To register music player resource was successful\n";
- }
- else
- {
- cout << "To register music player resource was unsuccessful\n";
- }
- }
- else if (selectedMenu == 2)
- {
- if (NULL == mpResourceHandle)
- {
- cout
- << "Error! No resource to unregister. Register resource first!"
- << endl;
- continue;
- }
-
- result = OCPlatform::unregisterResource(mpResourceHandle);
- if (OC_STACK_OK == result)
- {
- cout << "To unregister music player resource was successful\n";
- }
- else
- {
- cout << "To unregister music player resource was unsuccessful\n";
- }
-
- mpResourceHandle = NULL;
- }
- }
- }
- catch (OCException& e)
- {
- std::cout << "Exception: " << e.what() << std::endl;
- }
-
- return 0;
-}
-
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-#include <string>
-#include <cstdlib>
-#include <pthread.h>
-#include "OCPlatform.h"
-#include "OCApi.h"
-#include "ThingsManager.h"
-
-using namespace OC;
-using namespace OIC;
-
-static ThingsManager* gThingManager = NULL;
-
-static OCResourceHandle gPhoneResourceHandle = NULL;
-
-static std::shared_ptr< OCResource > gFindGroup = NULL;
-
-static std::string collectionResourceType = "core.group";
-
-static ActionSet* gPlayStart;
-
-static ActionSet* gPlayStop;
-
-void presenceCallback(std::string msg, OCStackResult res)
-{
- std::cout << "Presence Callback: " << msg << "(" << res << ")" << std::endl;
-}
-
-void onFindGroup(std::shared_ptr< OCResource > resource)
-{
- if (resource)
- {
- if (NULL == gPhoneResourceHandle)
- {
- cout
- << "onFindGroup : Error! No resource to join group. Register resource first!"
- << endl;
- return;
- }
-
- if (gFindGroup)
- {
- cout << "onFindGroup : Found group is already saved." << endl;
- }
- else
- {
- cout << "onFindGroup : Found group is saved now." << endl;
- gFindGroup = resource;
- {
- OCStackResult res;
- res = gThingManager->subscribeCollectionPresence( resource, &presenceCallback);
-
- std::cout << "Return Value: " << res << std::endl;
- }
- }
-
- gThingManager->joinGroup(gFindGroup, gPhoneResourceHandle);
- }
- else
- {
- cout << "onFindGroup : Resource is invalid. So a new Group Resource has to be created."
- << endl;
- }
-}
-
-void onAction(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
-{
- if (eCode == OC_STACK_OK)
- {
- cout << "onAction" << endl;
- }
- else
- {
- cout << "onAction : error - " << eCode << endl;
- }
-}
-
-void onGetChild(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
-{
- if (eCode == OC_STACK_OK)
- {
- gPlayStart = new ActionSet();
- gPlayStop = new ActionSet();
-
- gPlayStart->actionsetName = "playstart";
- gPlayStop->actionsetName = "playstop";
-
- std::vector< OCRepresentation > childList = rep.getChildren();
- OCRepresentation child;
- std::string resourceURI;
-
- QueryParamsMap query;
- std::string playStart;
- std::string playStop;
-
- std::vector< std::string > types;
- std::string resType;
-
- OCStackResult result;
-
- for (unsigned int i = 0; i < childList.size(); ++i)
- {
-// cout << "\n\tchild resource - " << i + 1 << endl;
-
- child = childList.at(i);
- resourceURI = child.getUri();
-
-// cout << "\t\tURI of the resource: " << resourceURI << endl;
-
-// cout << "\t\tList of resource types: " << endl;
-
- types = child.getResourceTypes();
-
- for (unsigned int j = 0; j < types.size(); ++j)
- {
- resType = types.at(j);
-// cout << "\t\t\t" << resType << endl;
-
- if (std::string::npos != resType.find("musicplayer"))
- {
- Capability *pStartCapa = new Capability;
- pStartCapa->capability = "play";
- pStartCapa->status = "on";
-
- Action* pPlayStart = new Action();
- pPlayStart->target = resourceURI;
- pPlayStart->listOfCapability.push_back(pStartCapa);
-
- gPlayStart->listOfAction.push_back(pPlayStart);
-
- Capability *pStopCapa = new Capability;
- pStopCapa->capability = "play";
- pStopCapa->status = "off";
-
- Action* pPlayStop = new Action();
- pPlayStop->target = resourceURI;
- pPlayStop->listOfCapability.push_back(pStopCapa);
-
- gPlayStop->listOfAction.push_back(pPlayStop);
- }
- else if (std::string::npos != resType.find("speaker"))
- {
- Capability *pStartCapa = new Capability;
- pStartCapa->capability = "volume";
- pStartCapa->status = "50";
-
- Action* pPlayStart = new Action();
- pPlayStart->target = resourceURI;
- pPlayStart->listOfCapability.push_back(pStartCapa);
-
- gPlayStart->listOfAction.push_back(pPlayStart);
-
- Capability *pStopCapa = new Capability;
- pStopCapa->capability = "volume";
- pStopCapa->status = "0";
-
- Action* pPlayStop = new Action();
- pPlayStop->target = resourceURI;
- pPlayStop->listOfCapability.push_back(pStopCapa);
-
- gPlayStop->listOfAction.push_back(pPlayStop);
- }
- }
- }
-
-// std::string temp = gThingManager->getStringFromActionSet (gPlayStart);
-// cout << "play start - " << temp << endl;
-
-// temp = gThingManager->getStringFromActionSet (gPlayStop);
-// cout << "play stop - " << temp << endl;
-
- if (0 == gPlayStart->listOfAction.empty())
- {
- result = gThingManager->addActionSet(gFindGroup, gPlayStart, onAction);
- if (OC_STACK_OK == result)
- {
- cout << "addActionSet(gPlayStart) was successful\n";
- }
- else
- {
- cout << "addActionSet(gPlayStart) was unsuccessful. result = " << result << endl;
- }
- }
-
- if (0 == gPlayStop->listOfAction.empty())
- {
- result = gThingManager->addActionSet(gFindGroup, gPlayStop, onAction);
- if (OC_STACK_OK == result)
- {
- cout << "addActionSet(gPlayStop) was successful\n";
- }
- else
- {
- cout << "addActionSet(gPlayStop) was unsuccessful. result = " << result << endl;
- }
- }
- }
- else
- {
- cout << "onGetChild : error - " << eCode << endl;
- }
-}
-
-int main(int argc, char* argv[])
-{
- // Create PlatformConfig object
- PlatformConfig cfg
- { OC::ServiceType::InProc, OC::ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos };
-
- OCPlatform::Configure(cfg);
- gThingManager = new ThingsManager();
-
- int selectedMenu;
- OCStackResult result;
-
- try
- {
- while (true)
- {
- // some operations
- cout << "(1) CREATE PHONE" << endl;
- cout
- << "(11) FIND & JOIN GROUP | (12) ADD GROUP ACTION | (13) PLAY START"
- << " | (14) PLAY STOP"<< endl;
- cout << "(15) DELETE GROUP ACTION | (16) LEAVE GROUP" << endl;
- cout << "(21) DELETE PHONE" << endl;
-
- std::cin >> selectedMenu;
-
- if (selectedMenu == 1)
- {
- if (gPhoneResourceHandle)
- {
- cout << "Phone resource is registered already." << endl;
- continue;
- }
-
- std::string resourceURi = "/core/phone";
- std::string resourceTypeName = "core.phone";
- std::string resourceInterface = DEFAULT_INTERFACE;
-
- result = OCPlatform::registerResource(gPhoneResourceHandle, resourceURi,
- resourceTypeName, resourceInterface,
- NULL, OC_DISCOVERABLE | OC_OBSERVABLE);
-
- if (OC_STACK_OK == result)
- {
- cout << "To register phone resource was successful\n";
- }
- else
- {
- cout << "To register phone resource was unsuccessful. result = " << result
- << endl;
- }
- }
- else if (selectedMenu == 11)
- {
- std::vector< std::string > types;
- types.clear();
- types.push_back(collectionResourceType);
-
- result = gThingManager->findGroup(types, &onFindGroup);
- if (OC_STACK_OK == result)
- {
- cout << "Finding group was successful\n";
- }
- else
- {
- cout << "Finding group was unsuccessful. result = " << result << endl;
- }
- }
- else if (selectedMenu == 12)
- {
- if (!gFindGroup)
- {
- cout << "gFindGroup is NULL. Please process step 1 and step 11 first." << endl;
- continue;
- }
-
- QueryParamsMap queryParamsMap;
- result = gFindGroup->get("", DEFAULT_INTERFACE, queryParamsMap, onGetChild);
- if (OC_STACK_OK == result)
- {
- cout << "gFindGroup->get was successful\n";
- }
- else
- {
- cout << "gFindGroup->get was unsuccessful. result = " << result << endl;
- }
- }
- else if (selectedMenu == 13)
- {
- if (!gFindGroup)
- {
- cout << "gFindGroup is NULL. Please process step 1 and step 11 first." << endl;
- continue;
- }
-
- if (!gPlayStart)
- {
- cout << "gPlayStart is NULL. Please process step 12 first." << endl;
- continue;
- }
-
- result = gThingManager->executeActionSet(gFindGroup, "playstart", onAction);
- if (OC_STACK_OK == result)
- {
- cout << "DoAction(playstart) was successful\n";
- }
- else
- {
- cout << "DoAction(playstart) was unsuccessful. result = " << result << endl;
- }
- }
- else if (selectedMenu == 14)
- {
- if (!gFindGroup)
- {
- cout << "gFindGroup is NULL. Please process step 1 and step 11 first." << endl;
- continue;
- }
-
- if (!gPlayStop)
- {
- cout << "gPlayStop is NULL. Please process step 12 first." << endl;
- continue;
- }
-
- result = gThingManager->executeActionSet(gFindGroup, "playstop", onAction);
- if (OC_STACK_OK == result)
- {
- cout << "DoAction(playstop) was successful\n";
- }
- else
- {
- cout << "DoAction(playstop) was unsuccessful. result = " << result << endl;
- }
- }
- else if (selectedMenu == 15)
- {
- if (!gFindGroup)
- {
- cout << "gFindGroup is NULL. Please process step 1 and step 11 first." << endl;
- continue;
- }
-
- if (!gPlayStart)
- {
- cout << "gPlayStart is NULL. Please process step 12 first." << endl;
- continue;
- }
-
- if (!gPlayStop)
- {
- cout << "gPlayStop is NULL. Please process step 12 first." << endl;
- continue;
- }
-
- result = gThingManager->deleteActionSet(gFindGroup, "playstart", onAction);
- if (OC_STACK_OK == result)
- {
- cout << "Delete Action(playstart) was successful\n";
- }
- else
- {
- cout << "Delete Action(playstart) was unsuccessful. result = " << result
- << endl;
- }
-
- result = gThingManager->deleteActionSet(gFindGroup, "playstop", onAction);
- if (OC_STACK_OK == result)
- {
- cout << "Delete Action(playstop) was successful\n";
- }
- else
- {
- cout << "Delete Action(playstop) was unsuccessful. result = " << result << endl;
- }
-
- Action* a;
- Capability* c;
-
- for (auto actionIter = gPlayStart->listOfAction.begin();
- actionIter != gPlayStart->listOfAction.end(); ++actionIter)
- {
- a = (*actionIter);
-
- for (auto capaIter = a->listOfCapability.begin();
- capaIter != a->listOfCapability.end(); ++capaIter)
- {
- c = (*capaIter);
- delete c;
- }
-
- delete a;
- }
-
- delete gPlayStart;
- gPlayStart = NULL;
-
- for (auto actionIter = gPlayStop->listOfAction.begin();
- actionIter != gPlayStop->listOfAction.end(); ++actionIter)
- {
- a = (*actionIter);
-
- for (auto capaIter = a->listOfCapability.begin();
- capaIter != a->listOfCapability.end(); ++capaIter)
- {
- c = (*capaIter);
- delete c;
- }
-
- delete a;
- }
-
- delete gPlayStop;
- gPlayStop = NULL;
- }
- else if (selectedMenu == 16)
- {
- if (NULL == gPhoneResourceHandle)
- {
- cout
- << "Error! No resource to leave group. Register resource first!"
- << endl;
- continue;
- }
-
- result = gThingManager->leaveGroup(gFindGroup, collectionResourceType, gPhoneResourceHandle);
- if (OC_STACK_OK == result)
- {
- cout << "Leaving group was successful\n";
- }
- else
- {
- cout << "Leaving group was unsuccessful. result = " << result << endl;
- }
- }
- else if (selectedMenu == 21)
- {
- if (NULL == gPhoneResourceHandle)
- {
- cout
- << "Error! No resource to unregister. Register resource first!"
- << endl;
- continue;
- }
-
- result = OCPlatform::unregisterResource(gPhoneResourceHandle);
- if (OC_STACK_OK == result)
- {
- cout << "To unregister phone resource was successful\n";
- }
- else
- {
- cout << "To unregister phone resource was unsuccessful. result = " << result
- << endl;
- }
- gPhoneResourceHandle = NULL;
- }
- }
-
- }
- catch (OCException& e)
- {
- std::cout << "Exception: " << e.what() << std::endl;
- }
-
- return 0;
-}
-
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-#include <string>
-#include <cstdlib>
-#include <pthread.h>
-#include "OCPlatform.h"
-#include "OCApi.h"
-#include "ThingsManager.h"
-
-using namespace OC;
-
-OCEntityHandlerResult speakerEntityHandler(const std::shared_ptr< OCResourceRequest > request)
-{
- cout << "speakerEntityHandler:\n";
-
- if (request)
- {
- // Get the request type and request flag
- std::string requestType = request->getRequestType();
- int requestFlag = request->getRequestHandlerFlag();
- std::string action;
-
- if (requestFlag == RequestHandlerFlag::RequestFlag)
- {
- cout << "\trequestFlag : Request\n";
-
- OCRepresentation rp = request->getResourceRepresentation();
-
- // If the request type is GET
- if (requestType == "GET")
- {
- cout << "\t\trequestType : GET\n";
- }
- else if (requestType == "PUT")
- {
- cout << "\t\trequestType : PUT\n";
-
- action = rp.getValue< std::string >("volume");
- cout << "\t\t\tvolume : " << action << endl;
- }
- else if (requestType == "POST")
- {
- cout << "\t\trequestType : POST\n";
- }
- else if (requestType == "DELETE")
- {
- cout << "\t\trequestType : DELETE\n";
- }
- }
- else if (requestFlag == RequestHandlerFlag::ObserverFlag)
- {
- cout << "\trequestFlag : Observer\n";
- }
- }
- else
- {
- cout << "Request invalid" << endl;
- }
-
- return OC_EH_OK;
-}
-
-int main(int argc, char* argv[])
-{
-
- // Create PlatformConfig object
- PlatformConfig cfg
- { OC::ServiceType::InProc, OC::ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos };
-
- OCPlatform::Configure(cfg);
-
- OCPlatform::startPresence(30);
-
- int selectedMenu;
- OCStackResult result;
- OCResourceHandle speakerResourceHandle = NULL;
-
- try
- {
- while (true)
- {
- // some operations
- cout << "(1) CREATE SPEAKER | (2) DELETE SPEAKER" << endl;
-
- std::cin >> selectedMenu;
-
- if (selectedMenu == 1)
- {
- if (speakerResourceHandle)
- {
- cout << "Speaker resource is registered already." << endl;
- continue;
- }
-
- std::string resourceURi = "/core/speaker";
- std::string resourceTypeName = "core.speaker";
-
- std::string resourceInterface = DEFAULT_INTERFACE;
-
- result = OCPlatform::registerResource(speakerResourceHandle, resourceURi,
- resourceTypeName, resourceInterface, speakerEntityHandler,
- OC_DISCOVERABLE | OC_OBSERVABLE);
- if (OC_STACK_OK == result)
- {
- cout << "To register speaker resource was successful\n";
- }
- else
- {
- cout << "To register speaker resource was unsuccessful\n";
- }
- }
- else if (selectedMenu == 2)
- {
- if (NULL == speakerResourceHandle)
- {
- cout
- << "Error! No resource to unregister. Register resource first!"
- << endl;
- continue;
- }
-
- result = OCPlatform::unregisterResource(speakerResourceHandle);
- if (OC_STACK_OK == result)
- {
- cout << "To unregister speaker resource was successful\n";
- }
- else
- {
- cout << "To unregister speaker resource was unsuccessful\n";
- }
-
- speakerResourceHandle = NULL;
- }
- }
- }
- catch (OCException& e)
- {
- std::cout << "Exception: " << e.what() << std::endl;
- }
-
- return 0;
-}
-
<listOptionValue builtIn="false" value=""..\..\..\..\sdk\inc""/>
<listOptionValue builtIn="false" value=""..\..\..\..\sdk\src""/>
<listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\c_common""/>
<listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\stack\include""/>
<listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\logger\include""/>
<listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\occoap\include""/>
* limitations under the License.
*
******************************************************************/
-#ifndef __CONFIGURATION_RESOURCE_H__
-#define __CONFIGURATION_RESOURCE_H__
+#ifndef CONFIGURATION_RESOURCE_H__
+#define CONFIGURATION_RESOURCE_H__
#include <functional>
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
#pragma once
+#define DEFAULT_DEVICENAME "n"
+#define DEFAULT_LOCATION "loc"
+#define DEFAULT_LOCATIONNAME "locn"
+#define DEFAULT_CURRENCY "c"
+#define DEFAULT_REGION "r"
+
using namespace OC;
typedef std::function<OCEntityHandlerResult(std::shared_ptr< OCResourceRequest > request)>
ResourceEntityHandler;
-static std::string defaultURIPrefix = "/oic/con";
-static std::string defaultResourceTypePrefix = "oic.con";
+static std::string defaultConURI = "/oic/con";
+static std::string defaultConResourceType = "oic.wk.con";
+extern std::string defaultDeviceName;
extern std::string defaultLocation;
-extern std::string defaultSystemTime;
+extern std::string defaultLocationName;
extern std::string defaultCurrency;
extern std::string defaultRegion;
public:
// Configuration members
std::string m_configurationUri;
+ std::string m_deviceName;
std::string m_location;
- std::string m_systemTime;
+ std::string m_locationName;
std::string m_currency;
std::string m_region;
std::vector< std::string > m_configurationTypes;
void deleteResource();
};
-#endif // __CONFIGURATION_RESOURCE_H__
\ No newline at end of file
+#endif // CONFIGURATION_RESOURCE_H__
\ No newline at end of file
*
******************************************************************/
-#ifndef __CONSERVERAPP_H__
-#define __CONSERVERAPP_H__
+#ifndef CONSERVERAPP_H__
+#define CONSERVERAPP_H__
#include <app.h>
#include <Elementary.h>
#include "OCPlatform.h"
#include "OCApi.h"
-#include "thingsmanager.h"
#ifdef LOG_TAG
#undef LOG_TAG
#define ELM_DEMO_EDJ "opt/usr/apps/org.tizen.conserverapp/res/ui_controls.edj"
-#endif // __CONSERVERAPP_H__
+#endif // CONSERVERAPP_H__
\ No newline at end of file
* limitations under the License.
*
******************************************************************/
-#ifndef __FACTORYSET_RESOURCE_H__
-#define __FACTORYSET_RESOURCE_H__
+#ifndef FACTORYSET_RESOURCE_H__
+#define FACTORYSET_RESOURCE_H__
#include <functional>
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
#include "configurationresource.h"
#pragma once
void deleteResource();
};
-#endif // __FACTORYSET_RESOURCE_H__
\ No newline at end of file
+#endif // FACTORYSET_RESOURCE_H__
\ No newline at end of file
* limitations under the License.
*
******************************************************************/
-#ifndef __DIAGNOSTICS_RESOURCE_H__
-#define __DIAGNOSTICS_RESOURCE_H__
+#ifndef MAINTENANCE_RESOURCE_H__
+#define MAINTENANCE_RESOURCE_H__
#include <functional>
+#include <thread>
+#include <string>
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
#pragma once
+#define DEFAULT_REBOOT "rb"
+#define DEFAULT_FACTORYRESET "fr"
+#define DEFAULT_STARTCOLLECTION "ssc"
+
using namespace OC;
typedef std::function<OCEntityHandlerResult(std::shared_ptr< OCResourceRequest > request)>
static std::string defaultReboot = "false";
static std::string defaultStartStatCollection = "false";
-class DiagnosticsResource
+class MaintenanceResource
{
public:
- // Diagnostics members
- std::string m_diagnosticsUri;
+ // Maintenance members
+ std::string m_maintenanceUri;
std::string m_factoryReset;
std::string m_reboot;
std::string m_startStatCollection;
- std::vector< std::string > m_diagnosticsTypes;
- std::vector< std::string > m_diagnosticsInterfaces;
- OCResourceHandle m_diagnosticsHandle;
- OCRepresentation m_diagnosticsRep;
+ std::vector< std::string > m_maintenanceTypes;
+ std::vector< std::string > m_maintenanceInterfaces;
+ OCResourceHandle m_maintenanceHandle;
+ OCRepresentation m_maintenanceRep;
public:
- DiagnosticsResource();
+ MaintenanceResource();
void createResource(ResourceEntityHandler callback);
- void setDiagnosticsRepresentation(OCRepresentation &rep);
+ void setMaintenanceRepresentation(OCRepresentation &rep);
- OCRepresentation getDiagnosticsRepresentation();
+ OCRepresentation getMaintenanceRepresentation();
std::string getUri();
- void diagnosticsMonitor(int second);
+ void maintenanceMonitor(int second);
std::function< void() > factoryReset;
void deleteResource();
};
-#endif // __DIAGNOSTICS_RESOURCE_H__
\ No newline at end of file
+#endif // MAINTENANCE_RESOURCE_H__
\ No newline at end of file
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
using namespace OC;
// Constructor
ConfigurationResource::ConfigurationResource() :
- m_location(defaultLocation), m_systemTime(defaultSystemTime), m_currency(
- defaultCurrency), m_region(defaultRegion)
+ m_deviceName(defaultDeviceName), m_location(defaultLocation),
+ m_locationName(defaultLocationName), m_currency(defaultCurrency),
+ m_region(defaultRegion)
{
- m_configurationUri = "/oic/con"; // URI of the resource
- m_configurationTypes.push_back("oic.con"); // resource type name
+ m_configurationUri = defaultConURI; // URI of the resource
+ m_configurationTypes.push_back(defaultConResourceType); // resource type name
m_configurationInterfaces.push_back(DEFAULT_INTERFACE); // resource interface
- m_configurationRep.setValue("loc", m_location);
- m_configurationRep.setValue("st", m_systemTime);
- m_configurationRep.setValue("c", m_currency);
- m_configurationRep.setValue("r", m_region);
+ m_configurationRep.setValue(DEFAULT_DEVICENAME, m_deviceName);
+ m_configurationRep.setValue(DEFAULT_LOCATION, m_location);
+ m_configurationRep.setValue(DEFAULT_LOCATIONNAME, m_locationName);
+ m_configurationRep.setValue(DEFAULT_CURRENCY, m_currency);
+ m_configurationRep.setValue(DEFAULT_REGION, m_region);
m_configurationRep.setUri(m_configurationUri);
m_configurationRep.setResourceTypes(m_configurationTypes);
m_configurationRep.setResourceInterfaces(m_configurationInterfaces);
- m_configurationHandle = NULL;
+ m_configurationHandle = nullptr;
}
// Creates a ConfigurationResource
void ConfigurationResource::setConfigurationRepresentation(OCRepresentation &rep)
{
- string value;
+ std::string value;
- if (rep.getValue("loc", value))
+ if (rep.getValue(DEFAULT_DEVICENAME, value))
+ {
+ m_deviceName = value;
+ dlog_print(DLOG_INFO, "ConfigurationResource", "#### m_deviceName: %s",
+ m_deviceName.c_str());
+ }
+
+ if (rep.getValue(DEFAULT_LOCATION, value))
{
m_location = value;
dlog_print(DLOG_INFO, "ConfigurationResource", "#### m_location: %s",
m_location.c_str());
}
- if (rep.getValue("st", value))
+ if (rep.getValue(DEFAULT_LOCATIONNAME, value))
{
- dlog_print(DLOG_INFO, "ConfigurationResource", "#### SystemTime is not"
- "allowed to be written");
+ m_locationName = value;
+ dlog_print(DLOG_INFO, "ConfigurationResource", "#### m_locationName: %s",
+ m_locationName.c_str());
}
- if (rep.getValue("c", value))
+ if (rep.getValue(DEFAULT_CURRENCY, value))
{
m_currency = value;
dlog_print(DLOG_INFO, "ConfigurationResource", "#### m_currency: %s",
m_currency.c_str());
}
- if (rep.getValue("r", value))
+ if (rep.getValue(DEFAULT_REGION, value))
{
m_region = value;
dlog_print(DLOG_INFO, "ConfigurationResource", "#### m_region: %s",
OCRepresentation ConfigurationResource::getConfigurationRepresentation()
{
- m_configurationRep.setValue("loc", m_location);
- m_configurationRep.setValue("st", m_systemTime);
- m_configurationRep.setValue("c", m_currency);
- m_configurationRep.setValue("r", m_region);
+ m_configurationRep.setValue(DEFAULT_DEVICENAME, m_deviceName);
+ m_configurationRep.setValue(DEFAULT_LOCATION, m_location);
+ m_configurationRep.setValue(DEFAULT_LOCATIONNAME, m_locationName);
+ m_configurationRep.setValue(DEFAULT_CURRENCY, m_currency);
+ m_configurationRep.setValue(DEFAULT_REGION, m_region);
return m_configurationRep;
}
// Assigns default values to all the attributes of the configuration resource
void ConfigurationResource::factoryReset()
{
+ m_deviceName = defaultDeviceName;
m_location = defaultLocation;
- m_systemTime = defaultSystemTime;
+ m_locationName = defaultLocationName;
m_currency = defaultCurrency;
m_region = defaultRegion;
}
void ConfigurationResource::deleteResource()
{
// Unregister the resource
- if (NULL != m_configurationHandle)
+ if (nullptr != m_configurationHandle)
{
OCPlatform::unregisterResource(m_configurationHandle);
}
#include <tizen.h>
#include <pthread.h>
+#include "ThingsConfiguration.h"
+#include "ThingsMaintenance.h"
#include "configurationresource.h"
-#include "diagnosticsresource.h"
+#include "maintenanceresource.h"
#include "factorysetresource.h"
-using namespace std;
using namespace OC;
using namespace OIC;
/* Default system configuration value's variables
The variable's names should be same as the names of "extern" variables defined in
"configurationresource.h" */
+std::string defaultDeviceName;
std::string defaultLocation;
+std::string defaultLocationName;
std::string defaultRegion;
-std::string defaultSystemTime;
std::string defaultCurrency;
-static ThingsManager *g_thingsmanager;
+static ThingsConfiguration *g_thingsConf;
const int SUCCESS_RESPONSE = 0;
OCEntityHandlerResult entityHandlerForResource(std::shared_ptr< OCResourceRequest > request);
ConfigurationResource *myConfigurationResource;
-DiagnosticsResource *myDiagnosticsResource;
+MaintenanceResource *myMaintenanceResource;
FactorySetResource *myFactorySetResource;
typedef std::function< void(OCRepresentation &) > putFunc;
res = std::bind(&ConfigurationResource::getConfigurationRepresentation,
myConfigurationResource);
}
- else if (uri == myDiagnosticsResource->getUri())
+ else if (uri == myMaintenanceResource->getUri())
{
- res = std::bind(&DiagnosticsResource::getDiagnosticsRepresentation,
- myDiagnosticsResource);
+ res = std::bind(&MaintenanceResource::getMaintenanceRepresentation,
+ myMaintenanceResource);
}
return res;
res = std::bind(&ConfigurationResource::setConfigurationRepresentation,
myConfigurationResource, std::placeholders::_1);
}
- else if (uri == myDiagnosticsResource->getUri())
+ else if (uri == myMaintenanceResource->getUri())
{
- res = std::bind(&DiagnosticsResource::setDiagnosticsRepresentation,
- myDiagnosticsResource, std::placeholders::_1);
+ res = std::bind(&MaintenanceResource::setMaintenanceRepresentation,
+ myMaintenanceResource, std::placeholders::_1);
}
return res;
// Updates the log in the UI
void *updateLog(void *data)
{
- string *log = (string *)data;
- //Show the log
- elm_entry_entry_append(log_entry, log->c_str());
- elm_entry_cursor_end_set(log_entry);
+ std::string *log = (std::string *)data;
- dlog_print(DLOG_INFO, LOG_TAG, "%s", log->c_str());
+ if (nullptr == log)
+ {
+ dlog_print(DLOG_INFO, LOG_TAG, "#### No log !!!!");
+ }
+ else
+ {
+ //Show the log
+ elm_entry_entry_append(log_entry, log->c_str());
+ elm_entry_cursor_end_set(log_entry);
+ dlog_print(DLOG_INFO, LOG_TAG, "%s", log->c_str());
+ }
dlog_print(DLOG_INFO, LOG_TAG, "#### updateLog exit!!!!");
-
return NULL;
}
{
if (NULL != myConfigurationResource)
myConfigurationResource->deleteResource();
- if (NULL != myDiagnosticsResource)
- myDiagnosticsResource->deleteResource();
+ if (NULL != myMaintenanceResource)
+ myMaintenanceResource->deleteResource();
if (NULL != myFactorySetResource)
myFactorySetResource->deleteResource();
+
+ delete g_thingsConf;
}
static void
logMessage += "GET request was successful<br>";
logMessage += "URI : " + rep.getUri() + "<br>";
- defaultRegion = rep.getValue< std::string >("r");
- defaultSystemTime = rep.getValue< std::string >("st");
- defaultCurrency = rep.getValue< std::string >("c");
- defaultLocation = rep.getValue< std::string >("loc");
+ defaultRegion = rep.getValue< std::string >(DEFAULT_REGION);
+ defaultCurrency = rep.getValue< std::string >(DEFAULT_CURRENCY);
+ defaultLocation = rep.getValue< std::string >(DEFAULT_LOCATION);
+ defaultLocationName = rep.getValue< std::string >(DEFAULT_LOCATIONNAME);
+ defaultDeviceName = rep.getValue< std::string >(DEFAULT_DEVICENAME);
+ logMessage += "Device Name : " + defaultDeviceName + "<br>";
logMessage += "Location : " + defaultLocation + "<br>";
- logMessage += "SystemTime : " + defaultSystemTime + "<br>";
+ logMessage += "Location Name : " + defaultLocationName + "<br>";
logMessage += "currency : " + defaultCurrency + "<br>";
logMessage += "Region : " + defaultRegion + "<br>";
static void
doBootStrap_cb(void *data , Evas_Object *obj , void *event_info)
{
- OCStackResult result = g_thingsmanager->doBootstrap(&onBootStrapCallback);
+
+ if (NULL == g_thingsConf)
+ {
+ dlog_print(DLOG_ERROR, LOG_TAG, "#### doBootstrap returned g_thingsConf NULL check");
+ return;
+ }
+
+ OCStackResult result = g_thingsConf->doBootstrap(&onBootStrapCallback);
+
if (OC_STACK_OK == result)
{
dlog_print(DLOG_INFO, LOG_TAG, "#### doBootstrap returned OC_STACK_OK");
myConfigurationResource = new ConfigurationResource();
myConfigurationResource->createResource(&entityHandlerForResource);
- myDiagnosticsResource = new DiagnosticsResource();
- myDiagnosticsResource->createResource(&entityHandlerForResource);
+ myMaintenanceResource = new MaintenanceResource();
+ myMaintenanceResource->createResource(&entityHandlerForResource);
myFactorySetResource = new FactorySetResource();
myFactorySetResource->createResource(&entityHandlerForResource);
- myDiagnosticsResource->factoryReset = std::function < void()
+ myMaintenanceResource->factoryReset = std::function < void()
> (std::bind(&ConfigurationResource::factoryReset,
myConfigurationResource));
// Configure the OCPlatform
configure_platform();
- g_thingsmanager = new ThingsManager();
+ g_thingsConf = new ThingsConfiguration();
return true;
}
#include <functional>
#include <dlog.h>
+#include <string.h>
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
+#include "configurationresource.h"
using namespace OC;
void FactorySetResource::setFactorySetRepresentation(OCRepresentation &rep)
{
- string value;
+ std::string value;
- if (rep.getValue("loc", value))
+ if (rep.getValue(DEFAULT_DEVICENAME, value))
+ {
+ m_deviceName = value;
+ dlog_print(DLOG_INFO, "FactorySetResource", "#### m_deviceName: %s",
+ m_deviceName.c_str());
+ }
+
+ if (rep.getValue(DEFAULT_LOCATION, value))
{
m_location = value;
dlog_print(DLOG_INFO, "FactorySetResource", "#### m_location: %s",
m_location.c_str());
}
- if (rep.getValue("st", value))
+ if (rep.getValue(DEFAULT_LOCATIONNAME, value))
{
- dlog_print(DLOG_INFO, "FactorySetResource", "#### SystemTime is not"
- "allowed to be written");
+ m_locationName = value;
+ dlog_print(DLOG_INFO, "FactorySetResource", "#### m_locationName: %s",
+ m_locationName.c_str());
}
- if (rep.getValue("c", value))
+ if (rep.getValue(DEFAULT_CURRENCY, value))
{
m_currency = value;
dlog_print(DLOG_INFO, "FactorySetResource", "#### m_currency: %s",
m_currency.c_str());
}
- if (rep.getValue("r", value))
+ if (rep.getValue(DEFAULT_REGION, value))
{
m_region = value;
dlog_print(DLOG_INFO, "FactorySetResource", "#### m_region: %s",
OCRepresentation FactorySetResource::getFactorySetRepresentation()
{
- m_configurationRep.setValue("loc", m_location);
- m_configurationRep.setValue("st", m_systemTime);
- m_configurationRep.setValue("c", m_currency);
- m_configurationRep.setValue("r", m_region);
+ m_configurationRep.setValue(DEFAULT_DEVICENAME, m_deviceName);
+ m_configurationRep.setValue(DEFAULT_LOCATION, m_location);
+ m_configurationRep.setValue(DEFAULT_LOCATIONNAME, m_locationName);
+ m_configurationRep.setValue(DEFAULT_CURRENCY, m_currency);
+ m_configurationRep.setValue(DEFAULT_REGION, m_region);
return m_configurationRep;
}
*
******************************************************************/
-#include "diagnosticsresource.h"
+#include "maintenanceresource.h"
#include <functional>
#include <dlog.h>
+#include <thread>
+#include <string>
#include "conserverapp.h"
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
-extern string logMessage;
+using namespace OC;
+
+extern std::string logMessage;
extern void *updateLog(void *);
-using namespace OC;
+static std::string defaultMntURI = "/oic/mnt";
+static std::string defaultMntResourceType = "oic.wk.mnt";
// Constructor
-DiagnosticsResource::DiagnosticsResource() :
+MaintenanceResource::MaintenanceResource() :
m_factoryReset(defaultFactoryReset), m_reboot(defaultReboot),
m_startStatCollection(defaultStartStatCollection)
{
- m_diagnosticsUri = "/oic/diag"; // URI of the resource
- m_diagnosticsTypes.push_back("oic.diag"); // resource type name
- m_diagnosticsInterfaces.push_back(DEFAULT_INTERFACE); // resource interface
- m_diagnosticsRep.setValue("fr", m_factoryReset);
- m_diagnosticsRep.setValue("rb", m_reboot);
- m_diagnosticsRep.setValue("ssc", m_startStatCollection);
- m_diagnosticsRep.setUri(m_diagnosticsUri);
- m_diagnosticsRep.setResourceTypes(m_diagnosticsTypes);
- m_diagnosticsRep.setResourceInterfaces(m_diagnosticsInterfaces);
- m_diagnosticsHandle = NULL;
+ m_maintenanceUri = defaultMntURI; // URI of the resource
+ m_maintenanceTypes.push_back(defaultMntResourceType); // resource type name
+ m_maintenanceInterfaces.push_back(DEFAULT_INTERFACE); // resource interface
+ m_maintenanceRep.setValue(DEFAULT_FACTORYRESET, m_factoryReset);
+ m_maintenanceRep.setValue(DEFAULT_REBOOT, m_reboot);
+ m_maintenanceRep.setValue(DEFAULT_STARTCOLLECTION, m_startStatCollection);
+ m_maintenanceRep.setUri(m_maintenanceUri);
+ m_maintenanceRep.setResourceTypes(m_maintenanceTypes);
+ m_maintenanceRep.setResourceInterfaces(m_maintenanceInterfaces);
+ m_maintenanceHandle = NULL;
}
// Creates a DiagnosticResource
-void DiagnosticsResource::createResource(ResourceEntityHandler callback)
+void MaintenanceResource::createResource(ResourceEntityHandler callback)
{
using namespace OC::OCPlatform;
if (NULL == callback)
{
- dlog_print(DLOG_INFO, "DiagnosticsResource", "#### Callback should be binded");
+ dlog_print(DLOG_INFO, "MaintenanceResource", "#### Callback should be binded");
return;
}
// This will internally create and register the resource
- OCStackResult result = registerResource(m_diagnosticsHandle, m_diagnosticsUri,
- m_diagnosticsTypes[0], m_diagnosticsInterfaces[0],
+ OCStackResult result = registerResource(m_maintenanceHandle, m_maintenanceUri,
+ m_maintenanceTypes[0], m_maintenanceInterfaces[0],
callback, OC_DISCOVERABLE | OC_OBSERVABLE);
if (OC_STACK_OK != result)
{
- dlog_print(DLOG_INFO, "DiagnosticsResource", "#### Resource creation"
- "(configuration) was unsuccessful");
+ dlog_print(DLOG_INFO, "MaintenanceResource", "#### Resource creation"
+ "(maintenance) was unsuccessful");
return;
}
- thread exec(
+ std::thread exec(
std::function< void(int second) >(
- std::bind(&DiagnosticsResource::diagnosticsMonitor, this,
+ std::bind(&MaintenanceResource::maintenanceMonitor, this,
std::placeholders::_1)), 1);
exec.detach();
- dlog_print(DLOG_INFO, "DiagnosticsResource", "#### Diagnostics Resource is Created");
+ dlog_print(DLOG_INFO, "MaintenanceResource", "#### maintenance Resource is Created");
}
-void DiagnosticsResource::setDiagnosticsRepresentation(OCRepresentation &rep)
+void MaintenanceResource::setMaintenanceRepresentation(OCRepresentation &rep)
{
- string value;
+ std::string value;
- if (rep.getValue("fr", value))
+ if (rep.getValue(DEFAULT_FACTORYRESET, value))
{
m_factoryReset = value;
- dlog_print(DLOG_INFO, "DiagnosticsResource", "#### m_factoryReset: %s",
+ dlog_print(DLOG_INFO, "MaintenanceResource", "#### m_factoryReset: %s",
m_factoryReset.c_str());
}
- if (rep.getValue("rb", value))
+ if (rep.getValue(DEFAULT_REBOOT, value))
{
m_reboot = value;
- dlog_print(DLOG_INFO, "DiagnosticsResource", "#### m_reboot: %s", m_reboot.c_str());
+ dlog_print(DLOG_INFO, "MaintenanceResource", "#### m_reboot: %s", m_reboot.c_str());
}
- if (rep.getValue("ssc", value))
+ if (rep.getValue(DEFAULT_STARTCOLLECTION, value))
{
m_startStatCollection = value;
- dlog_print(DLOG_INFO, "DiagnosticsResource", "#### m_startStatCollection: %s",
+ dlog_print(DLOG_INFO, "MaintenanceResource", "#### m_startStatCollection: %s",
m_startStatCollection.c_str());
}
}
-OCRepresentation DiagnosticsResource::getDiagnosticsRepresentation()
+OCRepresentation MaintenanceResource::getMaintenanceRepresentation()
{
- m_diagnosticsRep.setValue("fr", m_factoryReset);
- m_diagnosticsRep.setValue("rb", m_reboot);
- m_diagnosticsRep.setValue("ssc", m_startStatCollection);
+ m_maintenanceRep.setValue(DEFAULT_FACTORYRESET, m_factoryReset);
+ m_maintenanceRep.setValue(DEFAULT_REBOOT, m_reboot);
+ m_maintenanceRep.setValue(DEFAULT_STARTCOLLECTION, m_startStatCollection);
- return m_diagnosticsRep;
+ return m_maintenanceRep;
}
-std::string DiagnosticsResource::getUri()
+std::string MaintenanceResource::getUri()
{
- return m_diagnosticsUri;
+ return m_maintenanceUri;
}
// Handles the Reboot and FactoryReset request
-void DiagnosticsResource::diagnosticsMonitor(int second)
+void MaintenanceResource::maintenanceMonitor(int second)
{
while (1)
{
if (m_reboot == "true")
{
int res;
- dlog_print(DLOG_INFO, "DiagnosticsResource", "#### Reboot will be soon...");
+ dlog_print(DLOG_INFO, "MaintenanceResource", "#### Reboot will be soon...");
m_reboot = defaultReboot;
res = system("sudo reboot"); // System reboot
- dlog_print(DLOG_INFO, "DiagnosticsResource", "#### return: %d", res);
+ dlog_print(DLOG_INFO, "MaintenanceResource", "#### return: %d", res);
logMessage = "----------------------------<br>";
logMessage += "*** System Reboot Success ***<br>";
}
else if (m_factoryReset == "true")
{
- dlog_print(DLOG_INFO, "DiagnosticsResource", "#### Factory Reset will be soon...");
+ dlog_print(DLOG_INFO, "MaintenanceResource", "#### Factory Reset will be soon...");
m_factoryReset = defaultFactoryReset;
factoryReset();
}
}
// Deletes the diagnostic resource which has been created using createResource()
-void DiagnosticsResource::deleteResource()
+void MaintenanceResource::deleteResource()
{
// Unregister the resource
- if (NULL != m_diagnosticsHandle)
+ if (NULL != m_maintenanceHandle)
{
- OCPlatform::unregisterResource(m_diagnosticsHandle);
+ OCPlatform::unregisterResource(m_maintenanceHandle);
}
}
<listOptionValue builtIn="false" value=""..\..\..\..\sdk\inc""/>
<listOptionValue builtIn="false" value=""..\..\..\..\sdk\src""/>
<listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\include""/>
+ <listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\c_common""/>
<listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\stack\include""/>
<listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\logger\include""/>
<listOptionValue builtIn="false" value=""..\..\..\..\..\..\resource\csdk\occoap\include""/>
*
******************************************************************/
-#ifndef __TMSAMPLEAPP_H__
-#define __TMSAMPLEAPP_H__
+#ifndef TMSAMPLEAPP_H__
+#define TMSAMPLEAPP_H__
#include <app.h>
#include <Elementary.h>
#include "OCPlatform.h"
#include "OCApi.h"
-#include "ThingsManager.h"
+#include "GroupManager.h"
+#include "ThingsConfiguration.h"
+#include "ThingsMaintenance.h"
#ifdef LOG_TAG
#define ELM_DEMO_EDJ "opt/usr/apps/org.tizen.tmsampleapp/res/ui_controls.edj"
+#define FINDGROUP_TIMEOUT 5
+#define FINDRESOURCE_TIMEOUT 6
+
+#define DEFAULT_DEVICENAME "n"
+#define DEFAULT_LOCATION "loc"
+#define DEFAULT_LOCATIONNAME "locn"
+#define DEFAULT_CURRENCY "c"
+#define DEFAULT_REGION "r"
+
void group_cb(void *data, Evas_Object *obj, void *event_info);
void configuration_cb(void *data, Evas_Object *obj, void *event_info);
-#endif // __TMSAMPLEAPP_H__
\ No newline at end of file
+#endif // TMSAMPLEAPP_H__
\ No newline at end of file
using namespace std;
-#ifndef __TMUTIL_H__
-#define __TMUTIL_H__
+#ifndef TMUTIL_H__
+#define TMUTIL_H__
extern std::string getOCStackResultStringFromInt(int result);
-#endif // __TMUTIL_H__
\ No newline at end of file
+#endif // TMUTIL_H__
\ No newline at end of file
std::shared_ptr< OCResource > g_configurationCollection; // For a group of multiple resources
std::shared_ptr< OCResource > g_configurationResource; // For a single resource
-OCResourceHandle diagnosticsCollectionHandle = NULL;
-OCResourceHandle diagnosticsFoundHandle = NULL;
-std::shared_ptr< OCResource > g_diagnosticsCollection; // For a group of multiple resources
-std::shared_ptr< OCResource > g_diagnosticsResource; // For a single resource
+OCResourceHandle maintenanceCollectionHandle = NULL;
+OCResourceHandle maintenanceFoundHandle = NULL;
+std::shared_ptr< OCResource > g_maintenanceCollection; // For a group of multiple resources
+std::shared_ptr< OCResource > g_maintenanceResource; // For a single resource
OCResourceHandle setCollectionHandle = NULL;
OCResourceHandle setFoundHandle = NULL;
string CONFIGURATION_COLLECTION_RESOURCE_URI = "/core/a/configuration/resourceset";
string CONFIGURATION_COLLECTION_RESOURCE_TYPE = "core.configuration.resourceset";
-string DIAGNOSTIC_COLLECTION_RESOURCE_URI = "/core/a/diagnostics/resourceset";
-string DIAGNOSTIC_COLLECTION_RESOURCE_TYPE = "core.diagnostics.resourceset";
+string MAINTENANCE_COLLECTION_RESOURCE_URI = "/core/a/maintenance/resourceset";
+string MAINTENANCE_COLLECTION_RESOURCE_TYPE = "core.maintenance.resourceset";
string FACTORYSET_COLLECTION_RESOURCE_URI = "/core/a/factoryset/resourceset";
string FACTORYSET_COLLECTION_RESOURCE_TYPE = "core.factoryset.resourceset";
string CONFIGURATION_RESOURCE_URI = "/oic/con";
-string DIAGNOSTIC_RESOURCE_URI = "/oic/diag";
+string MAINTENANCE_RESOURCE_URI = "/oic/mnt";
string FACTORYSET_RESOURCE_URI = "/factorySet";
-ThingsManager *configthingsMgr = new ThingsManager();
+GroupManager *g_groupManager = nullptr;
+ThingsConfiguration *g_thingsConfig = nullptr;
+ThingsMaintenance *g_thingsMnt = nullptr;
+
typedef struct region_popup
{
if (resource->uri() == CONFIGURATION_COLLECTION_RESOURCE_URI)
g_configurationCollection = resource;
- else if (resource->uri() == DIAGNOSTIC_COLLECTION_RESOURCE_URI)
- g_diagnosticsCollection = resource;
+ else if (resource->uri() == MAINTENANCE_COLLECTION_RESOURCE_URI)
+ g_maintenanceCollection = resource;
else if (resource->uri() == FACTORYSET_COLLECTION_RESOURCE_URI)
g_setCollection = resource;
else
"g_configurationResource is not null");
}
}
- else if (resource->uri() == DIAGNOSTIC_RESOURCE_URI &&
- NULL != diagnosticsCollectionHandle)
+ else if (resource->uri() == MAINTENANCE_RESOURCE_URI &&
+ NULL != maintenanceCollectionHandle)
{
- OCPlatform::bindResource(diagnosticsCollectionHandle,
+ OCPlatform::bindResource(maintenanceCollectionHandle,
foundResourceHandle);
- diagnosticsFoundHandle = foundResourceHandle;
- if (NULL == g_diagnosticsResource)
+ maintenanceFoundHandle = foundResourceHandle;
+ if (NULL == g_maintenanceResource)
{
dlog_print(DLOG_INFO, LOG_TAG,
- "g_diagnosticsResource updated");
- g_diagnosticsResource = resource;
+ "g_maintenanceResource updated");
+ g_maintenanceResource = resource;
}
else
{
dlog_print(DLOG_INFO, LOG_TAG,
- "g_diagnosticsResource is not null");
+ "g_maintenanceResource is not null");
}
}
else if (resource->uri() == FACTORYSET_RESOURCE_URI &&
string logMessage = "Resource URI: " + rep.getUri() + "<br>";
dlog_print(DLOG_INFO, LOG_TAG, "#### Resource URI: %s", rep.getUri().c_str());
- if (rep.hasAttribute("loc"))
+ if (rep.hasAttribute(DEFAULT_DEVICENAME))
+ {
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Device Name : %s",
+ rep.getValue< std::string >(DEFAULT_DEVICENAME).c_str());
+ logMessage = logMessage + "Device Name : " +
+ rep.getValue< std::string >(DEFAULT_DEVICENAME) + "<br>";
+ }
+ if (rep.hasAttribute(DEFAULT_LOCATION))
{
dlog_print(DLOG_INFO, LOG_TAG, "#### Location : %s",
- rep.getValue< std::string >("loc").c_str());
- logMessage = logMessage + "Location : " + rep.getValue< std::string >("loc") + "<br>";
+ rep.getValue< std::string >(DEFAULT_LOCATION).c_str());
+ logMessage = logMessage + "Location : " +
+ rep.getValue< std::string >(DEFAULT_LOCATION) + "<br>";
}
- if (rep.hasAttribute("st"))
+ if (rep.hasAttribute(DEFAULT_LOCATIONNAME))
{
- dlog_print(DLOG_INFO, LOG_TAG, "#### SystemTime : %s",
- rep.getValue< std::string >("st").c_str());
- logMessage = logMessage + "SystemTime : " + rep.getValue< std::string >("st") + "<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Location Name : %s",
+ rep.getValue< std::string >(DEFAULT_LOCATIONNAME).c_str());
+ logMessage = logMessage + "Location Name: " +
+ rep.getValue< std::string >(DEFAULT_LOCATIONNAME) + "<br>";
}
- if (rep.hasAttribute("c"))
+ if (rep.hasAttribute(DEFAULT_CURRENCY))
{
dlog_print(DLOG_INFO, LOG_TAG, "#### Currency : %s",
- rep.getValue< std::string >("c").c_str());
- logMessage = logMessage + "Currency : " + rep.getValue< std::string >("c") + "<br>";
+ rep.getValue< std::string >(DEFAULT_CURRENCY).c_str());
+ logMessage = logMessage + "Currency : " +
+ rep.getValue< std::string >(DEFAULT_CURRENCY) + "<br>";
}
- if (rep.hasAttribute("r"))
+ if (rep.hasAttribute(DEFAULT_REGION))
{
dlog_print(DLOG_INFO, LOG_TAG, "#### Region : %s",
- rep.getValue< std::string >("r").c_str());
- logMessage = logMessage + "Region : " + rep.getValue< std::string >("r") + "<br>";
+ rep.getValue< std::string >(DEFAULT_REGION).c_str());
+ logMessage = logMessage + "Region : " +
+ rep.getValue< std::string >(DEFAULT_REGION) + "<br>";
}
logMessage += "----------------------<br>";
dlog_print(DLOG_INFO, LOG_TAG, " %s", logMessage.c_str());
string logMessage = "Resource URI: " + rep.getUri() + "<br>";
dlog_print(DLOG_INFO, LOG_TAG, "#### Resource URI: %s", rep.getUri().c_str());
- if (rep.hasAttribute("loc"))
+ if (rep.hasAttribute(DEFAULT_DEVICENAME))
+ {
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Device Name : %s",
+ rep.getValue< std::string >(DEFAULT_DEVICENAME).c_str());
+ logMessage = logMessage + "Device Name : "
+ + rep.getValue< std::string >(DEFAULT_DEVICENAME) + "<br>";
+ }
+ if (rep.hasAttribute(DEFAULT_LOCATION))
{
dlog_print(DLOG_INFO, LOG_TAG, "#### Location : %s",
- rep.getValue< std::string >("loc").c_str());
- logMessage = logMessage + "Location : " + rep.getValue< std::string >("loc") + "<br>";
+ rep.getValue< std::string >(DEFAULT_LOCATION).c_str());
+ logMessage = logMessage + "Location : "
+ + rep.getValue< std::string >(DEFAULT_LOCATION) + "<br>";
}
- if (rep.hasAttribute("st"))
+ if (rep.hasAttribute(DEFAULT_LOCATIONNAME))
{
- dlog_print(DLOG_INFO, LOG_TAG, "#### SystemTime : %s",
- rep.getValue< std::string >("st").c_str());
- logMessage = logMessage + "SystemTime : " + rep.getValue< std::string >("st") + "<br>";
+ dlog_print(DLOG_INFO, LOG_TAG, "#### Location Name : %s",
+ rep.getValue< std::string >(DEFAULT_LOCATIONNAME).c_str());
+ logMessage = logMessage + "Location Name : "
+ + rep.getValue< std::string >(DEFAULT_LOCATIONNAME) + "<br>";
}
- if (rep.hasAttribute("c"))
+ if (rep.hasAttribute(DEFAULT_CURRENCY))
{
dlog_print(DLOG_INFO, LOG_TAG, "#### Currency : %s",
- rep.getValue< std::string >("c").c_str());
- logMessage = logMessage + "Currency : " + rep.getValue< std::string >("c") + "<br>";
+ rep.getValue< std::string >(DEFAULT_CURRENCY).c_str());
+ logMessage = logMessage + "Currency : "
+ + rep.getValue< std::string >(DEFAULT_CURRENCY) + "<br>";
}
- if (rep.hasAttribute("r"))
+ if (rep.hasAttribute(DEFAULT_REGION))
{
dlog_print(DLOG_INFO, LOG_TAG, "#### Region : %s",
- rep.getValue< std::string >("r").c_str());
- logMessage = logMessage + "Region : " + rep.getValue< std::string >("r") + "<br>";
+ rep.getValue< std::string >(DEFAULT_REGION).c_str());
+ logMessage = logMessage + "Region : "
+ + rep.getValue< std::string >(DEFAULT_REGION) + "<br>";
}
logMessage += "----------------------<br>";
std::vector<string> resourceTypes;
resourceTypes.push_back(CONFIGURATION_COLLECTION_RESOURCE_TYPE);
- if (NULL != configthingsMgr)
+ if (NULL != g_groupManager)
{
- configthingsMgr->findCandidateResources(resourceTypes, &onFoundCollectionResource, 5);
+ g_groupManager->findCandidateResources(resourceTypes, &onFoundCollectionResource,
+ FINDGROUP_TIMEOUT);
}
resourceTypes.clear();
- resourceTypes.push_back(DIAGNOSTIC_COLLECTION_RESOURCE_TYPE);
- if (NULL != configthingsMgr)
+ resourceTypes.push_back(MAINTENANCE_COLLECTION_RESOURCE_TYPE);
+ if (NULL != g_groupManager)
{
- configthingsMgr->findCandidateResources(resourceTypes, &onFoundCollectionResource, 5);
+ g_groupManager->findCandidateResources(resourceTypes, &onFoundCollectionResource,
+ FINDGROUP_TIMEOUT);
}
resourceTypes.clear();
resourceTypes.push_back(FACTORYSET_COLLECTION_RESOURCE_TYPE);
- if (NULL != configthingsMgr)
+ if (NULL != g_groupManager)
{
- configthingsMgr->findCandidateResources(resourceTypes, &onFoundCollectionResource, 5);
+ g_groupManager->findCandidateResources(resourceTypes, &onFoundCollectionResource,
+ FINDGROUP_TIMEOUT);
}
dlog_print(DLOG_INFO, LOG_TAG, "#### calling findCandidateResources EXIT!!!!");
{
dlog_print(DLOG_INFO, LOG_TAG, "#### calling findCandidateResources ENTRY!!!!");
std::vector<string> resourceTypes;
- resourceTypes.push_back("oic.con");
+ resourceTypes.push_back("oic.wk.con");
- if (NULL != configthingsMgr)
+ if (NULL != g_groupManager)
{
- configthingsMgr->findCandidateResources(resourceTypes, &onFoundCandidateResource, 7);
+ g_groupManager->findCandidateResources(resourceTypes, &onFoundCandidateResource,
+ FINDRESOURCE_TIMEOUT);
}
resourceTypes.clear();
- resourceTypes.push_back("oic.diag");
- if (NULL != configthingsMgr)
+ resourceTypes.push_back("oic.wk.mnt");
+ if (NULL != g_groupManager)
{
- configthingsMgr->findCandidateResources(resourceTypes, &onFoundCandidateResource, 7);
+ g_groupManager->findCandidateResources(resourceTypes, &onFoundCandidateResource,
+ FINDRESOURCE_TIMEOUT);
}
resourceTypes.clear();
resourceTypes.push_back("factorySet");
- if (NULL != configthingsMgr)
+ if (NULL != g_groupManager)
{
- configthingsMgr->findCandidateResources(resourceTypes, &onFoundCandidateResource, 7);
+ g_groupManager->findCandidateResources(resourceTypes, &onFoundCandidateResource,
+ FINDRESOURCE_TIMEOUT);
}
dlog_print(DLOG_INFO, LOG_TAG, "#### calling findCandidateResources EXIT!!!!");
try
{
- configthingsMgr->getConfigurations(g_configurationCollection, configurations,
- &onGetConfigurationsCallback);
+ g_thingsConfig->getConfigurations(g_configurationCollection, configurations,
+ &onGetConfigurationsCallback);
+
+ isWaiting = 0;
}
catch (std::exception &e)
{
}
OCStackResult result;
- ConfigurationName name = "r";
+ ConfigurationName name = DEFAULT_REGION;
ConfigurationValue value = newRegionValue;
std::map< ConfigurationName, ConfigurationValue > configurations;
try
{
- result = configthingsMgr->updateConfigurations(g_configurationCollection, configurations,
+ result = g_thingsConfig->updateConfigurations(g_configurationCollection, configurations,
&onUpdateConfigurationsCallback);
}
catch (std::exception &e)
static void factoryReset(void *data, Evas_Object *obj, void *event_info)
{
dlog_print(DLOG_INFO, LOG_TAG, "#### factoryReset ENTRY!!!!");
- if (NULL == g_diagnosticsCollection || NULL == g_diagnosticsCollection.get())
+ if (NULL == g_maintenanceCollection || NULL == g_maintenanceCollection.get())
{
dlog_print(DLOG_ERROR, LOG_TAG, "Note that you first create a group to use this command");
string logMessage = "FIRST CREATE GROUP <br>";
try
{
- result = configthingsMgr->factoryReset(g_diagnosticsCollection, &onFactoryReset);
+ result = g_thingsMnt->factoryReset(g_maintenanceCollection, &onFactoryReset);
}
catch (std::exception &e)
{
static void reboot(void *data, Evas_Object *obj, void *event_info)
{
dlog_print(DLOG_INFO, LOG_TAG, "#### reboot ENTRY!!!!");
- if (NULL == g_diagnosticsCollection || NULL == g_diagnosticsCollection.get())
+ if (NULL == g_maintenanceCollection || NULL == g_maintenanceCollection.get())
{
dlog_print(DLOG_INFO, LOG_TAG, "Note that you first create a group to use this command");
string logMessage = "FIRST CREATE GROUP <br>";
try
{
- result = configthingsMgr->reboot(g_diagnosticsCollection, &onReboot);
+ result = g_thingsMnt->reboot(g_maintenanceCollection, &onReboot);
}
catch (std::exception &e)
{
{
dlog_print(DLOG_INFO, LOG_TAG, "#### getListOfSupportedConfigurationUnits ENTRY!!!!");
string listOfSupportedConfigurationUnits =
- configthingsMgr->getListOfSupportedConfigurationUnits();
+ g_thingsConfig->getListOfSupportedConfigurationUnits();
dlog_print(DLOG_INFO, LOG_TAG, "#### List : %s", listOfSupportedConfigurationUnits.c_str());
string logMessage;
createResourceCollection(CONFIGURATION_COLLECTION_RESOURCE_URI,
CONFIGURATION_COLLECTION_RESOURCE_TYPE,
configurationCollectionHandle);
- createResourceCollection(DIAGNOSTIC_COLLECTION_RESOURCE_URI,
- DIAGNOSTIC_COLLECTION_RESOURCE_TYPE,
- diagnosticsCollectionHandle);
+ createResourceCollection(MAINTENANCE_COLLECTION_RESOURCE_URI,
+ MAINTENANCE_COLLECTION_RESOURCE_TYPE,
+ maintenanceCollectionHandle);
createResourceCollection(FACTORYSET_COLLECTION_RESOURCE_URI,
FACTORYSET_COLLECTION_RESOURCE_TYPE,
setCollectionHandle);
+
+ g_groupManager = new GroupManager();
+ g_thingsConfig = new ThingsConfiguration();
+ g_thingsMnt = new ThingsMaintenance();
}
// Deletes all the resources
{
dlog_print(DLOG_INFO, LOG_TAG, "#### Destroy sequence called");
- deleteResource(configurationCollectionHandle, configurationFoundHandle);
+ deleteResource(setCollectionHandle, setFoundHandle);
- deleteResource(diagnosticsCollectionHandle, diagnosticsFoundHandle);
+ deleteResource(maintenanceCollectionHandle, maintenanceFoundHandle);
- deleteResource(setCollectionHandle, setFoundHandle);
+ deleteResource(configurationCollectionHandle, configurationFoundHandle);
+
+ delete g_thingsMnt;
+ delete g_thingsConfig;
+ delete g_groupManager;
dlog_print(DLOG_INFO, LOG_TAG, "#### Resources destroyed successfully");
}
shared_ptr< OCResource > g_resource ;
std::vector< string > lights;
-ThingsManager *groupThingsMgr = new ThingsManager();
+GroupManager *groupMgr = NULL;
typedef struct datetime_popup
{
string plainText;
if (rep.getValue("ActionSet", plainText))
{
- ActionSet *actionset = groupThingsMgr->getActionSetfromString(plainText);
+ ActionSet *actionset = groupMgr->getActionSetfromString(plainText);
if (NULL != actionset)
{
dlog_print(DLOG_INFO, LOG_TAG, "#### ACTIONSET NAME :: (%s)",
{
if (g_resource)
{
- groupThingsMgr->addActionSet(g_resource, actionSet, onPut);
+ groupMgr->addActionSet(g_resource, actionSet, onPut);
}
}
catch (std::exception &e)
{
if (g_resource)
{
- groupThingsMgr->addActionSet(g_resource, actionSet, onPut);
+ groupMgr->addActionSet(g_resource, actionSet, onPut);
}
}
catch (std::exception &e)
}
if (g_resource)
{
- groupThingsMgr->addActionSet(g_resource, allBulbOn, onPut);
+ groupMgr->addActionSet(g_resource, allBulbOn, onPut);
}
delete allBulbOn;
}
if (g_resource)
{
- groupThingsMgr->addActionSet(g_resource, allBulbOff, onPut);
+ groupMgr->addActionSet(g_resource, allBulbOff, onPut);
}
delete allBulbOff;
static void scheduled_AllbulbOff(void *data, Evas_Object *obj, void *event_info)
{
- groupThingsMgr->executeActionSet(g_resource, "AllBulbOffScheduledCall", &onPost);
+ groupMgr->executeActionSet(g_resource, "AllBulbOffScheduledCall", &onPost);
}
static void scheduled_AllbulbOffEx(void *data, Evas_Object *obj, void *event_info)
{
- groupThingsMgr->executeActionSet(g_resource, "AllBulbOffScheduledCall", 10, &onPost);
+ groupMgr->executeActionSet(g_resource, "AllBulbOffScheduledCall", 10, &onPost);
}
static void cancelScheduled_AllBulbOff(void *data, Evas_Object *obj, void *event_info)
{
- groupThingsMgr->cancelActionSet(g_resource, "AllBulbOffScheduledCall", &onPost);
+ groupMgr->cancelActionSet(g_resource, "AllBulbOffScheduledCall", &onPost);
}
static void recursive_allBulbOn(void *data, Evas_Object *obj, void *event_info)
{
- groupThingsMgr->executeActionSet(g_resource, "AllBulbOnRecursiveCall", &onPost);
+ groupMgr->executeActionSet(g_resource, "AllBulbOnRecursiveCall", &onPost);
}
static void recursive_allBulbOnEx(void *data, Evas_Object *obj, void *event_info)
{
- groupThingsMgr->executeActionSet(g_resource, "AllBulbOnRecursiveCall", 10, &onPost);
+ groupMgr->executeActionSet(g_resource, "AllBulbOnRecursiveCall", 10, &onPost);
}
static void cancelRecursive_allBulbOn(void *data, Evas_Object *obj, void *event_info)
{
- groupThingsMgr->cancelActionSet(g_resource, "AllBulbOnRecursiveCall", &onPost);
+ groupMgr->cancelActionSet(g_resource, "AllBulbOnRecursiveCall", &onPost);
}
/* Method for executing the action Set AllBulbOff that we have created using
{
if (g_resource)
{
- groupThingsMgr->executeActionSet(g_resource, BULBOFF, &onPost);
+ groupMgr->executeActionSet(g_resource, BULBOFF, &onPost);
}
}
catch (std::exception &e)
{
if (g_resource)
{
- groupThingsMgr->executeActionSet(g_resource, BULBON, &onPost);
+ groupMgr->executeActionSet(g_resource, BULBON, &onPost);
}
}
catch (std::exception &e)
{
if (g_resource)
{
- groupThingsMgr->getActionSet(g_resource, BULBOFF, &onPost);
+ groupMgr->getActionSet(g_resource, BULBOFF, &onPost);
}
}
catch (std::exception &e)
{
if (g_resource)
{
- groupThingsMgr->getActionSet(g_resource, BULBON, &onPost);
+ groupMgr->getActionSet(g_resource, BULBON, &onPost);
}
}
catch (std::exception &e)
{
if (g_resource)
{
- groupThingsMgr->deleteActionSet(g_resource, BULBOFF, &onPost);
+ groupMgr->deleteActionSet(g_resource, BULBOFF, &onPost);
}
}
catch (std::exception &e)
{
if (g_resource)
{
- groupThingsMgr->deleteActionSet(g_resource, BULBON, &onPost);
+ groupMgr->deleteActionSet(g_resource, BULBON, &onPost);
}
}
catch (std::exception &e)
static void create_group()
{
- if (NULL != groupThingsMgr)
+
+ groupMgr = new GroupManager();
+
+ if (NULL != groupMgr)
{
dlog_print(DLOG_INFO, LOG_TAG, "#### calling findCandidateResources from "
"create_group!!!!");
vector< string > types;
types.push_back("core.light");
- groupThingsMgr->findCandidateResources(types, &foundResources, 5);
+ groupMgr->findCandidateResources(types, &foundResources, FINDRESOURCE_TIMEOUT);
}
try
void findLightResource(void *data, Evas_Object *obj, void *event_info)
{
dlog_print(DLOG_INFO, LOG_TAG, "#### findLightResource ENTRY");
- if (NULL != groupThingsMgr)
+ if (NULL != groupMgr)
{
vector< string > types;
types.push_back("core.light");
- OCStackResult result = groupThingsMgr->findCandidateResources(types, &foundResources, 5);
+ OCStackResult result = groupMgr->findCandidateResources(types, &foundResources,
+ FINDRESOURCE_TIMEOUT);
if (result == OC_STACK_OK)
{
dlog_print(DLOG_INFO, LOG_TAG, "#### create_group -- findCandidateResources :: "
void observeBookMark(void *data, Evas_Object *obj, void *event_info)
{
dlog_print(DLOG_INFO, LOG_TAG, "#### observeBookMark ENTRY");
- if (NULL != groupThingsMgr)
+ if (NULL != groupMgr)
{
vector< string > types;
types.push_back("core.bookmark");
- OCStackResult result = groupThingsMgr->findCandidateResources(types, &foundResources, 5);
+ OCStackResult result = groupMgr->findCandidateResources(types, &foundResources,
+ FINDRESOURCE_TIMEOUT);
if (OC_STACK_OK == result)
{
dlog_print(DLOG_INFO, LOG_TAG, "#### create_group - findCandidateResources :: "
{
dlog_print(DLOG_ERROR, LOG_TAG, "Exception occured! (%s)", e.what());
}
+
+ delete groupMgr;
}
static void createActionSet(void *data, Evas_Object *obj, void *event_info)
static void find_group()
{
dlog_print(DLOG_INFO, LOG_TAG, "#### findGroup ENTRY");
- vector< string > resourceTypes;
- resourceTypes.push_back(resourceTypeName);
- OCStackResult result = groupThingsMgr->findGroup(resourceTypes, &foundResource);
- if (OC_STACK_OK == result)
- {
- dlog_print(DLOG_INFO, LOG_TAG, "#### findGroup returned OC_STACK_OK");
- }
- else
- {
- dlog_print(DLOG_INFO, LOG_TAG, "#### findGroup failed");
- }
+ std::string query = OC_RSRVD_WELL_KNOWN_URI;
+ query.append("?rt=");
+ query.append(resourceTypeName);
+
+ OCPlatform::findResource("", query, CT_DEFAULT, &foundResource);
+
dlog_print(DLOG_INFO, LOG_TAG, "#### findGroup EXIT");
}
*/
public:
+ /**
+ * API for extracting an action set string from the ActionSet class instance
+ *
+ * @param newActionSet pointer of ActionSet class instance
+ *
+ * @return std::string return value of this API.
+ * It returns an action set String.
+ * @note OCStackResult is defined in ocstack.h.
+ */
std::string getStringFromActionSet(const ActionSet *newActionSet);
+
+ /**
+ * API for extrracting ActionSet class instance from an action set string.
+ *
+ * @param desc description of an action set string
+ *
+ * @return ActionSet* return value of this API.
+ * It returns pointer of ActionSet.
+ */
ActionSet* getActionSetfromString(std::string desc);
+ /**
+ * API for adding an action set.
+ * Callback is called when the response of PUT operation arrives.
+ *
+ * @param resource resource pointer of the group resource
+ * @param newActionSet pointer of ActionSet class instance
+ * @param callback callback for PUT operation.
+ *
+ * @return Returns ::OC_STACK_OK if success.
+ *
+ * @note OCStackResult is defined in ocstack.h.
+ */
OCStackResult addActionSet(std::shared_ptr< OCResource > resource,
const ActionSet* newActionSet, PutCallback cb);
+
+ /**
+ * API for executing an existing action set.
+ * Callback is called when the response of POST operation arrives.
+ *
+ * @param resource resource pointer of the group resource
+ * @param actionsetName the action set name for executing the action set
+ * @param callback callback for POST operation.
+ *
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
+ */
OCStackResult executeActionSet(std::shared_ptr< OCResource > resource,
std::string actionsetName, PostCallback cb);
+
+ /**
+ * API for executing an existing action set.
+ * Callback is called when the response of POST operation arrives.
+ *
+ * @param resource resource pointer of the group resource
+ * @param actionsetName the action set name for executing the action set
+ * @param delay waiting time for until the action set run.
+ * @param callback callback for POST operation.
+ *
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
+ */
OCStackResult executeActionSet(std::shared_ptr< OCResource > resource,
std::string actionsetName, long int delay, PostCallback cb);
+
+ /**
+ * API for canceling an existing action set.
+ * Callback is called when the response of POST operation arrives.
+ *
+ * @param resource resource pointer of the group resource
+ * @param actionsetName the action set name for executing the action set
+ * @param callback callback for POST operation.
+ *
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
+ */
OCStackResult cancelActionSet(std::shared_ptr< OCResource > resource,
std::string actionsetName, PostCallback cb);
+
+ /**
+ * API for reading an existing action set.
+ * Callback is called when the response of GET operation arrives.
+ *
+ * @param resource resource pointer of the group resource
+ * @param actionsetName the action set name for reading the action set
+ * @param callback callback for GET operation.
+ *
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
+ */
OCStackResult getActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName,
PostCallback cb);
+
+ /**
+ * API for removing an existing action set.
+ * Callback is called when the response of POST operation arrives.
+ *
+ * @param resource resource pointer of the group resource
+ * @param actionsetName the action set name for removing the action set
+ * @param callback callback for POST operation.
+ *
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
+ */
OCStackResult deleteActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName,
PostCallback);
};
std::string getJSON();
};
-#define NUMCONFUNIT 5
+#define NUMCONFUNIT 6
typedef std::string ConfigurationName;
typedef std::string ConfigurationValue;
static ThingsConfiguration *thingsConfigurationInstance;
static ThingsConfiguration* getInstance();
- void deleteInstance();
+ // TODO: deprecated
+ void deleteInstance();
void setGroupManager(GroupManager *groupmanager);
/**
* @file
*
* This file contains the declaration of classes and its members related to
- * ThingsDiagnostics.
+ * ThingsMaintenance.
*/
-#ifndef __OC_THINGSDIAGNOSTICS__
-#define __OC_THINGSDIAGNOSTICS__
+#ifndef __OC_THINGSMAINTENANCE__
+#define __OC_THINGSMAINTENANCE__
#include <string>
#include <vector>
using namespace OC;
namespace OIC
{
- /// Declearation of Diagnostics Callback funtion type
+ /// Declearation of Maintenance Callback funtion type
typedef std::function<
void(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
- > DiagnosticsCallback;
+ > MaintenanceCallback;
/**
* @brief
* The following class is used as a item stacking in request queue. The class stores a request
- * and referential information (e.g., a diagnostics name, a target resource object, a callback
+ * and referential information (e.g., a maintenance name, a target resource object, a callback
* function passed from the applications, and a update value). When the function for updating/
- * getting diagnostics value is called from applications, this class instance is created and
+ * getting maintenance value is called from applications, this class instance is created and
* stored in the request queue. The queue is maintained in a std::map structure so if desiring
- * to find a specific request, you can find it by querying a diagnostics name.
+ * to find a specific request, you can find it by querying a maintenance name.
*/
- class DiagnosticsRequestEntry
+ class MaintenanceRequestEntry
{
public:
- DiagnosticsRequestEntry(std::string ID, DiagnosticsCallback callback,
+ MaintenanceRequestEntry(std::string ID, MaintenanceCallback callback,
std::shared_ptr< OCResource > resource, std::string updateVal);
- // Diagnostics Name (used in key value in std::map structure)
+ // Maintenance Name (used in key value in std::map structure)
// e.g., reboot and factoryset
std::string m_ID;
// Reference callback pointer
- DiagnosticsCallback m_callback;
+ MaintenanceCallback m_callback;
// Reference resource object
std::shared_ptr< OCResource > m_resource;
- // Update value only used for diagnostics update (always "true")
+ // Update value only used for maintenance update (always "true")
std::string m_updateVal;
};
/**
* @brief
- * The following class is used to store providing diagnostics name and its relevant information
+ * The following class is used to store providing maintenance name and its relevant information
* The relevant information includes a brief description, uri, and attribute key.
- * Note that a developer only specifies a diagnostics name, not URI nor attribute key, to
- * update a value to a remote. Thus, using diagnostics name, we convert it to more specific
+ * Note that a developer only specifies a maintenance name, not URI nor attribute key, to
+ * update a value to a remote. Thus, using maintenance name, we convert it to more specific
* information (i.e. uri and attribute key) to send a request. This class is reponsible to
* storing these information.
*/
- class DiagnosticsUnitInfo
+ class MaintenanceUnitInfo
{
public:
std::string m_name;
std::string m_attribute;
std::string m_uri;
- DiagnosticsUnitInfo(std::string name, std::string attribute, std::string uri);
+ MaintenanceUnitInfo(std::string name, std::string attribute, std::string uri);
// If a developer wants to know a list of configuration names, gives it in JSON format.
std::string getJSON();
};
#define NUMDIAGUNIT 3
- typedef std::string DiagnosticsName;
- typedef std::string DiagnosticsValue;
+ typedef std::string MaintenanceName;
+ typedef std::string MaintenanceValue;
- class ThingsDiagnostics
+ class ThingsMaintenance
{
public:
/**
- * Constructor for ThingsDiagnostics. Constructs a new ThingsDiagnostics
+ * Constructor for ThingsMaintenance. Constructs a new ThingsMaintenance
*/
- ThingsDiagnostics(void);
+ ThingsMaintenance(void);
/**
* Virtual destructor
*/
- ~ThingsDiagnostics(void);
+ ~ThingsMaintenance(void);
- static ThingsDiagnostics *thingsDiagnosticsInstance;
- static ThingsDiagnostics* getInstance();
- void deleteInstance();
+ static ThingsMaintenance *thingsMaintenanceInstance;
+ static ThingsMaintenance* getInstance();
+ // TODO: deprecated
+ void deleteInstance();
void setGroupManager(GroupManager *groupmanager);
/**
*
* NOTE: OCStackResult is defined in ocstack.h.
*/
- OCStackResult reboot(std::shared_ptr< OCResource > resource, DiagnosticsCallback callback);
+ OCStackResult reboot(std::shared_ptr< OCResource > resource, MaintenanceCallback callback);
/**
* API for factory reset on device
*/
OCStackResult factoryReset(std::shared_ptr< OCResource > resource,
- DiagnosticsCallback callback);
+ MaintenanceCallback callback);
/**
- * API to show a list of supported diagnostics units
+ * API to show a list of supported maintenance units
* Callback call when a response arrives.
*
* @return the list in JSON format
*/
- std::string getListOfSupportedDiagnosticsUnits();
+ std::string getListOfSupportedMaintenanceUnits();
private:
GroupManager *g_groupmanager;
- std::vector< DiagnosticsUnitInfo > DiagnosticsUnitTable;
+ std::vector< MaintenanceUnitInfo > MaintenanceUnitTable;
void onExecuteForGroupAction(const HeaderOptions& headerOptions,
const OCRepresentation& rep, const int eCode, std::string conf);
std::string conf);
std::shared_ptr< OCResource > getResource(std::string conf);
- DiagnosticsCallback getCallback(std::string conf);
+ MaintenanceCallback getCallback(std::string conf);
std::string getUpdateVal(std::string conf);
- std::string getAttributeByDiagnosticsName(DiagnosticsName name);
- std::string getUriByDiagnosticsName(DiagnosticsName name);
+ std::string getAttributeByMaintenanceName(MaintenanceName name);
+ std::string getUriByMaintenanceName(MaintenanceName name);
std::string getHostFromURI(std::string oldUri);
+++ /dev/null
-//******************************************************************
-//
-// 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.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/**
- * @file
- *
- * This file contains the declaration of ThingsManager class and its
- * members related to ThingsManager.
- */
-
-#ifndef __OC_THINGSMANAGER__
-#define __OC_THINGSMANAGER__
-
-#include <string>
-#include <vector>
-#include <map>
-#include <cstdlib>
-#include <ActionSet.h>
-#include "OCPlatform.h"
-#include "OCApi.h"
-
-using namespace OC;
-
-namespace OIC
-{
- /**
- * @class ThingsManager
- * @brief This class provides a set of functions regarding group management,
- * synchronization of group, configuration of things, and diagnostics about things.
- *
- */
- class ThingsManager
- {
- public:
- /**
- * Constructor for ThingsManager
- */
- ThingsManager(void);
-
- /**
- * Virtual destructor for ThingsManager
- */
- ~ThingsManager(void);
-
- /**
- * API for discoverying candidate resources.
- * Callback is called when all resource types are found.
- *
- * @param resourceTypes - required resource types(called "candidate")
- * @param candidateCallback - callback. Returns OCResource vector.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult findCandidateResources(std::vector< std::string > resourceTypes,
- std::function< void(std::vector< std::shared_ptr< OCResource > >) > callback,
- int waitsec);
-
- /**
- * API for subscribing child's state.
- *
- * @param resource - collection resource for subscribing presence of all child resources.
- * @param callback - callback funcion for result of child's presence.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult subscribeCollectionPresence(std::shared_ptr< OCResource > resource,
- std::function< void(std::string, OCStackResult) > callback);
-
- /**
- * API for registering and binding resource to group.
- *
- * @param childHandle - child resource handle. It will be filled from resource param.
- * @param resource - resource for registering and binding to group. It has all data.
- * @param collectionHandle - collection resource handle. It will be added child resource.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult bindResourceToGroup(OCResourceHandle& childHandle,
- std::shared_ptr< OCResource > resource, OCResourceHandle& collectionHandle);
-
- // Group Synchronization
-
- /**
- * API for finding a specific remote group when a resource tries to join a group.
- * Callback is called when a group is found or not.
- *
- * @param collectionResourceTypes - resource types of a group to find and join
- * @param callback - callback. It has OCResource param.
- * If a group is found, OCResource has the group resource.
- * Otherwise, OCResource is NULL.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: It return OC_STACK ERROR when it is already finding a group.
- * You should call this api after the group finding process has stopped.
- * OCStackResult is defined in ocstack.h.
- */
- OCStackResult findGroup(std::vector< std::string > collectionResourceTypes,
- FindCallback callback);
-
- /**
- * API for creating a new group.
- *
- * @param collectionResourceType - resource type of a group to create
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult createGroup(std::string collectionResourceType);
-
- /**
- * API for joining a group. This API is used when a resource that has a group tries
- * to find a specific remote resource and makes it join a group
- *
- * @param collectionResourceType - resource type of a group to join.
- * @param resourceHandle - resource handle to join a group.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: If you want to join the resource in the remote(other) process,
- * use joinGroup(const std::shared_ptr< OCResource >, OCResourceHandle)
- * instead of this.
- * OCStackResult is defined in ocstack.h.
- */
- OCStackResult joinGroup(std::string collectionResourceType,
- OCResourceHandle resourceHandle);
-
- /**
- * API for joining a group. This API is used when a resource that
- * doesn't have a group tries to find and join a specific remote group.
- *
- * @param resource - group resource pointer to join.
- * It can be the callback result of findGroup().
- * @param resourceHandle - resource handle to join a group.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: NOTE: If you want to join the resource in the same process,
- * use joinGroup(std::string, OCResourceHandle)
- * instead of this.
- * OCStackResult is defined in ocstack.h.
- */
- OCStackResult joinGroup(const std::shared_ptr< OCResource > resource,
- OCResourceHandle resourceHandle);
-
- /**
- * API for leaving a joined group.
- *
- * @param collectionResourceType - resource type of a group to leave.
- * @param resourceHandle - resource handle to leave a group.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult leaveGroup(std::string collectionResourceType,
- OCResourceHandle resourceHandle);
-
- /**
- * API for leaving a joined group.
- *
- * @param resource - group resource pointer to join.
- * It can be the callback result of findGroup().
- *
- * @param collectionResourceType - resource type of a group to leave.
- * @param resourceHandle - resource handle to leave a group.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult leaveGroup(const std::shared_ptr< OCResource > resource,
- std::string collectionResourceType,
- OCResourceHandle resourceHandle);
-
- /**
- * API for deleting a group.
- *
- * @param collectionResourceType - resource type of a group to delete.
- *
- * @return void
- */
- void deleteGroup(std::string collectionResourceType);
-
- /**
- * API for getting a list of joined groups.
- *
- * @return std::map - return value of this API.
- * It returns group resource type and group resource handle as a map type.
- */
- std::map< std::string, OCResourceHandle > getGroupList();
-
- // Things Configuration
-
- /**
- * API for updating configuration value of multiple things of a target group
- * or a single thing.
- * Callback is called when a response arrives.
- * Before using the below function, a developer should acquire a resource pointer of
- * (collection) resource that he wants to send a request by calling findResource() function
- * provided in OCPlatform. And he should also notice a "Configuration Name" term which
- * represents a nickname of a target attribute of a resource that he wants to update.
- * The base motivation to introduce the term is to avoid a usage of URI to access a resource
- * from a developer. Thus, a developer should know which configuration names are supported
- * by Things Configuration class and what the configuration name means.
- * To get a list of supported configuration names,
- * use getListOfSupportedConfigurationUnits()
- * function, which provides the list in JSON format.
- *
- * @param resource - resource pointer representing the target group or the single thing.
- * @param configurations - ConfigurationUnit: an attribute key of target resource.
- * (e.g., loc, st, c, r)
- * Value : a value to be updated
- * @param callback - callback for updateConfigurations.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult updateConfigurations(std::shared_ptr< OCResource > resource,
- std::map< std::string, std::string > configurations,
- std::function<
- void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
- const int eCode) > callback);
-
- /**
- * API for getting configuration value of multiple things of a target group
- * or a single thing.
- * Callback is called when a response arrives.
- *
- * @param resource - resource pointer representing the target group or the single thing.
- * @param configurations - ConfigurationUnit: an attribute key of target resource.
- * @param callback - callback for getConfigurations.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult getConfigurations(std::shared_ptr< OCResource > resource,
- std::vector< std::string > configurations,
- std::function<
- void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
- const int eCode) > callback);
-
- /**
- * API for showing the list of supported configuration units (attribute keys)
- * Callback is called when a response arrives.
- *
- * @param void
- * @return std::string - return value of this API.
- * It returns the list in JSON format
- */
- std::string getListOfSupportedConfigurationUnits();
-
- /**
- * API for boostrapping system configuration parameters from a bootstrap server.
- * Callback is called when a response from the bootstrap server arrives.
- *
- * @param callback - callback for doBootstrap.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult doBootstrap(
- std::function<
- void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
- const int eCode) > callback);
-
- // Things Diagnostics
-
- /**
- * API to let thing(device) reboot.
- * The target thing could be a group of multiple things or a single thing.
- * Callback is called when a response arrives.
- *
- * @param resource - resource pointer representing the target group
- * @param callback - callback for reboot.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult reboot(std::shared_ptr< OCResource > resource,
- std::function<
- void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
- const int eCode) > callback);
-
- /**
- * API for factory reset on thing(device).
- * The target thing could be a group of multiple things or a single thing.
- * Callback is called when a response arrives.
- *
- * @param resource - resource pointer representing the target group
- * @param callback - callback for factoryReset.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult factoryReset(std::shared_ptr< OCResource > resource,
- std::function<
- void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
- const int eCode) > callback);
-
- // Group Action.
-
- /**
- * API for extracting an action set string from the ActionSet class instance
- *
- * @param newActionSet - pointer of ActionSet class instance
- *
- * @return std::string - return value of this API.
- * It returns an action set String.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- std::string getStringFromActionSet(const ActionSet *newActionSet);
-
- /**
- * API for extrracting ActionSet class instance from an action set string.
- *
- * @param desc - description of an action set string
- *
- * @return ActionSet* - return value of this API.
- * It returns pointer of ActionSet.
- */
- ActionSet* getActionSetfromString(std::string desc);
-
- /**
- * API for adding an action set.
- * Callback is called when the response of PUT operation arrives.
- *
- * @param resource - resource pointer of the group resource
- * @param newActionSet - pointer of ActionSet class instance
- * @param callback - callback for PUT operation.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult addActionSet(std::shared_ptr< OCResource > resource,
- const ActionSet* newActionSet, PutCallback cb);
-
- /**
- * API for executing an existing action set.
- * Callback is called when the response of POST operation arrives.
- *
- * @param resource - resource pointer of the group resource
- * @param actionsetName - the action set name for executing the action set
- * @param callback - callback for POST operation.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult executeActionSet(std::shared_ptr< OCResource > resource,
- std::string actionsetName, PostCallback cb);
-
- /**
- * API for executing an existing action set.
- * Callback is called when the response of POST operation arrives.
- *
- * @param resource - resource pointer of the group resource
- * @param actionsetName - the action set name for executing the action set
- * @param delay - waiting time for until the action set run.
- * @param callback - callback for POST operation.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult executeActionSet(std::shared_ptr< OCResource > resource,
- std::string actionsetName, long int delay, PostCallback cb);
-
- /**
- * API for canceling an existing action set.
- * Callback is called when the response of POST operation arrives.
- *
- * @param resource - resource pointer of the group resource
- * @param actionsetName - the action set name for executing the action set
- * @param callback - callback for POST operation.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult cancelActionSet(std::shared_ptr< OCResource > resource,
- std::string actionsetName, PostCallback cb);
- /**
- * API for reading an existing action set.
- * Callback is called when the response of GET operation arrives.
- *
- * @param resource - resource pointer of the group resource
- * @param actionsetName - the action set name for reading the action set
- * @param callback - callback for GET operation.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult getActionSet(std::shared_ptr< OCResource > resource,
- std::string actionsetName, GetCallback cb);
-
- /**
- * API for removing an existing action set.
- * Callback is called when the response of POST operation arrives.
- *
- * @param resource - resource pointer of the group resource
- * @param actionsetName - the action set name for removing the action set
- * @param callback - callback for POST operation.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
- OCStackResult deleteActionSet(std::shared_ptr< OCResource > resource,
- std::string actionsetName, PostCallback);
-
- };
-}
-#endif /* __OC_THINGSMANAGER__*/
LOCAL_C_INCLUDES := $(LOCAL_PATH)/jniutil/inc \
$(OIC_SRC_DIR)/android/android_api/base/jni \
$(OIC_SRC_DIR)/resource/include \
+ $(OIC_SRC_DIR)/resource/c_common \
$(OIC_SRC_DIR)/resource/csdk/stack/include \
$(OIC_SRC_DIR)/resource/oc_logger/include \
$(OIC_SRC_DIR)/extlibs/boost/boost_1_58_0 \
tm_jni_env.AppendUnique(CXXFLAGS = ['-Wall', '-DLINUX', '-DNDEBUG'])
tm_jni_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions', '-std=c++0x'])
tm_jni_env.AppendUnique(LIBPATH = [base_jni+'/../libs/'+tm_jni_env.get('TARGET_ARCH')])
-tm_jni_env.PrependUnique(LIBS = ['ocstack-jni', 'TGMSDKLibrary', 'oc', 'gnustl_shared', 'log'])
+tm_jni_env.PrependUnique(LIBS = ['ocstack-jni', 'TGMSDKLibrary', 'oc', 'oc_logger', 'gnustl_shared', 'log'])
tm_jni_env.AppendUnique(CPPPATH = [tm_sdk+'/inc'])
tm_jni_env.AppendUnique(CPPPATH = [base_jni])
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
******************************************************************/
/**
- * @file jni_getter.h
- *
- * @brief This file contains the JGetter class declarations and its functions required
- * for getting and setting basic data types in C++ and Java
+ * @file
+ * This file contains the JGetter class declarations and its functions required
+ * for getting and setting basic data types in C++ and Java.
*/
-#ifndef __JNI_GETTER_H_
-#define __JNI_GETTER_H_
-
+#ifndef JNI_GETTER_H_
+#define JNI_GETTER_H_
#include <string>
#include <jni.h>
/**
- * @class JGetter
- * @brief This class provide utility for get/set basic data types in C++ and Java
- *
+ * This class provide utility for get/set basic data types in C++ and Java.
*/
class JGetter
{
public:
/**
- * This function is called to get String field from the C++ object
+ * This function is called to get String field from the C++ object.
*
* @param env
* JNI Environment reference
std::string &value);
/**
- * This function is called to get Boolean field from the C++ object
+ * This function is called to get Boolean field from the C++ object.
*
* @param env
* JNI Environment reference
bool &value);
/**
- * This function is called to get Integer field from the C++ object
+ * This function is called to get Integer field from the C++ object.
*
* @param env
* JNI Environment reference
static bool getJIntField(JNIEnv *env, jobject &object, const char *fieldName, int &value);
/**
- * This function is called to get Object reference from the C++ object
+ * This function is called to get Object reference from the C++ object.
*
* @param env
* JNI Environment reference
* @param value
* reference to Object reference mentioned in fieldName
*
- * @return returns true on success and false on failer.
+ * @return returns true on success and false on failure
*/
static bool getJObjectField(JNIEnv *env, jobject &object, const char *fieldName,
const char *fieldType, jobject &value);
};
-#endif //__JNI_GETTER_H_
\ No newline at end of file
+#endif //JNI_GETTER_H_
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
******************************************************************/
/**
- * @file jni_object.h
- *
- * @brief This file contains the JObject class declarations and its functions required
- * for getting and setting basic data types in C++ and Java
+ * @file
+ * This file contains the JObject class declarations and its functions required
+ * for getting and setting basic data types in C++ and Java.
*/
-#ifndef __JNI_OBJECT_H_
-#define __JNI_OBJECT_H_
-
+#ifndef JNI_OBJECT_H_
+#define JNI_OBJECT_H_
#include <jni.h>
#include "JniOcResource.h"
/**
- * @class JObject
- * @brief This class provides a set of functions for JNI object.
- *
+ * This class provides a set of functions for JNI object.
*/
class JObject
{
public:
/**
- * @brief constructor
+ * constructor
*/
JObject(JNIEnv *env);
/**
- * @brief constructor
+ * constructor
*/
JObject(JNIEnv *env, jobject obj);
/**
- * @brief constructor
+ * constructor
*/
JObject(JNIEnv *env, const char *classPath);
/**
- * @brief destructor
- *
+ * destructor
*/
virtual ~JObject();
* Function to get the jobject.
*
* @return jobject, returns a new JNI object or NULL otherwise.
- *
*/
virtual jobject getObject() const;
/**
* Function to detach the jobject.
- *
- * @return void
- *
*/
void detachObject();
*/
jclass m_pClazz;
/**
- * Boolean variable to check if an object is new
+ * Boolean variable to check if an object is new.
*/
bool m_fIsNewObject;
};
-#endif //__JNI_OBJECT_H_
\ No newline at end of file
+#endif //JNI_OBJECT_H_
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
******************************************************************/
/**
- * @file jni_setter.h
- *
- * @brief This file contains the JSetter class declarations and and its functions required
- * to set data types in C++ object from Java object
-*/
-
-#ifndef __JNI_SETTER_H_
-#define __JNI_SETTER_H_
+ * @file
+ * This file contains the JSetter class declarations and and its functions required
+ * to set data types in C++ object from Java object.
+ */
+#ifndef JNI_SETTER_H_
+#define JNI_SETTER_H_
#include <jni.h>
/**
- * @class JSetter
- * @brief This class provide utility to set data types in C++ object from Java object
- *
+ * This class provide utility to set data types in C++ object from Java object.
*/
class JSetter
{
jlong value);
/**
- * This function is called to Set Boolean field to C++ object
+ * This function is called to Set Boolean field to C++ object.
*
* @param env
* JNI Environment reference
*/
static bool setJBoolField(JNIEnv *env, jobject &object, const char *fieldName, bool value);
/**
- * This function is called to Set String field from the C++ object
+ * This function is called to Set String field from the C++ object.
*
* @param env
* JNI Environment reference
const char *fieldType, const jobject value);
};
-#endif //__JNI_SETTER_H_
\ No newline at end of file
+#endif //JNI_SETTER_H_
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
******************************************************************/
/**
- * @file jni_string.h
- *
- * @brief This file contains the declaration of JString class and its members related to JString.
- *
-*/
-
-#ifndef __JNI_STRING_H_
-#define __JNI_STRING_H_
+ * @file
+ * This file contains the declaration of JString class and its members related to JString.
+ */
+#ifndef JNI_STRING_H_
+#define JNI_STRING_H_
#include <string>
#include "jni_object.h"
/**
- * @class JString
- * @brief This class inherits JObject class and provides a set of functions for JNI String.
- *
+ * This class inherits JObject class and provides a set of functions for JNI String.
*/
class JString : public JObject
{
public:
/**
- * @brief constructor
+ * constructor
*/
JString(JNIEnv *env, jstring value);
/**
- * @brief constructor
+ * constructor
*/
JString(JNIEnv *env, const char *value);
/**
- * @brief constructor
+ * constructor
*/
JString(JNIEnv *env, const std::string &value);
/**
- * @brief destructor
+ * destructor
*/
~JString();
* @param value - String value to set to a private member variable.
*
* @return bool - true on success
- *
*/
bool getValue(std::string &value);
* Function to get the private string value.
*
* @return C String value.
- *
*/
const char *c_str();
private:
std::string m_cstr;
};
-#endif //__JNI_STRING_H_
+#endif //JNI_STRING_H_
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
******************************************************************/
/**
- * @file jni_things_manager_jvm.h
- *
- * @brief This file contains the essential declarations and functions required
- * for JNI implementation
+ * @file
+ * This file contains the essential declarations and functions required
+ * for JNI implementation.
*/
-#ifndef __JNI_THINGS_MANAGER_JVM_H_
-#define __JNI_THINGS_MANAGER_JVM_H_
-
+#ifndef JNI_THINGS_MANAGER_JVM_H_
+#define JNI_THINGS_MANAGER_JVM_H_
#include <jni.h>
#include <thread>
#include <mutex>
-#define TM_SERVICE_NATIVE_API_CLASS_PATH "org/iotivity/service/tm/ThingsManagerNativeInterface"
-#define TM_SERVICE_NATIVE_API_CLASS_TYPE "Lorg/iotivity/service/tm/ThingsManagerNativeInterface;"
+#define TM_SERVICE_GROUP_MANAGER_CLASS_PATH "org/iotivity/service/tm/GroupManager"
+#define TM_SERVICE_GROUP_MANAGER_CLASS_TYPE "Lorg/iotivity/service/tm/GroupManager;"
+
+#define TM_SERVICE_GROUP_SYNCHRONIZATION_CLASS_PATH "org/iotivity/service/tm/GroupSynchronization"
+#define TM_SERVICE_GROUP_SYNCHRONIZATION_CLASS_TYPE "Lorg/iotivity/service/tm/GroupSynchronization;"
-#define TM_SERVICE_CALLBACK_CLASS_PATH "org/iotivity/service/tm/ThingsManagerCallback"
-#define TM_SERVICE_CALLBACK_CLASS_TYPE "Lorg/iotivity/service/tm/ThingsManagerCallback;"
+#define TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH "org/iotivity/service/tm/ThingsConfiguration"
+#define TM_SERVICE_THINGS_CONFIGURATION_CLASS_TYPE "Lorg/iotivity/service/tm/ThingsConfigurationn;"
+
+#define TM_SERVICE_THINGS_MAINTENANCE_CLASS_PATH "org/iotivity/service/tm/ThingsMaintenance"
+#define TM_SERVICE_THINGS_MAINTENANCE_CLASS_TYPE "Lorg/iotivity/service/tm/ThingsMaintenance;"
#define TM_SERVICE_PLATFORM_CLASS_PATH "org/iotivity/base/OcPlatform"
#define TM_SERVICE_PLATFORM_CLASS_TYPE "Lorg/iotivity/base/OcPlatform;"
#define TM_JAVA_STRING_TYPE "Ljava/lang/String;"
/**
- * @class ThingsManagerJVM
- * @brief This class provides functions related to JNI Environment.
- *
+ * This class provides functions related to JNI Environment.
*/
class ThingsManagerJVM
{
public:
/**
- * @brief destructor
+ * destructor
*/
~ThingsManagerJVM() {};
/**
- * @brief Get JVM instance
+ * Get JVM instance
*/
static JNIEnv *getEnv();
/**
- * @brief Release aquired JVM instance
+ * Release aquired JVM instance.
*/
static void releaseEnv();
private:
/**
- * @brief constructor
+ * constructor
*/
ThingsManagerJVM();
/**
- * Mutex for thread synchronization
+ * Mutex for thread synchronization.
*/
static std::mutex m_currentThreadMutex;
};
#ifdef __cplusplus
}
#endif
-#endif //__JNI_THINGS_MANAGER_JVM_H_
\ No newline at end of file
+#endif //JNI_THINGS_MANAGER_JVM_H_
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
* limitations under the License.
*
******************************************************************/
+
#include "jni_getter.h"
#include <string>
#define LOG_TAG "TM_JGetter"
-
bool JGetter::getJStringField(JNIEnv *env, jobject &object, const char *fieldName,
std::string &value)
{
return true;
}
-
bool JGetter::getJBoolField(JNIEnv *env, jobject &object, const char *fieldName, bool &value)
{
if (NULL == env ||
+/* *****************************************************************
+ *
+ * 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 "jni_object.h"
-//#define NULL 0
#define LOG_TAG "TM_JObject"
-
-
JObject::JObject(JNIEnv *env) : m_pEnv( env ),
m_pObject(NULL),
m_pClazz( NULL ),
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
* limitations under the License.
*
******************************************************************/
+
#include "jni_setter.h"
#include <string>
#define LOG_TAG "TM_JSetter"
-
bool JSetter::setJStringField(JNIEnv *env, jobject &object, const char *fieldName,
const char *value)
{
return true;
}
-
bool JSetter::setJIntField(JNIEnv *env, jobject &object, const char *fieldName, int value)
{
if (NULL == env || NULL == fieldName)
return true;
}
-
bool JSetter::setJLongField(JNIEnv *env, jobject &object, const char *fieldName, jlong value)
{
if (NULL == env || NULL == fieldName)
return true;
}
-
bool JSetter::setJBoolField(JNIEnv *env, jobject &object, const char *fieldName, bool value)
{
if (NULL == env || NULL == fieldName)
return true;
}
-
bool JSetter::setJObjectField(JNIEnv *env, jobject &object, const char *fieldName,
const char *fieldType, const jobject value)
{
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
* limitations under the License.
*
******************************************************************/
+
#include "jni_string.h"
#define LOG_TAG "TM_JString"
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
* limitations under the License.
*
******************************************************************/
-#include "jni_things_manager_jvm.h"
+
#include <string>
-#include "jni_things_manager.h"
+
+#include "jni_things_manager_jvm.h"
+#include "jni_group_manager.h"
+#include "jni_group_synchronization.h"
+#include "jni_things_configuration.h"
+#include "jni_things_maintenance.h"
#include "jni_things_manager_util.h"
#include "JniOcResource.h"
#define TM_ERROR_JNI_FOUND_CLASS_FAILED -2005
/**
- * @class JClassMap
- * @brief This class provides functions for initializing the Java class path and Java class.
- *
+ * This class provides functions for initializing the Java class path and Java class.
*/
class JClassMap
{
public:
/**
- * Java Class
- */
+ * Java Class
+ */
jclass classRef;
/**
- * Java Class Path
- */
+ * Java Class Path
+ */
const char *szClassPath;
/**
- * @brief constructor
- */
+ * constructor
+ */
JClassMap(const char *path)
: classRef(NULL)
{
};
/**
- * @class JObjectMap
- * @brief This class provides functins for initializing the Java Class path and Java Class
- * Object.
- *
+ * This class provides functions for initializing the Java Class path
+ * and Java Class Object.
*/
class JObjectMap
{
public:
/**
- * Java Object
- */
+ * Java Object
+ */
jobject object;
/**
- * Java Class Path
- */
+ * Java Class Path
+ */
const char *szClassPath;
/**
- * @brief constructor
- */
+ * @brief constructor
+ */
JObjectMap(const char *path)
: object(NULL)
{
static JClassMap gJClassMapArray[] =
{
- JClassMap(TM_SERVICE_NATIVE_API_CLASS_PATH),
- JClassMap(TM_SERVICE_CALLBACK_CLASS_PATH),
+ JClassMap(TM_SERVICE_GROUP_MANAGER_CLASS_PATH),
+ JClassMap(TM_SERVICE_GROUP_SYNCHRONIZATION_CLASS_PATH),
+ JClassMap(TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH),
+ JClassMap(TM_SERVICE_THINGS_MAINTENANCE_CLASS_PATH),
JClassMap(TM_SERVICE_OCRESOURCE_PATH),
JClassMap(TM_SERVICE_OCREPRESENTATION_PATH),
JClassMap(TM_SERVICE_HEADER_OPTION_PATH),
static JObjectMap gJObjectMapArray[] =
{
- JObjectMap(TM_SERVICE_CALLBACK_CLASS_PATH)
+ JObjectMap(TM_SERVICE_GROUP_SYNCHRONIZATION_CLASS_PATH),
+ JObjectMap(TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH),
+ JObjectMap(TM_SERVICE_THINGS_MAINTENANCE_CLASS_PATH)
+};
+
+static JNINativeMethod gGroupManagerMethodTable[] =
+{
+ { "nativeFindCandidateResource", "(Ljava/util/Vector;I)I", (void *) JNIGroupManagerFindCandidateResource},
+ { "nativeSubscribeCollectionPresence", "(Lorg/iotivity/base/OcResource;)I", (void *) JNIGroupManagerSubscribeCollectionPresence},
+ { "nativeBindResourceToGroup", "(Lorg/iotivity/base/OcResource;Lorg/iotivity/base/OcResourceHandle;)Lorg/iotivity/base/OcResourceHandle;", (void *) JNIGroupManagerBindResourceToGroup},
+ { "nativeAddActionSet", "(Lorg/iotivity/base/OcResource;Lorg/iotivity/service/tm/ActionSet;)I", (void *) JNIGroupManagerAddActionSet},
+ { "nativeExecuteActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIGroupManagerExecuteActionSet},
+ { "nativeExecuteActionSetWithDelay", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;J)I", (void *) JNIGroupManagerExecuteActionSetWithDelay},
+ { "nativeCancelActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIGroupManagerCancelActionSet},
+ { "nativeGetActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIGroupManagerGetActionSet},
+ { "nativeDeleteActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIGroupManagerDeleteActionSet}
+};
+
+static JNINativeMethod gGroupSynchronizationMethodTable[] =
+{
+ { "nativeFindGroup", "(Ljava/util/Vector;)I", (void *) JNIGroupSynchronizationFindGroup},
+ { "nativeCreateGroup", "(Ljava/lang/String;)I", (void *) JNIGroupSynchronizationCreateGroup},
+ { "nativeJoinGroupString", "(Ljava/lang/String;Lorg/iotivity/base/OcResourceHandle;)I", (void *) JNIGroupSynchronizationJoinGroupString},
+ { "nativeJoinGroupObject", "(Lorg/iotivity/base/OcResource;Lorg/iotivity/base/OcResourceHandle;)I", (void *) JNIGroupSynchronizationJoinGroupObject},
+ { "nativeLeaveGroup", "(Ljava/lang/String;Lorg/iotivity/base/OcResourceHandle;)I", (void *) JNIGroupSynchronizationLeaveGroup},
+ { "nativeLeaveGroupForResource", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;Lorg/iotivity/base/OcResourceHandle;)I", (void *) JNIGroupSynchronizationLeaveGroupForResource},
+ { "nativeDeleteGroup", "(Ljava/lang/String;)V", (void *) JNIGroupSynchronizationDeleteGroup},
+ { "nativeGetGroupList", "()Ljava/util/Map;", (void *) JNIGroupSynchronizationGetGroupList}
+};
+
+static JNINativeMethod gThingsConfigurationMethodTable[] =
+{
+ { "nativeUpdateConfigurations", "(Lorg/iotivity/base/OcResource;Ljava/util/Map;)I", (void *) JNIThingsConfigurationUpdateConfigurations},
+ { "nativeGetConfigurations", "(Lorg/iotivity/base/OcResource;Ljava/util/Vector;)I", (void *) JNIThingsConfigurationGetConfigurations},
+ { "nativeGetListOfSupportedConfigurationUnits", "()Ljava/lang/String;", (void *) JNIThingsConfigurationGetListOfSupportedConfigurationUnits},
+ { "nativeDoBootstrap", "()I", (void *) JNIThingsConfigurationDoBootstrap},
};
-static JNINativeMethod gThingsManagerMethodTable[] =
+static JNINativeMethod gThingsMaintenanceMethodTable[] =
{
- { "findCandidateResources", "(Ljava/util/Vector;I)I", (void *) JNIThingsManagerFindCandidateResource},
- { "subscribeCollectionPresence", "(Lorg/iotivity/base/OcResource;)I", (void *) JNIThingsManagerSubscribeCollectionPresence},
- { "bindResourceToGroup", "(Lorg/iotivity/base/OcResource;Lorg/iotivity/base/OcResourceHandle;)Lorg/iotivity/base/OcResourceHandle;", (void *) JNIThingsManagerBindResourceToGroup},
- { "findGroup", "(Ljava/util/Vector;)I", (void *) JNIThingsManagerFindGroup},
- { "createGroup", "(Ljava/lang/String;)I", (void *) JNIThingsManagerCreateGroup},
- { "joinGroup", "(Ljava/lang/String;Lorg/iotivity/base/OcResourceHandle;)I", (void *) JNIThingsManagerJoinGroupString},
- { "joinGroup", "(Lorg/iotivity/base/OcResource;Lorg/iotivity/base/OcResourceHandle;)I", (void *) JNIThingsManagerJoinGroupObject},
- { "leaveGroup", "(Ljava/lang/String;Lorg/iotivity/base/OcResourceHandle;)I", (void *) JNIThingsManagerLeaveGroup},
- { "leaveGroup", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;Lorg/iotivity/base/OcResourceHandle;)I", (void *) JNIThingsManagerLeaveGroupForResource},
- { "deleteGroup", "(Ljava/lang/String;)V", (void *) JNIThingsManagerDeleteGroup},
- { "getGroupList", "()Ljava/util/Map;", (void *) JNIThingsManagerGetGroupList},
- { "updateConfigurations", "(Lorg/iotivity/base/OcResource;Ljava/util/Map;)I", (void *) JNIThingsManagerUpdateConfigurations},
- { "getConfigurations", "(Lorg/iotivity/base/OcResource;Ljava/util/Vector;)I", (void *) JNIThingsManagerGetConfigurations},
- { "getListOfSupportedConfigurationUnits", "()Ljava/lang/String;", (void *) JNIThingsManagerGetListOfSupportedConfigurationUnits},
- { "doBootstrap", "()I", (void *) JNIThingsManagerDoBootstrap},
- { "reboot", "(Lorg/iotivity/base/OcResource;)I", (void *) JNIThingsManagerReboot},
- { "factoryReset", "(Lorg/iotivity/base/OcResource;)I", (void *) JNIThingsManagerFactoryReset},
- { "addActionSet", "(Lorg/iotivity/base/OcResource;Lorg/iotivity/service/tm/ActionSet;)I", (void *) JNIThingsManagerAddActionSet},
- { "executeActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIThingsManagerExecuteActionSet},
- { "executeActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;J)I", (void *) JNIThingsManagerExecuteActionSetWithDelay},
- { "cancelActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIThingsManagerCancelActionSet},
- { "getActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIThingsManagerGetActionSet},
- { "deleteActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIThingsManagerDeleteActionSet},
+ { "nativeReboot", "(Lorg/iotivity/base/OcResource;)I", (void *) JNIThingsMaintenanceReboot},
+ { "nativeFactoryReset", "(Lorg/iotivity/base/OcResource;)I", (void *) JNIThingsMaintenanceFactoryReset},
+ { "nativeGetListOfSupportedMaintenanceUnits", "()Ljava/lang/String;", (void *) JNIThingsMaintenanceGetListOfSupportedConfigurationUnits}
+
};
-static int gThingsManagerMethodTableSize = sizeof(gThingsManagerMethodTable) / sizeof(
- gThingsManagerMethodTable[0]);
+static int gGroupManagerMethodTableSize = sizeof(gGroupManagerMethodTable) / sizeof(
+ gGroupManagerMethodTable[0]);
+
+static int gGroupSynchronizationMethodTableSize = sizeof(gGroupSynchronizationMethodTable) / sizeof(
+ gGroupSynchronizationMethodTable[0]);
+
+
+static int gThingsConfigurationMethodTableSize = sizeof(gThingsConfigurationMethodTable) / sizeof(
+ gThingsConfigurationMethodTable[0]);
+
+static int gThingsMaintenanceMethodTableSize = sizeof(gThingsMaintenanceMethodTable) / sizeof(
+ gThingsMaintenanceMethodTable[0]);
int InitializeJClassMapArray(JNIEnv *env)
return JNI_ERR;
}
- jclass thingsManagerClassRef = GetJClass(TM_SERVICE_NATIVE_API_CLASS_PATH);
- if (NULL == thingsManagerClassRef)
+ // Group Manager
+ jclass groupManagerClassRef = GetJClass(TM_SERVICE_GROUP_MANAGER_CLASS_PATH);
+
+ if (NULL == groupManagerClassRef)
{
LOGE("JNI_OnLoad: GetJClass gThingsManagerClass failed !");
return JNI_ERR;
}
- env->RegisterNatives(thingsManagerClassRef, gThingsManagerMethodTable,
- gThingsManagerMethodTableSize);
+
+ env->RegisterNatives(groupManagerClassRef, gGroupManagerMethodTable,
+ gGroupManagerMethodTableSize);
+
+ // Group Synchronization
+ jclass groupSynchronizationClassRef = GetJClass(TM_SERVICE_GROUP_SYNCHRONIZATION_CLASS_PATH);
+
+ if (NULL == groupSynchronizationClassRef)
+ {
+ LOGE("JNI_OnLoad: GetJClass gThingsManagerClass failed !");
+ return JNI_ERR;
+ }
+
+ env->RegisterNatives(groupSynchronizationClassRef, gGroupSynchronizationMethodTable,
+ gGroupSynchronizationMethodTableSize);
+
+ //Things Configuration
+ jclass thingsConfigurationClassRef = GetJClass(TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH);
+
+ if (NULL == thingsConfigurationClassRef)
+ {
+ LOGE("JNI_OnLoad: GetJClass gThingsManagerClass failed !");
+ return JNI_ERR;
+ }
+
+ env->RegisterNatives(thingsConfigurationClassRef, gThingsConfigurationMethodTable,
+ gThingsConfigurationMethodTableSize);
+
+ //Things Maintenance
+ jclass thingsMaintenanceClassRef = GetJClass(TM_SERVICE_THINGS_MAINTENANCE_CLASS_PATH);
+
+ if (NULL == thingsMaintenanceClassRef)
+ {
+ LOGE("JNI_OnLoad: GetJClass gThingsManagerClass failed !");
+ return JNI_ERR;
+ }
+
+ env->RegisterNatives(thingsMaintenanceClassRef, gThingsMaintenanceMethodTable,
+ gThingsMaintenanceMethodTableSize);
ThingsManagerJVM::m_jvm = vm;
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
******************************************************************/
/**
- * @file jni_action.h
- *
- * @brief This file contains the declaration of JniAction class and its members related to JniAction.
+ * @file
+ * This file contains the declaration of JniAction class and
+ * its members related to JniAction.
*/
-#ifndef __JNI_ACTION_H_
-#define __JNI_ACTION_H_
-
+#ifndef JNI_ACTION_H_
+#define JNI_ACTION_H_
#include <vector>
#include <string>
#include "jni_capability.h"
/**
- * @class JniAction
- * @brief This class provides a set of functions to get and set Action Class member variables
- *
+ * This class provides a set of functions to get and
+ * set Action Class member variables.
*/
class JniAction : public JObject
{
public:
/**
- * @brief constructor
+ * constructor
*/
JniAction(JNIEnv *env, jobject obj);
/**
- * @brief constructor
+ * constructor
*/
JniAction(JNIEnv *env);
/**
- * @brief destructor
- *
+ * destructor
*/
~JniAction();
/**
- * Retrieves target value from JniAction class object
+ * Retrieves target value from JniAction class object.
*
* @param target - target value
*
* @return Boolean, true on success, otherwise false
- *
*/
bool getTarget(std::string &target);
/**
- * Sets target value of JniAction class object
+ * Sets target value of JniAction class object.
*
* @param target - target value
*
* @return Boolean, true on success, otherwise false
- *
*/
bool setTarget(const std::string target);
/**
- * Retrieves capability values from JniAction class object
+ * Retrieves capability values from JniAction class object.
*
* @param capabilityList - capability list
*
bool getJniCapabilityValues(std::vector<OIC::Capability *> &capabilityList);
};
-#endif //__JNI_ACTION_H_
\ No newline at end of file
+#endif //JNI_ACTION_H_
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
******************************************************************/
/**
- * @file jni_action_set.h
- *
- * @brief This file contains the declaration of JniActionSet class
- * and its members related to JniActionSet.
+ * @file
+ * This file contains the declaration of JniActionSet class
+ * and its members related to JniActionSet.
*/
-#ifndef __JNI_ACTIONSET_H_
-#define __JNI_ACTIONSET_H_
-
+#ifndef JNI_ACTIONSET_H_
+#define JNI_ACTIONSET_H_
#include <vector>
#include <string>
-#include "ThingsManager.h"
+#include "GroupManager.h"
#include "ActionSet.h"
#include "jni_object.h"
#include "jni_action.h"
using namespace OIC;
/**
- * @class JniActionSet
- * @brief This class provides a set of functions to get and set ActionSet Class member variables
- *
+ * This class provides a set of functions to get and
+ * set ActionSet Class member variables.
*/
class JniActionSet : public JObject
{
public:
/**
- * @brief constructor
+ * constructor
*/
JniActionSet(JNIEnv *env, jobject obj);
/**
- * @brief constructor
+ * constructor
*/
JniActionSet(JNIEnv *env);
/**
- * @brief destructor
- *
+ * destructor
*/
~JniActionSet();
/**
- * Retrieves target value from JniActionSet class object
+ * Retrieves target value from JniActionSet class object.
*
* @param name - ActionSet Name
*
* @return Boolean, true on success, otherwise false
- *
*/
bool getJniActionSetName(std::string &name);
* @param name - ActionSet Name
*
* @return Boolean, true on success, otherwise false
- *
*/
bool setJniActionSetName(const std::string name);
/**
- * Retrieves capability values from JniActionSet class object
+ * Retrieves capability values from JniActionSet class object.
*
* @param actionList - List of Actions
*
bool getJniListOfActions(std::vector<OIC::Action *> &actionList);
/**
- * Converts actionSet class from java to CPP
+ * Converts actionSet class from java to CPP.
*
- * @param env - Default JNI Environment Pointer
+ * @param env - Default JNI Environment Pointer
* @param jnewActionSet - action set
*
* @return OIC CPP ActionSet
ActionSet *getActionSet(JNIEnv *env, jobject jnewActionSet);
/**
- * Converts Time class from java to CPP
+ * Converts Time class from java to CPP.
*
- * @param env - Default JNI Environment Pointer
+ * @param env - Default JNI Environment Pointer
* @param jnewActionSet - Java action set
- * @param pActionSet - CPP action set
+ * @param pActionSet - CPP action set
*
* @return Boolean, true on success, otherwise false
*/
bool setTimeInfo(JNIEnv *env, jobject jnewActionSet, OIC::ActionSet *pActionSet);
};
-#endif //__JNI_ACTIONSET_H_
+#endif //JNI_ACTIONSET_H_
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
******************************************************************/
/**
- * @file jni_capability.h
- *
- * @brief This file contains the utility functions for conversions from java to CPP
- * and viceversa
+ * @file
+ * This file contains the utility functions for conversions from java to CPP
+ * and viceversa.
*/
-#ifndef __JNI_CAPABILITY_H_
-#define __JNI_CAPABILITY_H_
-
+#ifndef JNI_CAPABILITY_H_
+#define JNI_CAPABILITY_H_
#include <string>
#include "jni_object.h"
/**
- * @class JniCapability
- * @brief This class provides a set of functions to get and set Capability Class member variables
- *
+ * This class provides a set of functions to get and
+ * set Capability Class member variables.
*/
class JniCapability : public JObject
{
public:
/**
- * @brief constructor
+ * constructor
*/
JniCapability(JNIEnv *env, jobject obj);
/**
- * @brief constructor
+ * constructor
*/
JniCapability(JNIEnv *env);
/**
- * @brief destructor
- *
+ * destructor
*/
~JniCapability();
/**
- * Retrieves Capability value from JniCapability class object
+ * Retrieves Capability value from JniCapability class object.
*
* @param capability
* [OUT] capability value
*
* @return Boolean, true on success, otherwise false
- *
*/
bool getJniCapabilityValue(std::string &capability);
/**
- * Sets Capability value of JniCapability class object
+ * Sets Capability value of JniCapability class object.
*
* @param capability
* [IN] capability value
*
* @return Boolean, true on success, otherwise false
- *
*/
bool setJniCapabilityValue(const std::string capability);
/**
- * Retrieves status of JniCapability class object
+ * Retrieves status of JniCapability class object.
*
* @param status
* [OUT] status
*
* @return Boolean, true on success, otherwise false
- *
*/
bool getJniCapabilityStatus(std::string &status);
* @param status
* [IN] status
*
- * @return Boolean, true on success, otherwise false
- *
+ * @return Boolean, true on success, otherwise false.
*/
bool setJniCapabilityStatus(const std::string status);
};
-#endif //__JNI_CAPABILITY_H_
\ No newline at end of file
+#endif //JNI_CAPABILITY_H_
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the declaration of Group Manager APIs
+ * for JNI implementation.
+ */
+
+#ifndef JNI_GROUP_MANAGER_H_
+#define JNI_GROUP_MANAGER_H_
+
+#include <stdio.h>
+#include <string.h>
+
+#include <jni.h>
+#include <jni_string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * API for discoverying candidate resources.
+ *
+ * @param resourceTypes - required resource types(called "candidate")
+ * @param waitSec - Delay time in seconds to add before starting to find the resources in network.
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIGroupManagerFindCandidateResource
+(JNIEnv *env, jobject interfaceObject, jobject resourceTypes, jint waitSec);
+
+/**
+ * API for subscribing child's state.
+ *
+ * @param resource - collection resource for subscribing presence of all child resources.
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIGroupManagerSubscribeCollectionPresence
+(JNIEnv *env, jobject interfaceObject, jobject resource);
+
+
+/**
+ * API for register and bind resource to group.
+ *
+ * @param resource - resource for register and bind to group. It has all data.
+ * @param collectionHandle - collection resource handle. It will be added child resource.
+ *
+ * @return childHandle - child resource handle.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jobject JNICALL JNIGroupManagerBindResourceToGroup
+(JNIEnv *env, jobject interfaceObject, jobject resource, jobject collectionHandle);
+
+/**
+ * API for adding an Action Set.
+ *
+ * @param resource - resource type representing the target group
+ * @param newActionSet - list of Action Set to be added
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+
+JNIEXPORT jint JNICALL JNIGroupManagerAddActionSet
+(JNIEnv *env, jobject interfaceObject, jobject resource, jobject newActionSet);
+
+/**
+ * API for executing the Action Set.
+ *
+ * @param resource - resource type representing the target group
+ * @param actionSetName - Action Set name for executing the Action set
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIGroupManagerExecuteActionSet
+(JNIEnv *env, jobject interfaceObject, jobject resource, jstring actionSetName);
+
+/**
+ * API for executing the Action Set.
+ *
+ * @param resource - resource type representing the target group
+ * @param actionSetName - Action Set name for executing the Action set
+ * @param delay - waiting time for until action set run.
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIGroupManagerExecuteActionSetWithDelay
+(JNIEnv *env, jobject interfaceObject, jobject resource, jstring actionSetName, jlong delay);
+
+/**
+ * API for cancelling the Action Set.
+ *
+ * @param resource - resource type representing the target group
+ * @param actionSetName - Action Set name for cancelling the Action set
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIGroupManagerCancelActionSet
+(JNIEnv *env, jobject interfaceObject, jobject resource, jstring actionSetName);
+
+
+/**
+ * API for reading the Action Set.
+ *
+ * @param resource - resource type representing the target group
+ * @param actionSetName - Action Set name for reading the Action set
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIGroupManagerGetActionSet
+(JNIEnv *env, jobject interfaceObject, jobject resource, jstring actionSetName);
+
+/**
+ * API for removing the Action Set.
+ *
+ * @param resource - resource type representing the target group
+ * @param actionSetName - Action Set name for removing the Action set
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIGroupManagerDeleteActionSet
+(JNIEnv *env, jobject interfaceObject, jobject resource, jstring actionSetName);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //JNI_GROUP_MANAGER_H_
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the declaration of GroupManagerCallbacks class
+ * and its members related to ThingsManagerCallbacks.
+ */
+
+#ifndef JNI_GROUP_MANAGER_CALLBACKS_H_
+#define JNI_GROUP_MANAGER_CALLBACKS_H_
+
+#include <string>
+
+#include "GroupManager.h"
+
+/**
+ *This class provides a set of callback functions for group management.
+ */
+class GroupManagerCallbacks
+{
+ public:
+ GroupManagerCallbacks() {}
+ virtual ~GroupManagerCallbacks() {}
+
+ /**
+ * This callback method is called when resources are discovered in network.
+ *
+ * @param resourceVector - List of resources discovered in the network
+ */
+ static void onFoundCandidateResource(std::vector< std::shared_ptr<OC::OCResource > >
+ resourceVector);
+
+ /**
+ * This callback method is called for child resource presence status.
+ *
+ * @param resource - URI of resource.
+ * @param result - error code.
+ */
+ static void onSubscribePresence(std::string resource, OCStackResult result);
+
+ /**
+ * This callback method is called when a response for the executeActionSet
+ * or deleteActionSet request just arrives.
+ *
+ * @param headerOptions - It comprises of optionID and optionData as members.
+ * @param rep - Configuration parameters are carried as a pair of attribute key and value
+ * in a form of OCRepresentation instance.
+ * @param eCode - error code.
+ */
+ static void onPostResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode);
+
+ /**
+ * This callback method is called when a response for the addActionSet request
+ * just arrives.
+ *
+ * @param headerOptions - It comprises of optionID and optionData as members.
+ * @param rep - Configuration parameters are carried as a pair of attribute key and value
+ * in a form of OCRepresentation instance.
+ * @param eCode - error code.
+ */
+ static void onPutResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode);
+
+ /**
+ * This callback method is called when a response for the getActionSet request
+ * just arrives.
+ *
+ * @param headerOptions - It comprises of optionID and optionData as members.
+ * @param rep - Configuration parameters are carried as a pair of attribute key and value
+ * in a form of OCRepresentation instance.
+ * @param eCode - error code.
+ */
+ static void onGetResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode);
+
+ /**
+ * This method invokes the Callback function with particular name and signature.
+ *
+ * @param headerOptions - It comprises of optionID and optionData as members.
+ * @param rep - Configuration parameters are carried as a pair of attribute key and value
+ * in a form of OCRepresentation instance.
+ * @param eCode - error code.
+ * @param callbackName - callbackName to be invoked.
+ * @param signature - Signature of the callback method to be called.
+ */
+ static void invokeCallback(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode,
+ const char *callbackName, const char *signature);
+};
+#endif //JNI_GROUP_MANAGER_CALLBACKS_H_
+
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the declaration of Group Synchronization APIs
+ * for JNI implementation.
+ */
+
+#ifndef JNI_GROUP_SYNCHRONIZATION_H_
+#define JNI_GROUP_SYNCHRONIZATION_H_
+
+#include <stdio.h>
+#include <string.h>
+
+#include <jni.h>
+#include <jni_string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * API for finding a specific remote group when a resource tries to join a group.
+ * Callback is called when a group is found or not.
+ *
+ * @param resourceTypes - resource types of a group to find and join
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: It return OC_STACK ERROR when It was finding a group.
+ * You should call this api when the group finding process has stopped.
+ * OCStackResult is defined in ocstack.h.
+ */
+
+JNIEXPORT jint JNICALL JNIGroupSynchronizationFindGroup
+(JNIEnv *env, jobject interfaceObject, jobject resourceTypes);
+
+/**
+ * API for creating a new group.
+ *
+ * @param resourceType - resource type of a group to create
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIGroupSynchronizationCreateGroup
+(JNIEnv *env, jobject interfaceObject, jstring resourceType);
+
+/**
+ * API for joining a group. This API is used when a resource that has a group tries
+ * to find a specific remote resource and makes it join a group
+ *
+ * @param resourceType - resource type of a group to join.
+ * @param resourceHandle - resource handle to join a group.
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: If you want to join the resource in the remote(other) process, use the API
+ * jniThingsManagerJoinGroupObject instead of this.
+ * OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIGroupSynchronizationJoinGroupString
+(JNIEnv *env, jobject interfaceObject, jstring resourceType, jobject resourceHandle);
+
+/**
+ * API for joining a group. This API is used when a resource that
+ * doesn't have a group tries to find and join a specific remote group.
+ *
+ * @param resource - group resource pointer to join.
+ * @param resourceHandle - resource handle to join a group.
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: NOTE: If you want to join the resource in the same process, use the API
+ * jniThingsManagerJoinGroupString instead of this.
+ * OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIGroupSynchronizationJoinGroupObject
+(JNIEnv *env, jobject interfaceObject, jobject resource, jobject resourceHandle);
+
+/**
+ * API for leaving a joined group.
+ *
+ * @param resourceType - resource type of a group to leave.
+ * @param resourceHandle - resource handle to join a group.
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIGroupSynchronizationLeaveGroup
+(JNIEnv *env, jobject interfaceObject, jstring resourceType, jobject resourceHandle);
+
+/**
+ * API for leaving a joined group.
+ *
+ * @param resource - resource of a group to leave.
+ * @param resourceType - resource type of a group to leave.
+ * @param resourceHandle - resource handle to join a group.
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIGroupSynchronizationLeaveGroupForResource
+(JNIEnv *env, jobject interfaceObject, jobject resource, jstring resourceType,
+ jobject resourceHandle);
+
+/**
+ * API for deleting a group.
+ *
+ * @param collectionResourceType - resource type of a group to delete.
+ *
+ * @return void
+ */
+JNIEXPORT void JNICALL JNIGroupSynchronizationDeleteGroup
+(JNIEnv *env, jobject interfaceObject, jstring collectionResourceType);
+
+/**
+ * API for getting a list of joined groups.
+ *
+ * @return std::map - return value of this API.
+ * It returns group resource type and group resource handle as a map type.
+ */
+JNIEXPORT jobject JNICALL JNIGroupSynchronizationGetGroupList
+(JNIEnv *env, jobject interfaceObject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //JNI_GROUP_SYNCHRONIZATION_H_
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the declaration of GroupSynchronizationCallbacks class.
+ */
+
+#ifndef JNI_GROUP_SYNCHRONIZATION_CALLBACKS_H_
+#define JNI_GROUP_SYNCHRONIZATION_CALLBACKS_H_
+
+#include <string>
+
+#include "GroupSynchronization.h"
+
+/**
+ * This class provides callback function for group Synchronization.
+ */
+class GroupSynchronizationCallbacks
+{
+
+ public:
+ GroupSynchronizationCallbacks() {}
+ virtual ~GroupSynchronizationCallbacks() {}
+
+ /**
+ * This callback method is called to notify whether group is found or not.
+ *
+ * @param resource - Resource URI
+ */
+ static void onFoundGroup(std::shared_ptr<OC::OCResource> resource);
+
+
+};
+#endif //JNI_GROUP_SYNCHRONIZATION_CALLBACKS_H_
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the declaration of Things Configuration API's
+ * for JNI implementation.
+ */
+
+#ifndef JNI_THINGS_CONFIGURATION_H_
+#define JNI_THINGS_CONFIGURATION_H_
+
+#include <stdio.h>
+#include <string.h>
+
+#include <jni.h>
+#include <jni_string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * API for updating configuration value of multiple things of a target group
+ * or a single thing.
+ * Before using the below function, a developer should acquire a resource pointer of
+ * (collection) resource that he wants to send a request by calling findResource() function
+ * provided in OCPlatform. And he should also notice a "Configuration Name" term which
+ * represents a nickname of a target attribute of a resource that he wants to update.
+ * The base motivation to introduce the term is to avoid a usage of URI to access a resource
+ * from a developer. Thus, a developer should know which configuration names are supported
+ * by Things Configuration class and what the configuration name means.
+ * To get a list of supported configuration names, use getListOfSupportedConfigurationUnits()
+ * function, which provides the list in JSON format.
+ *
+ * @param resource - resource pointer representing the target group or the single thing.
+ * @param configurations - ConfigurationUnit: a nickname of attribute of target resource
+ * (e.g., installedlocation, currency, (IP)address)
+ * Value : a value to be updated
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIThingsConfigurationUpdateConfigurations
+(JNIEnv *env, jobject interfaceObject, jobject resource, jobject configurations);
+
+/**
+ * API for getting configuration value of multiple things of a target group
+ * or a single thing.
+ *
+ * @param resource - resource pointer representing the target group or the single thing.
+ * @param configurations - ConfigurationUnit: a nickname of attribute of target resource.
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIThingsConfigurationGetConfigurations
+(JNIEnv *env, jobject interfaceObject, jobject resource, jobject configurations);
+
+/**
+ * API for showing the list of supported configuration units (configurable parameters).
+ *
+ * @return std::string - return value of this API.
+ * It returns the list in JSON format
+ */
+JNIEXPORT jstring JNICALL JNIThingsConfigurationGetListOfSupportedConfigurationUnits
+(JNIEnv *env, jobject interfaceObject);
+
+/**
+ * API for boostrapping system configuration parameters from a bootstrap server.
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIThingsConfigurationDoBootstrap
+(JNIEnv *env, jobject interfaceObject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //JNI_THINGS_CONFIGURATION_H_
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the declaration of ThingsConfigurationCallbacks class
+ */
+
+#ifndef JNI_THINGS_CONFIGURATON_CALLBACKS_H_
+#define JNI_THINGS_CONFIGURATON_CALLBACKS_H_
+
+#include <string>
+
+#include "ThingsConfiguration.h"
+
+/**
+ * This class provides a set of callback functions for things configuration.
+ */
+class ThingsConfigurationCallbacks
+{
+
+ public:
+ ThingsConfigurationCallbacks() {}
+ virtual ~ThingsConfigurationCallbacks() {}
+
+ /**
+ * This callback method is called when a response for the updateConfigurations request
+ * just arrives.
+ *
+ * @param headerOptions - It comprises of optionID and optionData as members.
+ * @param rep - Configuration parameters are carried as a pair of attribute key and value
+ * in a form of OCRepresentation instance.
+ * @param eCode - error code.
+ */
+ static void onUpdateConfigurationsResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode);
+
+ /**
+ * This callback method is called when a response for the getConfigurations request
+ * just arrives.
+ *
+ * @param headerOptions - It comprises of optionID and optionData as members.
+ * @param rep - Configuration parameters are carried as a pair of attribute key and value
+ * in a form of OCRepresentation instance.
+ * @param eCode - error code.
+ */
+ static void onGetConfigurationsResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode);
+
+ /**
+ * This callback method is called when a response for the doBootstrap request
+ * just arrives.
+ *
+ * @param headerOptions - It comprises of optionID and optionData as members.
+ * @param rep - Configuration parameters are carried as a pair of attribute key and value
+ * in a form of OCRepresentation instance.
+ * @param eCode - error code.
+ */
+ static void onBootStrapResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep,
+ const int eCode);
+
+ /**
+ * This method invokes the Callback function with particular name and signature.
+ *
+ * @param headerOptions - It comprises of optionID and optionData as members.
+ * @param rep - Configuration parameters are carried as a pair of attribute key and value
+ * in a form of OCRepresentation instance.
+ * @param eCode - error code.
+ * @param callbackName - callbackName to be invoked.
+ * @param signature - Signature of the callback method to be called.
+ */
+ static void invokeCallback(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode, const char *callbackName,
+ const char *signature);
+
+};
+#endif //JNI_GROUP_SYNCHRONIZATION_CALLBACKS_H_
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the declaration of Things Maintenance API's
+ * for JNI implementation.
+ */
+
+#ifndef JNI_THINGS_MAINTENANCE_H_
+#define JNI_THINGS_MAINTENANCE_H_
+
+#include <stdio.h>
+#include <string.h>
+
+#include <jni.h>
+#include <jni_string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * API to let thing(device) reboot.
+ * The target thing could be a group of multiple things or a single thing.
+ *
+ * @param resource - resource type representing the target group
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIThingsMaintenanceReboot
+(JNIEnv *env, jobject interfaceObject, jobject resource);
+
+/**
+ * API for factory reset on thing(device).
+ * The target thing could be a group of multiple things or a single thing.
+ *
+ * @param resource - resource type representing the target group
+ *
+ * @return OCStackResult - return value of this API.
+ * It returns OC_STACK_OK if success.
+ *
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+JNIEXPORT jint JNICALL JNIThingsMaintenanceFactoryReset
+(JNIEnv *env, jobject interfaceObject, jobject resource);
+
+
+/**
+ * API for showing the list of supported Maintenance units.
+ *
+ * @return std::string - return value of this API.
+ * It returns the list in JSON format
+ */
+JNIEXPORT jstring JNICALL JNIThingsMaintenanceGetListOfSupportedConfigurationUnits
+(JNIEnv *env, jobject interfaceObject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //JNI_THINGS_MAINTENANCE_H_
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains the declaration of ThingsMaintenanceCallbacks class.
+ */
+
+#ifndef JNI_THINGS_MAINTENANCE_CALLBACKS_H_
+#define JNI_THINGS_MAINTENANCE_CALLBACKS_H_
+
+#include <string>
+
+#include "ThingsMaintenance.h"
+
+/**
+ * This class provides a set of callback functions for things maintenance.
+ */
+class ThingsMaintenanceCallbacks
+{
+
+ public:
+ ThingsMaintenanceCallbacks() {}
+ virtual ~ThingsMaintenanceCallbacks() {}
+
+ /**
+ * This callback method is called when a response for the reboot request
+ * just arrives.
+ *
+ * @param headerOptions - It comprises of optionID and optionData as members.
+ * @param rep - Configuration parameters are carried as a pair of attribute key and value
+ * in a form of OCRepresentation instance.
+ * @param eCode - error code.
+ */
+ static void onRebootResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep,
+ const int eCode);
+
+ /**
+ * This callback method is called when a response for the factoryReset request
+ * just arrives.
+ *
+ * @param headerOptions - It comprises of optionID and optionData as members.
+ * @param rep - Configuration parameters are carried as a pair of attribute key and value
+ * in a form of OCRepresentation instance.
+ * @param eCode - error code.
+ */
+ static void onFactoryResetResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep,
+ const int eCode);
+
+ /**
+ * This method invokes the Callback function with particular name and signature.
+ *
+ * @param headerOptions - It comprises of optionID and optionData as members.
+ * @param rep - Configuration parameters are carried as a pair of attribute key and value
+ * in a form of OCRepresentation instance.
+ * @param eCode - error code.
+ * @param callbackName - callbackName to be invoked.
+ * @param signature - Signature of the callback method to be called.
+ */
+ static void invokeCallback(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode,
+ const char *callbackName, const char *signature);
+};
+#endif //JNI_THINGS_MAINTENANCE_CALLBACKS_H_
+++ /dev/null
-/******************************************************************
- *
- * 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.
- *
- ******************************************************************/
-
-/** @file jni_things_manager.h
- *
- * @brief This file contains the declaration of Things Manager service API's
- * for JNI implementation
- */
-
-#ifndef __JNI_THINGS_MANAGER_H_
-#define __JNI_THINGS_MANAGER_H_
-
-
-#include <stdio.h>
-#include <string.h>
-
-#include <jni.h>
-#include <jni_string.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * API for discoverying candidate resources.
- *
- * @param resourceTypes - required resource types(called "candidate")
- * @param waitSec - Delay time in seconds to add before starting to find the resources in network.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerFindCandidateResource
-(JNIEnv *env, jobject interfaceObject, jobject resourceTypes, jint waitSec);
-
-/**
- * API for subscribing child's state.
- *
- * @param resource - collection resource for subscribing presence of all child resources.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerSubscribeCollectionPresence
-(JNIEnv *env, jobject interfaceObject, jobject resource);
-
-/**
- * API for register and bind resource to group.
- *
- * @param resource - resource for register and bind to group. It has all data.
- * @param collectionHandle - collection resource handle. It will be added child resource.
- *
- * @return childHandle - child resource handle.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jobject JNICALL JNIThingsManagerBindResourceToGroup
-(JNIEnv *env, jobject interfaceObject, jobject resource, jobject collectionHandle);
-
-/**
- * API for finding a specific remote group when a resource tries to join a group.
- * Callback is called when a group is found or not.
- *
- * @param resourceTypes - resource types of a group to find and join
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: It return OC_STACK ERROR when It was finding a group.
- * You should call this api when the group finding process has stopped.
- * OCStackResult is defined in ocstack.h.
- */
-
-JNIEXPORT jint JNICALL JNIThingsManagerFindGroup
-(JNIEnv *env, jobject interfaceObject, jobject resourceTypes);
-
-/**
- * API for creating a new group.
- *
- * @param resourceType - resource type of a group to create
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerCreateGroup
-(JNIEnv *env, jobject interfaceObject, jstring resourceType);
-
-/**
- * API for joining a group. This API is used when a resource that has a group tries
- * to find a specific remote resource and makes it join a group
- *
- * @param resourceType - resource type of a group to join.
- * @param resourceHandle - resource handle to join a group.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: If you want to join the resource in the remote(other) process, use the API
- * jniThingsManagerJoinGroupObject instead of this.
- * OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerJoinGroupString
-(JNIEnv *env, jobject interfaceObject, jstring resourceType, jobject resourceHandle);
-
-/**
- * API for joining a group. This API is used when a resource that
- * doesn't have a group tries to find and join a specific remote group.
- *
- * @param resource - group resource pointer to join.
- * @param resourceHandle - resource handle to join a group.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: NOTE: If you want to join the resource in the same process, use the API
- * jniThingsManagerJoinGroupString instead of this.
- * OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerJoinGroupObject
-(JNIEnv *env, jobject interfaceObject, jobject resource, jobject resourceHandle);
-
-/**
- * API for leaving a joined group.
- *
- * @param resourceType - resource type of a group to leave.
- * @param resourceHandle - resource handle to join a group.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerLeaveGroup
-(JNIEnv *env, jobject interfaceObject, jstring resourceType, jobject resourceHandle);
-
-/**
- * API for leaving a joined group.
- *
- * @param resource - resource of a group to leave.
- * @param resourceType - resource type of a group to leave.
- * @param resourceHandle - resource handle to join a group.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerLeaveGroupForResource
-(JNIEnv *env, jobject interfaceObject, jobject resource, jstring resourceType,
- jobject resourceHandle);
-/**
- * API for deleting a group.
- *
- * @param collectionResourceType - resource type of a group to delete.
- *
- * @return void
- */
-JNIEXPORT void JNICALL JNIThingsManagerDeleteGroup
-(JNIEnv *env, jobject interfaceObject, jstring collectionResourceType);
-
-/**
- * API for getting a list of joined groups.
- *
- * @return std::map - return value of this API.
- * It returns group resource type and group resource handle as a map type.
- */
-JNIEXPORT jobject JNICALL JNIThingsManagerGetGroupList
-(JNIEnv *env, jobject interfaceObject);
-
-/**
- * API for updating configuration value of multiple things of a target group
- * or a single thing.
- * Before using the below function, a developer should acquire a resource pointer of
- * (collection) resource that he wants to send a request by calling findResource() function
- * provided in OCPlatform. And he should also notice a "Configuration Name" term which
- * represents a nickname of a target attribute of a resource that he wants to update.
- * The base motivation to introduce the term is to avoid a usage of URI to access a resource
- * from a developer. Thus, a developer should know which configuration names are supported
- * by Things Configuration class and what the configuration name means.
- * To get a list of supported configuration names, use getListOfSupportedConfigurationUnits()
- * function, which provides the list in JSON format.
- *
- * @param resource - resource pointer representing the target group or the single thing.
- * @param configurations - ConfigurationUnit: a nickname of attribute of target resource
- * (e.g., installedlocation, currency, (IP)address)
- * Value : a value to be updated
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerUpdateConfigurations
-(JNIEnv *env, jobject interfaceObject, jobject resource, jobject configurations);
-
-/**
- * API for getting configuration value of multiple things of a target group
- * or a single thing.
- *
- * @param resource - resource pointer representing the target group or the single thing.
- * @param configurations - ConfigurationUnit: a nickname of attribute of target resource.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerGetConfigurations
-(JNIEnv *env, jobject interfaceObject, jobject resource, jobject configurations);
-
-/**
- * API for showing the list of supported configuration units (configurable parameters)
- *
- * @return std::string - return value of this API.
- * It returns the list in JSON format
- */
-JNIEXPORT jstring JNICALL JNIThingsManagerGetListOfSupportedConfigurationUnits
-(JNIEnv *env, jobject interfaceObject);
-
-/**
- * API for boostrapping system configuration parameters from a bootstrap server.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerDoBootstrap
-(JNIEnv *env, jobject interfaceObject);
-
-/**
- * API to let thing(device) reboot.
- * The target thing could be a group of multiple things or a single thing.
- *
- * @param resource - resource type representing the target group
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerReboot
-(JNIEnv *env, jobject interfaceObject, jobject resource);
-
-/**
- * API for factory reset on thing(device).
- * The target thing could be a group of multiple things or a single thing.
- *
- * @param resource - resource type representing the target group
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerFactoryReset
-(JNIEnv *env, jobject interfaceObject, jobject resource);
-
-/**
- * API for adding an Action Set.
- *
- * @param resource - resource type representing the target group
- * @param newActionSet - list of Action Set to be added
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-
-JNIEXPORT jint JNICALL JNIThingsManagerAddActionSet
-(JNIEnv *env, jobject interfaceObject, jobject resource, jobject newActionSet);
-
-/**
- * API for executing the Action Set.
- *
- * @param resource - resource type representing the target group
- * @param actionSetName - Action Set name for executing the Action set
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerExecuteActionSet
-(JNIEnv *env, jobject interfaceObject, jobject resource, jstring actionSetName);
-
-/**
- * API for executing the Action Set.
- *
- * @param resource - resource type representing the target group
- * @param actionSetName - Action Set name for executing the Action set
- * @param delay - waiting time for until action set run.
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerExecuteActionSetWithDelay
-(JNIEnv *env, jobject interfaceObject, jobject resource, jstring actionSetName, jlong delay);
-
-/**
- * API for cancelling the Action Set.
- *
- * @param resource - resource type representing the target group
- * @param actionSetName - Action Set name for cancelling the Action set
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerCancelActionSet
-(JNIEnv *env, jobject interfaceObject, jobject resource, jstring actionSetName);
-
-
-/**
- * API for reading the Action Set.
- *
- * @param resource - resource type representing the target group
- * @param actionSetName - Action Set name for reading the Action set
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerGetActionSet
-(JNIEnv *env, jobject interfaceObject, jobject resource, jstring actionSetName);
-
-/**
- * API for removing the Action Set.
- *
- * @param resource - resource type representing the target group
- * @param actionSetName - Action Set name for removing the Action set
- *
- * @return OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
- */
-JNIEXPORT jint JNICALL JNIThingsManagerDeleteActionSet
-(JNIEnv *env, jobject interfaceObject, jobject resource, jstring actionSetName);
-
-#ifdef __cplusplus
-}
-#endif
-#endif //__JNI_THINGS_MANAGER_H_
\ No newline at end of file
+++ /dev/null
-/******************************************************************
- *
- * 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.
- *
- ******************************************************************/
-
-/** @file jni_things_manager_callbacks.h
- *
- * @brief This file contains the declaration of ThingsManagerCallbacks class
- * and its members related to ThingsManagerCallbacks.
- */
-
-#ifndef __JNI_THINGS_MANAGER_CALLBACKS_H_
-#define __JNI_THINGS_MANAGER_CALLBACKS_H_
-
-#include <string>
-
-#include "ThingsManager.h"
-
-/**
- * @class ThingsManagerCallbacks
- * @brief This class provides a set of callback functions for group management,
- * synchronization of group, configuration of things, and diagnostics about things.
- *
- */
-class ThingsManagerCallbacks
-{
-
- public:
- ThingsManagerCallbacks() {}
- virtual ~ThingsManagerCallbacks() {}
-
- /**
- * This callback method is called when resources are discovered in network.
- *
- * @param resourceVector - List of resources discovered in the network
- *
- * @return void
- */
- static void onFoundCandidateResource(std::vector< std::shared_ptr<OC::OCResource > >
- resourceVector);
-
- /**
- * This callback method is called to notify whether group is found or not.
- *
- * @param resource - Resource URI
- *
- * @return void
- */
- static void onFoundGroup(std::shared_ptr<OC::OCResource> resource);
-
- /**
- * This callback method is called for child resource presence status.
- *
- * @param resource - URI of resource.
- * @param result - error code.
- *
- * @return void
- */
- static void onSubscribePresence(std::string resource, OCStackResult result);
-
- /**
- * This callback method is called when a response for the updateConfigurations request
- * just arrives.
- *
- * @param headerOptions - It comprises of optionID and optionData as members.
- * @param rep - Configuration parameters are carried as a pair of attribute key and value
- * in a form of OCRepresentation instance.
- * @param eCode - error code.
- *
- * @return void
- */
- static void onUpdateConfigurationsResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode);
-
- /**
- * This callback method is called when a response for the getConfigurations request
- * just arrives.
- *
- * @param headerOptions - It comprises of optionID and optionData as members.
- * @param rep - Configuration parameters are carried as a pair of attribute key and value
- * in a form of OCRepresentation instance.
- * @param eCode - error code.
- *
- * @return void
- */
- static void onGetConfigurationsResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode);
-
- /**
- * This callback method is called when a response for the doBootstrap request
- * just arrives.
- *
- * @param headerOptions - It comprises of optionID and optionData as members.
- * @param rep - Configuration parameters are carried as a pair of attribute key and value
- * in a form of OCRepresentation instance.
- * @param eCode - error code.
- *
- * @return void
- */
- static void onBootStrapResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep,
- const int eCode);
-
- /**
- * This callback method is called when a response for the reboot request
- * just arrives.
- *
- * @param headerOptions - It comprises of optionID and optionData as members.
- * @param rep - Configuration parameters are carried as a pair of attribute key and value
- * in a form of OCRepresentation instance.
- * @param eCode - error code.
- *
- * @return void
- */
- static void onRebootResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep,
- const int eCode);
-
- /**
- * This callback method is called when a response for the factoryReset request
- * just arrives.
- *
- * @param headerOptions - It comprises of optionID and optionData as members.
- * @param rep - Configuration parameters are carried as a pair of attribute key and value
- * in a form of OCRepresentation instance.
- * @param eCode - error code.
- *
- * @return void
- */
- static void onFactoryResetResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep,
- const int eCode);
-
- /**
- * This callback method is called when a response for the executeActionSet
- * or deleteActionSet request just arrives.
- *
- * @param headerOptions - It comprises of optionID and optionData as members.
- * @param rep - Configuration parameters are carried as a pair of attribute key and value
- * in a form of OCRepresentation instance.
- * @param eCode - error code.
- *
- * @return void
- */
- static void onPostResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode);
-
- /**
- * This callback method is called when a response for the addActionSet request
- * just arrives.
- *
- * @param headerOptions - It comprises of optionID and optionData as members.
- * @param rep - Configuration parameters are carried as a pair of attribute key and value
- * in a form of OCRepresentation instance.
- * @param eCode - error code.
- *
- * @return void
- */
- static void onPutResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode);
-
- /**
- * This callback method is called when a response for the getActionSet request
- * just arrives.
- *
- * @param headerOptions - It comprises of optionID and optionData as members.
- * @param rep - Configuration parameters are carried as a pair of attribute key and value
- * in a form of OCRepresentation instance.
- * @param eCode - error code.
- *
- * @return void
- */
- static void onGetResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode);
-
- /**
- * This method invokes the Callback function with particular name and signature.
- *
- * @param headerOptions - It comprises of optionID and optionData as members.
- * @param rep - Configuration parameters are carried as a pair of attribute key and value
- * in a form of OCRepresentation instance.
- * @param eCode - error code.
- * @param callbackName - callbackName to be invoked.
- * @param signature - Signature of the callback method to be called.
- *
- * @return void
- */
- static void invokeCallback(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode,
- const char *callbackName, const char *signature);
-
-};
-#endif //__JNI_THINGS_MANAGER_CALLBACKS_H_
\ No newline at end of file
******************************************************************/
/**
- * @file jni_things_manager_util.h
- *
- * @brief This file contains the utility functions for conversions from java to CPP
- * and viceversa
+ * @file
+ * This file contains the utility functions for conversions from java to CPP
+ * and viceversa.
*/
-#ifndef __JNI_THINGS_MANAGER_UTILS_H_
-#define __JNI_THINGS_MANAGER_UTILS_H_
-
+#ifndef JNI_THINGS_MANAGER_UTILS_H_
+#define JNI_THINGS_MANAGER_UTILS_H_
#include <vector>
#include <map>
+#include "JniOcResource.h"
#include "jni_things_manager_jvm.h"
/**
- * Utility function for converting a Java Vector of Strings to CPP Vector of Strings
+ * Utility function for converting a Java Vector of Strings to CPP Vector of Strings.
*
- * @param env - Default JNI Environment pointer
+ * @param env - Default JNI Environment pointer
* @param jVectorString - Java Vector of Strings
- *
- * @return void
*/
std::vector<std::string> convertStringVector(JNIEnv *env, jobject jVectorString);
/**
- * Utility function for converting a Hash Map of Strings to CPP Map of Strings
+ * Utility function for converting a Hash Map of Strings to CPP Map of Strings.
*
- * @param env - Default JNI Environment pointer
+ * @param env - Default JNI Environment pointer
* @param jMapString - Java Map of Strings
- *
- * @return void
*/
std::map<std::string, std::string> convertStringMap(JNIEnv *env, jobject jMapString);
-#endif //__JNI_THINGS_MANAGER_UTILS_H_
+
+/**
+ * Utility function for converting ocResource Handle to java.
+ * @param env - Default JNI Environment pointer
+ * @param resourceHandle - Resource Handle
+ */
+jobject ocResourceHandleToJava(JNIEnv *env, jlong resourceHandle);
+
+/**
+ * Utility function for converting native ocResource to java ocResource.
+ * @param env - Default JNI Environment pointer
+ * @param resource - Native Resource
+ */
+jobject OcResourceToJava(JNIEnv *env, jlong resource);
+
+/**
+ * Utility function for converting native ocHeaderOption to java ocHeaderOption.
+ * @param env - Default JNI Environment pointer
+ * @param headerOption - Native headerOption
+ */
+jobject OcHeaderOptionToJava(JNIEnv *env, OC::HeaderOption::OCHeaderOption headerOption);
+
+/**
+ * Utility function for converting native ocRepresentation to java ocRepresentation.
+ * @param env - Default JNI Environment pointer
+ * @param ocRepresentation - Native ocRepresentation
+ */
+jobject OcRepresentationToJava(JNIEnv *env, jlong ocRepresentation);
+
+#endif //JNI_THINGS_MANAGER_UTILS_H_
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
* limitations under the License.
*
******************************************************************/
-#include "jni_action.h"
-#include <ActionSet.h>
+#include "jni_action.h"
#include "jni_things_manager_jvm.h"
#include "jni_getter.h"
#include "jni_setter.h"
+#include <ActionSet.h>
+
#define JACTION_TARGET ("target")
#define JACTION_LISTOF_CAPABILITY ("listOfCapability")
-
JniAction::JniAction(JNIEnv *env, jobject obj) : JObject(env, obj)
{
}
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
* limitations under the License.
*
******************************************************************/
-#include "jni_action_set.h"
+#include "jni_action_set.h"
#include "jni_things_manager_jvm.h"
#include "jni_getter.h"
#include "jni_setter.h"
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
* limitations under the License.
*
******************************************************************/
-#include "jni_capability.h"
+#include "jni_capability.h"
#include "jni_things_manager_jvm.h"
#include "jni_getter.h"
#include "jni_setter.h"
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "jni_group_manager.h"
+#include "JniOcResource.h"
+#include "JniOcResourceHandle.h"
+#include "GroupManager.h"
+#include "ActionSet.h"
+#include "jni_things_manager_jvm.h"
+#include "jni_things_manager_util.h"
+#include "jni_group_manager_callbacks.h"
+#include "jni_action_set.h"
+
+/**
+ * GroupManager static object
+ */
+static GroupManager g_GroupManager;
+
+JNIEXPORT jint JNICALL JNIGroupManagerFindCandidateResource(JNIEnv *env, jobject interfaceObject,
+ jobject jResourceTypes, jint waitSec)
+{
+ LOGI("JNIGroupManagerFindCandidateResource: Enter");
+
+ if (!jResourceTypes)
+ {
+ LOGE("JNIGroupManagerFindCandidateResource: jResourceTypes is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+ try
+ {
+ ocResult = g_GroupManager.findCandidateResources(convertStringVector(env, jResourceTypes),
+ &GroupManagerCallbacks::onFoundCandidateResource, (int)waitSec);
+
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupManagerFindCandidateResource: findCandidateResources failed!");
+ return ocResult;
+ }
+ }
+ catch (InitializeException &e)
+ {
+ LOGE("JNIGroupManagerFindCandidateResource: Exception occurred! %s, %d", e.reason().c_str(),
+ e.code());
+ return ocResult;
+ }
+
+ LOGI("JNIGroupManagerFindCandidateResource: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIGroupManagerSubscribeCollectionPresence(JNIEnv *env,
+ jobject interfaceObject,
+ jobject jResource)
+{
+ LOGI("JNIGroupManagerSubscribeCollectionPresence: Enter");
+
+ if (!jResource)
+ {
+ LOGE("JNIGroupManagerSubscribeCollectionPresence: jResource is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, jResource);
+ if (NULL == jniOcResource)
+ {
+ LOGE("JNIGroupManagerSubscribeCollectionPresence: Failed to get jni OcResource!");
+ return ocResult;
+ }
+
+ std::shared_ptr<OCResource> ocResource = jniOcResource->getOCResource();
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIGroupManagerSubscribeCollectionPresence: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ ocResult = g_GroupManager.subscribeCollectionPresence(ocResource,
+ &GroupManagerCallbacks::onSubscribePresence);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupManagerSubscribeCollectionPresence: subscribeCollectionPresence failed!");
+ return ocResult;
+ }
+
+ LOGI("JNIGroupManagerSubscribeCollectionPresence: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jobject JNICALL JNIGroupManagerBindResourceToGroup(JNIEnv *env, jobject interfaceObject,
+ jobject jResource, jobject jCollectionHandle)
+{
+ LOGI("JNIGroupManagerBindResourceToGroup: Enter");
+
+ if (!jResource || !jCollectionHandle)
+ {
+ LOGE("JNIGroupManagerBindResourceToGroup: Invalid parameter!");
+ return NULL;
+ }
+
+ std::shared_ptr<OCResource> ocResource;
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, jResource);
+ if (jniOcResource)
+ {
+ ocResource = jniOcResource->getOCResource();
+ }
+
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIGroupManagerBindResourceToGroup: Failed to get OCResource object!");
+ return NULL;
+ }
+
+ JniOcResourceHandle *jniOcCollectionHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(env,
+ jCollectionHandle);
+ if (NULL == jniOcCollectionHandle)
+ {
+ LOGE("JNIGroupManagerBindResourceToGroup: collection handle is null!");
+ return NULL;
+ }
+
+ jobject jResourceHandle = NULL;
+ try
+ {
+ OCResourceHandle ocChildHandle = NULL;
+ OCResourceHandle ocCollectionHandle = jniOcCollectionHandle->getOCResourceHandle();
+ OCStackResult ocResult = g_GroupManager.bindResourceToGroup(ocChildHandle, ocResource,
+ ocCollectionHandle);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupManagerBindResourceToGroup: bindResourceToGroup failed!");
+ return NULL;
+ }
+
+ // Convert OCResourceHandle to java type
+ JniOcResourceHandle *jniHandle = new JniOcResourceHandle(ocChildHandle);
+ jlong handle = reinterpret_cast<jlong>(jniHandle);
+ jResourceHandle = env->NewObject(g_cls_OcResourceHandle, g_mid_OcResourceHandle_N_ctor, handle);
+ if (env->ExceptionCheck())
+ {
+ LOGE("JNIGroupManagerBindResourceToGroup: Failed to create OcResourceHandle");
+ delete jniHandle;
+ return NULL;
+ }
+ }
+ catch (InitializeException &e)
+ {
+ LOGE("JNIGroupManagerBindResourceToGroup: Exception occurred! %s, %d", e.reason().c_str(),
+ e.code());
+ return NULL;
+ }
+
+ LOGI("JNIGroupManagerBindResourceToGroup: Exit");
+ return jResourceHandle;
+}
+
+JNIEXPORT jint JNICALL JNIGroupManagerAddActionSet(JNIEnv *env, jobject interfaceObject,
+ jobject resource,
+ jobject newActionSet)
+{
+ LOGI("JNIGroupManagerAddActionSet: Entry");
+
+ if ((!resource) || (!newActionSet))
+ {
+ LOGE("JNIGroupManagerAddActionSet: resource or newActionSet is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ std::shared_ptr<OCResource> ocResource;
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
+ if (jniOcResource)
+ {
+ ocResource = jniOcResource->getOCResource();
+ }
+
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIGroupManagerAddActionSet: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ JniActionSet *jActionSet = new JniActionSet(env, newActionSet);
+ ActionSet *pActionSet = jActionSet->getActionSet(env, newActionSet);
+ if (NULL == pActionSet)
+ {
+ LOGE("JNIGroupManagerAddActionSet: Failed to convert ActionSet!");
+ return ocResult;
+ }
+
+ ocResult = g_GroupManager.addActionSet(ocResource, pActionSet,
+ &GroupManagerCallbacks::onPutResponse);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupManagerAddActionSet: addActionSet is failed!");
+ }
+
+ delete pActionSet;
+ LOGI("JNIGroupManagerAddActionSet: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIGroupManagerExecuteActionSet(JNIEnv *env, jobject interfaceObject,
+ jobject resource, jstring jActionSetName)
+{
+ LOGI("JNIGroupManagerExecuteActionSet: Entry");
+
+ if ((!resource) || (!jActionSetName))
+ {
+ LOGE("JNIGroupManagerExecuteActionSet: resource or jActionSetName is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ std::shared_ptr<OCResource> ocResource;
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
+ if (jniOcResource)
+ {
+ ocResource = jniOcResource->getOCResource();
+ }
+
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIGroupManagerExecuteActionSet: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ const char *actionSetNamePointer = env->GetStringUTFChars(jActionSetName, 0);
+ if (NULL == actionSetNamePointer)
+ {
+ LOGE("JNIGroupManagerExecuteActionSet: Failed to convert jstring to char string!");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ std::string actionSetName(actionSetNamePointer);
+
+ ocResult = g_GroupManager.executeActionSet(ocResource, actionSetName,
+ &GroupManagerCallbacks::onPostResponse);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupManagerExecuteActionSet: executeActionSet is failed!");
+ }
+
+ env->ReleaseStringUTFChars(jActionSetName, actionSetNamePointer);
+ LOGI("JNIGroupManagerExecuteActionSet: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIGroupManagerExecuteActionSetWithDelay(JNIEnv *env,
+ jobject interfaceObject,
+ jobject resource, jstring jActionSetName, jlong delay)
+{
+ LOGI("JNIGroupManagerExecuteActionSetWithDelay: Entry");
+
+ if ((!resource) || (!jActionSetName))
+ {
+ LOGE("JNIGroupManagerExecuteActionSetWithDelay: resource or jActionSetName is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ std::shared_ptr<OCResource> ocResource;
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
+ if (jniOcResource)
+ {
+ ocResource = jniOcResource->getOCResource();
+ }
+
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIGroupManagerExecuteActionSetWithDelay: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ const char *actionSetNamePointer = env->GetStringUTFChars(jActionSetName, 0);
+ if (NULL == actionSetNamePointer)
+ {
+ LOGE("JNIGroupManagerExecuteActionSetWithDelay: Failed to convert jstring to char string!");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ std::string actionSetName(actionSetNamePointer);
+ if (0 == delay)
+ {
+ ocResult = g_GroupManager.executeActionSet(ocResource, actionSetName,
+ &GroupManagerCallbacks::onPostResponse);
+ }
+ else
+ {
+ ocResult = g_GroupManager.executeActionSet(ocResource, actionSetName,
+ (long int)delay,
+ &GroupManagerCallbacks::onPostResponse);
+ }
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupManagerExecuteActionSetWithDelay: executeActionSet is failed!");
+ }
+
+ env->ReleaseStringUTFChars(jActionSetName, actionSetNamePointer);
+ LOGI("JNIGroupManagerExecuteActionSetWithDelay: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIGroupManagerCancelActionSet(JNIEnv *env, jobject interfaceObject,
+ jobject resource, jstring jActionSetName)
+{
+ LOGI("JNIGroupManagerCancelActionSet: Entry");
+
+ if ((!resource) || (!jActionSetName))
+ {
+ LOGE("JNIGroupManagerCancelActionSet: resource or jActionSetName is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ std::shared_ptr<OCResource> ocResource;
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
+ if (jniOcResource)
+ {
+ ocResource = jniOcResource->getOCResource();
+ }
+
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIGroupManagerCancelActionSet: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ const char *actionSetNamePointer = env->GetStringUTFChars(jActionSetName, 0);
+ if (NULL == actionSetNamePointer)
+ {
+ LOGE("JNIGroupManagerCancelActionSet: Failed to get character sequence from jstring!");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ std::string actionSetName(actionSetNamePointer);
+
+ ocResult = g_GroupManager.cancelActionSet(ocResource, actionSetName,
+ &GroupManagerCallbacks::onPostResponse);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupManagerCancelActionSet: cancelActionSet is failed!");
+ }
+
+ env->ReleaseStringUTFChars(jActionSetName, actionSetNamePointer);
+ LOGI("JNIGroupManagerCancelActionSet: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIGroupManagerGetActionSet(JNIEnv *env, jobject interfaceObject,
+ jobject resource,
+ jstring jActionSetName)
+{
+ LOGI("JNIGroupManagerGetActionSet: Entry");
+
+ if ((!resource) || (!jActionSetName))
+ {
+ LOGE("JNIGroupManagerGetActionSet: resource or jActionSetName is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ std::shared_ptr<OCResource> ocResource;
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
+ if (jniOcResource)
+ {
+ ocResource = jniOcResource->getOCResource();
+ }
+
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIGroupManagerGetActionSet: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ const char *actionSetNamePointer = env->GetStringUTFChars(jActionSetName, 0);
+ std::string actionSetName(actionSetNamePointer);
+
+ ocResult = g_GroupManager.getActionSet(ocResource, actionSetName,
+ &GroupManagerCallbacks::onGetResponse);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupManagerGetActionSet: getActionSet is failed!");
+ }
+
+ env->ReleaseStringUTFChars(jActionSetName, actionSetNamePointer);
+ LOGI("JNIGroupManagerGetActionSet: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIGroupManagerDeleteActionSet(JNIEnv *env, jobject interfaceObject,
+ jobject resource,
+ jstring jActionSetName)
+{
+ LOGI("JNIGroupManagerDeleteActionSet: Entry");
+
+ if ((!resource) || (!jActionSetName))
+ {
+ LOGE("JNIGroupManagerDeleteActionSet: resource or jActionSetName is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ std::shared_ptr<OCResource> ocResource;
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
+ if (jniOcResource)
+ {
+ ocResource = jniOcResource->getOCResource();
+ }
+
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIGroupManagerDeleteActionSet: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ const char *actionSetNamePointer = env->GetStringUTFChars(jActionSetName, 0);
+ std::string actionSetName(actionSetNamePointer);
+
+ ocResult = g_GroupManager.deleteActionSet(ocResource, actionSetName,
+ &GroupManagerCallbacks::onPutResponse);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupManagerDeleteActionSet: deleteActionSet is failed!");
+ }
+
+ env->ReleaseStringUTFChars(jActionSetName, actionSetNamePointer);
+ LOGI("JNIGroupManagerDeleteActionSet: Exit");
+ return ocResult;
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "jni_group_manager_callbacks.h"
+#include "JniOcResource.h"
+#include "GroupManager.h"
+#include "jni_things_manager_jvm.h"
+#include "jni_things_manager_util.h"
+#include "jni_string.h"
+
+#define LOG_TAG "GroupManagerCallbacks"
+
+#define METHOD_ONRESOURCE_CALLBACK "(" TM_JAVA_VECTOR_TYPE")V"
+#define METHOD_ONPRESENCE_CALLBACK "(" TM_JAVA_STRING_TYPE"I)V"
+#define METHOD_ONPOST_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
+#define METHOD_ONPUT_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
+#define METHOD_ONGET_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
+
+void GroupManagerCallbacks::onFoundCandidateResource(
+ std::vector< std::shared_ptr<OC::OCResource>> resources)
+{
+ LOGI("onFoundCandidateResource : Enter");
+
+ if (resources.size() == 0)
+ {
+ LOGE("onFoundCandidateResource : found resources zero");
+ return;
+ }
+
+ JNIEnv *env = ThingsManagerJVM::getEnv();
+ if (env == NULL)
+ {
+ LOGE("onFoundCandidateResource : Getting JNIEnv failed");
+ return;
+ }
+
+ // Get GroupManagerCallback class reference
+ jclass groupManagerCallbacks = GetJClass(TM_SERVICE_GROUP_MANAGER_CLASS_PATH);
+
+ if (NULL == groupManagerCallbacks)
+ {
+ LOGE("onFoundCandidateResource : GetJClass TMServiceCallbackInterface failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ // Get onResourceCallback method reference
+ jmethodID method_id = env->GetStaticMethodID(groupManagerCallbacks, "onResourceFoundCallback",
+ METHOD_ONRESOURCE_CALLBACK);
+ if (NULL == method_id)
+ {
+ LOGE("findCandidateResource: onResourceCallback : GetMethodID failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ if ((env)->ExceptionCheck())
+ {
+ LOGE("findCandidateResource : ExceptionCheck failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jclass vectorCls = env->FindClass(TM_JAVA_VECTOR_CLASS_PATH);
+ if (!vectorCls)
+ {
+ LOGE("findCandidateResource: failed to get %s class reference", TM_JAVA_VECTOR_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jmethodID constr = env->GetMethodID(vectorCls, "<init>", "()V");
+ if (!constr)
+ {
+ LOGE("findCandidateResource: failed to get %s constructor", TM_JAVA_VECTOR_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jobject vectorObj = env->NewObject(vectorCls, constr);
+ if (!vectorObj)
+ {
+ LOGE("findCandidateResource: failed to create a %s object", TM_JAVA_VECTOR_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jmethodID addElement = env->GetMethodID(vectorCls, "addElement", "(Ljava/lang/Object;)V");
+ if (NULL == addElement)
+ {
+ LOGE("findCandidateResource: failed to create a addElement method");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ // Convert to java OCResource object
+ for (int i = 0; i < resources.size(); i++)
+ {
+ JniOcResource *jniOcResource = new JniOcResource(resources[i]);
+ if (!jniOcResource)
+ {
+ LOGE("findCandidateResource: failed to create a JniOcResource");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jobject resource = OcResourceToJava(env, reinterpret_cast<jlong>(jniOcResource));
+ env->CallVoidMethod(vectorObj, addElement, resource);
+ }
+
+ env->CallStaticVoidMethod(groupManagerCallbacks, method_id, vectorObj);
+
+ if ((env)->ExceptionCheck())
+ {
+ LOGE("findCandidateResource : CallVoidMethod failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ ThingsManagerJVM::releaseEnv();
+ LOGI("findCandidateResource : Exit");
+}
+
+void GroupManagerCallbacks::onSubscribePresence(std::string resource, OCStackResult result)
+{
+ LOGI("SubscribePresence : Entry");
+
+ JNIEnv *env = ThingsManagerJVM::getEnv();
+ if (env == NULL)
+ {
+ LOGE("SubscribePresence : Getting JNIEnv failed");
+ return;
+ }
+
+ // Get GroupManagerCallback class reference
+ jclass groupManagerCallbacks = GetJClass(TM_SERVICE_GROUP_MANAGER_CLASS_PATH);
+
+ if (NULL == groupManagerCallbacks)
+ {
+ LOGE("SubscribePresence : GetJClass TMServiceCallbackInterface failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jmethodID method_id = env->GetStaticMethodID(groupManagerCallbacks,
+ "onPresenceCallback",
+ METHOD_ONPRESENCE_CALLBACK);
+ if (NULL == method_id)
+ {
+ LOGE("SubscribePresence : GetMethodID failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ if ((env)->ExceptionCheck())
+ {
+ LOGE("SubscribePresence : ExceptionCheck failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ JString *jresource = new JString(env, resource);
+ if (jresource == NULL)
+ {
+ LOGE("resource value is invalid");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ env->CallStaticVoidMethod(groupManagerCallbacks, method_id, jresource->getObject(), (jint)result);
+
+ delete jresource;
+
+ if ((env)->ExceptionCheck())
+ {
+ LOGE("SubscribePresence : CallVoidMethod failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ LOGI("SubscribePresence : Exit");
+
+//METHOD_FAILURE:
+ ThingsManagerJVM::releaseEnv();
+}
+
+void GroupManagerCallbacks::onPostResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode)
+{
+ LOGI("PostResponse : Enter");
+
+ GroupManagerCallbacks::invokeCallback(headerOptions, rep, eCode, "onPostResponseCallback",
+ METHOD_ONPOST_CALLBACK);
+
+ LOGI("PostResponse : Exit");
+}
+
+void GroupManagerCallbacks::onPutResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode)
+{
+ LOGI("OnPutResponse : Enter");
+
+ GroupManagerCallbacks::invokeCallback(headerOptions, rep, eCode, "onPutResponseCallback",
+ METHOD_ONPUT_CALLBACK);
+
+ LOGI("OnPutResponse : Exit");
+}
+
+void GroupManagerCallbacks::onGetResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode)
+{
+ LOGI("OnGetResponse : Enter");
+
+ GroupManagerCallbacks::invokeCallback(headerOptions, rep, eCode, "onGetResponseCallback",
+ METHOD_ONGET_CALLBACK);
+
+ LOGI("OnGetResponse : Exit");
+}
+
+void GroupManagerCallbacks::invokeCallback(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode, const char *callbackName,
+ const char *signature)
+{
+ LOGI("InvokeCallback : Enter %s", callbackName);
+
+ JNIEnv *env = ThingsManagerJVM::getEnv();
+ if (env == NULL)
+ {
+ LOGE("InvokeCallback : Getting JNIEnv failed");
+ return;
+ }
+
+ // Get ThingsManagerCallback class reference
+ jclass groupManagerCallbacks = GetJClass(TM_SERVICE_GROUP_MANAGER_CLASS_PATH);
+ if (NULL == groupManagerCallbacks)
+ {
+ LOGE("InvokeCallback : GetJClass TMServiceCallbackInterface failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jmethodID method_id = env->GetStaticMethodID(groupManagerCallbacks, callbackName, signature);
+ if (!method_id)
+ {
+ LOGE("InvokeCallback : GetMethodID failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ if ((env)->ExceptionCheck())
+ {
+ LOGE("InvokeCallback : ExceptionCheck failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ // Convert vector<OC:HeaderOption::OCHeaderOption> to java type
+ jclass vectorCls = env->FindClass(TM_JAVA_VECTOR_CLASS_PATH);
+ if (!vectorCls)
+ {
+ LOGE("InvokeCallback: failed to get %s class reference", TM_JAVA_VECTOR_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jmethodID constr = env->GetMethodID(vectorCls, "<init>", "()V");
+ if (!constr)
+ {
+ LOGE("InvokeCallback: failed to get %s constructor", TM_JAVA_VECTOR_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jobject vectorObj = env->NewObject(vectorCls, constr);
+ if (!vectorObj)
+ {
+ LOGE("InvokeCallback: failed to create a %s object", TM_JAVA_VECTOR_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jmethodID addElement = env->GetMethodID(vectorCls, "addElement", "(Ljava/lang/Object;)V");
+ if (NULL == addElement)
+ {
+ LOGE("InvokeCallback: failed to create a addElement method");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jobject headerOptionTemp;
+ for (int i = 0; i < headerOptions.size(); i++)
+ {
+ headerOptionTemp = OcHeaderOptionToJava(env, headerOptions[i]);
+ env->CallVoidMethod(vectorObj, addElement, headerOptionTemp);
+ }
+
+ // Convert OCRepresentation to java type
+ jobject jrepresentation = OcRepresentationToJava(env, (jlong) reinterpret_cast<jlong>(&rep));
+ if (!jrepresentation)
+ {
+ LOGE("InvokeCallback : cannot create OCRepresentation class");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ env->CallStaticVoidMethod(groupManagerCallbacks, method_id, vectorObj, jrepresentation,
+ (jint)eCode);
+
+ if ((env)->ExceptionCheck())
+ {
+ LOGE("InvokeCallback : CallVoidMethod failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ ThingsManagerJVM::releaseEnv();
+ LOGI("InvokeCallback : Exit %s", callbackName);
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "jni_group_synchronization.h"
+#include "JniOcResource.h"
+#include "JniOcResourceHandle.h"
+#include "GroupManager.h"
+#include "ActionSet.h"
+#include "jni_things_manager_jvm.h"
+#include "jni_things_manager_util.h"
+#include "jni_group_synchronization_callbacks.h"
+#include "jni_action_set.h"
+
+using namespace OC;
+using namespace OIC;
+
+/**
+ * GroupSynchronization static object
+ */
+static GroupSynchronization g_GroupSynchronization;
+
+JNIEXPORT jint JNICALL JNIGroupSynchronizationFindGroup(JNIEnv *env, jobject interfaceObject,
+ jobject jResourceTypes)
+{
+ LOGI("JNIGroupSynchronizationFindGroup: Enter");
+
+ if (!jResourceTypes)
+ {
+ LOGE("JNIGroupSynchronizationFindGroup: jResourceTypes is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+ try
+ {
+ ocResult = g_GroupSynchronization.findGroup((convertStringVector(env, jResourceTypes)),
+ &GroupSynchronizationCallbacks::onFoundGroup);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupSynchronizationFindGroup: findGroup failed!");
+ return ocResult;
+ }
+ }
+ catch (InitializeException &e)
+ {
+ LOGE("JNIGroupSynchronizationFindGroup: Exception occurred! %s, %d", e.reason().c_str(),
+ e.code());
+ return ocResult;
+ }
+ LOGI("JNIGroupSynchronizationFindGroup: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIGroupSynchronizationCreateGroup(JNIEnv *env, jobject interfaceObject,
+ jstring jResourceType)
+{
+ LOGI("JNIGroupSynchronizationCreateGroup: Enter");
+
+ if (!jResourceType)
+ {
+ LOGE("JNIGroupSynchronizationCreateGroup: jResourceType is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ const char *resourceTypePointer = env->GetStringUTFChars(jResourceType, NULL);
+ if (NULL == resourceTypePointer)
+ {
+ LOGE("JNIGroupSynchronizationCreateGroup: Failed to convert jstring to char string!");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ std::string resourceType(resourceTypePointer);
+ try
+ {
+ ocResult = g_GroupSynchronization.createGroup(resourceType);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupSynchronizationCreateGroup: CreateGroup failed!");
+ }
+ }
+ catch (InitializeException &e)
+ {
+ LOGE("JNIGroupSynchronizationCreateGroup: Exception occurred! %s, %d", e.reason().c_str(),
+ e.code());
+ }
+ env->ReleaseStringUTFChars(jResourceType, resourceTypePointer);
+ LOGI("JNIGroupSynchronizationCreateGroup: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIGroupSynchronizationJoinGroupString(JNIEnv *env, jobject interfaceObject,
+ jstring jResourceType, jobject jResourceHandle)
+{
+ LOGI("JNIGroupSynchronizationJoinGroupString: Enter");
+
+ if ((!jResourceType) || (!jResourceHandle))
+ {
+ LOGE("JNIGroupSynchronizationJoinGroupString: jResourceType or jResourceHandle is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ const char *resourceTypePointer = env->GetStringUTFChars(jResourceType, NULL);
+ if (NULL == resourceTypePointer)
+ {
+ LOGE("JNIGroupSynchronizationJoinGroupString: Failed to convert jstring to char string!");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ std::string resourceType(resourceTypePointer);
+
+ JniOcResourceHandle *jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(env,
+ jResourceHandle);
+ try
+ {
+ OCResourceHandle ocResourceHandle = jniOcResourceHandle->getOCResourceHandle();
+ ocResult = g_GroupSynchronization.joinGroup(resourceType, ocResourceHandle);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupSynchronizationJoinGroupString: joinGroup failed!");
+ }
+ }
+ catch (InitializeException &e)
+ {
+ LOGE("JNIGroupSynchronizationJoinGroupString: Exception occurred! %s, %d", e.reason().c_str(),
+ e.code());
+ }
+ env->ReleaseStringUTFChars(jResourceType, resourceTypePointer);
+ LOGI("JNIGroupSynchronizationJoinGroupString: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIGroupSynchronizationJoinGroupObject(JNIEnv *env, jobject interfaceObject,
+ jobject jResource, jobject jResourceHandle)
+{
+ LOGI("JNIGroupSynchronizationJoinGroupObject: Enter");
+
+ if ((!jResource) || (!jResourceHandle))
+ {
+ LOGE("JNIGroupSynchronizationJoinGroupObject: jResource or jResourceHandle is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ std::shared_ptr<OCResource> ocResource;
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, jResource);
+ if (jniOcResource)
+ {
+ ocResource = jniOcResource->getOCResource();
+ }
+
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIGroupSynchronizationJoinGroupObject: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ JniOcResourceHandle *jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(env,
+ jResourceHandle);
+
+ try
+ {
+ OCResourceHandle resHandle = jniOcResourceHandle->getOCResourceHandle();
+
+ ocResult = g_GroupSynchronization.joinGroup(ocResource, resHandle);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupSynchronizationJoinGroupObject: joinGroup failed!");
+ return ocResult;
+ }
+ }
+ catch (InitializeException &e)
+ {
+ LOGE("JNIGroupSynchronizationJoinGroupObject: Exception occurred! %s, %d", e.reason().c_str(),
+ e.code());
+ return ocResult;
+ }
+ LOGI("JNIGroupSynchronizationJoinGroupObject: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIGroupSynchronizationLeaveGroup(JNIEnv *env, jobject interfaceObject,
+ jstring jResourceType,
+ jobject jResourceHandle)
+{
+ LOGI("JNIGroupSynchronizationLeaveGroup: Enter");
+
+ if ((!jResourceType) || (!jResourceHandle))
+ {
+ LOGE("JNIGroupSynchronizationLeaveGroup: jResourceType or jResourceHandle is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ const char *resourceTypePointer = env->GetStringUTFChars(jResourceType, NULL);
+ if (NULL == resourceTypePointer)
+ {
+ LOGE("JNIGroupSynchronizationLeaveGroup: Failed to convert jstring to char string!");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ std::string resourceType(resourceTypePointer);
+ JniOcResourceHandle *jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(env,
+ jResourceHandle);
+
+ try
+ {
+ OCResourceHandle ocResourceHandle = jniOcResourceHandle->getOCResourceHandle();
+
+ ocResult = g_GroupSynchronization.leaveGroup(resourceType, ocResourceHandle);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupSynchronizationLeaveGroup: leaveGroup failed!");
+ }
+ }
+ catch (InitializeException &e)
+ {
+ LOGE("JNIGroupSynchronizationLeaveGroup: Exception occurred! %s, %d", e.reason().c_str(),
+ e.code());
+ }
+ env->ReleaseStringUTFChars(jResourceType, resourceTypePointer);
+ LOGI("JNIGroupSynchronizationLeaveGroup: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIGroupSynchronizationLeaveGroupForResource(JNIEnv *env,
+ jobject interfaceObject,
+ jobject jResource,
+ jstring jResourceType,
+ jobject jResourceHandle)
+{
+ LOGI("JNIGroupSynchronizationLeaveGroupForResource: Enter");
+
+ if ((!jResource) || (!jResourceType) || (!jResourceHandle))
+ {
+ LOGE("JNIGroupSynchronizationLeaveGroupForResource: jResourceType or jResourceHandle is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, jResource);
+ if (NULL == jniOcResource)
+ {
+ LOGE("JNIGroupSynchronizationLeaveGroupForResource: Failed to get jni OcResource!");
+ return ocResult;
+ }
+
+ std::shared_ptr<OCResource> ocResource = jniOcResource->getOCResource();
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIGroupSynchronizationLeaveGroupForResource: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ const char *resourceTypePointer = env->GetStringUTFChars(jResourceType, NULL);
+ if (NULL == resourceTypePointer)
+ {
+ LOGE("JNIGroupSynchronizationLeaveGroupForResource: Failed to convert jstring to char string!");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ std::string resourceType(resourceTypePointer);
+ JniOcResourceHandle *jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(env,
+ jResourceHandle);
+
+ try
+ {
+ OCResourceHandle ocResourceHandle = jniOcResourceHandle->getOCResourceHandle();
+
+ ocResult = g_GroupSynchronization.leaveGroup(ocResource, resourceType, ocResourceHandle);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIGroupSynchronizationLeaveGroupForResource: leaveGroup failed!");
+ }
+ }
+ catch (InitializeException &e)
+ {
+ LOGE("JNIGroupSynchronizationLeaveGroupForResource: Exception occurred! %s, %d", e.reason().c_str(),
+ e.code());
+ }
+
+ env->ReleaseStringUTFChars(jResourceType, resourceTypePointer);
+ LOGI("JNIGroupSynchronizationLeaveGroupForResource: Exit");
+ return ocResult;
+}
+
+JNIEXPORT void JNICALL JNIGroupSynchronizationDeleteGroup(JNIEnv *env, jobject interfaceObject,
+ jstring jcollectionResourceType)
+{
+ LOGI("JNIGroupSynchronizationDeleteGroup: Enter");
+
+ if (!jcollectionResourceType)
+ {
+ LOGE("JNIGroupSynchronizationDeleteGroup: jcollectionResourceType is NULL!");
+ return;
+ }
+
+ const char *collectionResourceTypePointer = env->GetStringUTFChars(jcollectionResourceType, NULL);
+ if (NULL == collectionResourceTypePointer)
+ {
+ LOGE("JNIGroupSynchronizationDeleteGroup: Failed to convert jstring to char string!");
+ return;
+ }
+
+ std::string collectionResourceType(collectionResourceTypePointer);
+ try
+ {
+ g_GroupSynchronization.deleteGroup(collectionResourceType);
+ }
+ catch (InitializeException &e)
+ {
+ LOGE("JNIGroupSynchronizationDeleteGroup: Exception occurred! %s, %d", e.reason().c_str(),
+ e.code());
+ }
+
+ env->ReleaseStringUTFChars(jcollectionResourceType, collectionResourceTypePointer);
+ LOGI("JNIGroupSynchronizationDeleteGroup: Exit");
+}
+
+JNIEXPORT jobject JNICALL JNIGroupSynchronizationGetGroupList(JNIEnv *env, jobject interfaceObject)
+{
+ LOGI("JNIGroupSynchronizationGetGroupList: Enter");
+
+ std::map< std::string, OCResourceHandle> groupListMap;
+ jobject jGroupListMap;
+
+ groupListMap = g_GroupSynchronization.getGroupList();
+ if (groupListMap.empty())
+ {
+ LOGD("getGroupList Map is empty");
+ return NULL;
+ }
+
+ jclass clazz = env->FindClass("java/util/HashMap");
+ jmethodID init = env->GetMethodID(clazz, "<init>", "()V");
+ jGroupListMap = env->NewObject(clazz, init);
+ jmethodID putMethod = env->GetMethodID(clazz, "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+
+ for (auto it = groupListMap.begin(); it != groupListMap.end(); ++it)
+ {
+ jstring key = (*env).NewStringUTF( (*it).first.c_str() );
+ JniOcResourceHandle *jniOcResourceHandle = new JniOcResourceHandle(((*it).second));
+ jobject value = ocResourceHandleToJava(env, reinterpret_cast<jlong>(jniOcResourceHandle));
+ env->CallObjectMethod(jGroupListMap, putMethod, key, value);
+ }
+
+ LOGI("JNIGroupSynchronizationGetGroupList: Exit");
+ return jGroupListMap;
+}
+
+
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "jni_group_synchronization_callbacks.h"
+#include "JniOcResource.h"
+#include "GroupSynchronization.h"
+#include "jni_things_manager_jvm.h"
+#include "jni_things_manager_util.h"
+#include "jni_string.h"
+
+#define LOG_TAG "GroupSynchronizationCallbacks"
+
+#define METHOD_ONGROUP_FIND_CALLBACK "(" TM_SERVICE_OCRESOURCE_TYPE")V"
+
+void GroupSynchronizationCallbacks::onFoundGroup(std::shared_ptr<OC::OCResource> groupResource)
+{
+ LOGI("FindGroup : Enter");
+
+ if (NULL == groupResource.get())
+ {
+ LOGE("FindGroup : Invalid received GroupResource!");
+ return;
+ }
+
+ JNIEnv *env = ThingsManagerJVM::getEnv();
+ if (env == NULL)
+ {
+ LOGE("FindGroup : Getting JNIEnv failed");
+ return;
+ }
+
+ // Get ThingsManagerCallback class reference
+ jclass groupSynchronizationCallbacks = GetJClass(TM_SERVICE_GROUP_SYNCHRONIZATION_CLASS_PATH);
+ if (NULL == groupSynchronizationCallbacks)
+ {
+ LOGE("FindGroup : GetJClass TMServiceCallbackInterface failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ // Get the ThingsManagerCallback class instance
+ jobject jobjectCallback = GetJObjectInstance(TM_SERVICE_GROUP_SYNCHRONIZATION_CLASS_PATH);
+ if (NULL == jobjectCallback)
+ {
+ LOGE("FindGroup: getInstance failed!");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ // Get onGroupFindCallback method reference
+ jmethodID method_id = env->GetMethodID(groupSynchronizationCallbacks,
+ "onGroupFindCallback",
+ METHOD_ONGROUP_FIND_CALLBACK);
+ if (NULL == method_id)
+ {
+ LOGE("FindGroup : GetMethodID failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ if ((env)->ExceptionCheck())
+ {
+ LOGE("FindGroup : ExceptionCheck failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ JniOcResource *jniOcResource = new JniOcResource(groupResource);
+ if (!jniOcResource)
+ {
+ LOGE("FindGroup : groupResource is invalid!");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jobject resource = OcResourceToJava(env, reinterpret_cast<jlong>(jniOcResource));
+
+ env->CallVoidMethod(jobjectCallback, method_id, resource);
+
+ if ((env)->ExceptionCheck())
+ {
+ LOGE("FindGroup : CallVoidMethod failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ ThingsManagerJVM::releaseEnv();
+ LOGI("FindGroup : Exit");
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "jni_things_configuration.h"
+#include "JniOcResource.h"
+#include "JniOcResourceHandle.h"
+#include "ThingsConfiguration.h"
+#include "ActionSet.h"
+#include "jni_things_manager_jvm.h"
+#include "jni_things_manager_util.h"
+#include "jni_things_configuration_callbacks.h"
+#include "jni_action_set.h"
+
+using namespace OC;
+using namespace OIC;
+
+/**
+ * ThingsConfiguration static object
+ */
+static ThingsConfiguration g_ThingsConfiguration;
+
+JNIEXPORT jint JNICALL JNIThingsConfigurationUpdateConfigurations(JNIEnv *env,
+ jobject interfaceObject,
+ jobject resource, jobject configurations)
+{
+ LOGI("JNIThingsConfigurationUpdateConfigurations: Enter");
+
+ if ((!resource) || (!configurations))
+ {
+ LOGE("JNIThingsConfigurationUpdateConfigurations: resource or configurations is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ std::shared_ptr<OCResource> ocResource;
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
+ if (jniOcResource)
+ {
+ ocResource = jniOcResource->getOCResource();
+ }
+
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIThingsConfigurationUpdateConfigurations: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ std::map<std::string, std::string> configurationsMap;
+ configurationsMap = convertStringMap(env, configurations);
+ ocResult = g_ThingsConfiguration.updateConfigurations(ocResource, configurationsMap,
+ &ThingsConfigurationCallbacks::onUpdateConfigurationsResponse);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIThingsConfigurationUpdateConfigurations: updateConfigurations failed!");
+ return ocResult;
+ }
+
+ LOGI("JNIThingsConfigurationUpdateConfigurations: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIThingsConfigurationGetConfigurations(JNIEnv *env, jobject interfaceObject,
+ jobject resource, jobject configurations)
+{
+ LOGI("JNIThingsConfigurationGetConfigurations: Enter");
+
+ if ((!resource) || (!configurations))
+ {
+ LOGE("JNIThingsConfigurationGetConfigurations: resource or configurations is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ std::shared_ptr<OCResource> ocResource;
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
+ if (jniOcResource)
+ {
+ ocResource = jniOcResource->getOCResource();
+ }
+
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIThingsConfigurationGetConfigurations: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ ocResult = g_ThingsConfiguration.getConfigurations(ocResource,
+ (convertStringVector(env, configurations)),
+ &ThingsConfigurationCallbacks::onGetConfigurationsResponse);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIThingsConfigurationGetConfigurations: getConfigurations failed!");
+ return ocResult;
+ }
+
+ LOGI("JNIThingsConfigurationGetConfigurations: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jstring JNICALL JNIThingsConfigurationGetListOfSupportedConfigurationUnits(JNIEnv *env,
+ jobject interfaceObject)
+{
+ LOGI("JNIThingsConfigurationGetListOfSupportedConfigurationUnits: Enter");
+
+ std::string configListString = g_ThingsConfiguration.getListOfSupportedConfigurationUnits();
+ jstring jConfigListString = env->NewStringUTF(configListString.c_str());
+
+ LOGI("JNIThingsConfigurationGetListOfSupportedConfigurationUnits: Exit");
+ return jConfigListString;
+}
+
+JNIEXPORT jint JNICALL JNIThingsConfigurationDoBootstrap(JNIEnv *env, jobject interfaceObject)
+{
+ LOGI("JNIThingsConfigurationDoBootstrap: Enter");
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+ try
+ {
+ ocResult = g_ThingsConfiguration.doBootstrap(&ThingsConfigurationCallbacks::onBootStrapResponse);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIThingsConfigurationDoBootstrap: doBootstrap failed!");
+ return ocResult;
+ }
+ }
+ catch (InitializeException &e)
+ {
+ LOGE("JNIThingsConfigurationDoBootstrap: Exception occurred! %s, %d", e.reason().c_str(),
+ e.code());
+ return ocResult;
+ }
+
+ LOGI("JNIThingsConfigurationDoBootstrap: Exit");
+ return ocResult;
+}
+
+
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "jni_things_configuration_callbacks.h"
+#include "JniOcResource.h"
+#include "ThingsConfiguration.h"
+#include "jni_things_manager_jvm.h"
+#include "jni_things_manager_util.h"
+#include "jni_string.h"
+
+#define LOG_TAG "ThingsConfigurationCallbacks"
+
+#define METHOD_ONUPDATE_CONF_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
+#define METHOD_ONGET_CONF_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
+#define METHOD_ONBOOT_STRAP_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
+
+void ThingsConfigurationCallbacks::onUpdateConfigurationsResponse(const OC::HeaderOptions
+ &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode)
+{
+ LOGI("UpdateConfigurations : Enter");
+
+ ThingsConfigurationCallbacks::invokeCallback(headerOptions, rep, eCode,
+ "onUpdateConfigurationsCallback",
+ METHOD_ONUPDATE_CONF_CALLBACK);
+
+ LOGI("UpdateConfigurations : Exit");
+}
+
+void ThingsConfigurationCallbacks::onGetConfigurationsResponse(const OC::HeaderOptions
+ &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode)
+{
+ LOGI("GetConfigurations : Enter");
+
+ ThingsConfigurationCallbacks::invokeCallback(headerOptions, rep, eCode,
+ "onGetConfigurationsCallback",
+ METHOD_ONGET_CONF_CALLBACK);
+
+ LOGI("GetConfigurations : Exit");
+}
+
+void ThingsConfigurationCallbacks::onBootStrapResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode)
+{
+ LOGI("BootStrap : Enter");
+
+ ThingsConfigurationCallbacks::invokeCallback(headerOptions, rep, eCode, "onBootStrapCallback",
+ METHOD_ONBOOT_STRAP_CALLBACK);
+
+ LOGI("BootStrap : Exit");
+}
+
+void ThingsConfigurationCallbacks::invokeCallback(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode, const char *callbackName,
+ const char *signature)
+{
+ LOGI("InvokeCallback : Enter %s", callbackName);
+
+ JNIEnv *env = ThingsManagerJVM::getEnv();
+ if (env == NULL)
+ {
+ LOGE("InvokeCallback : Getting JNIEnv failed");
+ return;
+ }
+
+ // Get ThingsManagerCallback class reference
+ jclass thingsConfigurationCallbacks = GetJClass(TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH);
+ if (NULL == thingsConfigurationCallbacks)
+ {
+ LOGE("InvokeCallback : GetJClass TMServiceCallbackInterface failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ // Get the ThingsManagerCallback class instance
+ jobject jobjectCallback = GetJObjectInstance(TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH);
+ if (NULL == jobjectCallback)
+ {
+ LOGE("InvokeCallback: getInstance( %s) failed!", TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jmethodID method_id = env->GetMethodID(thingsConfigurationCallbacks, callbackName, signature);
+ if (!method_id)
+ {
+ LOGE("InvokeCallback : GetMethodID failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ if ((env)->ExceptionCheck())
+ {
+ LOGE("InvokeCallback : ExceptionCheck failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ // Convert vector<OC:HeaderOption::OCHeaderOption> to java type
+ jclass vectorCls = env->FindClass(TM_JAVA_VECTOR_CLASS_PATH);
+ if (!vectorCls)
+ {
+ LOGE("InvokeCallback: failed to get %s class reference", TM_JAVA_VECTOR_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jmethodID constr = env->GetMethodID(vectorCls, "<init>", "()V");
+ if (!constr)
+ {
+ LOGE("InvokeCallback: failed to get %s constructor", TM_JAVA_VECTOR_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jobject vectorObj = env->NewObject(vectorCls, constr);
+ if (!vectorObj)
+ {
+ LOGE("InvokeCallback: failed to create a %s object", TM_JAVA_VECTOR_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jmethodID addElement = env->GetMethodID(vectorCls, "addElement", "(Ljava/lang/Object;)V");
+ if (NULL == addElement)
+ {
+ LOGE("InvokeCallback: failed to create a addElement method");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jobject headerOptionTemp;
+ for (int i = 0; i < headerOptions.size(); i++)
+ {
+ headerOptionTemp = OcHeaderOptionToJava(env, headerOptions[i]);
+ env->CallVoidMethod(vectorObj, addElement, headerOptionTemp);
+ }
+
+ // Convert OCRepresentation to java type
+ jobject jrepresentation = OcRepresentationToJava(env, (jlong) reinterpret_cast<jlong>(&rep));
+ if (!jrepresentation)
+ {
+ LOGE("InvokeCallback : cannot create OCRepresentation class");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ env->CallVoidMethod(jobjectCallback, method_id, vectorObj, jrepresentation, (jint)eCode);
+
+ if ((env)->ExceptionCheck())
+ {
+ LOGE("InvokeCallback : CallVoidMethod failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ ThingsManagerJVM::releaseEnv();
+ LOGI("InvokeCallback : Exit %s", callbackName);
+}
+
+
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "jni_things_maintenance.h"
+#include "JniOcResource.h"
+#include "JniOcResourceHandle.h"
+#include "ThingsMaintenance.h"
+#include "ActionSet.h"
+#include "jni_things_manager_jvm.h"
+#include "jni_things_manager_util.h"
+#include "jni_things_maintenance_callbacks.h"
+#include "jni_action_set.h"
+
+using namespace OC;
+using namespace OIC;
+
+/**
+ * ThingsMaintenance static object
+ */
+static ThingsMaintenance g_ThingsMaintenance;
+
+JNIEXPORT jint JNICALL JNIThingsMaintenanceReboot(JNIEnv *env, jobject interfaceObject,
+ jobject resource)
+{
+ LOGI("JNIThingsMaintenanceReboot: Enter");
+
+ if (!resource)
+ {
+ LOGE("JNIThingsMaintenanceReboot: resource is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ std::shared_ptr<OCResource> ocResource;
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
+ if (jniOcResource)
+ {
+ ocResource = jniOcResource->getOCResource();
+ }
+
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIThingsMaintenanceReboot: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ ocResult = g_ThingsMaintenance.reboot(ocResource, &ThingsMaintenanceCallbacks::onRebootResponse);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIThingsMaintenanceReboot: reboot failed!");
+ return ocResult;
+ }
+
+ LOGI("JNIThingsMaintenanceReboot: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jint JNICALL JNIThingsMaintenanceFactoryReset(JNIEnv *env, jobject interfaceObject,
+ jobject resource)
+{
+ LOGI("JNIThingsMaintenanceFactoryReset: Enter");
+
+ if (!resource)
+ {
+ LOGE("JNIThingsMaintenanceFactoryReset: resource is NULL!");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult ocResult = OC_STACK_ERROR;
+
+ std::shared_ptr<OCResource> ocResource;
+ JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
+ if (jniOcResource)
+ {
+ ocResource = jniOcResource->getOCResource();
+ }
+
+ if (NULL == ocResource.get())
+ {
+ LOGE("JNIThingsMaintenanceFactoryReset: Failed to get OCResource object!");
+ return ocResult;
+ }
+
+ ocResult = g_ThingsMaintenance.factoryReset(ocResource,
+ &ThingsMaintenanceCallbacks::onFactoryResetResponse);
+ if (OC_STACK_OK != ocResult)
+ {
+ LOGE("JNIThingsMaintenanceFactoryReset: factoryReset failed!");
+ return ocResult;
+ }
+
+ LOGI("JNIThingsMaintenanceFactoryReset: Exit");
+ return ocResult;
+}
+
+JNIEXPORT jstring JNICALL JNIThingsMaintenanceGetListOfSupportedConfigurationUnits
+(JNIEnv *env, jobject interfaceObject)
+{
+ LOGI("JNIThingsMaintenanceGetListOfSupportedConfigurationUnits: Enter");
+
+ std::string configListString = g_ThingsMaintenance.getListOfSupportedMaintenanceUnits();
+ jstring jConfigListString = env->NewStringUTF(configListString.c_str());
+
+ LOGI("JNIThingsMaintenanceGetListOfSupportedConfigurationUnits: Exit");
+ return jConfigListString;
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 "jni_things_maintenance_callbacks.h"
+#include "JniOcResource.h"
+#include "ThingsMaintenance.h"
+#include "jni_things_manager_jvm.h"
+#include "jni_things_manager_util.h"
+#include "jni_string.h"
+
+#define LOG_TAG "ThingsMaintenanceCallbacks"
+
+#define METHOD_ONFACTORY_RESET_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
+#define METHOD_ONREBOOT_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
+
+void ThingsMaintenanceCallbacks::onRebootResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode)
+{
+ LOGI("OnReboot : Enter");
+
+ ThingsMaintenanceCallbacks::invokeCallback(headerOptions, rep, eCode, "onRebootCallback",
+ METHOD_ONREBOOT_CALLBACK);
+
+ LOGI("OnReboot : Exit");
+}
+
+void ThingsMaintenanceCallbacks::onFactoryResetResponse(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode)
+{
+ LOGI("OnFactoryReset : Enter");
+
+ ThingsMaintenanceCallbacks::invokeCallback(headerOptions, rep, eCode, "onFactoryResetCallback",
+ METHOD_ONFACTORY_RESET_CALLBACK);
+
+ LOGI("OnFactoryReset : Exit");
+}
+
+void ThingsMaintenanceCallbacks::invokeCallback(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &rep, const int eCode, const char *callbackName,
+ const char *signature)
+{
+ LOGI("InvokeCallback : Enter %s", callbackName);
+
+ JNIEnv *env = ThingsManagerJVM::getEnv();
+ if (env == NULL)
+ {
+ LOGE("InvokeCallback : Getting JNIEnv failed");
+ return;
+ }
+
+ // Get ThingsManagerCallback class reference
+ jclass thingsMaintenanceCallbacks = GetJClass(TM_SERVICE_THINGS_MAINTENANCE_CLASS_PATH);
+ if (NULL == thingsMaintenanceCallbacks)
+ {
+ LOGE("InvokeCallback : GetJClass TMServiceCallbackInterface failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ // Get the ThingsManagerCallback class instance
+ jobject jobjectCallback = GetJObjectInstance(TM_SERVICE_THINGS_MAINTENANCE_CLASS_PATH);
+ if (NULL == jobjectCallback)
+ {
+ LOGE("InvokeCallback: getInstance( %s) failed!", TM_SERVICE_THINGS_MAINTENANCE_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jmethodID method_id = env->GetMethodID(thingsMaintenanceCallbacks, callbackName, signature);
+ if (!method_id)
+ {
+ LOGE("InvokeCallback : GetMethodID failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ if ((env)->ExceptionCheck())
+ {
+ LOGE("InvokeCallback : ExceptionCheck failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ // Convert vector<OC:HeaderOption::OCHeaderOption> to java type
+ jclass vectorCls = env->FindClass(TM_JAVA_VECTOR_CLASS_PATH);
+ if (!vectorCls)
+ {
+ LOGE("InvokeCallback: failed to get %s class reference", TM_JAVA_VECTOR_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jmethodID constr = env->GetMethodID(vectorCls, "<init>", "()V");
+ if (!constr)
+ {
+ LOGE("InvokeCallback: failed to get %s constructor", TM_JAVA_VECTOR_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jobject vectorObj = env->NewObject(vectorCls, constr);
+ if (!vectorObj)
+ {
+ LOGE("InvokeCallback: failed to create a %s object", TM_JAVA_VECTOR_CLASS_PATH);
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jmethodID addElement = env->GetMethodID(vectorCls, "addElement", "(Ljava/lang/Object;)V");
+ if (NULL == addElement)
+ {
+ LOGE("InvokeCallback: failed to create a addElement method");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ jobject headerOptionTemp;
+ for (int i = 0; i < headerOptions.size(); i++)
+ {
+ headerOptionTemp = OcHeaderOptionToJava(env, headerOptions[i]);
+ env->CallVoidMethod(vectorObj, addElement, headerOptionTemp);
+ }
+
+ // Convert OCRepresentation to java type
+ jobject jrepresentation = OcRepresentationToJava(env, (jlong) reinterpret_cast<jlong>(&rep));
+ if (!jrepresentation)
+ {
+ LOGE("InvokeCallback : cannot create OCRepresentation class");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ env->CallVoidMethod(jobjectCallback, method_id, vectorObj, jrepresentation, (jint)eCode);
+
+ if ((env)->ExceptionCheck())
+ {
+ LOGE("InvokeCallback : CallVoidMethod failed");
+ ThingsManagerJVM::releaseEnv();
+ return;
+ }
+
+ ThingsManagerJVM::releaseEnv();
+ LOGI("InvokeCallback : Exit %s", callbackName);
+}
+++ /dev/null
-/******************************************************************
- *
- * 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 "jni_things_manager.h"
-
-#include "JniOcResource.h"
-#include "JniOcResourceHandle.h"
-#include "ThingsManager.h"
-#include "ActionSet.h"
-#include "jni_things_manager_jvm.h"
-#include "jni_things_manager_util.h"
-#include "jni_things_manager_callbacks.h"
-#include "jni_action_set.h"
-
-using namespace OC;
-using namespace OIC;
-
-/**
- * @var g_ThingsManager
- * @brief ThingsManager static object
- */
-static ThingsManager g_ThingsManager;
-
-jobject ocResourceHandleToJava(JNIEnv *env, jlong resourceHandle);
-
-JNIEXPORT jint JNICALL JNIThingsManagerFindCandidateResource(JNIEnv *env, jobject interfaceObject,
- jobject jResourceTypes, jint waitSec)
-{
- LOGI("JNIThingsManagerFindCandidateResource: Enter");
-
- if (!jResourceTypes)
- {
- LOGE("JNIThingsManagerFindCandidateResource: jResourceTypes is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
- try
- {
- ocResult = g_ThingsManager.findCandidateResources(convertStringVector(env, jResourceTypes),
- &ThingsManagerCallbacks::onFoundCandidateResource, (int)waitSec);
-
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerFindCandidateResource: findCandidateResources failed!");
- return ocResult;
- }
- }
- catch (InitializeException &e)
- {
- LOGE("JNIThingsManagerFindCandidateResource: Exception occurred! %s, %d", e.reason().c_str(),
- e.code());
- return ocResult;
- }
-
- LOGI("JNIThingsManagerFindCandidateResource: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerSubscribeCollectionPresence(JNIEnv *env,
- jobject interfaceObject,
- jobject jResource)
-{
- LOGI("JNIThingsManagerSubscribeCollectionPresence: Enter");
-
- if (!jResource)
- {
- LOGE("JNIThingsManagerSubscribeCollectionPresence: jResource is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, jResource);
- if (NULL == jniOcResource)
- {
- LOGE("JNIThingsManagerSubscribeCollectionPresence: Failed to get jni OcResource!");
- return ocResult;
- }
-
- std::shared_ptr<OCResource> ocResource = jniOcResource->getOCResource();
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerSubscribeCollectionPresence: Failed to get OCResource object!");
- return ocResult;
- }
-
- ocResult = g_ThingsManager.subscribeCollectionPresence(ocResource,
- &ThingsManagerCallbacks::onSubscribePresence);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerSubscribeCollectionPresence: subscribeCollectionPresence failed!");
- return ocResult;
- }
-
- LOGI("JNIThingsManagerSubscribeCollectionPresence: Exit");
- return ocResult;
-}
-
-JNIEXPORT jobject JNICALL JNIThingsManagerBindResourceToGroup(JNIEnv *env, jobject interfaceObject,
- jobject jResource, jobject jCollectionHandle)
-{
- LOGI("JNIThingsManagerBindResourceToGroup: Enter");
-
- if (!jResource || !jCollectionHandle)
- {
- LOGE("JNIThingsManagerBindResourceToGroup: Invalid parameter!");
- return NULL;
- }
-
- std::shared_ptr<OCResource> ocResource;
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, jResource);
- if (jniOcResource)
- {
- ocResource = jniOcResource->getOCResource();
- }
-
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerBindResourceToGroup: Failed to get OCResource object!");
- return NULL;
- }
-
- JniOcResourceHandle *jniOcCollectionHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(env,
- jCollectionHandle);
- if (NULL == jniOcCollectionHandle)
- {
- LOGE("JNIThingsManagerBindResourceToGroup: collection handle is null!");
- return NULL;
- }
-
- jobject jResourceHandle = NULL;
- try
- {
- OCResourceHandle ocChildHandle = NULL;
- OCResourceHandle ocCollectionHandle = jniOcCollectionHandle->getOCResourceHandle();
- OCStackResult ocResult = g_ThingsManager.bindResourceToGroup(ocChildHandle, ocResource, ocCollectionHandle);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerBindResourceToGroup: bindResourceToGroup failed!");
- return NULL;
- }
-
- // Convert OCResourceHandle to java type
- JniOcResourceHandle* jniHandle = new JniOcResourceHandle(ocChildHandle);
- jlong handle = reinterpret_cast<jlong>(jniHandle);
- jResourceHandle = env->NewObject(g_cls_OcResourceHandle, g_mid_OcResourceHandle_N_ctor, handle);
- if (env->ExceptionCheck())
- {
- LOGE("JNIThingsManagerBindResourceToGroup: Failed to create OcResourceHandle");
- delete jniHandle;
- return NULL;
- }
- }
- catch (InitializeException &e)
- {
- LOGE("JNIThingsManagerBindResourceToGroup: Exception occurred! %s, %d", e.reason().c_str(),
- e.code());
- return NULL;
- }
-
- LOGI("JNIThingsManagerBindResourceToGroup: Exit");
- return jResourceHandle;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerFindGroup(JNIEnv *env, jobject interfaceObject,
- jobject jResourceTypes)
-{
- LOGI("JNIThingsManagerFindGroup: Enter");
-
- if (!jResourceTypes)
- {
- LOGE("JNIThingsManagerFindGroup: jResourceTypes is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
- try
- {
- ocResult = g_ThingsManager.findGroup((convertStringVector(env, jResourceTypes)),
- &ThingsManagerCallbacks::onFoundGroup);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerFindGroup: findGroup failed!");
- return ocResult;
- }
- }
- catch (InitializeException &e)
- {
- LOGE("JNIThingsManagerFindGroup: Exception occurred! %s, %d", e.reason().c_str(),
- e.code());
- return ocResult;
- }
- LOGI("JNIThingsManagerFindGroup: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerCreateGroup(JNIEnv *env, jobject interfaceObject,
- jstring jResourceType)
-{
- LOGI("JNIThingsManagerCreateGroup: Enter");
-
- if (!jResourceType)
- {
- LOGE("JNIThingsManagerCreateGroup: jResourceType is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- const char *resourceTypePointer = env->GetStringUTFChars(jResourceType, NULL);
- if (NULL == resourceTypePointer)
- {
- LOGE("JNIThingsManagerCreateGroup: Failed to convert jstring to char string!");
- return OC_STACK_NO_MEMORY;
- }
-
- std::string resourceType(resourceTypePointer);
- try
- {
- ocResult = g_ThingsManager.createGroup(resourceType);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerCreateGroup: CreateGroup failed!");
- }
- }
- catch (InitializeException &e)
- {
- LOGE("JNIThingsManagerCreateGroup: Exception occurred! %s, %d", e.reason().c_str(),
- e.code());
- }
- env->ReleaseStringUTFChars(jResourceType, resourceTypePointer);
- LOGI("JNIThingsManagerCreateGroup: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerJoinGroupString(JNIEnv *env, jobject interfaceObject,
- jstring jResourceType, jobject jResourceHandle)
-{
- LOGI("JNIThingsManagerJoinGroupString: Enter");
-
- if ((!jResourceType) || (!jResourceHandle))
- {
- LOGE("JNIThingsManagerJoinGroupString: jResourceType or jResourceHandle is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- const char *resourceTypePointer = env->GetStringUTFChars(jResourceType, NULL);
- if (NULL == resourceTypePointer)
- {
- LOGE("JNIThingsManagerJoinGroupString: Failed to convert jstring to char string!");
- return OC_STACK_NO_MEMORY;
- }
-
- std::string resourceType(resourceTypePointer);
-
- JniOcResourceHandle *jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(env,
- jResourceHandle);
- try
- {
- OCResourceHandle ocResourceHandle = jniOcResourceHandle->getOCResourceHandle();
- ocResult = g_ThingsManager.joinGroup(resourceType, ocResourceHandle);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerJoinGroupString: joinGroup failed!");
- }
- }
- catch (InitializeException &e)
- {
- LOGE("JNIThingsManagerJoinGroupString: Exception occurred! %s, %d", e.reason().c_str(),
- e.code());
- }
- env->ReleaseStringUTFChars(jResourceType, resourceTypePointer);
- LOGI("JNIThingsManagerJoinGroupString: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerJoinGroupObject(JNIEnv *env, jobject interfaceObject,
- jobject jResource, jobject jResourceHandle)
-{
- LOGI("JNIThingsManagerJoinGroupObject: Enter");
-
- if ((!jResource) || (!jResourceHandle))
- {
- LOGE("JNIThingsManagerJoinGroupObject: jResource or jResourceHandle is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- std::shared_ptr<OCResource> ocResource;
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, jResource);
- if (jniOcResource)
- {
- ocResource = jniOcResource->getOCResource();
- }
-
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerJoinGroupObject: Failed to get OCResource object!");
- return ocResult;
- }
-
- JniOcResourceHandle *jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(env,
- jResourceHandle);
-
- try
- {
- OCResourceHandle resHandle = jniOcResourceHandle->getOCResourceHandle();
-
- ocResult = g_ThingsManager.joinGroup(ocResource, resHandle);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerJoinGroupObject: joinGroup failed!");
- return ocResult;
- }
- }
- catch (InitializeException &e)
- {
- LOGE("JNIThingsManagerJoinGroupObject: Exception occurred! %s, %d", e.reason().c_str(),
- e.code());
- return ocResult;
- }
- LOGI("JNIThingsManagerJoinGroupObject: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerLeaveGroup(JNIEnv *env, jobject interfaceObject,
- jstring jResourceType,
- jobject jResourceHandle)
-{
- LOGI("JNIThingsManagerLeaveGroup: Enter");
-
- if ((!jResourceType) || (!jResourceHandle))
- {
- LOGE("JNIThingsManagerLeaveGroup: jResourceType or jResourceHandle is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- const char *resourceTypePointer = env->GetStringUTFChars(jResourceType, NULL);
- if (NULL == resourceTypePointer)
- {
- LOGE("JNIThingsManagerLeaveGroup: Failed to convert jstring to char string!");
- return OC_STACK_NO_MEMORY;
- }
-
- std::string resourceType(resourceTypePointer);
- JniOcResourceHandle *jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(env,
- jResourceHandle);
-
- try
- {
- OCResourceHandle ocResourceHandle = jniOcResourceHandle->getOCResourceHandle();
-
- ocResult = g_ThingsManager.leaveGroup(resourceType, ocResourceHandle);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerLeaveGroup: leaveGroup failed!");
- }
- }
- catch (InitializeException &e)
- {
- LOGE("JNIThingsManagerLeaveGroup: Exception occurred! %s, %d", e.reason().c_str(),
- e.code());
- }
- env->ReleaseStringUTFChars(jResourceType, resourceTypePointer);
- LOGI("JNIThingsManagerLeaveGroup: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerLeaveGroupForResource(JNIEnv *env, jobject interfaceObject,
- jobject jResource,
- jstring jResourceType,
- jobject jResourceHandle)
-{
- LOGI("JNIThingsManagerLeaveGroupForResource: Enter");
-
- if ((!jResource) || (!jResourceType) || (!jResourceHandle))
- {
- LOGE("JNIThingsManagerLeaveGroupForResource: jResourceType or jResourceHandle is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, jResource);
- if (NULL == jniOcResource)
- {
- LOGE("JNIThingsManagerLeaveGroupForResource: Failed to get jni OcResource!");
- return ocResult;
- }
-
- std::shared_ptr<OCResource> ocResource = jniOcResource->getOCResource();
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerLeaveGroupForResource: Failed to get OCResource object!");
- return ocResult;
- }
-
- const char *resourceTypePointer = env->GetStringUTFChars(jResourceType, NULL);
- if (NULL == resourceTypePointer)
- {
- LOGE("JNIThingsManagerLeaveGroupForResource: Failed to convert jstring to char string!");
- return OC_STACK_NO_MEMORY;
- }
-
- std::string resourceType(resourceTypePointer);
- JniOcResourceHandle *jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(env,
- jResourceHandle);
-
- try
- {
- OCResourceHandle ocResourceHandle = jniOcResourceHandle->getOCResourceHandle();
-
- ocResult = g_ThingsManager.leaveGroup(ocResource, resourceType, ocResourceHandle);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerLeaveGroupForResource: leaveGroup failed!");
- }
- }
- catch (InitializeException &e)
- {
- LOGE("JNIThingsManagerLeaveGroupForResource: Exception occurred! %s, %d", e.reason().c_str(),
- e.code());
- }
-
- env->ReleaseStringUTFChars(jResourceType, resourceTypePointer);
- LOGI("JNIThingsManagerLeaveGroupForResource: Exit");
- return ocResult;
-}
-
-JNIEXPORT void JNICALL JNIThingsManagerDeleteGroup(JNIEnv *env, jobject interfaceObject,
- jstring jcollectionResourceType)
-{
- LOGI("JNIThingsManagerDeleteGroup: Enter");
-
- if (!jcollectionResourceType)
- {
- LOGE("JNIThingsManagerDeleteGroup: jcollectionResourceType is NULL!");
- return;
- }
-
- const char *collectionResourceTypePointer = env->GetStringUTFChars(jcollectionResourceType, NULL);
- if (NULL == collectionResourceTypePointer)
- {
- LOGE("JNIThingsManagerDeleteGroup: Failed to convert jstring to char string!");
- return;
- }
-
- std::string collectionResourceType(collectionResourceTypePointer);
- try
- {
- g_ThingsManager.deleteGroup(collectionResourceType);
- }
- catch (InitializeException &e)
- {
- LOGE("JNIThingsManagerDeleteGroup: Exception occurred! %s, %d", e.reason().c_str(),
- e.code());
- }
-
- env->ReleaseStringUTFChars(jcollectionResourceType, collectionResourceTypePointer);
- LOGI("JNIThingsManagerDeleteGroup: Exit");
-}
-
-JNIEXPORT jobject JNICALL JNIThingsManagerGetGroupList(JNIEnv *env, jobject interfaceObject)
-{
- LOGI("JNIThingsManagerGetGroupList: Enter");
-
- std::map< std::string, OCResourceHandle> groupListMap;
- jobject jGroupListMap;
-
- groupListMap = g_ThingsManager.getGroupList();
- if (groupListMap.empty())
- {
- LOGD("getGroupList Map is empty");
- return NULL;
- }
-
- jclass clazz = env->FindClass("java/util/HashMap");
- jmethodID init = env->GetMethodID(clazz, "<init>", "()V");
- jGroupListMap = env->NewObject(clazz, init);
- jmethodID putMethod = env->GetMethodID(clazz, "put",
- "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
-
- for (auto it = groupListMap.begin(); it != groupListMap.end(); ++it)
- {
- jstring key = (*env).NewStringUTF( (*it).first.c_str() );
- JniOcResourceHandle *jniOcResourceHandle = new JniOcResourceHandle(((*it).second));
- jobject value = ocResourceHandleToJava(env, reinterpret_cast<jlong>(jniOcResourceHandle));
- env->CallObjectMethod(jGroupListMap, putMethod, key, value);
- }
-
- LOGI("JNIThingsManagerGetGroupList: Exit");
- return jGroupListMap;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerUpdateConfigurations(JNIEnv *env, jobject interfaceObject,
- jobject resource, jobject configurations)
-{
- LOGI("JNIThingsManagerUpdateConfigurations: Enter");
-
- if ((!resource) || (!configurations))
- {
- LOGE("JNIThingsManagerUpdateConfigurations: resource or configurations is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- std::shared_ptr<OCResource> ocResource;
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
- if (jniOcResource)
- {
- ocResource = jniOcResource->getOCResource();
- }
-
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerUpdateConfigurations: Failed to get OCResource object!");
- return ocResult;
- }
-
- std::map<std::string, std::string> configurationsMap;
- configurationsMap = convertStringMap(env, configurations);
- ocResult = g_ThingsManager.updateConfigurations(ocResource, configurationsMap,
- &ThingsManagerCallbacks::onUpdateConfigurationsResponse);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerUpdateConfigurations: updateConfigurations failed!");
- return ocResult;
- }
-
- LOGI("JNIThingsManagerUpdateConfigurations: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerGetConfigurations(JNIEnv *env, jobject interfaceObject,
- jobject resource, jobject configurations)
-{
- LOGI("JNIThingsManagerGetConfigurations: Enter");
-
- if ((!resource) || (!configurations))
- {
- LOGE("JNIThingsManagerGetConfigurations: resource or configurations is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- std::shared_ptr<OCResource> ocResource;
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
- if (jniOcResource)
- {
- ocResource = jniOcResource->getOCResource();
- }
-
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerGetConfigurations: Failed to get OCResource object!");
- return ocResult;
- }
-
- ocResult = g_ThingsManager.getConfigurations(ocResource,
- (convertStringVector(env, configurations)),
- &ThingsManagerCallbacks::onGetConfigurationsResponse);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerGetConfigurations: getConfigurations failed!");
- return ocResult;
- }
-
- LOGI("JNIThingsManagerGetConfigurations: Exit");
- return ocResult;
-}
-
-JNIEXPORT jstring JNICALL JNIThingsManagerGetListOfSupportedConfigurationUnits(JNIEnv *env,
- jobject interfaceObject)
-{
- LOGI("JNIThingsManagerGetListOfSupportedConfigurationUnits: Enter");
-
- std::string configListString = g_ThingsManager.getListOfSupportedConfigurationUnits();
- jstring jConfigListString = env->NewStringUTF(configListString.c_str());
-
- LOGI("JNIThingsManagerGetListOfSupportedConfigurationUnits: Exit");
- return jConfigListString;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerDoBootstrap(JNIEnv *env, jobject interfaceObject)
-{
- LOGI("JNIThingsManagerDoBootstrap: Enter");
-
- OCStackResult ocResult = OC_STACK_ERROR;
- try
- {
- ocResult = g_ThingsManager.doBootstrap(&ThingsManagerCallbacks::onBootStrapResponse);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerDoBootstrap: doBootstrap failed!");
- return ocResult;
- }
- }
- catch (InitializeException &e)
- {
- LOGE("JNIThingsManagerDoBootstrap: Exception occurred! %s, %d", e.reason().c_str(),
- e.code());
- return ocResult;
- }
-
- LOGI("JNIThingsManagerDoBootstrap: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerReboot(JNIEnv *env, jobject interfaceObject,
- jobject resource)
-{
- LOGI("JNIThingsManagerReboot: Enter");
-
- if (!resource)
- {
- LOGE("JNIThingsManagerReboot: resource is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- std::shared_ptr<OCResource> ocResource;
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
- if (jniOcResource)
- {
- ocResource = jniOcResource->getOCResource();
- }
-
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerReboot: Failed to get OCResource object!");
- return ocResult;
- }
-
- ocResult = g_ThingsManager.reboot(ocResource, &ThingsManagerCallbacks::onRebootResponse);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerReboot: reboot failed!");
- return ocResult;
- }
-
- LOGI("JNIThingsManagerReboot: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerFactoryReset(JNIEnv *env, jobject interfaceObject,
- jobject resource)
-{
- LOGI("JNIThingsManagerFactoryReset: Enter");
-
- if (!resource)
- {
- LOGE("JNIThingsManagerFactoryReset: resource is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- std::shared_ptr<OCResource> ocResource;
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
- if (jniOcResource)
- {
- ocResource = jniOcResource->getOCResource();
- }
-
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerFactoryReset: Failed to get OCResource object!");
- return ocResult;
- }
-
- ocResult = g_ThingsManager.factoryReset(ocResource,
- &ThingsManagerCallbacks::onFactoryResetResponse);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerFactoryReset: factoryReset failed!");
- return ocResult;
- }
-
- LOGI("JNIThingsManagerFactoryReset: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerAddActionSet(JNIEnv *env, jobject interfaceObject,
- jobject resource,
- jobject newActionSet)
-{
- LOGI("JNIThingsManagerAddActionSet: Entry");
-
- if ((!resource) || (!newActionSet))
- {
- LOGE("JNIThingsManagerAddActionSet: resource or newActionSet is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- std::shared_ptr<OCResource> ocResource;
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
- if (jniOcResource)
- {
- ocResource = jniOcResource->getOCResource();
- }
-
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManageraAdActionSet: Failed to get OCResource object!");
- return ocResult;
- }
-
- JniActionSet *jActionSet = new JniActionSet(env, newActionSet);
- ActionSet *pActionSet = jActionSet->getActionSet(env, newActionSet);
- if (NULL == pActionSet)
- {
- LOGE("JNIThingsManageraAdActionSet: Failed to convert ActionSet!");
- return ocResult;
- }
-
- ocResult = g_ThingsManager.addActionSet(ocResource, pActionSet,
- &ThingsManagerCallbacks::onPutResponse);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerAddActionSet: addActionSet is failed!");
- }
-
- delete pActionSet;
- LOGI("JNIThingsManagerAddActionSet: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerExecuteActionSet(JNIEnv *env, jobject interfaceObject,
- jobject resource, jstring jActionSetName)
-{
- LOGI("JNIThingsManagerExecuteActionSet: Entry");
-
- if ((!resource) || (!jActionSetName))
- {
- LOGE("JNIThingsManagerExecuteActionSet: resource or jActionSetName is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- std::shared_ptr<OCResource> ocResource;
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
- if (jniOcResource)
- {
- ocResource = jniOcResource->getOCResource();
- }
-
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerExecuteActionSet: Failed to get OCResource object!");
- return ocResult;
- }
-
- const char *actionSetNamePointer = env->GetStringUTFChars(jActionSetName, 0);
- if (NULL == actionSetNamePointer)
- {
- LOGE("JNIThingsManagerExecuteActionSet: Failed to convert jstring to char string!");
- return OC_STACK_NO_MEMORY;
- }
-
- std::string actionSetName(actionSetNamePointer);
-
- ocResult = g_ThingsManager.executeActionSet(ocResource, actionSetName,
- &ThingsManagerCallbacks::onPostResponse);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerExecuteActionSet: executeActionSet is failed!");
- }
-
- env->ReleaseStringUTFChars(jActionSetName, actionSetNamePointer);
- LOGI("JNIThingsManagerExecuteActionSet: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerExecuteActionSetWithDelay(JNIEnv *env,
- jobject interfaceObject,
- jobject resource, jstring jActionSetName, jlong delay)
-{
- LOGI("JNIThingsManagerExecuteActionSet: Entry");
-
- if ((!resource) || (!jActionSetName))
- {
- LOGE("JNIThingsManagerExecuteActionSet: resource or jActionSetName is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- std::shared_ptr<OCResource> ocResource;
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
- if (jniOcResource)
- {
- ocResource = jniOcResource->getOCResource();
- }
-
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerExecuteActionSet: Failed to get OCResource object!");
- return ocResult;
- }
-
- const char *actionSetNamePointer = env->GetStringUTFChars(jActionSetName, 0);
- if (NULL == actionSetNamePointer)
- {
- LOGE("JNIThingsManagerExecuteActionSet: Failed to convert jstring to char string!");
- return OC_STACK_NO_MEMORY;
- }
-
- std::string actionSetName(actionSetNamePointer);
- if (0 == delay)
- {
- ocResult = g_ThingsManager.executeActionSet(ocResource, actionSetName,
- &ThingsManagerCallbacks::onPostResponse);
- }
- else
- {
- ocResult = g_ThingsManager.executeActionSet(ocResource, actionSetName,
- (long int)delay,
- &ThingsManagerCallbacks::onPostResponse);
- }
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerExecuteActionSet: executeActionSet is failed!");
- }
-
- env->ReleaseStringUTFChars(jActionSetName, actionSetNamePointer);
- LOGI("JNIThingsManagerExecuteActionSet: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerCancelActionSet(JNIEnv *env, jobject interfaceObject,
- jobject resource, jstring jActionSetName)
-{
- LOGI("JNIThingsManagerCancelActionSet: Entry");
-
- if ((!resource) || (!jActionSetName))
- {
- LOGE("JNIThingsManagerCancelActionSet: resource or jActionSetName is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- std::shared_ptr<OCResource> ocResource;
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
- if (jniOcResource)
- {
- ocResource = jniOcResource->getOCResource();
- }
-
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerCancelActionSet: Failed to get OCResource object!");
- return ocResult;
- }
-
- const char *actionSetNamePointer = env->GetStringUTFChars(jActionSetName, 0);
- if (NULL == actionSetNamePointer)
- {
- LOGE("JNIThingsManagerCancelActionSet: Failed to get character sequence from jstring!");
- return OC_STACK_NO_MEMORY;
- }
-
- std::string actionSetName(actionSetNamePointer);
-
- ocResult = g_ThingsManager.cancelActionSet(ocResource, actionSetName,
- &ThingsManagerCallbacks::onPostResponse);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerCancelActionSet: cancelActionSet is failed!");
- }
-
- env->ReleaseStringUTFChars(jActionSetName, actionSetNamePointer);
- LOGI("JNIThingsManagerCancelActionSet: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerGetActionSet(JNIEnv *env, jobject interfaceObject,
- jobject resource,
- jstring jActionSetName)
-{
- LOGI("JNIThingsManagerGetActionSet: Entry");
-
- if ((!resource) || (!jActionSetName))
- {
- LOGE("JNIThingsManagerGetActionSet: resource or jActionSetName is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- std::shared_ptr<OCResource> ocResource;
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
- if (jniOcResource)
- {
- ocResource = jniOcResource->getOCResource();
- }
-
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerGetActionSet: Failed to get OCResource object!");
- return ocResult;
- }
-
- const char *actionSetNamePointer = env->GetStringUTFChars(jActionSetName, 0);
- std::string actionSetName(actionSetNamePointer);
-
- ocResult = g_ThingsManager.getActionSet(ocResource, actionSetName,
- &ThingsManagerCallbacks::onGetResponse);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerGetActionSet: getActionSet is failed!");
- }
-
- env->ReleaseStringUTFChars(jActionSetName, actionSetNamePointer);
- LOGI("JNIThingsManagerGetActionSet: Exit");
- return ocResult;
-}
-
-JNIEXPORT jint JNICALL JNIThingsManagerDeleteActionSet(JNIEnv *env, jobject interfaceObject,
- jobject resource,
- jstring jActionSetName)
-{
- LOGI("JNIThingsManagerDeleteActionSet: Entry");
-
- if ((!resource) || (!jActionSetName))
- {
- LOGE("JNIThingsManagerDeleteActionSet: resource or jActionSetName is NULL!");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCStackResult ocResult = OC_STACK_ERROR;
-
- std::shared_ptr<OCResource> ocResource;
- JniOcResource *jniOcResource = JniOcResource::getJniOcResourcePtr(env, resource);
- if (jniOcResource)
- {
- ocResource = jniOcResource->getOCResource();
- }
-
- if (NULL == ocResource.get())
- {
- LOGE("JNIThingsManagerDeleteActionSet: Failed to get OCResource object!");
- return ocResult;
- }
-
- const char *actionSetNamePointer = env->GetStringUTFChars(jActionSetName, 0);
- std::string actionSetName(actionSetNamePointer);
-
- ocResult = g_ThingsManager.deleteActionSet(ocResource, actionSetName,
- &ThingsManagerCallbacks::onPutResponse);
- if (OC_STACK_OK != ocResult)
- {
- LOGE("JNIThingsManagerDeleteActionSet: deleteActionSet is failed!");
- }
-
- env->ReleaseStringUTFChars(jActionSetName, actionSetNamePointer);
- LOGI("JNIThingsManagerDeleteActionSet: Exit");
- return ocResult;
-}
-
-jobject ocResourceHandleToJava(JNIEnv *env, jlong resourceHandle)
-{
- jclass resourceClass = GetJClass(TM_SERVICE_OCRESOURCEHANDLE_PATH);
- if (NULL == resourceClass)
- {
- LOGE("ocResourceHandleToJava : failed to find OCResourceHandle java class!");
- return NULL;
- }
-
- jmethodID constructor = env->GetMethodID(resourceClass, "<init>", "(J)V");
- if (NULL == constructor)
- {
- LOGE("ocResourceHandleToJava: Failed to get constructor method!");
- return NULL;
- }
-
- jobject resourceObj = (jobject) env->NewObject(resourceClass, constructor, resourceHandle);
- if (NULL == resourceObj)
- {
- LOGE("ocResourceHandleToJava: Failed to create OCResouceHandle java object!");
- return NULL;
- }
-
- return resourceObj;
-}
+++ /dev/null
-/******************************************************************
- *
- * 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 "jni_things_manager_callbacks.h"
-#include "JniOcResource.h"
-#include "ThingsManager.h"
-#include "jni_things_manager_jvm.h"
-#include "jni_string.h"
-
-#define LOG_TAG "ThingsManagerCallbacks"
-
-#define METHOD_ONRESOURCE_CALLBACK "(" TM_JAVA_VECTOR_TYPE")V"
-#define METHOD_ONGROUP_FIND_CALLBACK "(" TM_SERVICE_OCRESOURCE_TYPE")V"
-#define METHOD_ONPRESENCE_CALLBACK "(" TM_JAVA_STRING_TYPE"I)V"
-#define METHOD_ONUPDATE_CONF_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
-#define METHOD_ONGET_CONF_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
-#define METHOD_ONBOOT_STRAP_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
-#define METHOD_ONFACTORY_RESET_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
-#define METHOD_ONREBOOT_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
-#define METHOD_ONPOST_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
-#define METHOD_ONPUT_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
-#define METHOD_ONGET_CALLBACK "(" TM_JAVA_VECTOR_TYPE TM_SERVICE_OCREPRESENTATION_TYPE"I)V"
-#define METHOD_TMCALLBACK_GETINSTANCE "()" TM_SERVICE_CALLBACK_CLASS_TYPE
-
-jobject OcResourceToJava(JNIEnv *env, jlong resource)
-{
- jclass resourceClass = GetJClass(TM_SERVICE_OCRESOURCE_PATH);
- if (NULL == resourceClass)
- {
- LOGE("OcResourceToJava : failed to find OCResouce java class!");
- return NULL;
- }
-
- jmethodID constructor = env->GetMethodID(resourceClass, "<init>", "(J)V");
- if (NULL == constructor)
- {
- LOGE("OcResourceToJava: Failed to get constructor method!");
- return NULL;
- }
-
- jobject resourceObj = (jobject) env->NewObject(resourceClass, constructor, resource);
- if (NULL == resourceObj)
- {
- LOGE("OcResourceToJava: Failed to create OCResouce java object!");
- return NULL;
- }
-
- return resourceObj;
-}
-
-jobject OcHeaderOptionToJava(JNIEnv *env, OC::HeaderOption::OCHeaderOption headerOption)
-{
- JString *optionData = new JString(env, headerOption.getOptionData());
- if (!optionData)
- {
- LOGE("OcHeaderOptionToJava : failed to get JString!");
- return NULL;
- }
-
- jclass headerOptionClass = GetJClass(TM_SERVICE_HEADER_OPTION_PATH);
- if (NULL == headerOptionClass)
- {
- LOGE("OcHeaderOptionToJava : failed to find OCRepresentation java class!");
- return NULL;
- }
-
- jmethodID constructor = env->GetMethodID(headerOptionClass, "<init>", "(JLjava/lang/String;)V");
- if (NULL == constructor)
- {
- LOGE("OcHeaderOptionToJava: Failed to get constructor method!");
- return NULL;
- }
-
- jobject headerOptionObj = (jobject) env->NewObject(headerOptionClass, constructor,
- (jlong)headerOption.getOptionID(), optionData);
- if (NULL == headerOptionObj)
- {
- LOGE("OcHeaderOptionToJava: Failed to create OCRepresentation java object!");
- return NULL;
- }
-
- return headerOptionObj;
-}
-
-jobject OcRepresentationToJava(JNIEnv *env, jlong ocRepresentation)
-{
- jclass ocRepresentationClass = GetJClass(TM_SERVICE_OCREPRESENTATION_PATH);
- if (NULL == ocRepresentationClass)
- {
- LOGE("OcRepresentationToJava : failed to find OCRepresentation java class!");
- return NULL;
- }
-
- jmethodID constructor = env->GetMethodID(ocRepresentationClass, "<init>", "(J)V");
- if (NULL == constructor)
- {
- LOGE("OcRepresentationToJava: Failed to get constructor method!");
- return NULL;
- }
-
- jobject ocRepresentationObj = (jobject) env->NewObject(ocRepresentationClass, constructor,
- ocRepresentation);
- if (NULL == ocRepresentationObj)
- {
- LOGE("OcRepresentationToJava: Failed to create OCRepresentation java object!");
- return NULL;
- }
-
- return ocRepresentationObj;
-}
-
-void ThingsManagerCallbacks::onFoundCandidateResource(
- std::vector< std::shared_ptr<OC::OCResource>> resources)
-{
- LOGI("findCandidateResource : Enter");
-
- if (resources.size() == 0)
- {
- LOGE("findCandidateResource : found resources zero");
- return;
- }
-
- JNIEnv *env = ThingsManagerJVM::getEnv();
- if (env == NULL)
- {
- LOGE("findCandidateResource : Getting JNIEnv failed");
- return;
- }
-
- // Get ThingsManagerCallback class reference
- jclass thingsManagerCallbacks = GetJClass(TM_SERVICE_CALLBACK_CLASS_PATH);
- if (NULL == thingsManagerCallbacks)
- {
- LOGE("findCandidateResource : GetJClass TMServiceCallbackInterface failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- // Get the ThingsManagerCallback class instance
- jobject jobjectCallback = GetJObjectInstance(TM_SERVICE_CALLBACK_CLASS_PATH);
- if (NULL == jobjectCallback)
- {
- LOGE("getInstance( %s) failed!", TM_SERVICE_CALLBACK_CLASS_PATH);
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- // Get onResourceCallback method reference
- jmethodID method_id = env->GetMethodID(thingsManagerCallbacks,
- "onResourceCallback", METHOD_ONRESOURCE_CALLBACK);
- if (NULL == method_id)
- {
- LOGE("findCandidateResource: onResourceCallback : GetMethodID failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- if ((env)->ExceptionCheck())
- {
- LOGE("findCandidateResource : ExceptionCheck failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- jclass vectorCls = env->FindClass(TM_JAVA_VECTOR_CLASS_PATH);
- if (!vectorCls)
- {
- LOGE("findCandidateResource: failed to get %s class reference", TM_JAVA_VECTOR_CLASS_PATH);
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- jmethodID constr = env->GetMethodID(vectorCls, "<init>", "()V");
- if (!constr)
- {
- LOGE("findCandidateResource: failed to get %s constructor", TM_JAVA_VECTOR_CLASS_PATH);
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- jobject vectorObj = env->NewObject(vectorCls, constr);
- if (!vectorObj)
- {
- LOGE("findCandidateResource: failed to create a %s object", TM_JAVA_VECTOR_CLASS_PATH);
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- jmethodID addElement = env->GetMethodID(vectorCls, "addElement", "(Ljava/lang/Object;)V");
- if (NULL == addElement)
- {
- LOGE("findCandidateResource: failed to create a addElement method");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- // Convert to java OCResource object
- for (int i = 0; i < resources.size(); i++)
- {
- JniOcResource *jniOcResource = new JniOcResource(resources[i]);
- if (!jniOcResource)
- {
- LOGE("findCandidateResource: failed to create a JniOcResource");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- jobject resource = OcResourceToJava(env, reinterpret_cast<jlong>(jniOcResource));
- env->CallVoidMethod(vectorObj, addElement, resource);
- }
-
- env->CallVoidMethod(jobjectCallback, method_id, vectorObj);
-
- if ((env)->ExceptionCheck())
- {
- LOGE("findCandidateResource : CallVoidMethod failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- ThingsManagerJVM::releaseEnv();
- LOGI("findCandidateResource : Exit");
-}
-
-void ThingsManagerCallbacks::onFoundGroup(std::shared_ptr<OC::OCResource> groupResource)
-{
- LOGI("FindGroup : Enter");
-
- if (NULL == groupResource.get())
- {
- LOGE("FindGroup : Invalid received GroupResource!");
- return;
- }
-
- JNIEnv *env = ThingsManagerJVM::getEnv();
- if (env == NULL)
- {
- LOGE("FindGroup : Getting JNIEnv failed");
- return;
- }
-
- // Get ThingsManagerCallback class reference
- jclass thingsManagerCallbacks = GetJClass(TM_SERVICE_CALLBACK_CLASS_PATH);
- if (NULL == thingsManagerCallbacks)
- {
- LOGE("FindGroup : GetJClass TMServiceCallbackInterface failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- // Get the ThingsManagerCallback class instance
- jobject jobjectCallback = GetJObjectInstance(TM_SERVICE_CALLBACK_CLASS_PATH);
- if (NULL == jobjectCallback)
- {
- LOGE("FindGroup: getInstance( %s) failed!", TM_SERVICE_CALLBACK_CLASS_PATH);
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- // Get onGroupFindCallback method reference
- jmethodID method_id = env->GetMethodID(thingsManagerCallbacks,
- "onGroupFindCallback",
- METHOD_ONGROUP_FIND_CALLBACK);
- if (NULL == method_id)
- {
- LOGE("FindGroup : GetMethodID failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- if ((env)->ExceptionCheck())
- {
- LOGE("FindGroup : ExceptionCheck failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- JniOcResource *jniOcResource = new JniOcResource(groupResource);
- if (!jniOcResource)
- {
- LOGE("FindGroup : groupResource is invalid!");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- jobject resource = OcResourceToJava(env, reinterpret_cast<jlong>(jniOcResource));
-
- env->CallVoidMethod(jobjectCallback, method_id, resource);
-
- if ((env)->ExceptionCheck())
- {
- LOGE("FindGroup : CallVoidMethod failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- ThingsManagerJVM::releaseEnv();
- LOGI("FindGroup : Exit");
-}
-
-void ThingsManagerCallbacks::onSubscribePresence(std::string resource, OCStackResult result)
-{
- LOGI("SubscribePresence : Entry");
-
- JNIEnv *env = ThingsManagerJVM::getEnv();
- if (env == NULL)
- {
- LOGE("SubscribePresence : Getting JNIEnv failed");
- return;
- }
-
- // Get ThingsManagerCallback class reference
- jclass thingsManagerCallbacks = GetJClass(TM_SERVICE_CALLBACK_CLASS_PATH);
- if (NULL == thingsManagerCallbacks)
- {
- LOGE("findCandidateResource : GetJClass TMServiceCallbackInterface failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- // Get getInstance method reference
- jmethodID getinstance_method_id = env->GetStaticMethodID(thingsManagerCallbacks,
- "getInstance", METHOD_TMCALLBACK_GETINSTANCE);
- if (NULL == getinstance_method_id)
- {
- LOGE("getInstance : GetMethodID failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- // Get the ThingsManagerCallback class instance
- jobject jobjectCallback = env->CallStaticObjectMethod(thingsManagerCallbacks,
- getinstance_method_id);
- if (NULL == jobjectCallback)
- {
- LOGE("getInstance( %s) failed!", TM_SERVICE_CALLBACK_CLASS_PATH);
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- jmethodID method_id = env->GetMethodID(thingsManagerCallbacks,
- "onPresenceCallback",
- METHOD_ONPRESENCE_CALLBACK);
- if (NULL == method_id)
- {
- LOGE("SubscribePresence : GetMethodID failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- if ((env)->ExceptionCheck())
- {
- LOGE("SubscribePresence : ExceptionCheck failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- JString *jresource = new JString(env, resource);
- if (jresource == NULL)
- {
- LOGE("resource value is invalid");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- env->CallVoidMethod(jobjectCallback, method_id, jresource->getObject(), (jint)result);
-
- delete jresource;
-
- if ((env)->ExceptionCheck())
- {
- LOGE("SubscribePresence : CallVoidMethod failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- LOGI("SubscribePresence : Exit");
-
-//METHOD_FAILURE:
- ThingsManagerJVM::releaseEnv();
-}
-
-void ThingsManagerCallbacks::onUpdateConfigurationsResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode)
-{
- LOGI("UpdateConfigurations : Enter");
-
- ThingsManagerCallbacks::invokeCallback(headerOptions, rep, eCode, "onUpdateConfigurationsCallback",
- METHOD_ONUPDATE_CONF_CALLBACK);
-
- LOGI("UpdateConfigurations : Exit");
-}
-
-void ThingsManagerCallbacks::onGetConfigurationsResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode)
-{
- LOGI("GetConfigurations : Enter");
-
- ThingsManagerCallbacks::invokeCallback(headerOptions, rep, eCode, "onGetConfigurationsCallback",
- METHOD_ONGET_CONF_CALLBACK);
-
- LOGI("GetConfigurations : Exit");
-}
-
-void ThingsManagerCallbacks::onBootStrapResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode)
-{
- LOGI("BootStrap : Enter");
-
- ThingsManagerCallbacks::invokeCallback(headerOptions, rep, eCode, "onBootStrapCallback",
- METHOD_ONBOOT_STRAP_CALLBACK);
-
- LOGI("BootStrap : Exit");
-}
-
-void ThingsManagerCallbacks::onRebootResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode)
-{
- LOGI("OnReboot : Enter");
-
- ThingsManagerCallbacks::invokeCallback(headerOptions, rep, eCode, "onRebootCallback",
- METHOD_ONREBOOT_CALLBACK);
-
- LOGI("OnReboot : Exit");
-}
-
-void ThingsManagerCallbacks::onFactoryResetResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode)
-{
- LOGI("OnFactoryReset : Enter");
-
- ThingsManagerCallbacks::invokeCallback(headerOptions, rep, eCode, "onFactoryResetCallback",
- METHOD_ONFACTORY_RESET_CALLBACK);
-
- LOGI("OnFactoryReset : Exit");
-}
-
-void ThingsManagerCallbacks::onPostResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode)
-{
- LOGI("PostResponse : Enter");
-
- ThingsManagerCallbacks::invokeCallback(headerOptions, rep, eCode, "onPostResponseCallback",
- METHOD_ONPOST_CALLBACK);
-
- LOGI("PostResponse : Exit");
-}
-
-void ThingsManagerCallbacks::onPutResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode)
-{
- LOGI("OnPutResponse : Enter");
-
- ThingsManagerCallbacks::invokeCallback(headerOptions, rep, eCode, "onPutResponseCallback",
- METHOD_ONPUT_CALLBACK);
-
- LOGI("OnPutResponse : Exit");
-}
-
-
-void ThingsManagerCallbacks::onGetResponse(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode)
-{
- LOGI("OnGetResponse : Enter");
-
- ThingsManagerCallbacks::invokeCallback(headerOptions, rep, eCode, "onGetResponseCallback",
- METHOD_ONGET_CALLBACK);
-
- LOGI("OnGetResponse : Exit");
-}
-
-void ThingsManagerCallbacks::invokeCallback(const OC::HeaderOptions &headerOptions,
- const OC::OCRepresentation &rep, const int eCode, const char *callbackName,
- const char *signature)
-{
- LOGI("InvokeCallback : Enter %s", callbackName);
-
- JNIEnv *env = ThingsManagerJVM::getEnv();
- if (env == NULL)
- {
- LOGE("InvokeCallback : Getting JNIEnv failed");
- return;
- }
-
- // Get ThingsManagerCallback class reference
- jclass thingsManagerCallbacks = GetJClass(TM_SERVICE_CALLBACK_CLASS_PATH);
- if (NULL == thingsManagerCallbacks)
- {
- LOGE("InvokeCallback : GetJClass TMServiceCallbackInterface failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- // Get the ThingsManagerCallback class instance
- jobject jobjectCallback = GetJObjectInstance(TM_SERVICE_CALLBACK_CLASS_PATH);
- if (NULL == jobjectCallback)
- {
- LOGE("InvokeCallback: getInstance( %s) failed!", TM_SERVICE_CALLBACK_CLASS_PATH);
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- jmethodID method_id = env->GetMethodID(thingsManagerCallbacks, callbackName, signature);
- if (!method_id)
- {
- LOGE("InvokeCallback : GetMethodID failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- if ((env)->ExceptionCheck())
- {
- LOGE("InvokeCallback : ExceptionCheck failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- // Convert vector<OC:HeaderOption::OCHeaderOption> to java type
- jclass vectorCls = env->FindClass(TM_JAVA_VECTOR_CLASS_PATH);
- if (!vectorCls)
- {
- LOGE("InvokeCallback: failed to get %s class reference", TM_JAVA_VECTOR_CLASS_PATH);
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- jmethodID constr = env->GetMethodID(vectorCls, "<init>", "()V");
- if (!constr)
- {
- LOGE("InvokeCallback: failed to get %s constructor", TM_JAVA_VECTOR_CLASS_PATH);
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- jobject vectorObj = env->NewObject(vectorCls, constr);
- if (!vectorObj)
- {
- LOGE("InvokeCallback: failed to create a %s object", TM_JAVA_VECTOR_CLASS_PATH);
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- jmethodID addElement = env->GetMethodID(vectorCls, "addElement", "(Ljava/lang/Object;)V");
- if (NULL == addElement)
- {
- LOGE("InvokeCallback: failed to create a addElement method");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- jobject headerOptionTemp;
- for (int i = 0; i < headerOptions.size(); i++)
- {
- headerOptionTemp = OcHeaderOptionToJava(env, headerOptions[i]);
- env->CallVoidMethod(vectorObj, addElement, headerOptionTemp);
- }
-
- // Convert OCRepresentation to java type
- jobject jrepresentation = OcRepresentationToJava(env, (jlong) reinterpret_cast<jlong>(&rep));
- if (!jrepresentation)
- {
- LOGE("InvokeCallback : cannot create OCRepresentation class");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- env->CallVoidMethod(jobjectCallback, method_id, vectorObj, jrepresentation, (jint)eCode);
-
- if ((env)->ExceptionCheck())
- {
- LOGE("InvokeCallback : CallVoidMethod failed");
- ThingsManagerJVM::releaseEnv();
- return;
- }
-
- ThingsManagerJVM::releaseEnv();
- LOGI("InvokeCallback : Exit %s", callbackName);
-}
\ No newline at end of file
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
* limitations under the License.
*
******************************************************************/
+
#include "jni_things_manager_util.h"
#include "JniOcResource.h"
+#include "jni_string.h"
+
+jobject ocResourceHandleToJava(JNIEnv *env, jlong resourceHandle)
+{
+ jclass resourceClass = GetJClass(TM_SERVICE_OCRESOURCEHANDLE_PATH);
+ if (NULL == resourceClass)
+ {
+ LOGE("ocResourceHandleToJava : failed to find OCResourceHandle java class!");
+ return NULL;
+ }
+
+ jmethodID constructor = env->GetMethodID(resourceClass, "<init>", "(J)V");
+ if (NULL == constructor)
+ {
+ LOGE("ocResourceHandleToJava: Failed to get constructor method!");
+ return NULL;
+ }
+
+ jobject resourceObj = (jobject) env->NewObject(resourceClass, constructor, resourceHandle);
+ if (NULL == resourceObj)
+ {
+ LOGE("ocResourceHandleToJava: Failed to create OCResouceHandle java object!");
+ return NULL;
+ }
+ return resourceObj;
+}
+
+jobject OcResourceToJava(JNIEnv *env, jlong resource)
+{
+ jclass resourceClass = GetJClass(TM_SERVICE_OCRESOURCE_PATH);
+ if (NULL == resourceClass)
+ {
+ LOGE("OcResourceToJava : failed to find OCResouce java class!");
+ return NULL;
+ }
+
+ jmethodID constructor = env->GetMethodID(resourceClass, "<init>", "(J)V");
+ if (NULL == constructor)
+ {
+ LOGE("OcResourceToJava: Failed to get constructor method!");
+ return NULL;
+ }
+
+ jobject resourceObj = (jobject) env->NewObject(resourceClass, constructor, resource);
+ if (NULL == resourceObj)
+ {
+ LOGE("OcResourceToJava: Failed to create OCResouce java object!");
+ return NULL;
+ }
+ return resourceObj;
+}
+
+jobject OcHeaderOptionToJava(JNIEnv *env, OC::HeaderOption::OCHeaderOption headerOption)
+{
+ JString *optionData = new JString(env, headerOption.getOptionData());
+ if (!optionData)
+ {
+ LOGE("OcHeaderOptionToJava : failed to get JString!");
+ return NULL;
+ }
+
+ jclass headerOptionClass = GetJClass(TM_SERVICE_HEADER_OPTION_PATH);
+ if (NULL == headerOptionClass)
+ {
+ LOGE("OcHeaderOptionToJava : failed to find OCRepresentation java class!");
+ return NULL;
+ }
+
+ jmethodID constructor = env->GetMethodID(headerOptionClass, "<init>", "(JLjava/lang/String;)V");
+ if (NULL == constructor)
+ {
+ LOGE("OcHeaderOptionToJava: Failed to get constructor method!");
+ return NULL;
+ }
+
+ jobject headerOptionObj = (jobject) env->NewObject(headerOptionClass, constructor,
+ (jlong)headerOption.getOptionID(), optionData);
+ if (NULL == headerOptionObj)
+ {
+ LOGE("OcHeaderOptionToJava: Failed to create OCRepresentation java object!");
+ return NULL;
+ }
+ return headerOptionObj;
+}
+
+jobject OcRepresentationToJava(JNIEnv *env, jlong ocRepresentation)
+{
+ jclass ocRepresentationClass = GetJClass(TM_SERVICE_OCREPRESENTATION_PATH);
+ if (NULL == ocRepresentationClass)
+ {
+ LOGE("OcRepresentationToJava : failed to find OCRepresentation java class!");
+ return NULL;
+ }
+
+ jmethodID constructor = env->GetMethodID(ocRepresentationClass, "<init>", "(J)V");
+ if (NULL == constructor)
+ {
+ LOGE("OcRepresentationToJava: Failed to get constructor method!");
+ return NULL;
+ }
+
+ jobject ocRepresentationObj = (jobject) env->NewObject(ocRepresentationClass, constructor,
+ ocRepresentation);
+ if (NULL == ocRepresentationObj)
+ {
+ LOGE("OcRepresentationToJava: Failed to create OCRepresentation java object!");
+ return NULL;
+ }
+ return ocRepresentationObj;
+}
std::vector<std::string> convertStringVector(JNIEnv *env, jobject jVectorString)
{
env->ReleaseStringUTFChars(jContactInfoObj, buff);
}
-
return vectorString;
}
env->ReleaseStringUTFChars(jMapKeyStr, key);
env->ReleaseStringUTFChars(jMapValueStr, value);
}
-
return mapString;
}
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
******************************************************************/
/**
- * @file Action.java
- *
- * @brief This file contains class which provides functions to retrieve the Action details from a
- * Segment.
+ * @file
+ * This file contains class which provides functions to retrieve the Action
+ * details from a Segment.
*/
package org.iotivity.service.tm;
import android.util.Log;
/**
- * This class provides functions to retrieve the Action details from a
- * Segment.
- *
+ * This class provides functions to retrieve the Action details from a Segment.
*/
public class Action {
private static final String LOG_TAG = "Action";
* uri=coap://10.251.44.228:49858/a/light|power=10)
*
* @return String for a specific action.
- *
*/
public String toString() {
StringBuilder result = new StringBuilder();
/**
* This function parses the Segment value to retrieve sub segments separated
- * by a vertical bar(|): URI and a pair of attribute key and value
+ * by a vertical bar(|): URI and a pair of attribute key and value.
*
* @param actionString
* Segment String
*
* @return Action needed by remote devices as members of a specific group
- *
*/
public static Action toAction(String actionString) {
Action result = new Action();
result.listOfCapability.add(capability);
}
}
-
return result;
}
}
* limitations under the License.
*
******************************************************************/
+
/**
- * @file ActionSet.java
- *
- * @brief This file contains class which provides functions to retrieve ActionSet from plain text.
- *
+ * @file
+ * This file contains class which provides functions to retrieve ActionSet from plain text.
*/
package org.iotivity.service.tm;
import android.util.Log;
/**
- * This class provides functions to retrieve ActionSet from plain text.
- * An ActionSet is a set of descriptions of actions needed by remote
- * devices as members of a specific group. To create an ActionSet, one
- * needs to know the Delimeter serialization.
- *
+ * This class provides functions to retrieve ActionSet from plain text. An
+ * ActionSet is a set of descriptions of actions needed by remote devices as
+ * members of a specific group. To create an ActionSet, one needs to know the
+ * Delimeter serialization.
*/
public class ActionSet extends Time {
/**
* and a pair of attribute key and value.
*
* @return String for a specific action.
- *
*/
@Override
public String toString() {
*
* @return ActionSet which is a set of descriptions of actions needed by
* remote devices as members of a specific group.
- *
*/
public static ActionSet toActionSet(String actionsetString) {
if (0 == actionsetString.length()) {
result.listOfAction.add(action);
}
}
-
return result;
}
}
* limitations under the License.
*
******************************************************************/
+
/**
- * @file Capability.java
- *
- * @brief This file contains class which provides functions to specify an attribute key and value
- * of the target resource
+ * @file
+ * This file contains class which provides functions to specify an attribute key and value
+ * of the target resource.
*
*/
import android.util.Log;
/**
- * This class needs to be created to specify an attribute key and value
- * of the target resource. The attribute key and value are written in
- * capability and status variables of Capability instance class,
- * respectively. After filling the Capability instance, store it to
- * listOfCapability vector variable of Action instance.
- *
+ * This class needs to be created to specify an attribute key and value of the
+ * target resource. The attribute key and value are written in capability and
+ * status variables of Capability instance class, respectively. After filling
+ * the Capability instance, store it to listOfCapability vector variable of
+ * Action instance.
*/
public class Capability {
/**
* This function generates a Capability String.
*
* @return String for a specific Capability.
- *
*/
public String toString() {
StringBuilder result = new StringBuilder();
* Capability in String format.
*
* @return Capability class.
- *
*/
public static Capability toCapability(String capabilityString) {
StringTokenizer tokenizer = new StringTokenizer(capabilityString, "=");
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains class which provides functions
+ * for group management.
+ */
+
+package org.iotivity.service.tm;
+
+import java.util.Vector;
+
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcHeaderOption;
+import org.iotivity.base.OcRepresentation;
+import org.iotivity.base.OcResource;
+import org.iotivity.base.OcResourceHandle;
+
+import android.util.Log;
+
+/**
+ * This class provides a set of APIs relating to Group Management.
+ */
+public class GroupManager {
+
+ private static IFindCandidateResourceListener s_resourceListener;
+ private static ISubscribePresenceListener s_presenceListener;
+ private static IActionListener actionListener;
+
+ private final String LOG_TAG = this.getClass()
+ .getSimpleName();
+
+ // Native methods
+ private static native int nativeFindCandidateResource(
+ Vector<String> resourceTypes, int waitTime);
+
+ private static native int nativeSubscribeCollectionPresence(
+ OcResource resource);
+
+ public static native OcResourceHandle nativeBindResourceToGroup(
+ OcResource resource, OcResourceHandle collectionHandle);
+
+ public static native int nativeAddActionSet(OcResource resource,
+ ActionSet actionSet);
+
+ public static native int nativeExecuteActionSet(OcResource resource,
+ String actionsetName);
+
+ public static native int nativeExecuteActionSetWithDelay(
+ OcResource resource, String actionsetName, long delay);
+
+ public static native int nativeCancelActionSet(OcResource resource,
+ String actionsetName);
+
+ public static native int nativeGetActionSet(OcResource resource,
+ String actionsetName);
+
+ public static native int nativeDeleteActionSet(OcResource resource,
+ String actionsetName);
+
+ static {
+ System.loadLibrary("gnustl_shared");
+ System.loadLibrary("oc_logger");
+ System.loadLibrary("connectivity_abstraction");
+ System.loadLibrary("ca-interface");
+ System.loadLibrary("octbstack");
+ System.loadLibrary("oc");
+ System.loadLibrary("TGMSDKLibrary");
+ System.loadLibrary("ocstack-jni");
+ System.loadLibrary("things-manager-jni");
+ }
+
+ /**
+ * Provides interface for getting notification when resources are discovered
+ * in network.
+ */
+ public interface IFindCandidateResourceListener {
+
+ /**
+ * This callback method will be called whenever resource is discovered
+ * in the network.
+ *
+ * @param resources
+ * List of resources discovered in the network
+ */
+ public void onResourceFoundCallback(Vector<OcResource> resources);
+ }
+
+ /**
+ * Provides interface for getting child resource presence status.
+ */
+ public interface ISubscribePresenceListener {
+
+ /**
+ * This callback method will be called for child resource presence
+ * status.
+ *
+ * @param resource
+ * URI of resource.
+ * @param result
+ * error code.
+ */
+ public void onPresenceCallback(String resource, int result);
+ }
+
+ /**
+ * Provides interface for receiving the callback for the GET, PUT and POST
+ * requested actions.
+ */
+ public interface IActionListener {
+
+ /**
+ * This callback method is called when a asynchronous response for the
+ * getActionSet request is received.
+ *
+ * @param headerOptions
+ * It comprises of optionID and optionData as members.
+ * @param rep
+ * Configuration parameters are carried as a pair of
+ * attribute key and value in a form of OCRepresentation
+ * instance.
+ * @param errorValue
+ * error code.
+ */
+ public void onGetResponseCallback(Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue);
+
+ /**
+ * This callback method is called when a asynchronous response for the
+ * addActionSet request is received.
+ *
+ * @param headerOptions
+ * It comprises of optionID and optionData as members.
+ * @param rep
+ * Configuration parameters are carried as a pair of
+ * attribute key and value in a form of OCRepresentation
+ * instance.
+ * @param errorValue
+ * error code.
+ */
+ public void onPutResponseCallback(Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue);
+
+ /**
+ * This callback method is called when a asynchronous response for the
+ * executeActionSet or deleteActionSet request is received.
+ *
+ * @param headerOptions
+ * It comprises of optionID and optionData as members.
+ * @param rep
+ * Configuration parameters are carried as a pair of
+ * attribute key and value in a form of OCRepresentation
+ * instance.
+ * @param errorValue
+ * error code.
+ */
+ public void onPostResponseCallback(
+ Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
+ int errorValue);
+ }
+
+ /**
+ * Set listener for receiving notification of resource discovery.
+ *
+ * @param listener
+ * IFindCandidateResourceListener to receive the discovered
+ * resources.
+ */
+ public void setFindCandidateResourceListener(
+ IFindCandidateResourceListener listener) {
+ s_resourceListener = listener;
+ }
+
+ /**
+ * Set listener for receiving responses of Get, PUT and POST requests.
+ *
+ * @param listener
+ * IActionListener to receive Get, PUT and POST request
+ * responses.
+ */
+ public void setActionListener(IActionListener listener) {
+ actionListener = listener;
+ }
+
+ /**
+ * Set listener for receiving child resource presence notifications.
+ *
+ * @param listener
+ * ISubscribePresenceListener to receive child resource presence
+ * state.
+ */
+ public void setSubscribePresenceListener(ISubscribePresenceListener listener) {
+ s_presenceListener = listener;
+ }
+
+ /**
+ * API for discovering candidate resources with waiting delay. This
+ * operation returns all resources of given type on the network service.
+ * This operation is sent via multicast to all services. However, the filter
+ * limits the responders to just those that support the resource type in the
+ * query. Currently only exact matches are supported.
+ * <p>
+ * Listener should be set using setFindCandidateResourceListener API
+ * <p>
+ * Listener IFindCandidateResourceListener::onResourceCallback will be
+ * notified when resource is discovered in network.
+ *
+ * @param resourceTypes
+ * required resource types(called "candidate")
+ * @param waitTime
+ * Delay time to add in seconds before starting to find the
+ * resources in network.
+ *
+ * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
+ * code.
+ */
+ public OCStackResult findCandidateResources(Vector<String> resourceTypes,
+ int waitTime) {
+ OCStackResult result;
+ if (null == s_resourceListener) {
+ result = OCStackResult.OC_STACK_ERROR;
+ } else {
+ int ordinal = nativeFindCandidateResource(resourceTypes, waitTime);
+ result = OCStackResult.conversion(ordinal);
+ }
+ return result;
+ }
+
+ /**
+ * API for subscribing child's state. Listener
+ * <p>
+ * ISubscribePresenceListener::onPresenceCallback will be notified for
+ * resource presence status
+ * </p>
+ *
+ * @param resource
+ * collection resource for subscribing presence of all child
+ * resources
+ *
+ * @return OCStackResult - return value of this API. It returns OC_STACK_OK
+ * if success.
+ */
+ public OCStackResult subscribeCollectionPresence(OcResource resource)
+ throws OcException {
+ String LOG_TAG = this.getClass().getSimpleName();
+
+ OCStackResult result;
+ if (null == s_presenceListener) {
+ result = OCStackResult.OC_STACK_ERROR;
+ } else {
+
+ int ordinal = nativeSubscribeCollectionPresence(resource);
+ Log.i(LOG_TAG, "Ordinal value = : " + ordinal);
+ result = OCStackResult.conversion(ordinal);
+ }
+ return result;
+ }
+
+ /**
+ * API for register and bind resource to group.
+ *
+ * @param resource
+ * resource for register and bind to group. It has all data.
+ * @param collectionHandle
+ * collection resource handle. It will be added child resource.
+ *
+ * @return OcResourceHandle - Child resource handle.
+ */
+ public OcResourceHandle bindResourceToGroup(OcResource resource,
+ OcResourceHandle collectionHandle) throws OcException {
+ return nativeBindResourceToGroup(resource, collectionHandle);
+ }
+
+ /**
+ * API for adding a new ActionSet onto a specific resource.
+ *
+ * <p>
+ * Listener should be set using setActionListener API.
+ * <p>
+ * Listener IActionListener::onPutResponseCallback will be notified when the
+ * response of PUT operation arrives.
+ *
+ * @param resource
+ * resource pointer of the group resource
+ * @param actionSet
+ * pointer of ActionSet
+ *
+ * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
+ * code.
+ */
+ public OCStackResult addActionSet(OcResource resource, ActionSet actionSet)
+ throws OcException {
+ if (null == actionListener) {
+ Log.e(LOG_TAG, "addActionSet: listener not set!");
+ return OCStackResult.OC_STACK_LISTENER_NOT_SET;
+ }
+ int ordinal = nativeAddActionSet(resource, actionSet);
+
+ return OCStackResult.conversion(ordinal);
+ }
+
+ /**
+ * API for executing a specific ActionSet belonging to a specific resource.
+ *
+ * <p>
+ * Listener should be set using setActionListener API.
+ * <p>
+ * Listener IActionListener::onPostResponseCallback will be notified when
+ * the response of POST operation arrives.
+ *
+ * @param resource
+ * resource pointer of the group resource
+ * @param actionsetName
+ * ActionSet name for removing the ActionSet
+ *
+ * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
+ * code.
+ */
+ public OCStackResult executeActionSet(OcResource resource,
+ String actionsetName) throws OcException {
+ if (null == actionListener) {
+ Log.e(LOG_TAG, "executeActionSet: listener not set!");
+ return OCStackResult.OC_STACK_LISTENER_NOT_SET;
+ }
+
+ int ordinal = nativeExecuteActionSet(resource, actionsetName);
+
+ return OCStackResult.conversion(ordinal);
+ }
+
+ /**
+ * API for executing a specific ActionSet belonging to a specific resource.
+ *
+ * <p>
+ * Listener should be set using setActionListener API.
+ * <p>
+ * Listener IActionListener::onPostResponseCallback will be notified when
+ * the response of POST operation arrives.
+ *
+ * @param resource
+ * resource pointer of the group resource
+ * @param actionsetName
+ * ActionSet name for removing the ActionSet
+ * @param delay
+ * Wait time for the ActionSet execution
+ *
+ * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
+ * code.
+ */
+ public OCStackResult executeActionSet(OcResource resource,
+ String actionsetName, long delay) throws OcException {
+ if (null == actionListener) {
+ Log.e(LOG_TAG, "executeActionSet: listener not set!");
+ return OCStackResult.OC_STACK_LISTENER_NOT_SET;
+ }
+
+ OCStackResult result;
+ int ordinal = nativeExecuteActionSetWithDelay(resource, actionsetName,
+ delay);
+ result = OCStackResult.conversion(ordinal);
+
+ return result;
+ }
+
+ /**
+ * API to cancel the existing ActionSet.
+ *
+ * <p>
+ * Listener should be set using setActionListener API.
+ * <p>
+ * Listener IActionListener::onPostResponseCallback will be notified when
+ * the response of POST operation arrives.
+ *
+ * @param resource
+ * resource pointer of the group resource.
+ * @param actionsetName
+ * ActionSet name that has to be cancelled.
+ *
+ * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
+ * code.
+ */
+
+ public OCStackResult cancelActionSet(OcResource resource,
+ String actionsetName) throws OcException {
+ if (null == actionListener) {
+ Log.e(LOG_TAG, "cancelActionSet: listener not set!");
+ return OCStackResult.OC_STACK_LISTENER_NOT_SET;
+ }
+
+ OCStackResult result;
+ int ordinal = nativeCancelActionSet(resource, actionsetName);
+ result = OCStackResult.conversion(ordinal);
+
+ return result;
+ }
+
+ /**
+ * API to to get an existing ActionSet belonging to a specific resource.
+ *
+ * <p>
+ * Listener should be set using setActionListener API.
+ * <p>
+ * Listener IActionListener::onPostResponseCallback will be notified when
+ * the response of POST operation arrives.
+ *
+ * @param resource
+ * resource pointer of the group resource
+ * @param actionsetName
+ * ActionSet name for removing the ActionSet
+ *
+ * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
+ * code.
+ */
+ public OCStackResult getActionSet(OcResource resource, String actionsetName)
+ throws OcException {
+ if (null == actionListener) {
+ Log.e(LOG_TAG, "getActionSet: listener not set!");
+ return OCStackResult.OC_STACK_LISTENER_NOT_SET;
+ }
+
+ OCStackResult result;
+ int ordinal = nativeGetActionSet(resource, actionsetName);
+ result = OCStackResult.conversion(ordinal);
+
+ return result;
+ }
+
+ /**
+ * API to delete an existing ActionSet belonging to a specific resource.
+ *
+ * <p>
+ * Listener should be set using setActionListener API.
+ * <p>
+ * Listener IActionListener::onPutResponseCallback will be notified when the
+ * response of PUT operation arrives.
+ *
+ * @param resource
+ * resource pointer of the group resource
+ * @param actionsetName
+ * ActionSet name for removing the ActionSet
+ *
+ * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
+ * code.
+ */
+ public OCStackResult deleteActionSet(OcResource resource,
+ String actionsetName) throws OcException {
+ if (null == actionListener) {
+ Log.e(LOG_TAG, "deleteActionSet: listener not set!");
+ return OCStackResult.OC_STACK_LISTENER_NOT_SET;
+ }
+
+ OCStackResult result;
+ int ordinal = nativeDeleteActionSet(resource, actionsetName);
+ result = OCStackResult.conversion(ordinal);
+
+ return result;
+ }
+
+ // ******** JNI UTILITY FUNCTIONS **********//
+
+ /*
+ * This callback method will be called from JNI whenever resource is
+ * discovered in the network.
+ */
+ private static void onResourceFoundCallback(Vector<OcResource> resources) {
+ if (null != s_resourceListener)
+ s_resourceListener.onResourceFoundCallback(resources);
+ }
+
+ /*
+ * This callback method is called from JNI for child resource presence
+ * status.
+ */
+ private static void onPresenceCallback(String resource, int errorValue) {
+ if (null != s_presenceListener) {
+ Log.i("ThingsManagerCallback : onPresenceCallback",
+ "Received Callback from JNI");
+ s_presenceListener.onPresenceCallback(resource, errorValue);
+ }
+ }
+
+ /*
+ * This callback method is called from JNI when a response for the
+ * executeActionSet or deleteActionSet request just arrives.
+ */
+ private static void onPostResponseCallback(
+ Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
+ int errorValue) {
+ if (null != actionListener)
+ actionListener.onPostResponseCallback(headerOptions, rep,
+ errorValue);
+ }
+
+ /*
+ * This callback method is called from JNI when a response for the
+ * addActionSet request just arrives.
+ */
+ private static void onPutResponseCallback(
+ Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
+ int errorValue) {
+ if (null != actionListener)
+ actionListener
+ .onPutResponseCallback(headerOptions, rep, errorValue);
+ }
+
+ /*
+ * This callback method is called from JNI when a response for the
+ * getActionSet request just arrives.
+ */
+ private static void onGetResponseCallback(
+ Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
+ int errorValue) {
+ if (null != actionListener)
+ actionListener
+ .onGetResponseCallback(headerOptions, rep, errorValue);
+ }
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains class which provides functions
+ * related to Group Synchronization.
+ */
+
+package org.iotivity.service.tm;
+
+import java.util.Map;
+import java.util.Vector;
+
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcResource;
+import org.iotivity.base.OcResourceHandle;
+
+import android.util.Log;
+
+/**
+ * This class provides a set of APIs relating to Group Synchronization.
+ */
+public class GroupSynchronization {
+
+ private IFindGroupListener groupListener;
+ private final String LOG_TAG = this.getClass()
+ .getSimpleName();
+
+ private static GroupSynchronization s_groupSynchronizationInstance;
+
+ // Native methods
+ private static native int nativeFindGroup(
+ Vector<String> collectionResourceTypes);
+
+ private static native int nativeCreateGroup(String collectionResourceType);
+
+ private static native int nativeJoinGroupString(
+ String collectionResourceType, OcResourceHandle resourceHandle);
+
+ private static native int nativeJoinGroupObject(OcResource resource,
+ OcResourceHandle resourceHandle);
+
+ private static native int nativeLeaveGroup(String collectionResourceType,
+ OcResourceHandle resourceHandle);
+
+ private static native int nativeLeaveGroupForResource(OcResource resource,
+ String collectionResourceType, OcResourceHandle resourceHandle);
+
+ private static native void nativeDeleteGroup(String collectionResourceType);
+
+ private static native Map<String, OcResourceHandle> nativeGetGroupList();
+
+ static {
+ System.loadLibrary("gnustl_shared");
+ System.loadLibrary("oc_logger");
+ System.loadLibrary("connectivity_abstraction");
+ System.loadLibrary("ca-interface");
+ System.loadLibrary("octbstack");
+ System.loadLibrary("oc");
+ System.loadLibrary("TGMSDKLibrary");
+ System.loadLibrary("ocstack-jni");
+ System.loadLibrary("things-manager-jni");
+ }
+
+ /**
+ * Function for Getting instance of GroupSynchronization object.
+ *
+ * @return GroupSynchronization instance.
+ */
+ public static GroupSynchronization getInstance() {
+ if (null == s_groupSynchronizationInstance) {
+ s_groupSynchronizationInstance = new GroupSynchronization();
+ }
+ return s_groupSynchronizationInstance;
+ }
+
+ /**
+ * Provides interface for getting group discovery status.
+ */
+ public interface IFindGroupListener {
+ /**
+ * This callback method will be called to notify whether group is found
+ * or not.
+ *
+ * @param resource
+ * URI of resource.
+ */
+ public void onGroupFindCallback(OcResource resource);
+ }
+
+ /**
+ * Set listener for receiving notification on whether the requested group is
+ * found or not.
+ *
+ * @param listener
+ * IFindGroupListener to receive group discovery status.
+ */
+ public void setGroupListener(IFindGroupListener listener) {
+ groupListener = listener;
+ }
+
+ /**
+ * API for finding a specific remote group when a resource tries to join a
+ * group.
+ * <p>
+ * IFindGroupListener::onGroupFindCallback will be called to notify whether
+ * requested group found or not.
+ * </p>
+ *
+ * @param resourceTypes
+ * resource types of a group to find and join
+ *
+ * @return OCStackResult - return value of this API. It returns OC_STACK_OK
+ * if success.
+ */
+ public OCStackResult findGroup(Vector<String> resourceTypes) {
+ OCStackResult result;
+ if (null == groupListener) {
+ result = OCStackResult.OC_STACK_ERROR;
+ } else {
+ int ordinal = nativeFindGroup(resourceTypes);
+ result = OCStackResult.conversion(ordinal);
+ }
+ return result;
+ }
+
+ /**
+ * API for creating a new group.
+ *
+ * @param resourceType
+ * resource type of a group to create
+ *
+ * @return OCStackResult - return value of this API. It returns OC_STACK_OK
+ * if success.
+ */
+ public OCStackResult createGroup(String resourceType) {
+ OCStackResult result;
+ int ordinal = nativeCreateGroup(resourceType);
+ result = OCStackResult.conversion(ordinal);
+ return result;
+ }
+
+ /**
+ * API for joining a group. This API is used when a resource that has a
+ * group tries to find a specific remote resource and makes it join a group.
+ *
+ * @param resourceType
+ * resource type of a group to join.
+ * @param resourceHandle
+ * resource handle to join a group.
+ *
+ * @return OCStackResult - return value of this API. It returns OC_STACK_OK
+ * if success.
+ */
+ public OCStackResult joinGroup(String resourceType,
+ OcResourceHandle resourceHandle) {
+ OCStackResult result;
+
+ int ordinal = nativeJoinGroupString(resourceType, resourceHandle);
+ result = OCStackResult.conversion(ordinal);
+
+ return result;
+ }
+
+ /**
+ * API for joining a group. This API is used when a resource that doesn't
+ * have a group tries to find and join a specific remote group.
+ *
+ * @param resource
+ * group resource to join.
+ * @param resourceHandle
+ * resource handle to join a group.
+ *
+ * @return OCStackResult - return value of this API. It returns OC_STACK_OK
+ * if success.
+ */
+ public OCStackResult joinGroup(OcResource resource,
+ OcResourceHandle resourceHandle) throws OcException {
+
+ OCStackResult result;
+ int ordinal = nativeJoinGroupObject(resource, resourceHandle);
+ result = OCStackResult.conversion(ordinal);
+
+ return result;
+ }
+
+ /**
+ * API for leaving a joined group.
+ *
+ * @param resourceType
+ * resource type of a group to leave.
+ * @param resourceHandle
+ * resource handle to leave a group.
+ *
+ * @return OCStackResult - return value of this API. It returns OC_STACK_OK
+ * if success.
+ */
+ public OCStackResult leaveGroup(String resourceType,
+ OcResourceHandle resourceHandle) {
+
+ OCStackResult result;
+ int ordinal = nativeLeaveGroup(resourceType, resourceHandle);
+ result = OCStackResult.conversion(ordinal);
+
+ return result;
+ }
+
+ /**
+ * API for leaving a joined group.
+ *
+ * @param resource
+ * resource of a group to leave.
+ * @param resourceType
+ * resource type of a group to leave.
+ * @param resourceHandle
+ * resource handle to leave a group.
+ *
+ * @return OCStackResult - return value of this API. It returns OC_STACK_OK
+ * if success.
+ */
+ public OCStackResult leaveGroup(OcResource resource, String resourceType,
+ OcResourceHandle resourceHandle) {
+
+ OCStackResult result;
+ int ordinal = nativeLeaveGroupForResource(resource, resourceType,
+ resourceHandle);
+ result = OCStackResult.conversion(ordinal);
+
+ return result;
+ }
+
+ /**
+ * API for deleting a group.
+ *
+ * @param collectionResourceType
+ * resource type of a group to delete.
+ */
+ public void deleteGroup(String collectionResourceType) {
+ nativeDeleteGroup(collectionResourceType);
+ }
+
+ /**
+ * API for getting a list of joined groups.
+ *
+ * @return Returns group resource type and group resource handle as a map
+ * table.
+ */
+ public Map<String, OcResourceHandle> getGroupList() {
+ return nativeGetGroupList();
+ }
+
+ // ******** JNI UTILITY FUNCTION **********//
+
+ /*
+ * This callback method is called from JNI to notify whether group is found
+ * or not.
+ */
+ public void onGroupFindCallback(OcResource resource) {
+ if (null != groupListener) {
+ Log.i("ThingsManagerCallback : onGroupFindCallback",
+ "Received Callback from JNI");
+ groupListener.onGroupFindCallback(resource);
+ }
+ }
+}
+++ /dev/null
-/******************************************************************
- *
- * 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.
- *
- ******************************************************************/
-
-/**
- * @file IActionListener.java
- *
- * @brief This file provides interface for receiving the callback for the GET, PUT and POST requested
- * actions.
- *
- */
-
-package org.iotivity.service.tm;
-
-import java.util.Vector;
-
-import org.iotivity.base.OcHeaderOption;
-import org.iotivity.base.OcRepresentation;
-
-/**
- * Provides interface for receiving the callback for the GET, PUT and
- * POST requested actions.
- */
-public interface IActionListener {
- /**
- * This callback method is called when a asynchronous response for the getActionSet
- * request is received.
- *
- * @param headerOptions
- * It comprises of optionID and optionData as members.
- * @param rep
- * Configuration parameters are carried as a pair of attribute
- * key and value in a form of OCRepresentation instance.
- * @param errorValue
- * error code.
- *
- */
- public void onGetResponseCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue);
-
- /**
- * This callback method is called when a asynchronous response for the addActionSet
- * request is received.
- *
- * @param headerOptions
- * It comprises of optionID and optionData as members.
- * @param rep
- * Configuration parameters are carried as a pair of attribute
- * key and value in a form of OCRepresentation instance.
- * @param errorValue
- * error code.
- *
- */
- public void onPutResponseCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue);
-
- /**
- * This callback method is called when a asynchronous response for the executeActionSet
- * or deleteActionSet request is received.
- *
- * @param headerOptions
- * It comprises of optionID and optionData as members.
- * @param rep
- * Configuration parameters are carried as a pair of attribute
- * key and value in a form of OCRepresentation instance.
- * @param errorValue
- * error code.
- *
- */
- public void onPostResponseCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue);
-}
+++ /dev/null
-/******************************************************************
- *
- * 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.
- *
- ******************************************************************/
-
-/**
- * @file IConfigurationListener.java
- *
- * @brief This file provides interface for receiving asynchronous response for
- * configuration APIs.
- */
-
-package org.iotivity.service.tm;
-
-import java.util.Vector;
-
-import org.iotivity.base.OcHeaderOption;
-import org.iotivity.base.OcRepresentation;
-
-/**
- * Provides interface for receiving asynchronous response for
- * configuration APIs.
- */
-public interface IConfigurationListener {
- /**
- * Asynchronous response callback for ThingsManager::doBootstrap API.
- */
- public void onBootStrapCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue);
-
- /**
- * Asynchronous response callback for ThingsManager::updateConfigurations
- * API.
- */
- public void onUpdateConfigurationsCallback(
- Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
- int errorValue);
-
- /**
- * Asynchronous response callback for ThingsManager::getConfigurations API.
- */
- public void onGetConfigurationsCallback(
- Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
- int errorValue);
-}
+++ /dev/null
-/******************************************************************
- *
- * 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.
- *
- ******************************************************************/
-
-/**
- * @file IDiagnosticsListener.java
- *
- * @brief This file provides interface for receiving asynchronous response for
- * diagnostic feature APIs.
- */
-
-package org.iotivity.service.tm;
-
-import java.util.Vector;
-
-import org.iotivity.base.OcHeaderOption;
-import org.iotivity.base.OcRepresentation;
-
-/**
- * Provides interface for receiving asynchronous response for diagnostic
- * feature APIs.
- */
-public interface IDiagnosticsListener {
- /**
- * Asynchronous response callback for ThingsManager::reboot API.
- */
- public void onRebootCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue);
-
- /**
- * Asynchronous response callback for ThingsManager::factoryReset API.
- */
- public void onFactoryResetCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue);
-}
-/******************************************************************
+/* *****************************************************************
*
* Copyright 2015 Samsung Electronics All Rights Reserved.
*
* limitations under the License.
*
******************************************************************/
+
/**
- * @file OCStackResult.java
- *
- * @brief This file provides a Enum which contains Status codes for Success and Errors
- *
+ * @file
+ * This file provides a Enum which contains Status codes
+ * for Success and Errors
*/
package org.iotivity.service.tm;
* This Enum contains Status codes for Success and Errors
*/
public enum OCStackResult {
+
OC_STACK_OK,
OC_STACK_RESOURCE_CREATED,
OC_STACK_RESOURCE_DELETED,
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains class which provides functions for
+ * things configuration.
+ */
+
+package org.iotivity.service.tm;
+
+import java.util.Map;
+import java.util.Vector;
+
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcHeaderOption;
+import org.iotivity.base.OcRepresentation;
+import org.iotivity.base.OcResource;
+
+import android.util.Log;
+
+/**
+ * This class provides a set of APIs relating to Things Configuration.
+ */
+public class ThingsConfiguration {
+
+ private IConfigurationListener configurationListener;
+ private static ThingsConfiguration s_thingsConfigurationInstance;
+ private final String LOG_TAG = this.getClass()
+ .getSimpleName();
+
+ // Native Methods
+ private static native int nativeUpdateConfigurations(OcResource resource,
+ Map<String, String> configurations);
+
+ private static native int nativeGetConfigurations(OcResource resource,
+ Vector<String> configurations);
+
+ private static native String nativeGetListOfSupportedConfigurationUnits();
+
+ private static native int nativeDoBootstrap();
+
+ /**
+ * Function for Getting instance of ThingsConfiguration object.
+ *
+ * @return ThingsConfiguration instance.
+ *
+ */
+ public static ThingsConfiguration getInstance() {
+ if (null == s_thingsConfigurationInstance) {
+ s_thingsConfigurationInstance = new ThingsConfiguration();
+ }
+ return s_thingsConfigurationInstance;
+ }
+
+ /**
+ * Provides interface for receiving asynchronous response for configuration
+ * APIs.
+ */
+ public interface IConfigurationListener {
+ /**
+ * Asynchronous response callback for doBootstrap API.
+ *
+ * @param headerOptions
+ * It comprises of optionID and optionData as members.
+ * @param rep
+ * Configuration parameters are carried as a pair of
+ * attribute key and value in a form of OCRepresentation
+ * instance.
+ * @param errorValue
+ * error code.
+ */
+ public void onBootStrapCallback(Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue);
+
+ /**
+ * Asynchronous response callback for updateConfigurations API.
+ *
+ * @param headerOptions
+ * It comprises of optionID and optionData as members.
+ * @param rep
+ * Configuration parameters are carried as a pair of
+ * attribute key and value in a form of OCRepresentation
+ * instance.
+ * @param errorValue
+ * error code.
+ */
+ public void onUpdateConfigurationsCallback(
+ Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
+ int errorValue);
+
+ /**
+ * Asynchronous response callback for getConfigurations API.
+ *
+ * @param headerOptions
+ * It comprises of optionID and optionData as members.
+ * @param rep
+ * Configuration parameters are carried as a pair of
+ * attribute key and value in a form of OCRepresentation
+ * instance.
+ * @param errorValue
+ * error code.
+ */
+ public void onGetConfigurationsCallback(
+ Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
+ int errorValue);
+ }
+
+ /**
+ * Set listener for receiving asynchronous response for configuration APIs.
+ *
+ * @param listener
+ * IConfigurationListener to receive asynchronous response for
+ * configuration APIs.
+ */
+ public void setConfigurationListener(IConfigurationListener listener) {
+ configurationListener = listener;
+ }
+
+ /**
+ * API for updating configuration value of multiple things of a target group
+ * or a single thing to a resource server(s).
+ *
+ * <p>
+ * Listener should be set using setConfigurationListener API.
+ * <p>
+ * Listener IConfigurationListener::onUpdateConfigurationsCallback will be
+ * notified when the response of update configuration arrives.
+ *
+ * @param resource
+ * resource representing the target group or the single thing. It
+ * is a pointer of resource instance of Configuration resource.
+ * The resource pointer can be acquired by performing
+ * findResource() function with a dedicated resource type,
+ * "oic.con". Note that, the resource pointer represents not only
+ * a single simple resource but also a collection resource
+ * composing multiple simple resources. In other words, using
+ * these APIs, developers can send a series of requests to
+ * multiple things by calling the corresponding function at once.
+ * @param configurations
+ * ConfigurationUnit: a nickname of attribute of target resource
+ * (e.g., installed location, currency, (IP)address) Value : a
+ * value to be updated. It represents an indicator of which
+ * resource developers want to access and which value developers
+ * want to update. Basically, developers could use a resource URI
+ * to access a specific resource but a resource URI might be hard
+ * for all developers to memorize lots of URIs, especially in the
+ * case of long URIs. To relieve the problem, Things
+ * Configuration introduces a easy-memorizing name, called
+ * ConfigurationName, instead of URI. And ConfigurationValue used
+ * in updateConfiguration() function indicates a value to be
+ * updated. Note that, only one configuration parameter is
+ * supported in this release. Multiple configuration parameters
+ * will be supported in future release.
+ *
+ * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
+ * code.
+ */
+ public OCStackResult updateConfigurations(OcResource resource,
+ Map<String, String> configurations) throws OcException {
+ OCStackResult result;
+ if (null == configurationListener) {
+ result = OCStackResult.OC_STACK_ERROR;
+ } else {
+ int ordinal = nativeUpdateConfigurations(resource, configurations);
+ result = OCStackResult.conversion(ordinal);
+ }
+ return result;
+ }
+
+ /**
+ * API for getting configuration value of multiple things of a target group
+ * or a single thing.To get a value, users need to know a Configuration Name
+ * indicating the target resource. In this release, the Configuration Name
+ * is "configuration".An update value is not needed. After that, users store
+ * them in form of a Vector and then use a getConfigurations() function.
+ *
+ * @param resource
+ * resource representing the target group or the single thing.
+ * @param configurations
+ * ConfigurationUnit: a nickname of attribute of target resource.
+ *
+ * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
+ * code.
+ */
+ public OCStackResult getConfigurations(OcResource resource,
+ Vector<String> configurations) throws OcException {
+ OCStackResult result;
+ if (null == configurationListener) {
+ result = OCStackResult.OC_STACK_ERROR;
+ } else {
+ int ordinal = nativeGetConfigurations(resource, configurations);
+ result = OCStackResult.conversion(ordinal);
+ }
+ return result;
+ }
+
+ /**
+ * API for getting the list of supported configuration units (configurable
+ * parameters). It shows which Configuration Names are supported and their
+ * brief descriptions. This information is provided in JSON format.
+ *
+ * @return Returns the configuration list in JSON format.
+ */
+ public String getListOfSupportedConfigurationUnits() {
+ return nativeGetListOfSupportedConfigurationUnits();
+ }
+
+ /**
+ * API for bootstrapping system configuration parameters from a bootstrap
+ * server.
+ * <p>
+ * Listener should be set using setConfigurationListener API.
+ * <p>
+ * Listener IConfigurationListener::onBootStrapCallback will be notified
+ * when the response arrives.
+ *
+ * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
+ * code.
+ */
+ public OCStackResult doBootstrap() {
+ if (null == configurationListener) {
+ Log.e(LOG_TAG, "doBootstrap: listener not set!");
+ return OCStackResult.OC_STACK_LISTENER_NOT_SET;
+ }
+
+ OCStackResult result;
+ int ordinal = nativeDoBootstrap();
+ result = OCStackResult.conversion(ordinal);
+ return result;
+ }
+
+ // ******** JNI UTILITY FUNCTIONS **********//
+
+ /*
+ * This callback method is called from JNI when a response for the
+ * updateConfigurations request just arrives.
+ */
+ public void onUpdateConfigurationsCallback(
+ Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
+ int errorValue) {
+ if (null != configurationListener)
+ configurationListener.onUpdateConfigurationsCallback(headerOptions,
+ rep, errorValue);
+ }
+
+ /*
+ * This callback method is called from JNI when a response for the
+ * getConfigurations request just arrives.
+ */
+ public void onGetConfigurationsCallback(
+ Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
+ int errorValue) {
+ if (null != configurationListener)
+ configurationListener.onGetConfigurationsCallback(headerOptions,
+ rep, errorValue);
+ }
+
+ /*
+ * This callback method is called from JNI when a response for the
+ * doBootstrap request just arrives.
+ */
+ public void onBootStrapCallback(Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue) {
+ if (null != configurationListener) {
+ Log.i("ThingsManagerCallback : onBootStrapCallback",
+ "Received Callback from JNI");
+ configurationListener.onBootStrapCallback(headerOptions, rep,
+ errorValue);
+ }
+ }
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
+/**
+ * @file
+ * This file contains class which provides functions
+ * for things maintenance.
+ */
+
+package org.iotivity.service.tm;
+
+import java.util.Vector;
+
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcHeaderOption;
+import org.iotivity.base.OcRepresentation;
+import org.iotivity.base.OcResource;
+
+import android.util.Log;
+
+/**
+ * This class provides a set of APIs relating to Things Maintenance.
+ */
+public class ThingsMaintenance {
+
+ private IThingsMaintenanceListener thingsMaintenanceListener;
+ private static ThingsMaintenance s_thingsMaintenanceInstance;
+ private final String LOG_TAG = this.getClass()
+ .getSimpleName();
+
+ // Native methods
+ private static native int nativeReboot(OcResource resource);
+
+ private static native int nativeFactoryReset(OcResource resource);
+
+ private static native String nativeGetListOfSupportedMaintenanceUnits();
+
+ /**
+ * Function for Getting instance of ThingsMaintenance object.
+ *
+ * @return ThingsMaintenance instance.
+ */
+ public static ThingsMaintenance getInstance() {
+ if (null == s_thingsMaintenanceInstance) {
+ s_thingsMaintenanceInstance = new ThingsMaintenance();
+ }
+ return s_thingsMaintenanceInstance;
+ }
+
+ /**
+ * Provides interface for receiving asynchronous response for Things
+ * Maintenance feature APIs.
+ */
+ public interface IThingsMaintenanceListener {
+ /**
+ * Asynchronous response callback for reboot API.
+ *
+ * @param headerOptions
+ * It comprises of optionID and optionData as members.
+ * @param rep
+ * Configuration parameters are carried as a pair of
+ * attribute key and value in a form of OCRepresentation
+ * instance.
+ * @param errorValue
+ * error code.
+ */
+ public void onRebootCallback(Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue);
+
+ /**
+ * Asynchronous response callback for factoryReset API.
+ *
+ * @param headerOptions
+ * It comprises of optionID and optionData as members.
+ * @param rep
+ * Configuration parameters are carried as a pair of
+ * attribute key and value in a form of OCRepresentation
+ * instance.
+ * @param errorValue
+ * error code.
+ */
+ public void onFactoryResetCallback(
+ Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
+ int errorValue);
+ }
+
+ /**
+ * Set listener for receiving asynchronous response for Things Maintenance
+ * APIs.
+ *
+ * @param listener
+ * IThingsMaintenanceListener to receive asynchronous response
+ * for diagnostic feature APIs.
+ */
+ public void setThingsMaintenanceListener(IThingsMaintenanceListener listener) {
+ thingsMaintenanceListener = listener;
+ }
+
+ /**
+ * API to is used to send a request to a server(thing or device) to be
+ * rebooted. On receiving the request, the server attempts to reboot itself
+ * in a deterministic time. The target thing could be a group of multiple
+ * things or a single thing.
+ * <p>
+ * Listener should be set using setDiagnosticsListener API.
+ * <p>
+ * Listener IThingsMaintenanceListener::onRebootCallback will be notified
+ * when the response arrives.
+ *
+ * @param resource
+ * resource pointer representing the target group
+ *
+ * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
+ * code.
+ */
+ public OCStackResult reboot(OcResource resource) throws OcException {
+
+ OCStackResult result;
+ int ordinal = nativeReboot(resource);
+ result = OCStackResult.conversion(ordinal);
+
+ return result;
+ }
+
+ /**
+ * API to restore all configuration parameters to default one on
+ * thing(device). All configuration parameters refers Configuration
+ * resource, which they could have been modified for various reasons (e.g.,
+ * for a request to update a value). If developers on the client want to
+ * restore the parameters, just use the factoryReset function.The target
+ * thing could be a group of multiple things or a single thing.
+ *
+ * <p>
+ * Listener should be set using setDiagnosticsListener API.
+ * <p>
+ * Listener IThingsMaintenanceListener::onFactoryResetCallback will be
+ * notified when the response arrives.
+ *
+ * @param resource
+ * resource pointer representing the target group
+ *
+ * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
+ * code.
+ */
+ public OCStackResult factoryReset(OcResource resource) throws OcException {
+
+ OCStackResult result;
+ int ordinal = nativeFactoryReset(resource);
+ result = OCStackResult.conversion(ordinal);
+
+ return result;
+ }
+
+ /**
+ * This callback method is called when a response for the reboot request
+ * just arrives.
+ *
+ * @param headerOptions
+ * It comprises of optionID and optionData as members.
+ * @param rep
+ * Configuration parameters are carried as a pair of attribute
+ * key and value in a form of OCRepresentation instance.
+ * @param errorValue
+ * error code.
+ */
+ public void onRebootCallback(Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue) {
+ if (null != thingsMaintenanceListener) {
+ Log.i("ThingsManagerCallback : onRebootCallback",
+ "Received Callback from JNI");
+ thingsMaintenanceListener.onRebootCallback(headerOptions, rep,
+ errorValue);
+ }
+ }
+
+ /**
+ * This callback method is called when a response for the factoryReset
+ * request just arrives.
+ *
+ * @param headerOptions
+ * It comprises of optionID and optionData as members.
+ * @param rep
+ * Configuration parameters are carried as a pair of attribute
+ * key and value in a form of OCRepresentation instance.
+ * @param errorValue
+ * error code.
+ */
+ public void onFactoryResetCallback(Vector<OcHeaderOption> headerOptions,
+ OcRepresentation rep, int errorValue) {
+ if (null != thingsMaintenanceListener) {
+ Log.i("ThingsManagerCallback : onFactoryResetCallback",
+ "Received Callback from JNI");
+ thingsMaintenanceListener.onFactoryResetCallback(headerOptions,
+ rep, errorValue);
+ }
+ }
+
+ /**
+ * API for getting the list of supported Maintenance units. It shows which
+ * Maintenance Names are supported and their brief descriptions. This
+ * information is provided in JSON format.
+ *
+ * @return Returns the configuration list in JSON format.
+ */
+ public String getListOfSupportedMaintenanceUnits() {
+ return nativeGetListOfSupportedMaintenanceUnits();
+ }
+}
+++ /dev/null
-/******************************************************************
- *
- * 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.
- *
- ******************************************************************/
-/**
- * @file ThingsManager.java
- *
- * @brief This file provides a class for a set of APIs relating to group management,
- * synchronization of group, configuration of things, and diagnostics
- * about things.
- *
- */
-
-package org.iotivity.service.tm;
-
-import java.util.Map;
-import java.util.Vector;
-
-import org.iotivity.base.OcException;
-import org.iotivity.base.OcResource;
-import org.iotivity.base.OcResourceHandle;
-
-import android.util.Log;
-
-/**
- * This class provides a set of APIs relating to group management,
- * synchronization of group, configuration of things, and diagnostics
- * about things.
- *
- */
-public class ThingsManager {
-
- private IFindCandidateResourceListener resourceListener;
- private ISubscribePresenceListener presenceListener;
- private IFindGroupListener groupListener;
- private IConfigurationListener configurationListener;
- private IDiagnosticsListener diagnosticsListener;
- private IActionListener actionListener;
- private final String LOG_TAG = this.getClass()
- .getSimpleName();
-
- private final ThingsManagerCallback thingsManagerCallbackInterfaceObj;
- private final ThingsManagerInterface thingsManagerInterfaceObj;
-
- static {
- System.loadLibrary("gnustl_shared");
- System.loadLibrary("oc_logger");
- System.loadLibrary("connectivity_abstraction");
- System.loadLibrary("ca-interface");
- System.loadLibrary("octbstack");
- System.loadLibrary("oc");
- System.loadLibrary("TGMSDKLibrary");
- System.loadLibrary("ocstack-jni");
- System.loadLibrary("things-manager-jni");
- }
-
- /**
- * Constructor for ThingsManager. Constructs a new ThingsManager.
- */
- public ThingsManager() {
- thingsManagerCallbackInterfaceObj = ThingsManagerCallback.getInstance();
- thingsManagerInterfaceObj = ThingsManagerInterface.getInstance();
- }
-
- /**
- * Set listener for receiving notification of resource discovery.
- *
- * @param listener
- * IFindCandidateResourceListener to receive the
- * discovered resources.
- */
- public void setFindCandidateResourceListener(
- IFindCandidateResourceListener listener) {
- resourceListener = listener;
- thingsManagerCallbackInterfaceObj
- .registerFindCandidateResourceListener(listener);
- thingsManagerInterfaceObj
- .registerFindCandidateResourceListener(listener);
- }
-
- /**
- * Set listener for receiving child resource presence notifications.
- *
- * @param listener
- * ISubscribePresenceListener to receive child resource
- * presence state.
- */
- public void setSubscribePresenceListener(ISubscribePresenceListener listener) {
- presenceListener = listener;
- thingsManagerCallbackInterfaceObj
- .registerSubscribePresenceListener(listener);
- thingsManagerInterfaceObj.registerSubscribePresenceListener(listener);
- }
-
- /**
- * Set listener for receiving notification on whether the requested group is
- * found or not.
- *
- * @param listener
- * IFindGroupListener to receive group discovery status.
- */
- public void setGroupListener(IFindGroupListener listener) {
- groupListener = listener;
- thingsManagerCallbackInterfaceObj.registerGroupListener(listener);
- thingsManagerInterfaceObj.registerGroupListener(listener);
- }
-
- /**
- * Set listener for receiving asynchronous response for configuration APIs.
- *
- * @param listener
- * IConfigurationListener to receive asynchronous response
- * for configuration APIs.
- */
- public void setConfigurationListener(IConfigurationListener listener) {
- configurationListener = listener;
- thingsManagerCallbackInterfaceObj
- .registerConfigurationListener(listener);
- thingsManagerInterfaceObj.registerConfigurationListener(listener);
- }
-
- /**
- * Set listener for receiving asynchronous response for diagnostic feature
- * APIs.
- *
- * @param listener
- * IDiagnosticsListener to receive asynchronous response
- * for diagnostic feature APIs.
- */
- public void setDiagnosticsListener(IDiagnosticsListener listener) {
- diagnosticsListener = listener;
- thingsManagerCallbackInterfaceObj.registerDiagnosticsListener(listener);
- }
-
- /**
- * Set listener for receiving responses of Get, PUT and POST requests.
- *
- * @param listener
- * IActionListener to receive Get, PUT and POST request
- * responses.
- */
- public void setActionListener(IActionListener listener) {
- actionListener = listener;
- thingsManagerCallbackInterfaceObj.registerActionListener(listener);
- }
-
- /**
- * API for discovering candidate resources with waiting delay. This
- * operation returns all resources of given type on the network service.
- * This operation is sent via multicast to all services. However, the filter
- * limits the responders to just those that support the resource type in the
- * query. Currently only exact matches are supported.
- * <p>
- * Listener should be set using setFindCandidateResourceListener API
- * <p>
- * Listener IFindCandidateResourceListener::onResourceCallback
- * will be notified when resource is discovered in network.
- *
- * @param resourceTypes
- * required resource types(called "candidate")
- * @param waitTime
- * Delay time to add in seconds before starting to find the
- * resources in network.
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult findCandidateResources(Vector<String> resourceTypes,
- int waitTime) {
- if (null == resourceListener) {
- Log.e(LOG_TAG,"findCandidateResources: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj.findCandidateResources(
- resourceTypes, waitTime);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "findCandidateResources: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for subscribing child's state. It subscribes the presence state of
- * the resource. By making this subscription, every time a server
- * adds/removes/alters a resource, starts or is intentionally stopped, a
- * notification is sent to subscriber.
- *
- * <p>
- * Listener should be set using setSubscribePresenceListener API.
- * <p>
- * Listener ISubscribePresenceListener::onPresenceCallback will
- * be notified for resource presence status
- *
- * @param resource
- * collection resource for subscribing presence of all child
- * resources
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult subscribeCollectionPresence(OcResource resource)
- throws OcException {
- if (null == presenceListener) {
- Log.e(LOG_TAG,"subscribeCollectionPresence: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj
- .subscribeCollectionPresence(resource);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "subscribeCollectionPresence: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for finding a specific remote group when a resource tries to join a
- * group.
- * <p>
- * Listener should be set using setGroupListener API
- * <p>
- * Listener IFindGroupListener::onGroupFindCallback will be
- * called to notify whenever a requested group is found.
- *
- * @param collectionResourceTypes
- * resource types of a group to find and join
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- *
- */
- public OCStackResult findGroup(Vector<String> collectionResourceTypes) {
- if (null == groupListener) {
- Log.e(LOG_TAG,"findGroup: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = result = thingsManagerInterfaceObj.findGroup(collectionResourceTypes);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "findGroup: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for creating a new group.
- *
- * @param collectionResourceType
- * resource type of a group to create
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- */
- public OCStackResult createGroup(String collectionResourceType) {
- OCStackResult result = thingsManagerInterfaceObj.createGroup(collectionResourceType);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "createGroup: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for joining a group. This API is used for joining the resource
- * to local group which is created using @createGroup API.
- *
- * @param collectionResourceType
- * resource type of a group to join.
- * @param resourceHandle
- * resource handle to join a group.
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult joinGroup(String collectionResourceType,
- OcResourceHandle resourceHandle) {
- OCStackResult result = thingsManagerInterfaceObj.joinGroup(collectionResourceType,
- resourceHandle);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "joinGroup: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for joining a group. This API is used for joining the resource to
- * remote group.
- *
- * @param resource
- * group resource to join.
- * @param resourceHandle
- * resource handle to join a group.
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult joinGroup(OcResource resource,
- OcResourceHandle resourceHandle) throws OcException {
- OCStackResult result = thingsManagerInterfaceObj.joinGroup(resource, resourceHandle);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "joinGroup: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for leaving a joined local group.
- *
- * @param collectionResourceType
- * resource type of a group to leave.
- * @param resourceHandle
- * resource handle to leave a group.
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult leaveGroup(String collectionResourceType,
- OcResourceHandle resourceHandle) {
- OCStackResult result = thingsManagerInterfaceObj.leaveGroup(collectionResourceType,
- resourceHandle);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "leaveGroup: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for leaving a joined remote group.
- *
- * @param resource
- * resource of a group to leave.
- * @param collectionResourceType
- * resource type of a group to leave.
- * @param resourceHandle
- * resource handle to leave a group.
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult leaveGroup(OcResource resource, String collectionResourceType,
- OcResourceHandle resourceHandle) {
- OCStackResult result = thingsManagerInterfaceObj.leaveGroup(resource, collectionResourceType,
- resourceHandle);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "leaveGroup: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for deleting a created group.
- *
- * @param collectionResourceType
- * resource type of a group to delete.
- *
- */
- public void deleteGroup(String collectionResourceType) {
- thingsManagerInterfaceObj.deleteGroup(collectionResourceType);
- }
-
- /**
- * API for getting a list of local groups.
- *
- * @return Returns the map with the group resource type and group
- * resource handle on successs otherwise null.
- *
- */
- public Map<String, OcResourceHandle> getGroupList() {
- return thingsManagerInterfaceObj.getGroupList();
- }
-
- /**
- * API for registering and binding a resource to group.
- *
- * @param resource
- * resource for register and bind to group. It has all data.
- * @param collectionHandle
- * collection resource handle. It will be the added child
- * resource.
- *
- * @return OcResourceHandle - Child resource handle.
- *
- */
- public OcResourceHandle bindResourceToGroup(OcResource resource,
- OcResourceHandle collectionHandle)
- throws OcException {
- return thingsManagerInterfaceObj.bindResourceToGroup(resource,
- collectionHandle);
- }
-
- /**
- * API for updating configuration value of multiple things of a target group
- * or a single thing to a resource server(s).
- *
- * <p>
- * Listener should be set using setConfigurationListener API.
- * <p>
- * Listener IConfigurationListener::onUpdateConfigurationsCallback will be
- * notified when the response of update configuration arrives.
- *
- * @param resource
- * resource representing the target group or the single thing.
- * It is a pointer of resource instance of Configuration
- * resource. The resource pointer can be acquired by performing
- * findResource() function with a dedicated resource type,
- * "oic.con". Note that, the resource pointer represents not only
- * a single simple resource but also a collection resource
- * composing multiple simple resources. In other words, using
- * these APIs, developers can send a series of requests to
- * multiple things by calling the corresponding function at once.
- * @param configurations
- * ConfigurationUnit: a nickname of attribute of target
- * resource (e.g., installed location, currency, (IP)address)
- * Value : a value to be updated. It represents an indicator of
- * which resource developers want to access and which value
- * developers want to update. Basically, developers could use a
- * resource URI to access a specific resource but a resource URI
- * might be hard for all developers to memorize lots of URIs,
- * especially in the case of long URIs. To relieve the problem,
- * Things Configuration introduces a easy-memorizing name, called
- * ConfigurationName, instead of URI. And ConfigurationValue used
- * in updateConfiguration() function indicates a value to be
- * updated. Note that, only one configuration parameter is
- * supported in this release. Multiple configuration parameters
- * will be supported in future release.
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult updateConfigurations(OcResource resource,
- Map<String, String> configurations) throws OcException {
- if (null == configurationListener) {
- Log.e(LOG_TAG,"updateConfigurations: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj.updateConfigurations(resource,
- configurations);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "updateConfigurations: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for getting configuration value of multiple things of a target group
- * or a single thing.To get a value, users need to know a Configuration Name
- * indicating the target resource. In this release, the Configuration Name
- * is "configuration".An update value is not needed. After that, users store
- * them in form of a Vector and then use a getConfigurations() function.
- *
- * @param resource
- * resource representing the target group or the single thing.
- * @param configurations
- * ConfigurationUnit: a nickname of attribute of target
- * resource.
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult getConfigurations(OcResource resource,
- Vector<String> configurations) throws OcException {
- if (null == configurationListener) {
- Log.e(LOG_TAG,"getConfigurations: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj.getConfigurations(resource,
- configurations);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "getConfigurations: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for getting the list of supported configuration units (configurable
- * parameters). It shows which Configuration Names are supported and their
- * brief descriptions. This information is provided in JSON format.
- *
- * @return Returns the configuration list in JSON format.
- *
- */
- public String getListOfSupportedConfigurationUnits() {
- return thingsManagerInterfaceObj.getListOfSupportedConfigurationUnits();
- }
-
- /**
- * API for bootstrapping system configuration parameters from a bootstrap
- * server.
- * <p>
- * Listener should be set using setConfigurationListener API.
- * <p>
- * Listener IConfigurationListener::onBootStrapCallback will be
- * notified when the response arrives.
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult doBootstrap() {
- if (null == configurationListener) {
- Log.e(LOG_TAG,"doBootstrap: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj.doBootstrap();
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "doBootstrap: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API to is used to send a request to a server(thing or device) to be
- * rebooted. On receiving the request, the server attempts to reboot itself
- * in a deterministic time. The target thing could be a group of multiple
- * things or a single thing.
- * <p>
- * Listener should be set using setDiagnosticsListener API.
- * <p>
- * Listener IDiagnosticsListener::onRebootCallback will be
- * notified when the response arrives.
- * @param resource
- * resource pointer representing the target group
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult reboot(OcResource resource) throws OcException {
- if (null == diagnosticsListener) {
- Log.e(LOG_TAG,"reboot: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj.reboot(resource);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "reboot: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API to restore all configuration parameters to default one on
- * thing(device). All configuration parameters refers Configuration
- * resource, which they could have been modified for various reasons (e.g.,
- * for a request to update a value). If developers on the client want to
- * restore the parameters, just use the factoryReset function.The target
- * thing could be a group of multiple things or a single thing.
- *
- * <p>
- * Listener should be set using setDiagnosticsListener API.
- * <p>
- * Listener IDiagnosticsListener::onFactoryResetCallback will be
- * notified when the response arrives.
- *
- * @param resource
- * resource pointer representing the target group
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult factoryReset(OcResource resource) throws OcException {
- if (null == diagnosticsListener) {
- Log.e(LOG_TAG,"factoryReset: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj.factoryReset(resource);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "factoryReset: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for adding a new ActionSet onto a specific resource.
- *
- * <p>
- * Listener should be set using setActionListener API.
- * <p>
- * Listener IActionListener::onPutResponseCallback will be
- * notified when the response of PUT operation arrives.
- * @param resource
- * resource pointer of the group resource
- * @param actionSet
- * pointer of ActionSet
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult addActionSet(OcResource resource, ActionSet actionSet)
- throws OcException {
- if (null == actionListener) {
- Log.e(LOG_TAG,"addActionSet: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj
- .addActionSet(resource, actionSet);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "addActionSet: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for executing a specific ActionSet belonging to a specific resource.
- *
- * <p>
- * Listener should be set using setActionListener API.
- * <p>
- * Listener IActionListener::onPostResponseCallback will be
- * notified when the response of POST operation arrives.
- *
- * @param resource
- * resource pointer of the group resource
- * @param actionsetName
- * ActionSet name for removing the ActionSet
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult executeActionSet(OcResource resource,
- String actionsetName) throws OcException {
- if (null == actionListener) {
- Log.e(LOG_TAG,"executeActionSet: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj
- .executeActionSet(resource, actionsetName);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "executeActionSet: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API for executing a specific ActionSet belonging to a specific resource.
- *
- * <p>
- * Listener should be set using setActionListener API.
- * <p>
- * Listener IActionListener::onPostResponseCallback will be
- * notified when the response of POST operation arrives.
- *
- * @param resource
- * resource pointer of the group resource
- * @param actionsetName
- * ActionSet name for removing the ActionSet
- * @param delay
- * Wait time for the ActionSet execution
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult executeActionSet(OcResource resource,
- String actionsetName, long delay) throws OcException {
- if (null == actionListener) {
- Log.e(LOG_TAG,"executeActionSet: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj
- .executeActionSet(resource, actionsetName, delay);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "executeActionSet: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API to cancel the existing ActionSet.
- *
- * <p>
- * Listener should be set using setActionListener API.
- * <p>
- * Listener IActionListener::onPostResponseCallback will be
- * notified when the response of POST operation arrives.
- * @param resource
- * resource pointer of the group resource.
- * @param actionsetName
- * ActionSet name that has to be cancelled.
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
-
- public OCStackResult cancelActionSet(OcResource resource,
- String actionsetName) throws OcException {
- if (null == actionListener) {
- Log.e(LOG_TAG,"cancelActionSet: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj.cancelActionSet(resource,
- actionsetName);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "cancelActionSet: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API to to get an existing ActionSet belonging to a specific resource.
- *
- * <p>
- * Listener should be set using setActionListener API.
- * <p>
- * Listener IActionListener::onPostResponseCallback will be
- * notified when the response of POST operation arrives.
- * @param resource
- * resource pointer of the group resource
- * @param actionsetName
- * ActionSet name for removing the ActionSet
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult getActionSet(OcResource resource, String actionsetName)
- throws OcException {
- if (null == actionListener) {
- Log.e(LOG_TAG,"getActionSet: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj.getActionSet(resource,
- actionsetName);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "getActionSet: returned error: " + result.name());
- }
-
- return result;
- }
-
- /**
- * API to delete an existing ActionSet belonging to a specific resource.
- *
- * <p>
- * Listener should be set using setActionListener API.
- * <p>
- * Listener IActionListener::onPutResponseCallback will be
- * notified when the response of PUT operation arrives.
- *
- * @param resource
- * resource pointer of the group resource
- * @param actionsetName
- * ActionSet name for removing the ActionSet
- *
- * @return OCStackResult - OC_STACK_OK on success, otherwise a failure error
- * code.
- *
- */
- public OCStackResult deleteActionSet(OcResource resource,
- String actionsetName) throws OcException {
- if (null == actionListener) {
- Log.e(LOG_TAG,"deleteActionSet: listener not set!");
- return OCStackResult.OC_STACK_LISTENER_NOT_SET;
- }
-
- OCStackResult result = thingsManagerInterfaceObj.deleteActionSet(resource,
- actionsetName);
- if (OCStackResult.OC_STACK_OK != result) {
- Log.e(LOG_TAG, "deleteActionSet: returned error: " + result.name());
- }
-
- return result;
- }
-
-}
+++ /dev/null
-/******************************************************************
- *
- * 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.
- *
- ******************************************************************/
-
-/**
- * @file ThingsManagerCallback.java
- *
- * @brief This file provides a class for a set of callback functions for group management,
- * synchronization of group, configuration of things, and diagnostics
- * about things.
- *
- */
-
-package org.iotivity.service.tm;
-
-import java.util.Vector;
-
-import org.iotivity.base.OcHeaderOption;
-import org.iotivity.base.OcRepresentation;
-import org.iotivity.base.OcResource;
-
-import android.util.Log;
-
-/**
- * This class provides a set of callback functions for group management,
- * synchronization of group, configuration of things, and diagnostics
- * about things.
- *
- */
-class ThingsManagerCallback {
-
- private IFindCandidateResourceListener resourceListener;
- private ISubscribePresenceListener presenceListener;
- private IFindGroupListener groupListener;
- private IConfigurationListener configurationListener;
- private IDiagnosticsListener diagnosticsListener;
- private IActionListener actionListener;
- private static ThingsManagerCallback thingsManagerCallbackInterfaceObj;
-
- private ThingsManagerCallback() {
- }
-
- /**
- * Function for Getting instance of ThingsManagerCallback object.
- *
- * @return ThingsManagerCallback instance.
- *
- */
- public static synchronized ThingsManagerCallback getInstance() {
- if (null == thingsManagerCallbackInterfaceObj) {
- thingsManagerCallbackInterfaceObj = new ThingsManagerCallback();
- }
- return thingsManagerCallbackInterfaceObj;
- }
-
- /**
- * Register listener for findCandidateResource callback.
- *
- * @param listener
- * interface for getting notification when resources are
- * discovered in network.
- *
- */
- public void registerFindCandidateResourceListener(
- IFindCandidateResourceListener listener) {
- resourceListener = listener;
- }
-
- /**
- * Register listener for subscribeCollectionPresence callback.
- *
- * @param listener
- * interface for getting notification regarding child resource
- * presence status.
- *
- */
- public void registerSubscribePresenceListener(
- ISubscribePresenceListener listener) {
- presenceListener = listener;
- }
-
- /**
- * Register listener for find group callback.
- *
- * @param listener
- * interface for getting notification on whether the group is
- * found or not.
- *
- */
- public void registerGroupListener(IFindGroupListener listener) {
- groupListener = listener;
- }
-
- /**
- * Register listener for updateConfigurations and getConfigurations
- * callback.
- *
- * @param listener
- * interface for getting notification on configuration values
- * information or when configuration value is updated for
- * multiple things of a target group or a single thing.
- *
- */
- public void registerConfigurationListener(IConfigurationListener listener) {
- configurationListener = listener;
- }
-
- /**
- * Register listener for doBootstrap, reboot and factoryReset callbacks.
- *
- * @param listener
- * interface for receiving asynchronous response for diagnostic
- * feature APIs.
- *
- */
- public void registerDiagnosticsListener(IDiagnosticsListener listener) {
- diagnosticsListener = listener;
- }
-
- /**
- * Register listener for getActionSet, executeActionSet and deleteActionSet
- * callback.
- *
- * @param listener
- * interface for receiving the callback for the GET, PUT and
- * POST requested actions.
- *
- */
- public void registerActionListener(IActionListener listener) {
- actionListener = listener;
- }
-
- /**
- * Unregister listener for findCandidateResource callback.
- *
- */
- public void unregisterFindCandidateResourceListener() {
- resourceListener = null;
- }
-
- /**
- * Unregister listener for subscribeCollectionPresence callback.
- *
- */
- public void unregisterSubscribePresenceListener() {
- presenceListener = null;
- }
-
- /**
- * Unregister listener for find group callback.
- *
- */
- public void unregisterGroupListener() {
- groupListener = null;
- }
-
- /**
- * Unregister listener for updateConfigurations and getConfigurations
- * callback.
- *
- */
- public void unregisterConfigurationListener() {
- configurationListener = null;
- }
-
- /**
- * Unregister listener for doBootstrap, reboot and factoryReset callbacks.
- *
- */
- public void unregisterDiagnosticsListener() {
- diagnosticsListener = null;
- }
-
- /**
- * Unregister listener for getActionSet, executeActionSet and
- * deleteActionSet callback.
- *
- */
- public void unregisterActionListener() {
- actionListener = null;
- }
-
- /**
- * This callback method will be called whenever resource is discovered in
- * the network.
- *
- * @param resources
- * List of resources discovered in the network
- *
- */
- public void onResourceCallback(Vector<OcResource> resources) {
- if (null != resourceListener)
- resourceListener.onResourceCallback(resources);
- }
-
- /**
- * This callback method is called when a response for the executeActionSet
- * or deleteActionSet request just arrives.
- *
- * @param headerOptions
- * It comprises of optionID and optionData as members.
- * @param rep
- * Configuration parameters are carried as a pair of attribute
- * key and value in a form of OCRepresentation instance.
- * @param errorValue
- * error code.
- *
- */
- public void onPostResponseCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue) {
- if (null != actionListener)
- actionListener.onPostResponseCallback(headerOptions, rep,
- errorValue);
- }
-
- /**
- * This callback method is called when a response for the addActionSet
- * request just arrives.
- *
- * @param headerOptions
- * It comprises of optionID and optionData as members.
- * @param rep
- * Configuration parameters are carried as a pair of attribute
- * key and value in a form of OCRepresentation instance.
- * @param errorValue
- * error code.
- *
- */
- public void onPutResponseCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue) {
- if (null != actionListener)
- actionListener
- .onPutResponseCallback(headerOptions, rep, errorValue);
- }
-
- /**
- * This callback method is called when a response for the getActionSet
- * request just arrives.
- *
- * @param headerOptions
- * It comprises of optionID and optionData as members.
- * @param rep
- * Configuration parameters are carried as a pair of attribute
- * key and value in a form of OCRepresentation instance.
- * @param errorValue
- * error code.
- *
- */
- public void onGetResponseCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue) {
- if (null != actionListener)
- actionListener
- .onGetResponseCallback(headerOptions, rep, errorValue);
- }
-
- /**
- * This callback method is called when a response for the
- * updateConfigurations request just arrives.
- *
- * @param headerOptions
- * It comprises of optionID and optionData as members.
- * @param rep
- * Configuration parameters are carried as a pair of attribute
- * key and value in a form of OCRepresentation instance.
- * @param errorValue
- * error code.
- *
- */
- public void onUpdateConfigurationsCallback(
- Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
- int errorValue) {
- if (null != configurationListener)
- configurationListener.onUpdateConfigurationsCallback(headerOptions,
- rep, errorValue);
- }
-
- /**
- * This callback method is called when a response for the getConfigurations
- * request just arrives.
- *
- * @param headerOptions
- * It comprises of optionID and optionData as members.
- * @param rep
- * Configuration parameters are carried as a pair of attribute
- * key and value in a form of OCRepresentation instance.
- * @param errorValue
- * error code.
- *
- */
- public void onGetConfigurationsCallback(
- Vector<OcHeaderOption> headerOptions, OcRepresentation rep,
- int errorValue) {
- if (null != configurationListener)
- configurationListener.onGetConfigurationsCallback(headerOptions,
- rep, errorValue);
- }
-
- /**
- * This callback method is called when a response for the doBootstrap
- * request just arrives.
- *
- * @param headerOptions
- * It comprises of optionID and optionData as members.
- * @param rep
- * Configuration parameters are carried as a pair of attribute
- * key and value in a form of OCRepresentation instance.
- * @param errorValue
- * error code.
- *
- */
- public void onBootStrapCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue) {
- if (null != configurationListener) {
- Log.i("ThingsManagerCallback : onBootStrapCallback",
- "Received Callback from JNI");
- configurationListener.onBootStrapCallback(headerOptions, rep,
- errorValue);
- }
- }
-
- /**
- * This callback method is called when a response for the reboot request
- * just arrives.
- *
- * @param headerOptions
- * It comprises of optionID and optionData as members.
- * @param rep
- * Configuration parameters are carried as a pair of attribute
- * key and value in a form of OCRepresentation instance.
- * @param errorValue
- * error code.
- *
- */
- public void onRebootCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue) {
- if (null != diagnosticsListener) {
- Log.i("ThingsManagerCallback : onRebootCallback",
- "Received Callback from JNI");
- diagnosticsListener
- .onRebootCallback(headerOptions, rep, errorValue);
- }
- }
-
- /**
- * This callback method is called when a response for the factoryReset
- * request just arrives.
- *
- * @param headerOptions
- * It comprises of optionID and optionData as members.
- * @param rep
- * Configuration parameters are carried as a pair of attribute
- * key and value in a form of OCRepresentation instance.
- * @param errorValue
- * error code.
- *
- */
- public void onFactoryResetCallback(Vector<OcHeaderOption> headerOptions,
- OcRepresentation rep, int errorValue) {
- if (null != diagnosticsListener) {
- Log.i("ThingsManagerCallback : onFactoryResetCallback",
- "Received Callback from JNI");
- diagnosticsListener.onFactoryResetCallback(headerOptions, rep,
- errorValue);
- }
- }
-
- /**
- * This callback method is called to notify whether group is found or not.
- *
- * @param resource
- * Resource URI
- *
- */
- public void onGroupFindCallback(OcResource resource) {
- if (null != groupListener) {
- Log.i("ThingsManagerCallback : onGroupFindCallback",
- "Received Callback from JNI");
- groupListener.onGroupFindCallback(resource);
- }
- }
-
- /**
- * This callback method is called for child resource presence status.
- *
- * @param resource
- * URI of resource.
- * @param errorValue
- * error code.
- *
- */
- public void onPresenceCallback(String resource, int errorValue) {
- if (null != presenceListener) {
- Log.i("ThingsManagerCallback : onPresenceCallback",
- "Received Callback from JNI");
- presenceListener.onPresenceCallback(resource, errorValue);
- }
- }
-
-}
+++ /dev/null
-/******************************************************************
- *
- * 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.
- *
- ******************************************************************/
-/**
- * @file ThingsManagerInterface.java
- *
- * @brief This file provides a class which acts as an interface for Things Manager API calls between
- * ThingsManager and ThingsManagerNativeInterface
- *
- */
-
-package org.iotivity.service.tm;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Vector;
-
-import org.iotivity.base.OcException;
-import org.iotivity.base.OcResource;
-import org.iotivity.base.OcResourceHandle;
-
-import android.util.Log;
-
-/**
- * This class acts as an interface for Things Manager API calls between
- * ThingsManager and ThingsManagerNativeInterface
- *
- */
-class ThingsManagerInterface {
-
- private IFindCandidateResourceListener resourceListener;
- private ISubscribePresenceListener presenceListener;
- private IFindGroupListener groupListener;
- private IConfigurationListener configurationListener;
- private static ThingsManagerInterface thingsManagerInterfaceObj;
-
- private ThingsManagerInterface() {
- }
-
- /**
- * Function for Getting instance of ThingsManagerInterface object.
- *
- * @return ThingsManagerInterface instance.
- *
- */
- public static synchronized ThingsManagerInterface getInstance() {
- if (null == thingsManagerInterfaceObj) {
- thingsManagerInterfaceObj = new ThingsManagerInterface();
- }
- return thingsManagerInterfaceObj;
- }
-
- /**
- * Register listener for findCandidateResource callback.
- *
- * @param listener
- * interface for getting notification when resources are
- * discovered in network.
- *
- */
- public void registerFindCandidateResourceListener(
- IFindCandidateResourceListener listener) {
- resourceListener = listener;
- }
-
- /**
- * Register listener for subscribeCollectionPresence callback.
- *
- * @param listener
- * interface for getting notification regarding child resource
- * presence status.
- *
- */
- public void registerSubscribePresenceListener(
- ISubscribePresenceListener listener) {
- presenceListener = listener;
- }
-
- /**
- * Register listener for register group and find group callback.
- *
- * @param listener
- * interface for getting notification on whether the group is
- * found or not.
- *
- */
- public void registerGroupListener(IFindGroupListener listener) {
- groupListener = listener;
- }
-
- /**
- * Register listener for updateConfigurations and getConfigurations
- * callback.
- *
- * @param listener
- * interface for getting notification on configuration values
- * information or when configuration value is updated for
- * multiple things of a target group or a single thing.
- *
- */
- public void registerConfigurationListener(IConfigurationListener listener) {
- configurationListener = listener;
- }
-
- /**
- * Unregister listener for findCandidateResource callback.
- *
- */
- public void unregisterFindCandidateResourceListener() {
- resourceListener = null;
- }
-
- /**
- * Unregister listener for subscribeCollectionPresence callback.
- *
- */
- public void unregisterSubscribePresenceListener() {
- presenceListener = null;
- }
-
- /**
- * Unregister listener for registerGroup and findGroup callback.
- *
- */
- public void unregisterGroupListener() {
- groupListener = null;
- }
-
- /**
- * Unregister listener for updateConfigurations and getConfigurations
- * callback.
- *
- */
- public void unregisterConfigurationListener() {
- configurationListener = null;
- }
-
- /**
- * API for discovering candidate resources with waiting delay. Listener
- * <p>
- * IFindCandidateResourceListener::onResourceCallback will be notified
- * when resource is discovered in network.
- * </p>
- *
- * @param resourceTypes
- * required resource types(called "candidate")
- * @param waitTime
- * Time duration in seconds to find the resources in network
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public OCStackResult findCandidateResources(Vector<String> resourceTypes,
- int waitTime) {
- OCStackResult result;
- if (null == resourceListener) {
- result = OCStackResult.OC_STACK_ERROR;
- } else {
- int ordinal = ThingsManagerNativeInterface.findCandidateResources(
- resourceTypes, waitTime);
- result = OCStackResult.conversion(ordinal);
- }
- return result;
- }
-
- /**
- * API for subscribing child's state. Listener
- * <p>
- * ISubscribePresenceListener::onPresenceCallback will be notified for
- * resource presence status
- * </p>
- *
- * @param resource
- * collection resource for subscribing presence of all child
- * resources
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public OCStackResult subscribeCollectionPresence(OcResource resource)
- throws OcException {
- String LOG_TAG = this.getClass().getSimpleName();
-
- OCStackResult result;
- if (null == presenceListener) {
- result = OCStackResult.OC_STACK_ERROR;
- } else {
-
- int ordinal = ThingsManagerNativeInterface
- .subscribeCollectionPresence(resource);
- Log.i(LOG_TAG, "Ordinal value = : " + ordinal);
- result = OCStackResult.conversion(ordinal);
- }
- return result;
- }
-
- /**
- * API for finding a specific remote group when a resource tries to join a
- * group.
- * <p>
- * IFindGroupListener::onGroupFindCallback will be called to notify
- * whether requested group found or not.
- * </p>
- *
- * @param resourceTypes
- * resource types of a group to find and join
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public OCStackResult findGroup(Vector<String> resourceTypes) {
- OCStackResult result;
- if (null == groupListener) {
- result = OCStackResult.OC_STACK_ERROR;
- } else {
- int ordinal = ThingsManagerNativeInterface.findGroup(resourceTypes);
- result = OCStackResult.conversion(ordinal);
- }
- return result;
- }
-
- /**
- * API for creating a new group.
- *
- * @param resourceType
- * resource type of a group to create
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public OCStackResult createGroup(String resourceType) {
- OCStackResult result;
- int ordinal = ThingsManagerNativeInterface.createGroup(resourceType);
- result = OCStackResult.conversion(ordinal);
- return result;
- }
-
- /**
- * API for joining a group. This API is used when a resource that has a
- * group tries to find a specific remote resource and makes it join a group.
- *
- * @param resourceType
- * resource type of a group to join.
- * @param resourceHandle
- * resource handle to join a group.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public OCStackResult joinGroup(String resourceType,
- OcResourceHandle resourceHandle) {
- OCStackResult result;
-
- int ordinal = ThingsManagerNativeInterface.joinGroup(resourceType,
- resourceHandle);
- result = OCStackResult.conversion(ordinal);
-
- return result;
- }
-
- /**
- * API for joining a group. This API is used when a resource that doesn't
- * have a group tries to find and join a specific remote group.
- *
- * @param resource
- * group resource to join.
- * @param resourceHandle
- * resource handle to join a group.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public OCStackResult joinGroup(OcResource resource,
- OcResourceHandle resourceHandle) throws OcException {
-
- OCStackResult result;
- int ordinal = ThingsManagerNativeInterface.joinGroup(resource,
- resourceHandle);
- result = OCStackResult.conversion(ordinal);
-
- return result;
- }
-
- /**
- * API for leaving a joined group.
- *
- * @param resourceType
- * resource type of a group to leave.
- * @param resourceHandle
- * resource handle to leave a group.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public OCStackResult leaveGroup(String resourceType,
- OcResourceHandle resourceHandle) {
-
- OCStackResult result;
- int ordinal = ThingsManagerNativeInterface.leaveGroup(resourceType,
- resourceHandle);
- result = OCStackResult.conversion(ordinal);
-
- return result;
- }
-
- /**
- * API for leaving a joined group.
- *
- * @param resource
- * resource of a group to leave.
- * @param resourceType
- * resource type of a group to leave.
- * @param resourceHandle
- * resource handle to leave a group.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public OCStackResult leaveGroup(OcResource resource, String resourceType,
- OcResourceHandle resourceHandle) {
-
- OCStackResult result;
- int ordinal = ThingsManagerNativeInterface.leaveGroup(resource,
- resourceType, resourceHandle);
- result = OCStackResult.conversion(ordinal);
-
- return result;
- }
-
- /**
- * API for deleting a group.
- *
- * @param collectionResourceType
- * resource type of a group to delete.
- *
- */
- public void deleteGroup(String collectionResourceType) {
- ThingsManagerNativeInterface.deleteGroup(collectionResourceType);
- }
-
- /**
- * API for getting a list of joined groups.
- *
- * @return Returns group resource type and group resource handle as a map
- * table.
- *
- */
- public Map<String, OcResourceHandle> getGroupList() {
- return ThingsManagerNativeInterface.getGroupList();
- }
-
- /**
- * API for register and bind resource to group.
- *
- * @param resource
- * resource for register and bind to group. It has all data.
- * @param collectionHandle
- * collection resource handle. It will be added child resource.
- *
- * @return OcResourceHandle - Child resource handle.
- */
- public OcResourceHandle bindResourceToGroup(OcResource resource,
- OcResourceHandle collectionHandle)
- throws OcException {
- return ThingsManagerNativeInterface.bindResourceToGroup(
- resource, collectionHandle);
- }
-
- /**
- * API for updating configuration value of multiple things of a target group
- * or a single thing.
- *
- * @param resource
- * resource representing the target group or the single thing.
- * @param configurations
- * ConfigurationUnit: a nickname of attribute of target
- * resource (e.g., installed location, currency, (IP)address)
- * Value : a value to be updated
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public OCStackResult updateConfigurations(OcResource resource,
- Map<String, String> configurations) throws OcException {
- OCStackResult result;
- if (null == configurationListener) {
- result = OCStackResult.OC_STACK_ERROR;
- } else {
- int ordinal = ThingsManagerNativeInterface.updateConfigurations(
- resource, configurations);
- result = OCStackResult.conversion(ordinal);
- }
- return result;
-
- }
-
- /**
- * API for getting configuration value of multiple things of a target group
- * or a single thing.
- *
- * @param resource
- * resource representing the target group or the single thing.
- * @param configurations
- * ConfigurationUnit: a nickname of attribute of target
- * resource.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public OCStackResult getConfigurations(OcResource resource,
- Vector<String> configurations) throws OcException {
- OCStackResult result;
- if (null == configurationListener) {
- result = OCStackResult.OC_STACK_ERROR;
- } else {
- int ordinal = ThingsManagerNativeInterface.getConfigurations(
- resource, configurations);
- result = OCStackResult.conversion(ordinal);
- }
- return result;
- }
-
- /**
- * API for showing the list of supported configuration units (configurable
- * parameters)
- *
- * @return Returns the configuration list in JSON format.
- *
- */
- public String getListOfSupportedConfigurationUnits() {
-
- return ThingsManagerNativeInterface
- .getListOfSupportedConfigurationUnits();
- }
-
- /**
- * API for bootstrapping system configuration parameters from a bootstrap
- * server.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public OCStackResult doBootstrap() {
-
- OCStackResult result;
- int ordinal = ThingsManagerNativeInterface.doBootstrap();
- result = OCStackResult.conversion(ordinal);
-
- return result;
- }
-
- /**
- * API to let thing(device) reboot. The target thing could be a group of
- * multiple things or a single thing.
- *
- * @param resource
- * resource pointer representing the target group
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success
- */
- public OCStackResult reboot(OcResource resource) throws OcException {
-
- OCStackResult result;
- int ordinal = ThingsManagerNativeInterface.reboot(resource);
- result = OCStackResult.conversion(ordinal);
-
- return result;
- }
-
- /**
- * API for factory reset on thing(device). The target thing could be a group
- * of multiple things or a single thing.
- *
- * @param resource
- * resource pointer representing the target group
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public OCStackResult factoryReset(OcResource resource) throws OcException {
-
- OCStackResult result;
- int ordinal = ThingsManagerNativeInterface.factoryReset(resource);
- result = OCStackResult.conversion(ordinal);
-
- return result;
- }
-
- /**
- * API for adding an Action Set. Callback is called when the response of PUT
- * operation arrives.
- *
- * @param resource
- * resource pointer of the group resource
- * @param actionSet
- * pointer of Action Set
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public OCStackResult addActionSet(OcResource resource, ActionSet actionSet)
- throws OcException {
-
- int ordinal = ThingsManagerNativeInterface.addActionSet(resource,
- actionSet);
-
- return OCStackResult.conversion(ordinal);
- }
-
- /**
- * API for executing the Action Set. Callback is called when the response of
- * POST operation arrives.
- *
- * @param resource
- * resource pointer of the group resource
- * @param actionsetName
- * Action Set name for removing the Action set
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public OCStackResult executeActionSet(OcResource resource,
- String actionsetName) throws OcException {
-
- int ordinal = ThingsManagerNativeInterface.executeActionSet(resource,
- actionsetName);
-
- return OCStackResult.conversion(ordinal);
- }
-
- /**
- * API for executing the Action Set. Callback is called when the response of
- * POST operation arrives.
- *
- * @param resource
- * resource pointer of the group resource
- * @param actionsetName
- * Action Set name for removing the Action set
- * @param delay
- * waiting time for until action set run.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public OCStackResult executeActionSet(OcResource resource,
- String actionsetName, long delay) throws OcException {
-
- OCStackResult result;
- int ordinal = ThingsManagerNativeInterface.executeActionSet(resource,
- actionsetName, delay);
- result = OCStackResult.conversion(ordinal);
-
- return result;
- }
-
- /**
- * API for cancelling the Action Set. Callback is called when the response
- * of POST operation arrives.
- *
- * @param resource
- * resource pointer of the group resource
- * @param actionsetName
- * Action Set name for removing the Action set
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public OCStackResult cancelActionSet(OcResource resource,
- String actionsetName) throws OcException {
-
- OCStackResult result;
- int ordinal = ThingsManagerNativeInterface.cancelActionSet(resource,
- actionsetName);
- result = OCStackResult.conversion(ordinal);
-
- return result;
- }
-
- /**
- * API for reading the Action Set. Callback is called when the response of
- * GET operation arrives.
- *
- * @param resource
- * resource pointer of the group resource
- * @param actionsetName
- * Action Set name for removing the Action set
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public OCStackResult getActionSet(OcResource resource, String actionsetName)
- throws OcException {
-
- OCStackResult result;
- int ordinal = ThingsManagerNativeInterface.getActionSet(resource,
- actionsetName);
- result = OCStackResult.conversion(ordinal);
-
- return result;
- }
-
- /**
- * API for removing the action set. Callback is called when the response of
- * POST operation arrives.
- *
- * @param resource
- * resource pointer of the group resource
- * @param actionsetName
- * Action Set name for removing the Action set
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public OCStackResult deleteActionSet(OcResource resource,
- String actionsetName) throws OcException {
-
- OCStackResult result;
- int ordinal = ThingsManagerNativeInterface.deleteActionSet(resource,
- actionsetName);
- result = OCStackResult.conversion(ordinal);
-
- return result;
- }
-}
+++ /dev/null
-/******************************************************************
- *
- * 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.
- *
- ******************************************************************/
-/**
- * @file ThingsManagerNativeInterface.java
- *
- * @brief This file provides a class which provides a set of native functions relating to group
- * management, synchronization of group, configuration of things, and
- * diagnostics about things.
- */
-
-package org.iotivity.service.tm;
-
-import java.util.Map;
-import java.util.Vector;
-
-import org.iotivity.base.OcResource;
-import org.iotivity.base.OcResourceHandle;
-
-/**
- * This class provides a set of native functions relating to group
- * management, synchronization of group, configuration of things, and
- * diagnostics about things.
- *
- */
-class ThingsManagerNativeInterface {
- /**
- * Native function for discoverying candidate resources.
- *
- * @param resourceTypes
- * - required resource types(called "candidate")
- * @param waitTime
- * - Delay time in seconds to add before starting to find the
- * resources in network.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public static native int findCandidateResources(
- Vector<String> resourceTypes, int waitTime);
-
- /**
- * Native function for subscribing child's state.
- *
- * @param resource
- * - collection resource for subscribing presence of all child
- * resources.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public static native int subscribeCollectionPresence(OcResource resource);
-
- /**
- * Native function for register and bind resource to group.
- *
- * @param resource
- * - resource for register and bind to group. It has all data.
- * @param collectionHandle
- * - collection resource handle. It will be added child resource.
- *
- * @return OcResourceHandle - Child resource handle.
- *
- */
- public static native OcResourceHandle bindResourceToGroup(OcResource resource,
- OcResourceHandle collectionHandle);
-
- /**
- * Native function for finding a specific remote group when a resource tries
- * to join a group. Callback is called when a group is found or not.
- *
- * @param collectionResourceTypes
- * - resource types of a group to find and join
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public static native int findGroup(Vector<String> collectionResourceTypes);
-
- /**
- * Native function for creating a new group.
- *
- * @param collectionResourceType
- * - resource type of a group to create
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public static native int createGroup(String collectionResourceType);
-
- /**
- * Native function for joining a group. This API is used when a resource
- * that has a group tries to find a specific remote resource and makes it
- * join a group.
- *
- * @param collectionResourceType
- * - resource type of a group to join.
- * @param resourceHandle
- * - resource handle to join a group.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public static native int joinGroup(String collectionResourceType,
- OcResourceHandle resourceHandle);
-
- /**
- * Native function for joining a group. This is used when a resource that
- * doesn't have a group tries to find and join a specific remote group.
- *
- * @param resource
- * - group resource to join.
- * @param resourceHandle
- * - resource handle to join a group.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public static native int joinGroup(OcResource resource,
- OcResourceHandle resourceHandle);
-
- /**
- * Native function for leaving a joined group.
- *
- * @param collectionResourceType
- * - resource type of a group to leave.
- * @param resourceHandle
- * - resource handle to leave a group.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public static native int leaveGroup(String collectionResourceType,
- OcResourceHandle resourceHandle);
-
- /**
- * Native function for leaving a joined group.
- *
- * @param resource
- * - resource of a group to leave.
- * @param collectionResourceType
- * - resource type of a group to leave.
- * @param resourceHandle
- * - resource handle to leave a group.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public static native int leaveGroup(OcResource resource,
- String collectionResourceType, OcResourceHandle resourceHandle);
-
- /**
- * Native function for deleting a group.
- *
- * @param collectionResourceType
- * - resource type of a group to delete.
- *
- *
- */
- public static native void deleteGroup(String collectionResourceType);
-
- /**
- * Native function for getting a list of joined groups.
- *
- * @return Returns group resource type and group resource handle as a map
- * table.
- *
- */
- public static native Map<String, OcResourceHandle> getGroupList();
-
- /**
- * Native function for updating configuration value of multiple things of a
- * target group or a single thing.
- *
- * @param resource
- * - resource representing the target group or the single thing.
- * @param configurations
- * - ConfigurationUnit: a nickname of attribute of target
- * resource (e.g., installed location, currency, (IP)address)
- * Value : a value to be updated
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public static native int updateConfigurations(OcResource resource,
- Map<String, String> configurations);
-
- /**
- * Native function for getting configuration value of multiple things of a
- * target group or a single thing.
- *
- * @param resource
- * - resource representing the target group or the single thing.
- * @param configurations
- * - ConfigurationUnit: a nickname of attribute of target
- * resource.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- *
- */
- public static native int getConfigurations(OcResource resource,
- Vector<String> configurations);
-
- /**
- * Native function for showing the list of supported configuration units
- * (configurable parameters)
- *
- * @return Returns the configuration list in JSON format.
- *
- */
- public static native String getListOfSupportedConfigurationUnits();
-
- /**
- * Native function for bootstrapping system configuration parameters from a
- * bootstrap server.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public static native int doBootstrap();
-
- /**
- * Native function to let thing(device) reboot. The target thing could be a
- * group of multiple things or a single thing.
- *
- * @param resource
- * - resource pointer representing the target group
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success
- */
- public static native int reboot(OcResource resource);
-
- /**
- * Native function for factory reset on thing(device). The target thing
- * could be a group of multiple things or a single thing.
- *
- * @param resource
- * - resource pointer representing the target group
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public static native int factoryReset(OcResource resource);
-
- /**
- * Native function for adding an Action Set. Callback is called when the
- * response of PUT operation arrives.
- *
- * @param resource
- * - resource pointer of the group resource
- * @param actionSet
- * - pointer of Action Set
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public static native int addActionSet(OcResource resource,
- ActionSet actionSet);
-
- /**
- * Native function for executing the Action Set. Callback is called when the
- * response of POST operation arrives.
- *
- * @param resource
- * - resource pointer of the group resource
- * @param actionsetName
- * - Action Set name for removing the Action set
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public static native int executeActionSet(OcResource resource,
- String actionsetName);
-
- /**
- * Native function for executing the Action Set. Callback is called when the
- * response of POST operation arrives.
- *
- * @param resource
- * - resource pointer of the group resource
- * @param actionsetName
- * - Action Set name for removing the Action set
- * @param delay
- * - waiting time for until action set run.
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public static native int executeActionSet(OcResource resource,
- String actionsetName, long delay);
-
- /**
- * Native function for cancelling the Action Set. Callback is called when
- * the response of POST operation arrives.
- *
- * @param resource
- * - resource pointer of the group resource
- * @param actionsetName
- * - Action Set name for removing the Action set
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public static native int cancelActionSet(OcResource resource,
- String actionsetName);
-
- /**
- * Native function for reading the Action Set. Callback is called when the
- * response of GET operation arrives.
- *
- * @param resource
- * - resource pointer of the group resource
- * @param actionsetName
- * - Action Set name for removing the Action set
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public static native int getActionSet(OcResource resource,
- String actionsetName);
-
- /**
- * Native function for removing the action set. Callback is called when the
- * response of POST operation arrives.
- *
- * @param resource
- * - resource pointer of the group resource
- * @param actionsetName
- * - Action Set name for removing the Action set
- *
- * @return OCStackResult - return value of this API. It returns OC_STACK_OK
- * if success.
- */
- public static native int deleteActionSet(OcResource resource,
- String actionsetName);
-}
+/* *****************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************/
+
package org.iotivity.service.tm;
import android.util.Log;
/**
- * This class provides time-related information used for
- * scheduled/recursive group action features. Along with time-related
- * variables, it also provides various useful functionality including
- * translating time to second unit
+ * This class provides time-related information used for scheduled/recursive
+ * group action features. Along with time-related variables, it also provides
+ * various useful functionality including translating time to second unit
*/
public class Time {
* Second to be set
* @param dayOfTheWeek
* Day of the week to be set
- *
*/
public void setTime(int year, int month, int day, int hour, int min,
int sec, int dayOfTheWeek) {
*
* @param seconds
* time delay in seconds
- *
*/
public void setDelay(long seconds) {
if (mType != ActionSetType.NONE) {
* Get absolute time in seconds.
*
* @return long - Absolute time in seconds.
- *
*/
public long getSecAbsTime() {
long interval;
* Get the type of ActionSet.
*
* @return ActionSetType - Type of ActionSet.
- *
*/
public ActionSetType getType() {
return mType;
* Get the time delay in seconds set in the ActionSet.
*
* @return long - Delay in seconds.
- *
*/
public long getDelay() {
return mDelay;
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-#include "GroupSynchronization.h"
-#include "logger.h"
-
-using namespace OC;
-using namespace std;
-
-#define TAG "GROUP_SYNC"
-
-namespace OIC
-{
- GroupSynchronization* GroupSynchronization::groupSyncnstance = NULL;
- bool GroupSynchronization::bIsFinding = false;
-
- GroupSynchronization* GroupSynchronization::getInstance()
- {
- if (groupSyncnstance == NULL)
- {
- groupSyncnstance = new GroupSynchronization();
- }
- return groupSyncnstance;
- }
-
- void GroupSynchronization::deleteInstance()
- {
- if (groupSyncnstance)
- {
- delete groupSyncnstance;
- groupSyncnstance = NULL;
- }
- }
-
- OCStackResult GroupSynchronization::findGroup(
- std::vector< std::string > collectionResourceTypes, FindCallback callback)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::findGroup");
-
- if(bIsFinding)
- {
- OC_LOG(DEBUG, TAG, "It was searching already.");
- return OC_STACK_ERROR;
- }
-
- std::lock_guard < std::mutex > guard(foundGroupMutex);
- foundGroupResourceList.clear();
- findCallback = callback;
-
- if (findCallback == NULL)
- {
- OC_LOG(DEBUG, TAG, "Find callback is NULL.");
- return OC_STACK_ERROR;
- }
-
- for (unsigned int i = 0; i < collectionResourceTypes.size(); ++i)
- {
-
- std::string query = OC_RSRVD_WELL_KNOWN_URI;
- query.append("?rt=");
- query.append(collectionResourceTypes.at(i));
-
- OCPlatform::findResource("", query,
- CT_DEFAULT,
- std::bind(&GroupSynchronization::onFindGroup, this,
- std::placeholders::_1));
- }
-
- bIsFinding = true;
-
- // thread to check if GroupSynchronization::onFoundGroup is called or not.
- std::thread t(std::bind(&GroupSynchronization::checkFindGroup, this));
- t.detach();
-
- return OC_STACK_OK;
- }
-
- OCStackResult GroupSynchronization::createGroup(std::string collectionResourceType)
- {
- std::lock_guard < std::mutex > guard(foundGroupMutex);
- foundGroupResourceList.clear();
-
- OCResourceHandle collectionResHandle = NULL;
- OCResourceHandle groupSyncResHandle = NULL;
-
- if (0 == collectionResourceType.length())
- {
- OC_LOG(DEBUG, TAG,
- "GroupSynchronization::createGroup : Error! Input params are wrong.");
- return OC_STACK_INVALID_PARAM;
- }
-
- OC_LOG(DEBUG, TAG, "GroupSynchronization::createGroup - The created group is added.");
-
- OCStackResult result;
-
- // creating master collection resource
- std::string collectionUri = "/" + collectionResourceType;
- std::size_t i;
- while ((i = collectionUri.find(".")) != std::string::npos)
- {
- collectionUri.replace(i, 1, "/");
- }
-
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::createGroup : collection uri - %s, type - %s",
- collectionUri.c_str(), collectionResourceType.c_str());
-
- std::string resourceInterface = DEFAULT_INTERFACE;
-
- result = OCPlatform::registerResource(collectionResHandle, collectionUri,
- collectionResourceType, resourceInterface, NULL, OC_DISCOVERABLE | OC_OBSERVABLE);
- if (result != OC_STACK_OK)
- {
- OC_LOG_V(DEBUG, TAG, "To register resource (%s) was unsuccessful. result - %d",
- collectionUri.c_str(), result);
- goto Error;
- }
-
- {
- OCPlatform::bindInterfaceToResource(collectionResHandle, GROUP_INTERFACE);
- if (result != OC_STACK_OK)
- {
- OC_LOG_V(DEBUG, TAG,
- "To bind Interface (collection) was unsuccessful. result - %d",
- result);
- }
-
- collectionResourceHandleList[collectionResourceType] = collectionResHandle;
-
- // creating master group sync resource
- std::string groupSyncUri = collectionUri + "/groupsync";
- std::string groupSyncResType = collectionResourceType + ".groupsync";
-
- result = OCPlatform::registerResource(groupSyncResHandle, groupSyncUri,
- groupSyncResType, resourceInterface,
- std::bind(&GroupSynchronization::groupEntityHandler, this,
- std::placeholders::_1), OC_DISCOVERABLE | OC_OBSERVABLE);
- if (result != OC_STACK_OK)
- {
- OC_LOG_V(DEBUG, TAG,
- "To register resource (groupsync) was unsuccessful. result - %d", result);
- goto Error;
- }
-
- groupSyncResourceHandleList[collectionResourceType] = groupSyncResHandle;
-
- return OC_STACK_OK;
- }
- Error:
-
- if (collectionResHandle)
- {
- OCPlatform::unregisterResource(collectionResHandle);
- auto iterator = collectionResourceHandleList.find(collectionResourceType);
- if (iterator != collectionResourceHandleList.end())
- {
- collectionResourceHandleList.erase(iterator);
- }
- }
-
- if (groupSyncResHandle)
- {
- OCPlatform::unregisterResource(groupSyncResHandle);
- auto iterator = groupSyncResourceHandleList.find(collectionResourceType);
- if (iterator != groupSyncResourceHandleList.end())
- {
- groupSyncResourceHandleList.erase(iterator);
- }
- }
-
- return OC_STACK_NO_RESOURCE;
- }
-
- OCStackResult GroupSynchronization::joinGroup(std::string collectionResourceType,
- OCResourceHandle resourceHandle)
- {
- std::lock_guard < std::mutex > guard(foundGroupMutex);
- if ((0 == collectionResourceType.length()) || (!resourceHandle))
- {
- OC_LOG(DEBUG, TAG,
- "GroupSynchronization::joinGroup : Error! input params are wrong.");
- return OC_STACK_INVALID_PARAM;
- }
-
- auto resIt = collectionResourceHandleList.find(collectionResourceType);
- if (resIt == collectionResourceHandleList.end())
- {
- OC_LOG(DEBUG, TAG,
- "GroupSynchronization::joinGroup : error! There is no collection to join");
- return OC_STACK_INVALID_PARAM;
- }
-
- OCResourceHandle collectionResHandle = resIt->second;
- try{
- OCStackResult result = OCPlatform::bindResource(collectionResHandle, resourceHandle);
- if (result != OC_STACK_OK)
- {
- OC_LOG_V(DEBUG, TAG,
- "GroupSynchronization::joinGroup : To bind resource was unsuccessful." \
- " result - %d", result);
- return OC_STACK_ERROR;
- }
- } catch(OCException &e) {
- return OC_STACK_INVALID_PARAM;
- }
-
- OC_LOG(DEBUG, TAG,
- "GroupSynchronization::joinGroup : To bind collectionResHandle and resourceHandle");
-
- std::vector< OCResourceHandle > childHandleList;
-
- auto childIt = childResourceHandleList.find(collectionResHandle);
- if (childIt != childResourceHandleList.end())
- {
- childHandleList = childIt->second;
- }
-
- childHandleList.push_back(resourceHandle);
- childResourceHandleList[collectionResHandle] = childHandleList;
-
- deviceResourceHandleList.push_back(resourceHandle);
-
- debugGroupSync();
-
- return OC_STACK_OK;
- }
-
- OCStackResult GroupSynchronization::joinGroup(const std::shared_ptr< OCResource > resource,
- OCResourceHandle resourceHandle)
- {
- std::lock_guard < std::mutex > guard(foundGroupMutex);
- if ((!resource) || (!resourceHandle))
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::joinGroup : Error! Input params are wrong.");
- return OC_STACK_INVALID_PARAM;
- }
-
- OC_LOG(DEBUG, TAG, "GroupSynchronization::joinGroup");
-
- // making representation to join group
- std::string method = "joinGroup";
- std::vector< std::string > type = resource->getResourceTypes();
- std::string resourceType;
- resourceType.append(OCGetResourceTypeName(resourceHandle, 0));
-
- OCRepresentation rep;
- rep.setValue("method", method);
- rep.setValue("collectionResourceType", type[0]);
- rep.setValue("resourceType", resourceType);
-
- OC_LOG_V(DEBUG, TAG, "\tmethod - %s", method.c_str());
- OC_LOG_V(DEBUG, TAG, "\tcollectionResourceType - %s", type[0].c_str());
- OC_LOG_V(DEBUG, TAG, "\tresourceType - %s", resourceType.c_str());
-
- // creating group sync resource with the received collection resource.
- // entity handler of group sync is used to join group.
- std::string host = resource->host();
- std::string uri = resource->uri() + "/groupsync";
-
- std::vector< std::string > resourceTypes;
- std::string temp;
- for (unsigned int i = 0; i < type.size(); ++i)
- {
- temp = type[0] + ".groupsync";
- resourceTypes.push_back(temp);
- }
-
- std::vector< std::string > resourceInterface;
- resourceInterface.push_back(DEFAULT_INTERFACE);
-
- OCResource::Ptr groupSyncResource =
- OCPlatform::constructResourceObject(host, uri,
-
- CT_DEFAULT, false,
- resourceTypes, resourceInterface);
-
- // OCResource::Ptr groupSyncResource = OCPlatform::constructResourceObject(host, uri,
- // OC_WIFI, false, resourceTypes, resourceInterface);
-
- groupSyncResourceList[type[0]] = groupSyncResource;
-
- OC_LOG(DEBUG, TAG, "GroupSynchronization::joinGroup : creating groupSyncResource.");
-
- // Create QueryParameters Map and add query params (if any)
- QueryParamsMap queryParamsMap;
-
- // request to join group to the remote group sync resource
- OCStackResult result = groupSyncResource->put(rep, queryParamsMap,
- std::bind(&GroupSynchronization::onJoinGroup, this, std::placeholders::_1,
- std::placeholders::_2, std::placeholders::_3));
- if (OC_STACK_OK == result)
- {
- OC_LOG(DEBUG, TAG,
- "GroupSynchronization::joinGroup : groupSyncResource->put was successful.");
- }
- else
- {
- OC_LOG_V(DEBUG, TAG,
- "GroupSynchronization::joinGroup : groupSyncResource->put was unsuccessful." \
- "result - %d", result);
- }
-
- // saving the remote collection resource.
- // It is used in onJoinGroup() and onGetJoinedRemoteChild().
- remoteCollectionResource = resource;
-
- // saving the resource handle to join. It is used in onGetJoinedRemoteChild()
- deviceResourceHandle = resourceHandle;
-
- return OC_STACK_OK;
- }
-
- OCStackResult GroupSynchronization::leaveGroup(std::string collectionResourceType,
- OCResourceHandle resourceHandle)
- {
- if ((0 == collectionResourceType.length()) || (!resourceHandle))
- {
- OC_LOG(DEBUG, TAG,
- "GroupSynchronization::leaveGroup : Error! Input params are wrong.");
- return OC_STACK_INVALID_PARAM;
- }
-
- OC_LOG_V(DEBUG, TAG,
- "GroupSynchronization::leaveGroup : collectionResourceType - %s",
- collectionResourceType.c_str());
-
- OCResourceHandle collectionResHandle;
- auto handleIt = groupSyncResourceHandleList.find(collectionResourceType);
-
- // if groupSyncResourceHandleList has resourceType,
- // this app created collection resource handle.
- if (handleIt != groupSyncResourceHandleList.end())
- {
- handleIt = collectionResourceHandleList.find(collectionResourceType);
- if (handleIt == collectionResourceHandleList.end())
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::leaveGroup : Error!" \
- "There is no collection resource handle to leave.");
- return OC_STACK_INVALID_PARAM;
- }
-
- collectionResHandle = handleIt->second;
- if(collectionResHandle == NULL)
- return OC_STACK_INVALID_PARAM;
-
- OCStackResult result;
- try
- {
- result = OCPlatform::unbindResource(collectionResHandle, resourceHandle);
- if (OC_STACK_OK == result)
- {
- OC_LOG(DEBUG, TAG,
- "GroupSynchronization::leaveGroup : To unbind resource was successful.");
- }
- else
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::leaveGroup : " \
- "To unbind resource was unsuccessful. result - %d", result);
- return result;
- }
- } catch(OCException &e) {
- OC_LOG_V(DEBUG, TAG, "ERROR : %s", e.reason().c_str());
- return OC_STACK_NO_RESOURCE;
- }
-
- auto It = std::find(deviceResourceHandleList.begin(), deviceResourceHandleList.end(),
- resourceHandle);
- if (It == deviceResourceHandleList.end()) // there is no resource handle to find
- {
- try
- {
- result = OCPlatform::unregisterResource(resourceHandle);
- if (OC_STACK_OK == result)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::leaveGroup : " \
- "To unregister resource was successful.");
- }
- else
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::leaveGroup : " \
- "To unregister resource was unsuccessful. result - %d", result);
- return result;
- }
- } catch(OCException &e)
- {
- OC_LOG_V(DEBUG, TAG, "ERROR : %s", e.reason().c_str());
- return OC_STACK_NO_RESOURCE;
- }
- }
- else
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::leaveGroup : " \
- "This resource cannot be unregistered.");
- deviceResourceHandleList.erase(It);
- }
-
- auto handleListIt = childResourceHandleList.find(collectionResHandle);
- if (handleListIt == childResourceHandleList.end())
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::leaveGroup : " \
- "Error! There is no child resource list to delete.");
- return OC_STACK_INVALID_PARAM;
- }
-
- std::vector< OCResourceHandle > childList = handleListIt->second;
- auto childIt = std::find(childList.begin(), childList.end(), resourceHandle);
- if (childIt != childList.end())
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::groupEntityHandler : " \
- "Found! The resource to leave is found.");
- childList.erase(childIt);
- }
-
- childResourceHandleList[collectionResHandle] = childList;
-
- debugGroupSync();
- }
-
- return OC_STACK_OK;
- }
-
-OCStackResult GroupSynchronization::leaveGroup(
- const std::shared_ptr<OCResource> resource,
- std::string collectionResourceType, OCResourceHandle resourceHandle)
- {
- if ((!resource) || (!resourceHandle))
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::joinGroup : Error! Input params are wrong.");
- return OC_STACK_INVALID_PARAM;
- }
-
- OC_LOG(DEBUG, TAG, "GroupSynchronization::joinGroup");
-
- // making representation to join group
- std::vector< std::string > type = resource->getResourceTypes();
- std::string host = resource->host();
- std::string uri = resource->uri() + "/groupsync";
-
- std::vector< std::string > resourceTypes;
- std::string temp;
- for (unsigned int i = 0; i < type.size(); ++i)
- {
- temp = type[0] + ".groupsync";
- resourceTypes.push_back(temp);
- }
-
- std::vector< std::string > resourceInterface;
- resourceInterface.push_back(DEFAULT_INTERFACE);
-
- OCResource::Ptr groupSyncResource;
- groupSyncResource = OCPlatform::constructResourceObject(host, uri,
- CT_DEFAULT, false,
- resourceTypes, resourceInterface);
- // groupSyncResource = OCPlatform::constructResourceObject(host, uri,
- // OC_WIFI, false, resourceTypes, resourceInterface);
-
- // making representation to leave group
- std::string method = "leaveGroup";
-// std::string type = OCGetResourceTypeName(collectionResourceType, 0);
- std::string resourceType;
- resourceType.append(OCGetResourceTypeName(resourceHandle, 0));
-
- OCRepresentation rep;
- rep.setValue("method", method);
- rep.setValue("collectionResourceType", collectionResourceType);
- rep.setValue("resourceType", resourceType);
-
- OC_LOG_V(DEBUG, TAG, "\tmethod - %s", method.c_str());
- OC_LOG_V(DEBUG, TAG, "\tcollectionResourceType - %s", collectionResourceType.c_str());
- OC_LOG_V(DEBUG, TAG, "\tresourceType - %s", resourceType.c_str());
-
- QueryParamsMap queryParamsMap;
-
- // request to leave group to the remote group sync resource
- OCStackResult result = groupSyncResource->put(rep, queryParamsMap,
- std::bind(&GroupSynchronization::onLeaveGroup, this, std::placeholders::_1,
- std::placeholders::_2, std::placeholders::_3));
- if (OC_STACK_OK == result)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::leaveGroup : " \
- "groupSyncResource->put was successful.");
- }
- else
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::leaveGroup : " \
- "groupSyncResource->put was unsuccessful. result - %d", result);
- }
- return result;
- }
-
- void GroupSynchronization::deleteGroup(std::string collectionResourceType)
- {
- if (0 == collectionResourceType.length())
- {
- OC_LOG(DEBUG, TAG,
- "GroupSynchronization::deleteGroup : Error! Input params are wrong.");
- return;
- }
-
- OC_LOG(DEBUG, TAG, "GroupSynchronization::deleteGroup");
-
- OCStackResult result;
- OCResourceHandle resourceHandle;
-
- auto handleIt = groupSyncResourceHandleList.find(collectionResourceType);
-
- // if groupSyncResourceHandleList has resourceType,
- // group sync of this app created collection resource.
- if (handleIt != groupSyncResourceHandleList.end())
- {
- resourceHandle = handleIt->second; // group sync resource handle
- result = OCPlatform::unregisterResource(resourceHandle);
- if (OC_STACK_OK == result)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::deleteGroup : " \
- "To unregister group sync resource handle was successful.");
- }
- else
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::deleteGroup : " \
- "To unregister group sync resource handle was unsuccessful. " \
- "result - %d", result);
- }
-
- groupSyncResourceHandleList.erase(handleIt);
- }
-
- auto resourceIt = groupSyncResourceList.find(collectionResourceType);
- if (resourceIt != groupSyncResourceList.end())
- {
- groupSyncResourceList.erase(resourceIt);
- }
-
- handleIt = collectionResourceHandleList.find(collectionResourceType);
- if (handleIt == collectionResourceHandleList.end())
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::deleteGroup : " \
- "Error! There is no collection resource handle to delete.");
- return;
- }
- OCResourceHandle collectionResHandle = handleIt->second;
-
- collectionResourceHandleList.erase(handleIt);
-
- auto handleListIt = childResourceHandleList.find(collectionResHandle);
- if (handleListIt == childResourceHandleList.end())
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::deleteGroup : " \
- "There is no child resource list to delete.");
-
- result = OCPlatform::unregisterResource(collectionResHandle);
- if (result == OC_STACK_OK)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::deleteGroup : " \
- "To unregister collection resource handle was successful.");
- }
- else
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::deleteGroup : " \
- " To unregister collection resource handle was unsuccessful. result - %d",
- result);
- }
-
- debugGroupSync();
- return;
- }
-
- std::vector< OCResourceHandle > childList = handleListIt->second;
-
- childResourceHandleList.erase(handleListIt);
-
- result = OCPlatform::unbindResources(collectionResHandle, childList);
- if (OC_STACK_OK == result)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::deleteGroup : " \
- "To unbind resources was successful.");
- }
- else
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::deleteGroup : " \
- "To unbind resources was unsuccessful. result - %d", result);
- }
-
- result = OCPlatform::unregisterResource(collectionResHandle);
- if (result == OC_STACK_OK)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::deleteGroup : " \
- "To unregister collection resource handle was successful.");
- }
- else
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::deleteGroup : " \
- " To unregister collection resource handle was unsuccessful. result - %d",
- result);
- }
-
- std::vector< OCResourceHandle >::iterator It;
-
- for (unsigned int i = 0; i < childList.size(); i++)
- {
- resourceHandle = childList.at(i);
-
- It = std::find(deviceResourceHandleList.begin(), deviceResourceHandleList.end(),
- resourceHandle);
- if (It != deviceResourceHandleList.end()) // find !!
- {
- deviceResourceHandleList.erase(It);
- }
- else
- {
- result = OCPlatform::unregisterResource(resourceHandle);
- if (OC_STACK_OK == result)
- {
- OC_LOG_V(DEBUG, TAG,
- "GroupSynchronization::deleteGroup : UnregisterResource(%d)" \
- " was successful.", i + 1);
- }
- else
- {
- OC_LOG_V(DEBUG, TAG,
- "GroupSynchronization::deleteGroup : UnregisterResource(%d)" \
- " was unsuccessful. result - ", i + 1, result);
- }
- }
- }
-
- debugGroupSync();
- }
-
- std::map< std::string, OCResourceHandle > GroupSynchronization::getGroupList()
- {
- return collectionResourceHandleList;
- }
-
- OCEntityHandlerResult GroupSynchronization::groupEntityHandler(
- const std::shared_ptr< OCResourceRequest > request)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::groupEntityHandler");
-
- if (request)
- {
- // Get the request type and request flag
- std::string requestType = request->getRequestType();
- int requestFlag = request->getRequestHandlerFlag();
-
- if (requestFlag == RequestHandlerFlag::RequestFlag)
- {
- OC_LOG(DEBUG, TAG, "\trequestFlag : Request");
-
- // If the request type is GET
- if (requestType == "GET")
- {
- OC_LOG(DEBUG, TAG, "\t\trequestType : GET");
- }
- else if (requestType == "PUT")
- {
- OC_LOG(DEBUG, TAG, "\t\trequestType : PUT");
-
- //get method name, group resource type and resource type to join group
- OCRepresentation rp = request->getResourceRepresentation();
- std::string methodType = rp.getValue< std::string >("method");
- std::string collectionResourceType = rp.getValue< std::string >(
- "collectionResourceType");
- std::string resourceType = rp.getValue< std::string >("resourceType");
-
- OC_LOG_V(DEBUG, TAG, "\t\t\tmethod : %s", methodType.c_str());
- OC_LOG_V(DEBUG, TAG, "\t\t\tcollection resourceType : %s",
- collectionResourceType.c_str());
- OC_LOG_V(DEBUG, TAG, "\t\t\tresourceType : %s", resourceType.c_str());
-
- auto handleIt = collectionResourceHandleList.find(collectionResourceType);
- if (handleIt == collectionResourceHandleList.end())
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::groupEntityHandler : " \
- "Error! There is no collection resource handle to delete.");
- return OC_EH_ERROR;
- }
- collectionResourceHandle = handleIt->second;
- // in case of join group it is used in onFindResource()
-
- if (methodType == "joinGroup")
- {
- std::string resourceName = OC_RSRVD_WELL_KNOWN_URI;
- resourceName.append("?rt=");
- resourceName.append(resourceType);
- OC_LOG_V(DEBUG, TAG, "\t\t\tresourceName : %s", resourceName.c_str());
-
- resourceRequest = request;
-
- OCPlatform::findResource("", resourceName,
- CT_DEFAULT,
- std::bind(&GroupSynchronization::onFindResource, this,
- std::placeholders::_1));
-
- return OC_EH_SLOW;
- }
- else if (methodType == "leaveGroup")
- {
- auto it = childResourceHandleList.find(collectionResourceHandle);
- if (it == childResourceHandleList.end())
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::groupEntityHandler : " \
- "Error! There is no child resource list.");
- return OC_EH_ERROR;
- }
-
- std::vector< OCResourceHandle > childList = it->second;
- OCResourceHandle resourceHandle;
- for (auto childIt = childList.begin(); childIt != childList.end();)
- {
- resourceHandle = (*childIt);
- char* type = (char*) OCGetResourceTypeName(resourceHandle, 0);
-
- if (0 == resourceType.compare(type))
- {
- OC_LOG_V(DEBUG, TAG,
- "GroupSynchronization::groupEntityHandler : " \
- "Found! The resource to leave is found. - %s", type);
-
- childIt = childList.erase(childIt++);
-
- OCStackResult result = OCPlatform::unbindResource(
- collectionResourceHandle, resourceHandle);
- if (OC_STACK_OK == result)
- {
- OC_LOG(DEBUG, TAG,
- "GroupSynchronization::groupEntityHandler : " \
- "To unbind resource was successful.");
- }
- else
- {
- OC_LOG_V(DEBUG, TAG,
- "GroupSynchronization::groupEntityHandler : " \
- "To unbind resource was unsuccessful. result - %d",
- result);
- }
-
- result = OCPlatform::unregisterResource(resourceHandle);
- if (OC_STACK_OK == result)
- {
- OC_LOG(DEBUG, TAG,
- "GroupSynchronization::groupEntityHandler : " \
- "To unregister resource was successful.");
- }
- else
- {
- OC_LOG_V(DEBUG, TAG,
- "GroupSynchronization::groupEntityHandler : "
- "To unregister resource was unsuccessful. result - %d",
- result);
- }
- }
- else
- {
- ++childIt;
- }
-
- }
-
- childResourceHandleList[collectionResourceHandle] = childList;
-
- debugGroupSync();
-
- auto pResponse = std::make_shared< OC::OCResourceResponse >();
- pResponse->setRequestHandle(request->getRequestHandle());
- pResponse->setResourceHandle(request->getResourceHandle());
- pResponse->setErrorCode(200);
- pResponse->setResponseResult(OC_EH_OK);
-
- OCRepresentation rep = request->getResourceRepresentation();
- pResponse->setResourceRepresentation(rep, DEFAULT_INTERFACE);
- if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::groupEntityHandler : " \
- "sendResponse is successful.");
- }
- }
-
- if (methodType != "") //TODO: Check groupmethodtype NULL
- {
- }
- }
- else if (requestType == "POST")
- {
- // POST request operations
- }
- else if (requestType == "DELETE")
- {
- // DELETE request operations
- }
- }
- else if (requestFlag == RequestHandlerFlag::ObserverFlag)
- {
- OC_LOG(DEBUG, TAG, "\trequestFlag : Observer");
- }
- }
- else
- {
- OC_LOG(DEBUG, TAG, "Request invalid");
- }
-
- return OC_EH_OK;
- }
-
- void GroupSynchronization::onFindGroup(std::shared_ptr< OCResource > resource)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::onFindGroup");
-
- try
- {
- if (resource)
- {
- // Debugging
- std::string resourceURI;
- std::string hostAddress;
-
- // Get the resource URI
- resourceURI = resource->uri();
- OC_LOG_V(DEBUG, TAG, "\tURI of the resource: %s", resourceURI.c_str());
-
- // Get the resource host address
- hostAddress = resource->host();
- OC_LOG_V(DEBUG, TAG, "\tHost address of the resource: %s", hostAddress.c_str());
-
- hostAddress.append(resourceURI);
-
-#ifndef NDEBUG
- // Get the resource types
- OC_LOG(DEBUG, TAG, "\tList of resource types: ");
- for (auto &resourceTypes : resource->getResourceTypes())
- {
- OC_LOG_V(DEBUG, TAG, "\t\t", resourceTypes.c_str());
- }
-
- // Get the resource interfaces
- OC_LOG(DEBUG, TAG, "\tList of resource interfaces: ");
- for (auto &resourceInterfaces : resource->getResourceInterfaces())
- {
- OC_LOG_V(DEBUG, TAG, "\t\t", resourceInterfaces.c_str());
- }
-#endif
-
- if (false == IsSameGroup(resource))
- {
- saveGroup(resource);
- findCallback(resource);
- }
- }
- else
- {
- // Resource is invalid
- OC_LOG(DEBUG, TAG, "Resource is invalid");
- findCallback(NULL);
- }
-
- bIsFinding = false;
- }
- catch (std::exception& e)
- {
- //log(e.what());
- }
- }
-
- void GroupSynchronization::checkFindGroup(void)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::checkFindGroup");
-
- for (int i = 0; i < 15; i++)
- {
- std::chrono::milliseconds workTime(300);
- std::this_thread::sleep_for(workTime);
-
- std::lock_guard < std::mutex > guard(foundGroupMutex);
-
- if (false == foundGroupResourceList.empty())
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::checkFoundGroup : " \
- "Some group is received.");
- return;
- }
- }
-
- OC_LOG(DEBUG, TAG, "GroupSynchronization::checkFoundGroup : " \
- "It is failed to find resource within 3s.");
-
- onFindGroup(NULL);
- return;
- }
-
- bool GroupSynchronization::IsSameGroup(std::shared_ptr< OCResource > resource)
- {
- std::lock_guard < std::mutex > guard(foundGroupMutex);
-
- if (true == foundGroupResourceList.empty())
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::IsSameGroup : There is no found group.");
- return false;
- }
-
- std::string foundHostAddress, savedHostAddress;
- std::string foundHostUri, savedHostUri;
- foundHostAddress = resource->host();
- foundHostUri = resource->uri();
-
- for (unsigned int i = 0; i < foundGroupResourceList.size(); ++i)
- {
- savedHostAddress = (foundGroupResourceList.at(i))->host();
- savedHostUri = (foundGroupResourceList.at(i))->uri();
-
- if (0 == foundHostAddress.compare(savedHostAddress.c_str()))
- {
- if( 0 == foundHostUri.compare(savedHostAddress) )
- {
- OC_LOG(DEBUG, TAG,
- "GroupSynchronization::IsSameGroup : Found! The same group is found.");
- return true;
- }
- }
- }
-
- OC_LOG(DEBUG, TAG, "GroupSynchronization::IsSameGroup : There is no same group.");
- return false;
- }
-
- void GroupSynchronization::saveGroup(std::shared_ptr< OCResource > resource)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::saveGroup");
-
- std::lock_guard < std::mutex > guard(foundGroupMutex);
-
- foundGroupResourceList.push_back(resource);
- }
-
- void GroupSynchronization::onJoinGroup(const HeaderOptions& headerOptions,
- const OCRepresentation& rep, const int eCode)
- {
- if (eCode != OC_STACK_OK)
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::onJoinGroup : error - %d", eCode);
- return;
- }
- }
-
- void GroupSynchronization::onFindResource(std::shared_ptr< OCResource > resource)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::onFindResource");
-
- if (resource)
- {
- if(NULL == collectionResourceHandle)
- return;
-
- // start of debugging
- std::string resourceURI;
- std::string hostAddress;
-
- // Get the resource URI
- resourceURI = resource->uri();
- OC_LOG_V(DEBUG, TAG, "\tURI of the resource: %s", resourceURI.c_str());
-
- // Get the resource host address
- hostAddress = resource->host();
- OC_LOG_V(DEBUG, TAG, "\tHost address of the resource: %s", hostAddress.c_str());
-
- hostAddress.append(resourceURI);
-
-#ifndef NDEBUG
- // Get the resource types
- OC_LOG(DEBUG, TAG, "\tList of resource types: ");
- for (auto &resourceTypes : resource->getResourceTypes())
- {
- OC_LOG_V(DEBUG, TAG, "\t\t%s", resourceTypes.c_str());
- }
-
- // Get the resource interfaces
- OC_LOG(DEBUG, TAG, "\tList of resource interfaces: ");
- for (auto &resourceInterfaces : resource->getResourceInterfaces())
- {
- OC_LOG_V(DEBUG, TAG, "\t\t%s", resourceInterfaces.c_str());
- }
- // end of debugging
-#endif
-
- OCResourceHandle resourceHandle;
- OCStackResult result = OCPlatform::registerResource(resourceHandle, resource);
- if (result != OC_STACK_OK)
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::" \
- "onFindResource - Resource to join creation was unsuccessful. result - %d",
- result);
- return;
- }
-
- result = OCPlatform::bindResource(collectionResourceHandle, resourceHandle);
- if (result != OC_STACK_OK)
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::onFindResource : " \
- "To bind resource was unsuccessful. result - %d", result);
- return;
- }
-
- OC_LOG(DEBUG, TAG, "GroupSynchronization::onFindResource : " \
- "To bind joinGroupHandle and resourceHandle was successful.");
-
- auto it = childResourceHandleList.find(collectionResourceHandle);
- std::vector< OCResourceHandle > childHandleList;
- if (it != childResourceHandleList.end())
- {
- childHandleList = it->second;
- }
-
- childHandleList.push_back(resourceHandle);
- childResourceHandleList[collectionResourceHandle] = childHandleList;
-
- auto pResponse = std::make_shared< OC::OCResourceResponse >();
- pResponse->setRequestHandle(resourceRequest->getRequestHandle());
- pResponse->setResourceHandle(resourceRequest->getResourceHandle());
- pResponse->setErrorCode(200);
- pResponse->setResponseResult(OC_EH_OK);
-
- OCRepresentation rep = resourceRequest->getResourceRepresentation();
- pResponse->setResourceRepresentation(rep);
- try{
- if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
- {
- OC_LOG(DEBUG, TAG,
- "GroupSynchronization::onFindResource : sendResponse is successful.");
- }
- }
- catch( OCException &e )
- {
- // OC_LOG(DEBUG, TAG, e.what);
- return;
- }
- }
- else
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::onFindResource : " \
- "Resource is invalid. So a new Group Resource has to be created.");
- }
-
- debugGroupSync();
- }
-
- void GroupSynchronization::onGetJoinedRemoteChild(const HeaderOptions& headerOptions,
- const OCRepresentation& rep, const int eCode)
- {
- if (eCode != OC_STACK_OK)
- {
- OC_LOG_V(DEBUG, TAG,
- "GroupSynchronization::onGetJoinedRemoteChild : error - %d", eCode);
- return;
- }
-
- std::string resourceURI;
- std::vector< OCRepresentation > childList;
- OCRepresentation child;
-
- OC_LOG(DEBUG, TAG, "GroupSynchronization::onGetJoinedRemoteChild");
-#ifndef NDEBUG
- // debugging
- // Get the resource URI
- resourceURI = rep.getUri();
- OC_LOG_V(DEBUG, TAG, "\tURI of the resource: %s", resourceURI.c_str());
-
- // Get the resource types
- OC_LOG(DEBUG, TAG, "\tList of resource types: ");
-
- for (auto &resourceTypes : rep.getResourceTypes())
- {
- OC_LOG_V(DEBUG, TAG, "\t\t%s", resourceTypes.c_str());
- }
-
- // Get the resource interfaces
- OC_LOG(DEBUG, TAG, "\tList of resource interfaces: ");
- for (auto &resourceInterfaces : rep.getResourceInterfaces())
- {
- OC_LOG_V(DEBUG, TAG, "\t\t%s", resourceInterfaces.c_str());
- }
-
- childList = rep.getChildren();
- for (unsigned int i = 0; i < childList.size(); ++i)
- {
- OC_LOG_V(DEBUG, TAG, "\tchild resource - %d", i + 1);
-
- child = childList.at(i);
- resourceURI = child.getUri();
- OC_LOG_V(DEBUG, TAG, "\t\tURI of the resource: %s", resourceURI.c_str());
-
- OC_LOG_V(DEBUG, TAG, "\t\tList of resource types: ");
- for (auto &types : child.getResourceTypes())
- {
- OC_LOG_V(DEBUG, TAG, "\t\t\t%s", types.c_str());
- }
-
- OC_LOG(DEBUG, TAG, "\tList of resource interfaces: ");
- for (auto &interfaces : child.getResourceInterfaces())
- {
- OC_LOG_V(DEBUG, TAG, "\t\t\t%s", interfaces.c_str());
- }
- }
-#endif
-
- // creating remote collection resource handle
- OCResourceHandle remoteCollectionResourceHandle;
- resourceURI = remoteCollectionResource->uri();
- std::vector< std::string > types = remoteCollectionResource->getResourceTypes();
- std::vector< std::string > interfaces = remoteCollectionResource->getResourceInterfaces();
-
- OCStackResult result = OCPlatform::registerResource(remoteCollectionResourceHandle,
- resourceURI, types[0], interfaces[0], NULL, OC_OBSERVABLE);
- if (result != OC_STACK_OK)
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::onGetJoinedRemoteChild - " \
- "To register remoteCollectionResourceHandle" \
- " was unsuccessful. result - %d", result);
- return;
- }
- OC_LOG(DEBUG, TAG, "GroupSynchronization::onGetJoinedRemoteChild : " \
- "To register remoteCollectionResourceHandle was successful.");
-
- // binding remote collection resource handle and resource handle to join
- collectionResourceHandleList[types[0]] = remoteCollectionResourceHandle;
-
- result = OCPlatform::bindResource(remoteCollectionResourceHandle, deviceResourceHandle);
- if (OC_STACK_OK == result)
- {
- OC_LOG(DEBUG, TAG, "GroupSynchronization::onGetJoinedRemoteChild : " \
- "binding remoteCollectionResourceHandle and deviceResourceHandle");
- }
- else
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::onGetJoinedRemoteChild - " \
- "To bind remoteCollectionResourceHandle and deviceResourceHandle " \
- "was unsuccessful. result - %d", result);
- }
-
- std::vector< OCResourceHandle > childHandleList;
- childHandleList.push_back(deviceResourceHandle);
- deviceResourceHandleList.push_back(deviceResourceHandle);
-
- // binding copied remote collection resource handle and copied remote resource
- OCResourceHandle resourceHandle;
- for (unsigned int i = 0; i < childList.size(); ++i)
- {
- OC_LOG_V(DEBUG, TAG, "\tremote resource - %d", i + 1);
-
- child = childList.at(i);
- resourceURI = child.getUri();
- types = child.getResourceTypes();
- interfaces = child.getResourceInterfaces();
-
- if (0 == types[0].compare(OCGetResourceTypeName(deviceResourceHandle, 0)))
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::onGetJoinedRemoteChild : %s" \
- " is bind already.", types[0].c_str());
- continue;
- }
-
- result = OCPlatform::registerResource(resourceHandle, resourceURI, types[0],
- interfaces[0], NULL, OC_OBSERVABLE);
- if (OC_STACK_OK == result)
- {
- result = OCPlatform::bindResource(remoteCollectionResourceHandle, resourceHandle);
- if (result != OC_STACK_OK)
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::onGetJoinedRemoteChild - " \
- "binding remoteCollectionResourceHandle and resourceHandle " \
- "was unsuccessful. result - %d", result);
- OCPlatform::unregisterResource(resourceHandle);
- }
-
- childHandleList.push_back(resourceHandle);
- OC_LOG(DEBUG, TAG, "GroupSynchronization::onGetJoinedRemoteChild : " \
- "binding remoteCollectionResourceHandle and resourceHandle");
- }
- else
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::onGetJoinedRemoteChild - " \
- "To register remoteCollectionResourceHandle was unsuccessful." \
- " result - %d", result);
- }
- }
-
- childResourceHandleList[remoteCollectionResourceHandle] = childHandleList;
- // this handle list is used to leave group
-
- debugGroupSync();
- }
-
- void GroupSynchronization::onLeaveGroup(const HeaderOptions& headerOptions,
- const OCRepresentation& rep, const int eCode)
- {
- if (eCode != OC_STACK_OK)
- {
- OC_LOG_V(DEBUG, TAG, "GroupSynchronization::onLeaveGroup : error - %d", eCode);
- return;
- }
-
- OC_LOG(DEBUG, TAG, "GroupSynchronization::onLeaveGroup");
- debugGroupSync();
- }
-
- void GroupSynchronization::debugGroupSync(void)
- {
-#ifndef NDEBUG
- OC_LOG(DEBUG, TAG, "GroupSynchronization::debugGroupSync");
-
- unsigned int i;
- std::map< std::string, OCResourceHandle >::iterator handleIt;
- std::map< OCResourceHandle, std::vector< OCResourceHandle > >::iterator childIt;
- std::string type;
- OCResourceHandle resourceHandle;
- std::vector< OCResourceHandle > handleList;
- std::shared_ptr< OCResource > resource;
-
- OC_LOG(DEBUG, TAG, "Resource Handle Created by App");
- for (i = 0; i < deviceResourceHandleList.size(); i++)
- {
- resourceHandle = deviceResourceHandleList.at(i);
-
- OC_LOG_V(DEBUG, TAG, "%d. details", i + 1);
- OC_LOG_V(DEBUG, TAG, "\turi - %s", OCGetResourceUri(resourceHandle));
- OC_LOG_V(DEBUG, TAG, "\tresource type - %s",
- OCGetResourceTypeName(resourceHandle, 0));
- OC_LOG_V(DEBUG, TAG, "\tresource interface - %s",
- OCGetResourceInterfaceName(resourceHandle, 0));
- }
-
- OC_LOG_V(DEBUG, TAG, "Group Sync Resource Handle List. The number is %d",
- groupSyncResourceHandleList.size());
-
- i = 1;
- for (handleIt = groupSyncResourceHandleList.begin();
- handleIt != groupSyncResourceHandleList.end(); ++handleIt)
- {
- type = handleIt->first;
- OC_LOG_V(DEBUG, TAG, "\t%d. group sync resource type - %s", i, type.c_str());
- OC_LOG(DEBUG, TAG, "\tdetails");
-
- resourceHandle = handleIt->second;
- OC_LOG_V(DEBUG, TAG, "\turi - %s",
- OCGetResourceUri(resourceHandle));
- OC_LOG_V(DEBUG, TAG, "\tresource type - %s",
- OCGetResourceTypeName(resourceHandle, 0));
- OC_LOG_V(DEBUG, TAG, "\tresource interface - %s",
- OCGetResourceInterfaceName(resourceHandle, 0));
-
- i++;
- }
-
- OC_LOG_V(DEBUG, TAG, "Copied Remote Group Sync Resource List. The number is %d",
- groupSyncResourceList.size());
- std::vector< std::string > list;
- i = 1;
- for (auto resourceIt = groupSyncResourceList.begin();
- resourceIt != groupSyncResourceList.end(); ++resourceIt)
- {
- type = resourceIt->first;
- OC_LOG_V(DEBUG, TAG, "\t%d. group sync resource type - %s", i, type.c_str());
- OC_LOG(DEBUG, TAG, "\tdetails");
-
- resource = resourceIt->second;
- OC_LOG_V(DEBUG, TAG, "\thost - %s", resource->host().c_str());
- OC_LOG_V(DEBUG, TAG, "\turi - %s", resource->uri().c_str());
- list = resource->getResourceTypes();
- OC_LOG_V(DEBUG, TAG, "\tresource type - %s", list[0].c_str());
- list = resource->getResourceInterfaces();
- OC_LOG_V(DEBUG, TAG, "\tresource interface - %s", list[0].c_str());
- i++;
- }
-
- OC_LOG(DEBUG, TAG, "Collection Resource Handle List");
- i = 1;
- for (handleIt = collectionResourceHandleList.begin();
- handleIt != collectionResourceHandleList.end(); ++handleIt)
- {
- type = handleIt->first;
- OC_LOG_V(DEBUG, TAG, "\t%d. collection resource type - %s", i, type.c_str());
- OC_LOG(DEBUG, TAG, "\tdetails");
-
- resourceHandle = handleIt->second;
- OC_LOG_V(DEBUG, TAG, "\turi - %s", OCGetResourceUri(resourceHandle));
- OC_LOG_V(DEBUG, TAG, "\tresource type - %s",
- OCGetResourceTypeName(resourceHandle, 0));
- OC_LOG_V(DEBUG, TAG, "\tresource interface - %s",
- OCGetResourceInterfaceName(resourceHandle, 0));
-
- childIt = childResourceHandleList.find(resourceHandle);
- if (childIt != childResourceHandleList.end())
- {
- handleList = childIt->second;
- for (unsigned int j = 0; j < handleList.size(); j++)
- {
-
- OC_LOG_V(DEBUG, TAG, "\t\t%d. child resource details", j + 1);
-
- resourceHandle = handleList.at(j);
- OC_LOG_V(DEBUG, TAG, "\t\turi - %s",
- OCGetResourceUri(resourceHandle));
- OC_LOG_V(DEBUG, TAG, "\t\tresource type - %s",
- OCGetResourceTypeName(resourceHandle, 0));
- OC_LOG_V(DEBUG, TAG, "\t\tresource interface - %s",
- OCGetResourceInterfaceName(resourceHandle, 0));
- }
- }
- i++;
- }
-#endif
- }
-}
+++ /dev/null
-//******************************************************************
-//
-// 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.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/**
- * @file
- *
- * This file contains the declaration of classes and its members related to
- * GroupSynchronization.
- */
-
-#ifndef __OC_GROUPSYNCHRONIZATION__
-#define __OC_GROUPSYNCHRONIZATION__
-
-#include <string>
-#include <vector>
-#include <map>
-#include <cstdlib>
-#include "OCPlatform.h"
-#include "OCApi.h"
-
-using namespace OC;
-
-namespace OIC
-{
-class GroupSynchronization
-{
-private:
-
- std::map< std::string, OCResourceHandle > collectionResourceHandleList;
- // collection resource handle list
- std::map< OCResourceHandle, std::vector< OCResourceHandle > > childResourceHandleList;
-
- std::map< std::string, OCResourceHandle > groupSyncResourceHandleList;
- // group sync resource handle list
- std::map< std::string, std::shared_ptr< OCResource > > groupSyncResourceList;
- // remote group sync resource list
-
- std::vector< OCResourceHandle > deviceResourceHandleList; // these cannot be removed.
- OCResourceHandle deviceResourceHandle;
-
- OCResourceHandle collectionResourceHandle; // collection handle
- std::shared_ptr< OCResource > remoteCollectionResource;
-
- FindCallback findCallback;
-
- std::vector< std::shared_ptr< OCResource > > foundGroupResourceList;
-
- std::mutex foundGroupMutex;
-// std::mutex groupSyncMutex;
-
- std::shared_ptr< OCResourceRequest > resourceRequest; // this is used for slow response
-
- static GroupSynchronization* groupSyncnstance;
- static bool bIsFinding;
-
- GroupSynchronization()
- {
- collectionResourceHandleList.clear();
- childResourceHandleList.clear();
- groupSyncResourceHandleList.clear();
- groupSyncResourceList.clear();
- deviceResourceHandleList.clear();
-
- deviceResourceHandle = NULL;
- collectionResourceHandle = NULL;
- remoteCollectionResource = NULL;
- findCallback = NULL;
- }
- ;
-
- ~GroupSynchronization()
- {
- std::map< std::string, OCResourceHandle >::iterator handleIt;
- for (handleIt = collectionResourceHandleList.begin();
- handleIt != collectionResourceHandleList.end(); ++handleIt)
- {
- deleteGroup(handleIt->first);
- }
- }
- ;
-
-public:
-
- static GroupSynchronization* getInstance();
- void deleteInstance();
-
- OCStackResult findGroup(std::vector< std::string > collectionResourceTypes,
- FindCallback callback);
- OCStackResult createGroup(std::string collectionResourceType);
- OCStackResult joinGroup(std::string collectionResourceTyps,
- OCResourceHandle resourceHandle);
- OCStackResult joinGroup(const std::shared_ptr< OCResource > resource,
- OCResourceHandle resourceHandle);
- OCStackResult leaveGroup(std::string collectionResourceType,
- OCResourceHandle resourceHandle);
- OCStackResult leaveGroup(const std::shared_ptr< OCResource > resource,
- std::string collectionResourceType,
- OCResourceHandle resourceHandle);
- void deleteGroup(std::string collectionResourceType);
-
- std::map< std::string, OCResourceHandle > getGroupList();
-
-private:
-
- OCEntityHandlerResult groupEntityHandler(
- const std::shared_ptr< OCResourceRequest > request);
-
- void onFindGroup(std::shared_ptr< OCResource > resource);
- void onJoinGroup(const HeaderOptions& headerOptions, const OCRepresentation& rep,
- const int eCode);
- void onFindResource(std::shared_ptr< OCResource > resource);
- void onGetJoinedRemoteChild(const HeaderOptions& headerOptions, const OCRepresentation& rep,
- const int eCode);
- void onLeaveGroup(const HeaderOptions& headerOptions, const OCRepresentation& rep,
- const int eCode);
-// void onSubscribePresence (OCStackResult result,
-// const unsigned int nonce/*, std::string resourceType, std::string host*/);
-
- void checkFindGroup(void);
- bool IsSameGroup(std::shared_ptr< OCResource > resource);
- void saveGroup(std::shared_ptr< OCResource > resource);
-
- void debugGroupSync(void);
-
-};
-}
-#endif // __OC_GROUPSYNCHRONIZATION__
ConfigurationUnitInfo unit[] =
{
{ "all", "All attributes", "/oic/con" },
- { "r", "Region", "/oic/con" },
- { "st", "System Time", "/oic/con"},
+ { "n", "Device Name", "/oic/con"},
{ "loc", "Location", "/oic/con"},
+ { "locn", "Location Name", "/oic/con"},
+ { "r", "Region", "/oic/con" },
{ "c","Currency", "/oic/con" } };
for (int i = 0; i < NUMCONFUNIT; i++)
#include <OCPlatform.h>
#include <cstdlib>
-#include "ThingsDiagnostics.h"
+#include "ThingsMaintenance.h"
using namespace OC;
namespace OIC
{
- std::map< std::string, DiagnosticsRequestEntry > diagnosticsRequestTable;
- ThingsDiagnostics* ThingsDiagnostics::thingsDiagnosticsInstance = NULL;
+ std::map< std::string, MaintenanceRequestEntry > maintenanceRequestTable;
+ ThingsMaintenance* ThingsMaintenance::thingsMaintenanceInstance = NULL;
- DiagnosticsRequestEntry::DiagnosticsRequestEntry(std::string ID, DiagnosticsCallback callback,
+ MaintenanceRequestEntry::MaintenanceRequestEntry(std::string ID, MaintenanceCallback callback,
std::shared_ptr< OCResource > resource, std::string updateVal)
{
m_ID = ID;
m_updateVal = updateVal;
}
- DiagnosticsUnitInfo::DiagnosticsUnitInfo(std::string name,
+ MaintenanceUnitInfo::MaintenanceUnitInfo(std::string name,
std::string attribute,
std::string uri)
{
m_uri = uri;
}
- std::string DiagnosticsUnitInfo::getJSON()
+ std::string MaintenanceUnitInfo::getJSON()
{
std::string res;
return res;
}
- ThingsDiagnostics::ThingsDiagnostics()
+ ThingsMaintenance::ThingsMaintenance()
{
- DiagnosticsUnitInfo unit[] =
+ MaintenanceUnitInfo unit[] =
{
- { "rb", "Reboot", "/oic/diag"},
- { "ssc", "StartStatCollection", "/oic/diag"},
- { "fr", "Factory Reset", "/oic/diag" } };
+ { "rb", "Reboot", "/oic/mnt"},
+ { "ssc", "StartStatCollection", "/oic/mnt"},
+ { "fr", "Factory Reset", "/oic/mnt" } };
for (int i = 0; i < NUMDIAGUNIT; i++)
- DiagnosticsUnitTable.push_back(unit[i]);
+ MaintenanceUnitTable.push_back(unit[i]);
}
- ThingsDiagnostics::~ThingsDiagnostics()
+ ThingsMaintenance::~ThingsMaintenance()
{
}
- void ThingsDiagnostics::setGroupManager(GroupManager *groupmanager)
+ void ThingsMaintenance::setGroupManager(GroupManager *groupmanager)
{
g_groupmanager = groupmanager;
}
- ThingsDiagnostics* ThingsDiagnostics::getInstance()
+ ThingsMaintenance* ThingsMaintenance::getInstance()
{
- if (thingsDiagnosticsInstance == NULL)
+ if (thingsMaintenanceInstance == NULL)
{
- thingsDiagnosticsInstance = new ThingsDiagnostics();
+ thingsMaintenanceInstance = new ThingsMaintenance();
}
- return thingsDiagnosticsInstance;
+ return thingsMaintenanceInstance;
}
- void ThingsDiagnostics::deleteInstance()
+ void ThingsMaintenance::deleteInstance()
{
- if (thingsDiagnosticsInstance)
+ if (thingsMaintenanceInstance)
{
- delete thingsDiagnosticsInstance;
- thingsDiagnosticsInstance = NULL;
+ delete thingsMaintenanceInstance;
+ thingsMaintenanceInstance = NULL;
}
}
- std::string ThingsDiagnostics::getAttributeByDiagnosticsName(DiagnosticsName name)
+ std::string ThingsMaintenance::getAttributeByMaintenanceName(MaintenanceName name)
{
- for (auto it = DiagnosticsUnitTable.begin(); DiagnosticsUnitTable.end() != it; it++)
+ for (auto it = MaintenanceUnitTable.begin(); MaintenanceUnitTable.end() != it; it++)
{
if ((*it).m_name == name)
return (*it).m_attribute;
return "";
}
- std::string ThingsDiagnostics::getUriByDiagnosticsName(DiagnosticsName name)
+ std::string ThingsMaintenance::getUriByMaintenanceName(MaintenanceName name)
{
- for (auto it = DiagnosticsUnitTable.begin(); DiagnosticsUnitTable.end() != it; it++)
+ for (auto it = MaintenanceUnitTable.begin(); MaintenanceUnitTable.end() != it; it++)
{
if ((*it).m_name == name)
return (*it).m_uri;
return "";
}
- std::string ThingsDiagnostics::getUpdateVal(std::string diag)
+ std::string ThingsMaintenance::getUpdateVal(std::string mnt)
{
- std::map< std::string, DiagnosticsRequestEntry >::iterator it =
- diagnosticsRequestTable.find(diag);
+ std::map< std::string, MaintenanceRequestEntry >::iterator it =
+ maintenanceRequestTable.find(mnt);
- if (it == diagnosticsRequestTable.end())
+ if (it == maintenanceRequestTable.end())
return NULL;
else
return it->second.m_updateVal;
}
- std::shared_ptr< OCResource > ThingsDiagnostics::getResource(std::string diag)
+ std::shared_ptr< OCResource > ThingsMaintenance::getResource(std::string mnt)
{
- std::map< std::string, DiagnosticsRequestEntry >::iterator it =
- diagnosticsRequestTable.find(diag);
+ std::map< std::string, MaintenanceRequestEntry >::iterator it =
+ maintenanceRequestTable.find(mnt);
- if (it == diagnosticsRequestTable.end())
+ if (it == maintenanceRequestTable.end())
return NULL;
else
return it->second.m_resource;
}
- DiagnosticsCallback ThingsDiagnostics::getCallback(std::string diag)
+ MaintenanceCallback ThingsMaintenance::getCallback(std::string mnt)
{
- std::map< std::string, DiagnosticsRequestEntry >::iterator it =
- diagnosticsRequestTable.find(diag);
+ std::map< std::string, MaintenanceRequestEntry >::iterator it =
+ maintenanceRequestTable.find(mnt);
- if (it == diagnosticsRequestTable.end())
+ if (it == maintenanceRequestTable.end())
return NULL;
else
return it->second.m_callback;
}
- std::string ThingsDiagnostics::getHostFromURI(std::string oldUri)
+ std::string ThingsMaintenance::getHostFromURI(std::string oldUri)
{
size_t f;
std::string newUri;
return newUri;
}
- std::string ThingsDiagnostics::getListOfSupportedDiagnosticsUnits()
+ std::string ThingsMaintenance::getListOfSupportedMaintenanceUnits()
{
std::string res;
- res = "{\"Diagnostics Units\":[";
+ res = "{\"Maintenance Units\":[";
- auto it = DiagnosticsUnitTable.begin();
+ auto it = MaintenanceUnitTable.begin();
while (1)
{
res = res + (*it).getJSON();
it++;
- if (it == DiagnosticsUnitTable.end())
+ if (it == MaintenanceUnitTable.end())
break;
else
res += ",";
return res;
}
- void ThingsDiagnostics::onGetChildInfoForUpdate(const HeaderOptions& headerOptions,
- const OCRepresentation& rep, const int eCode, std::string diag)
+ void ThingsMaintenance::onGetChildInfoForUpdate(const HeaderOptions& headerOptions,
+ const OCRepresentation& rep, const int eCode, std::string mnt)
{
if (eCode != OC_STACK_OK)
{
std::cout << "onGet Response error: " << eCode << std::endl;
- getCallback(diag)(headerOptions, rep, eCode);
+ getCallback(mnt)(headerOptions, rep, eCode);
return ;
}
std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
}
- // Get information by using diagnostics name(diag)
- std::shared_ptr < OCResource > resource = getResource(diag);
- std::string actionstring = diag;
- std::string uri = getUriByDiagnosticsName(diag);
- std::string attrKey = diag;
+ // Get information by using maintenance name(mnt)
+ std::shared_ptr < OCResource > resource = getResource(mnt);
+ std::string actionstring = mnt;
+ std::string uri = getUriByMaintenanceName(mnt);
+ std::string attrKey = mnt;
if (uri == "")
return;
// Required information consists of a host address, URI, attribute key, and
// attribute value.
ActionSet *newActionSet = new ActionSet();
- newActionSet->actionsetName = diag;
+ newActionSet->actionsetName = mnt;
for (auto oit = children.begin(); oit != children.end(); ++oit)
{
Capability *newCapability = new Capability();
newCapability->capability = attrKey;
- newCapability->status = getUpdateVal(diag);
+ newCapability->status = getUpdateVal(mnt);
newAction->listOfCapability.push_back(newCapability);
newActionSet->listOfAction.push_back(newAction);
std::function<
void(const HeaderOptions& headerOptions,
const OCRepresentation& rep, const int eCode) >(
- std::bind(&ThingsDiagnostics::onCreateActionSet, this,
+ std::bind(&ThingsMaintenance::onCreateActionSet, this,
std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, diag)));
+ std::placeholders::_3, mnt)));
delete(newActionSet);
}
}
- void ThingsDiagnostics::onCreateActionSet(const HeaderOptions& headerOptions,
- const OCRepresentation& rep, const int eCode, std::string diag)
+ void ThingsMaintenance::onCreateActionSet(const HeaderOptions& headerOptions,
+ const OCRepresentation& rep, const int eCode, std::string mnt)
{
if (eCode != OC_STACK_OK)
{
std::cout << "onPut Response error: " << eCode << std::endl;
- getCallback(diag)(headerOptions, rep, eCode);
+ getCallback(mnt)(headerOptions, rep, eCode);
return ;
}
std::cout << "PUT request was successful" << std::endl;
- std::shared_ptr < OCResource > resource = getResource(diag);
+ std::shared_ptr < OCResource > resource = getResource(mnt);
if (resource)
{
// Now, it is time to execute the action set.
- g_groupmanager->executeActionSet(resource, diag,
+ g_groupmanager->executeActionSet(resource, mnt,
std::function<
void(const HeaderOptions& headerOptions,
const OCRepresentation& rep, const int eCode) >(
- std::bind(&ThingsDiagnostics::onExecuteForGroupAction, this,
+ std::bind(&ThingsMaintenance::onExecuteForGroupAction, this,
std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, diag)));
+ std::placeholders::_3, mnt)));
}
}
- void ThingsDiagnostics::onExecuteForGroupAction(const HeaderOptions& headerOptions,
- const OCRepresentation& rep, const int eCode, std::string diag)
+ void ThingsMaintenance::onExecuteForGroupAction(const HeaderOptions& headerOptions,
+ const OCRepresentation& rep, const int eCode, std::string mnt)
{
if (eCode != OC_STACK_OK)
{
std::cout << "onPut Response error: " << eCode << std::endl;
- getCallback(diag)(headerOptions, rep, eCode);
+ getCallback(mnt)(headerOptions, rep, eCode);
return ;
}
std::cout << "PUT request was successful" << std::endl;
- getCallback(diag)(headerOptions, rep, eCode);
+ getCallback(mnt)(headerOptions, rep, eCode);
// Delete the created actionset
- std::shared_ptr < OCResource > resource = getResource(diag);
+ std::shared_ptr < OCResource > resource = getResource(mnt);
if (resource)
{
- g_groupmanager->deleteActionSet(resource, diag,
+ g_groupmanager->deleteActionSet(resource, mnt,
std::function<
void(const HeaderOptions& headerOptions,
const OCRepresentation& rep, const int eCode) >(
- std::bind(&ThingsDiagnostics::onDeleteGroupAction, this,
+ std::bind(&ThingsMaintenance::onDeleteGroupAction, this,
std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, diag)));
+ std::placeholders::_3, mnt)));
}
}
- void ThingsDiagnostics::onDeleteGroupAction(const HeaderOptions& headerOptions,
- const OCRepresentation& rep, const int eCode, std::string diag)
+ void ThingsMaintenance::onDeleteGroupAction(const HeaderOptions& headerOptions,
+ const OCRepresentation& rep, const int eCode, std::string mnt)
{
if (eCode != OC_STACK_OK)
{
- std::cout << "Delete actionset returned with error: " << eCode << diag << std::endl;
+ std::cout << "Delete actionset returned with error: " << eCode << mnt << std::endl;
return;
}
- std::cout << "Deleted the actionset created!" << diag<< std::endl;
+ std::cout << "Deleted the actionset created!" << mnt<< std::endl;
}
- void ThingsDiagnostics::onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep,
- const int eCode, std::string diag)
+ void ThingsMaintenance::onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+ const int eCode, std::string mnt)
{
if (eCode != OC_STACK_OK)
{
std::cout << "onPut Response error: " << eCode << std::endl;
- getCallback(diag)(headerOptions, rep, eCode);
+ getCallback(mnt)(headerOptions, rep, eCode);
return ;
}
std::cout << "PUT request was successful" << std::endl;
- getCallback(diag)(headerOptions, rep, eCode);
+ getCallback(mnt)(headerOptions, rep, eCode);
}
- bool ThingsDiagnostics::isSimpleResource(std::shared_ptr< OCResource > resource)
+ bool ThingsMaintenance::isSimpleResource(std::shared_ptr< OCResource > resource)
{
for (unsigned int i = 0; i < resource->getResourceTypes().size(); ++i)
{
return true;
}
- OCStackResult ThingsDiagnostics::reboot(std::shared_ptr< OCResource > resource,
- DiagnosticsCallback callback)
+ OCStackResult ThingsMaintenance::reboot(std::shared_ptr< OCResource > resource,
+ MaintenanceCallback callback)
{
if (!resource)
{
return OC_STACK_ERROR;
}
- std::string diag = "rb";
+ std::string mnt = "rb";
// Check the request queue if a previous request is still left. If so, remove it.
- std::map< std::string, DiagnosticsRequestEntry >::iterator iter =
- diagnosticsRequestTable.find(diag);
- if (iter != diagnosticsRequestTable.end())
- diagnosticsRequestTable.erase(iter);
+ std::map< std::string, MaintenanceRequestEntry >::iterator iter =
+ maintenanceRequestTable.find(mnt);
+ if (iter != maintenanceRequestTable.end())
+ maintenanceRequestTable.erase(iter);
// Create new request entry stored in the queue
- DiagnosticsRequestEntry newCallback(diag, callback, resource, "true");
- diagnosticsRequestTable.insert(std::make_pair(diag, newCallback));
+ MaintenanceRequestEntry newCallback(mnt, callback, resource, "true");
+ maintenanceRequestTable.insert(std::make_pair(mnt, newCallback));
QueryParamsMap query;
OCRepresentation rep;
{
// This resource is a simple resource. Just send a PUT message
OCRepresentation rep;
- rep.setValue < std::string > (diag, "true");
+ rep.setValue < std::string > (mnt, "true");
return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
std::function<
void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
const int eCode) >(
- std::bind(&ThingsDiagnostics::onPut, this, std::placeholders::_1,
- std::placeholders::_2, std::placeholders::_3, diag)));
+ std::bind(&ThingsMaintenance::onPut, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3, mnt)));
}
else
{
std::function<
void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
const int eCode) >(
- std::bind(&ThingsDiagnostics::onGetChildInfoForUpdate, this,
+ std::bind(&ThingsMaintenance::onGetChildInfoForUpdate, this,
std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, diag)));
+ std::placeholders::_3, mnt)));
}
}
- OCStackResult ThingsDiagnostics::factoryReset(std::shared_ptr< OCResource > resource,
- DiagnosticsCallback callback)
+ OCStackResult ThingsMaintenance::factoryReset(std::shared_ptr< OCResource > resource,
+ MaintenanceCallback callback)
{
if (!resource)
{
return OC_STACK_ERROR;
}
- std::string diag = "fr";
+ std::string mnt = "fr";
// Check the request queue if a previous request is still left. If so, remove it.
- std::map< std::string, DiagnosticsRequestEntry >::iterator iter =
- diagnosticsRequestTable.find(diag);
- if (iter != diagnosticsRequestTable.end())
- diagnosticsRequestTable.erase(iter);
+ std::map< std::string, MaintenanceRequestEntry >::iterator iter =
+ maintenanceRequestTable.find(mnt);
+ if (iter != maintenanceRequestTable.end())
+ maintenanceRequestTable.erase(iter);
// Create new request entry stored in the queue
- DiagnosticsRequestEntry newCallback(diag, callback, resource, "true");
- diagnosticsRequestTable.insert(std::make_pair(diag, newCallback));
+ MaintenanceRequestEntry newCallback(mnt, callback, resource, "true");
+ maintenanceRequestTable.insert(std::make_pair(mnt, newCallback));
QueryParamsMap query;
OCRepresentation rep;
std::function<
void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
const int eCode) >(
- std::bind(&ThingsDiagnostics::onPut, this, std::placeholders::_1,
- std::placeholders::_2, std::placeholders::_3, diag)));
+ std::bind(&ThingsMaintenance::onPut, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3, mnt)));
}
else
{
std::function<
void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
const int eCode) >(
- std::bind(&ThingsDiagnostics::onGetChildInfoForUpdate, this,
+ std::bind(&ThingsMaintenance::onGetChildInfoForUpdate, this,
std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, diag)));
+ std::placeholders::_3, mnt)));
}
}
}
+++ /dev/null
-//******************************************************************
-//
-// 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.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/**
- * @file
- *
- */
-
-#include "ThingsManager.h"
-#include "GroupManager.h"
-#include "GroupSynchronization.h"
-#include "ThingsConfiguration.h"
-#include "ThingsDiagnostics.h"
-#include <algorithm>
-#include <thread>
-
-using namespace OC;
-namespace OIC
-{
-
- GroupManager *g_groupManager;
- GroupSynchronization *g_groupSync = NULL;
- ThingsConfiguration *g_thingsConf = NULL;
- ThingsDiagnostics *g_thingsDiag = NULL;
-
- ThingsManager::ThingsManager(void)
- {
- g_groupManager = new GroupManager();
- g_groupSync = GroupSynchronization::getInstance();
- g_thingsConf = ThingsConfiguration::getInstance();
- g_thingsDiag = ThingsDiagnostics::getInstance();
- g_thingsConf->setGroupManager(g_groupManager);
- g_thingsDiag->setGroupManager(g_groupManager);
- }
-
- /**
- * Virtual destructor
- */
- ThingsManager::~ThingsManager(void)
- {
- delete g_groupManager;
- g_groupSync->deleteInstance();
- g_thingsConf->deleteInstance();
- g_thingsDiag->deleteInstance();
- }
-
- OCStackResult ThingsManager::findCandidateResources(std::vector< std::string > resourceTypes,
- std::function< void(std::vector< std::shared_ptr< OCResource > >) > callback,
- int waitsec)
- {
- OCStackResult result = g_groupManager->findCandidateResources(resourceTypes, callback,
- waitsec);
-
- return result;
- }
-
- OCStackResult ThingsManager::subscribeCollectionPresence(std::shared_ptr< OCResource > resource,
- std::function< void(std::string, OCStackResult) > callback)
- {
- OCStackResult result = g_groupManager->subscribeCollectionPresence(resource, callback);
-
- return result;
- }
-
- OCStackResult ThingsManager::bindResourceToGroup(OCResourceHandle& childHandle, std::shared_ptr< OCResource > resource, OCResourceHandle& collectionHandle)
- {
- OCStackResult result = g_groupManager->bindResourceToGroup(childHandle,resource,collectionHandle);
-
- return result;
- }
-
- OCStackResult ThingsManager::findGroup(std::vector< std::string > collectionResourceTypes,
- FindCallback callback)
- {
- OCStackResult result = g_groupSync->findGroup(collectionResourceTypes, callback);
-
- return result;
- }
-
- OCStackResult ThingsManager::createGroup(std::string collectionResourceType)
- {
- OCStackResult result = g_groupSync->createGroup(collectionResourceType);
-
- return result;
- }
-
- OCStackResult ThingsManager::joinGroup(std::string collectionResourceType,
- OCResourceHandle resourceHandle)
- {
- OCStackResult result = g_groupSync->joinGroup(collectionResourceType, resourceHandle);
-
- return result;
- }
-
- OCStackResult ThingsManager::joinGroup(const std::shared_ptr< OCResource > resource,
- OCResourceHandle resourceHandle)
- {
- OCStackResult result = g_groupSync->joinGroup(resource, resourceHandle);
-
- return result;
- }
-
- OCStackResult ThingsManager::leaveGroup(std::string collectionResourceType,
- OCResourceHandle resourceHandle)
- {
- OCStackResult result = g_groupSync->leaveGroup(collectionResourceType, resourceHandle);
-
- return result;
- }
-
- OCStackResult ThingsManager::leaveGroup(const std::shared_ptr< OCResource > resource,
- std::string collectionResourceType,
- OCResourceHandle resourceHandle)
- {
- return g_groupSync->leaveGroup(resource, collectionResourceType, resourceHandle);
- }
-
- void ThingsManager::deleteGroup(std::string collectionResourceType)
- {
- g_groupSync->deleteGroup(collectionResourceType);
- }
-
- std::map< std::string, OCResourceHandle > ThingsManager::getGroupList()
- {
- return g_groupSync->getGroupList();
- }
-
- OCStackResult ThingsManager::updateConfigurations(std::shared_ptr< OCResource > resource,
- std::map< ConfigurationName, ConfigurationValue > configurations,
- ConfigurationCallback callback)
- {
- return g_thingsConf->updateConfigurations(resource, configurations, callback);
- }
- OCStackResult ThingsManager::getConfigurations(std::shared_ptr< OCResource > resource,
- std::vector< ConfigurationName > configurations, ConfigurationCallback callback)
- {
- return g_thingsConf->getConfigurations(resource, configurations, callback);
- }
- std::string ThingsManager::getListOfSupportedConfigurationUnits()
- {
- return g_thingsConf->getListOfSupportedConfigurationUnits();
- }
-
- OCStackResult ThingsManager::doBootstrap(ConfigurationCallback callback)
- {
- return g_thingsConf->doBootstrap(callback);
- }
-
- OCStackResult ThingsManager::reboot(std::shared_ptr< OCResource > resource,
- ConfigurationCallback callback)
- {
- return g_thingsDiag->reboot(resource, callback);
- }
- OCStackResult ThingsManager::factoryReset(std::shared_ptr< OCResource > resource,
- ConfigurationCallback callback)
- {
- return g_thingsDiag->factoryReset(resource, callback);
- }
-
- std::string ThingsManager::getStringFromActionSet(const ActionSet *newActionSet)
- {
- return g_groupManager->getStringFromActionSet(newActionSet);
- }
- ActionSet* ThingsManager::getActionSetfromString(std::string desc)
- {
- return g_groupManager->getActionSetfromString(desc);
- }
- OCStackResult ThingsManager::addActionSet(std::shared_ptr< OCResource > resource,
- const ActionSet* newActionSet, PutCallback cb)
- {
- return g_groupManager->addActionSet(resource, newActionSet, cb);
- }
- OCStackResult ThingsManager::executeActionSet(std::shared_ptr< OCResource > resource,
- std::string actionsetName, PostCallback cb)
- {
- return g_groupManager->executeActionSet(resource, actionsetName, cb);
- }
- OCStackResult ThingsManager::executeActionSet(std::shared_ptr< OCResource > resource,
- std::string actionsetName, long int delay, PostCallback cb)
- {
- return g_groupManager->executeActionSet(resource, actionsetName, delay, cb);
- }
- OCStackResult ThingsManager::cancelActionSet(std::shared_ptr< OCResource > resource,
- std::string actionsetName, PostCallback cb)
- {
- return g_groupManager->cancelActionSet(resource, actionsetName, cb);
- }
- OCStackResult ThingsManager::getActionSet(std::shared_ptr< OCResource > resource,
- std::string actionsetName, GetCallback cb)
- {
- return g_groupManager->getActionSet(resource, actionsetName, cb);
- }
- OCStackResult ThingsManager::deleteActionSet(std::shared_ptr< OCResource > resource,
- std::string actionsetName, PostCallback cb)
- {
- return g_groupManager->deleteActionSet(resource, actionsetName, cb);
- }
-}
--- /dev/null
+<manifest>
+ <define>
+ <domain name="iotivity-test" />
+ <permit>
+ <smack permit="system::use_internet" type="w" />
+ </permit>
+ <request>
+ <smack request="system::use_internet" type="w" />
+ <smack request="connman::get" type="w" />
+ </request>
+ </define>
+ <request>
+ <domain name="iotivity-test" />
+ </request>
+</manifest>
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
Name: iotivity
-Version: 0.9.1
+Version: 0.9.2
Release: 0
Summary: IoTivity Base Stack & IoTivity Services
Group: System Environment/Libraries
License: Apache-2.0
URL: https://www.iotivity.org/
Source0: %{name}-%{version}.tar.bz2
-
+Source1001: %{name}.manifest
+Source1002: %{name}-test.manifest
BuildRequires: gettext, expat-devel
BuildRequires: python, libcurl-devel
BuildRequires: scons
Requires(postun): /sbin/ldconfig
Requires(post): /sbin/ldconfig
+%define release_mode false
+%define secure_mode 0
+
%description
IoTivity Base (RICH & LITE) Stack & IoTivity Services
+%package service
+Summary: Development files for %{name}
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description service
+The %{name}-service package contains service libraries files for
+developing applications that use %{name}-service.
+
+%package test
+Summary: Development files for %{name}
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description test
+The %{name}-test package contains example files to show
+how the iotivity works using %{name}-test
+
%package devel
Summary: Development files for %{name}
Group: Development/Libraries
%prep
%setup -q -n %{name}-%{version}
+cp %{SOURCE1001} .
+%if 0%{?tizen_version_major} < 3
+cp %{SOURCE1002} .
+%else
+cp %{SOURCE1001} ./%{name}-test.manifest
+%endif
%build
-%ifarch armv7l
-export RPM_ARCH=armeabi-v7a
-%else
-%ifarch %arm
-export RPM_ARCH=arm
-%else
-%ifarch aarch64
-export RPM_ARCH=arm64
-%else
-%ifarch i586 i686 %{ix86}
-export RPM_ARCH=x86
-%else
-export RPM_ARCH=%{_arch}
+%define RPM_ARCH %{_arch}
+
+%ifarch armv7l armv7hl armv7nhl armv7tnhl armv7thl
+%define RPM_ARCH "armeabi-v7a"
%endif
+
+%ifarch aarch64
+%define RPM_ARCH "arm64"
%endif
+
+%ifarch x86_64
+%define RPM_ARCH "x86_64"
%endif
+
+%ifarch %{ix86}
+%define RPM_ARCH "x86"
%endif
-scons -j 4 TARGET_OS=tizen TARGET_ARCH=$RPM_ARCH TARGET_TRANSPORT=IP
+scons -j 4 TARGET_OS=tizen TARGET_ARCH=%{RPM_ARCH} TARGET_TRANSPORT=IP RELEASE=%{release_mode} SECURED=%{secure_mode}
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}%{_includedir}
-mkdir -p %{buildroot}%{_includedir}/targets
mkdir -p %{buildroot}%{_libdir}
-mkdir -p %{buildroot}%{_sbindir}
-
-cp out/tizen/*/release/lib*.so %{buildroot}%{_libdir}
-cp out/tizen/*/release/libSSMSDK.a %{buildroot}%{_libdir}
-cp out/tizen/*/release/libppm.a %{buildroot}%{_libdir}
-cp out/tizen/*/release/service/protocol-plugin/plugins/mqtt-fan/*.so %{buildroot}%{_libdir}
-cp out/tizen/*/release/service/protocol-plugin/plugins/mqtt-light/*.so %{buildroot}%{_libdir}
-cp /usr/lib/libuuid.so %{buildroot}%{_libdir}
-
-cp resource/csdk/stack/include/ocstack.h %{buildroot}%{_includedir}
-cp resource/csdk/stack/include/ocstackconfig.h %{buildroot}%{_includedir}
-cp resource/oc_logger/include/oc_logger.hpp %{buildroot}%{_includedir}
-cp resource/oc_logger/include/oc_log_stream.hpp %{buildroot}%{_includedir}
-cp resource/oc_logger/include/oc_logger.h %{buildroot}%{_includedir}
-cp resource/oc_logger/include/oc_logger_types.h %{buildroot}%{_includedir}
-cp resource/oc_logger/include/targets/oc_console_logger.h %{buildroot}%{_includedir}/targets
-cp resource/oc_logger/include/targets/oc_ostream_logger.h %{buildroot}%{_includedir}/targets
+mkdir -p %{buildroot}%{_bindir}
+
+
+%if %{release_mode} == "true"
+%define build_mode release
+%else
+%define build_mode debug
+%endif
+
+cp out/tizen/*/%{build_mode}/resource/examples/devicediscoveryclient %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/devicediscoveryserver %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/fridgeclient %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/fridgeserver %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/garageclient %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/garageserver %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/groupclient %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/groupserver %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/lightserver %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/presenceclient %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/presenceserver %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/roomclient %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/roomserver %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/simpleclient %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/simpleclientHQ %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/simpleclientserver %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/simpleserver %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/simpleserverHQ %{buildroot}%{_bindir}
+cp out/tizen/*/%{build_mode}/resource/examples/threadingsample %{buildroot}%{_bindir}
+
+cp out/tizen/*/%{build_mode}/lib*.so %{buildroot}%{_libdir}
+cp out/tizen/*/%{build_mode}/libSSMSDK.a %{buildroot}%{_libdir}
+cp out/tizen/*/%{build_mode}/libppm.a %{buildroot}%{_libdir}
+
+cp resource/csdk/stack/include/*.h %{buildroot}%{_includedir}
+cp resource/csdk/logger/include/*.h %{buildroot}%{_includedir}
+cp resource/csdk/ocrandom/include/*.h %{buildroot}%{_includedir}
+cp -r resource/oc_logger/include/* %{buildroot}%{_includedir}
cp resource/include/*.h %{buildroot}%{_includedir}
cp service/things-manager/sdk/inc/*.h %{buildroot}%{_includedir}
cp service/soft-sensor-manager/SDK/cpp/include/*.h %{buildroot}%{_includedir}
+cp service/protocol-plugin/plugin-manager/src/*.h %{buildroot}%{_includedir}
-%clean
-rm -rf %{buildroot}
-
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
+%manifest %{name}.manifest
%defattr(-,root,root,-)
-%{_libdir}/lib*.so
-%{_libdir}/lib*.a
-%{_libdir}/fanserver*.so
-%{_libdir}/lightserver*.so
+%{_libdir}/liboc.so
+%{_libdir}/liboc_logger.so
+%{_libdir}/liboc_logger_core.so
+%{_libdir}/liboctbstack.so
+%{_libdir}/libconnectivity_abstraction.so
+
+%files service
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%{_libdir}/libBMISensor.so
+%{_libdir}/libDiscomfortIndexSensor.so
+%{_libdir}/libmosquittopp.so
+%{_libdir}/libpmimpl.so
+%{_libdir}/libSSMCore.so
+%{_libdir}/libNotificationManager.so
+%{_libdir}/libHueBundle.so
+%{_libdir}/librcs_client.so
+%{_libdir}/librcs_common.so
+%{_libdir}/librcs_container.so
+%{_libdir}/librcs_server.so
+
+%files test
+%manifest %{name}-test.manifest
+%defattr(-,root,root,-)
+%{_bindir}/devicediscoveryclient
+%{_bindir}/devicediscoveryserver
+%{_bindir}/fridgeclient
+%{_bindir}/fridgeserver
+%{_bindir}/garageclient
+%{_bindir}/garageserver
+%{_bindir}/groupclient
+%{_bindir}/groupserver
+%{_bindir}/lightserver
+%{_bindir}/presenceclient
+%{_bindir}/presenceserver
+%{_bindir}/roomclient
+%{_bindir}/roomserver
+%{_bindir}/simpleclient
+%{_bindir}/simpleclientHQ
+%{_bindir}/simpleclientserver
+%{_bindir}/simpleserver
+%{_bindir}/simpleserverHQ
+%{_bindir}/threadingsample
%files devel
%defattr(-,root,root,-)
+%{_libdir}/lib*.a
%{_includedir}/*