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
'''
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 (NULL == env)
+ {
+ return;
+ }
env->DeleteGlobalRef(m_jListener);
- if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
+ 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 (NULL == 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();
-//}
-//
-/*
-* //******************************************************************
-* //
-* // 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"
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))
{
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");
}
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");
}
{
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();
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;
* 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;
* 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;
}
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;
}
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;
}
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;
}
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");
return nullptr;
}
JniEntityHandler* entityHandler = new JniEntityHandler(env, jListener);
- EntityHandler handleEntityCallback = [entityHandler](const std::shared_ptr<OCResourceRequest> request) ->
- OCEntityHandlerResult{
- return entityHandler->handleEntity(request);
- };
+ 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");
* 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");
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)
typeName = env->GetStringUTFChars(jResourceTypeName, NULL);
}
- JniOcResourceHandle* jniOcResourceHandle = JniOcResourceHandle::getJniOcResourceHandlePtr(
- env, jResourceHandle);
+ JniOcResourceHandle* jniOcResourceHandle =
+ JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle);
if (!jniOcResourceHandle) return;
try
interfaceName = env->GetStringUTFChars(jResourceInterfaceName, NULL);
}
- 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;
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;
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;
* 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)
{
JniOcResource::~JniOcResource()
{
LOGD("~JniOcResource()");
+
+ m_sharedResource->cancelObserve();
m_sharedResource = NULL;
jint envRet;
jint ret;
JNIEnv *env = GetJNIEnv(ret);
if (NULL == env) return;
+
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
+
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
}
if (NULL == env) return;
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
if (NULL == env) return;
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
if (NULL == env) return;
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
if (NULL == env) return;
env->DeleteWeakGlobalRef(m_jwListener);
+ m_jwListener = nullptr;
if (JNI_EDETACHED == ret) g_jvm->DetachCurrentThread();
}
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 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,
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
package="org.iotivity.base.examples.fridgeclient" >
<uses-sdk tools:overrideLibrary="org.iotivity.base"></uses-sdk>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.BLUETOOTH"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+ <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
+ <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"/>
+
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
<uses-sdk tools:overrideLibrary="org.iotivity.base"></uses-sdk>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.BLUETOOTH"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+ <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
+ <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"/>
+
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
package="org.iotivity.guiclient"
xmlns:tools="http://schemas.android.com/tools">
- <uses-permission android:name="android.permission.INTERNET" />
<uses-sdk tools:overrideLibrary="org.iotivity.base"></uses-sdk>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.BLUETOOTH"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+ <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
+ <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"/>
+
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
<uses-sdk tools:overrideLibrary="org.iotivity.base"></uses-sdk>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.BLUETOOTH"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+ <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
+ <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"/>
<application
android:allowBackup="true"
<uses-sdk tools:overrideLibrary="org.iotivity.base"></uses-sdk>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.BLUETOOTH"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+ <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
+ <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"/>
<application
android:allowBackup="true"
# 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 ====================="
-
-
{
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;
-}
# compilation list. This is an extra overhead as stack is never going to use ".o" generated
# for these examples.
if 'examples' not in root:
- matches.extend(Glob(root + '/' + pattern, ondisk, source, strings))
+ matches.extend(Glob(os.path.join(root, pattern), ondisk, source, strings))
return matches
# To make sure the src is built in 'BUILD_DIR' (by default it will be built at
if env.get('CPU'):
prefix += env.get('CPU') + '_'
- build_dir = env.get('BUILD_DIR') + '/arduino/'
+ build_dir = os.path.join(env.get('BUILD_DIR'), 'arduino')
for src in srcs:
- obj = src.path.replace(arduino_home, build_dir)
+ if (os.path.isabs(src.path)):
+ obj = src.path.replace(arduino_home, build_dir)
+ else:
+ obj = os.path.join(build_dir, src.path)
i = obj.rfind('.')
obj = obj[0:i]
if env.get('OBJSUFFIX'):
return objs
def __import_lib(env, lib):
- lib_path = arduino_home + '/libraries/' + lib
+ lib_path = os.path.join(arduino_home, 'libraries', lib)
if not os.path.exists(lib_path):
if target_arch == 'avr':
- lib_path = arduino_home + '/hardware/arduino/avr/libraries/' + lib
+ lib_path = os.path.join(arduino_home, 'hardware', 'arduino', 'avr', 'libraries', lib)
else:
- lib_path = arduino_home + '/hardware/arduino/sam/libraries/' + lib
+ lib_path = os.path.join(arduino_home, 'hardware', 'arduino', 'sam', 'libraries', lib)
- if os.path.exists(lib_path + '/src'):
- lib_path = lib_path + '/src'
+ if os.path.exists(os.path.join(lib_path, 'src')):
+ lib_path = os.path.join(lib_path, 'src')
env.AppendUnique(CPPPATH = [lib_path])
- if os.path.exists(lib_path + '/utility'):
- env.AppendUnique(CPPPATH = [lib_path + '/utility'])
+ if os.path.exists(os.path.join(lib_path, 'utility')):
+ env.AppendUnique(CPPPATH = [os.path.join(lib_path, 'utility')])
lib_src = []
lib_src.extend(__search_files(lib_path, '*.S'))
if env.get('CPU'):
prefix += env.get('CPU') + '_'
- core = env.get('BUILD_DIR', '.') + '/arduino/' + prefix + 'core'
+ core = os.path.join(env.get('BUILD_DIR', '.'), 'arduino', prefix + 'core')
s_core = env.StaticLibrary(core, core_obj)
env.AppendUnique(LIBS = [File(s_core[0])])
# Verify that the arduino, time, red bear, and nordic libraries are
# installed. If not, get them and install them.
-SConscript(env.get('SRC_DIR') + '/extlibs/arduino/SConscript')
+SConscript(os.path.join(env.get('SRC_DIR'), 'extlibs', 'arduino', 'SConscript'))
arduino_home = env.get('ARDUINO_HOME')
print 'ARDUINO_HOME = ' + env.get('ARDUINO_HOME')
# BOARD / CPU option
# Get IDE version
-if os.path.exists(arduino_home + '/lib/version.txt'):
- vf = open(arduino_home + '/lib/version.txt', 'r')
+if os.path.exists(os.path.join(arduino_home, 'lib', 'version.txt')):
+ vf = open(os.path.join(arduino_home, 'lib', 'version.txt'), 'r')
version = vf.readline().replace('.', '').strip()
else:
print '''
if version[0:2] == '10':
is_1_0_x = True
- boards_info = __parse_config(arduino_home + '/hardware/arduino/boards.txt')
- env.PrependENVPath('PATH', arduino_home + '/hardware/tools/avr/bin/')
+ boards_info = __parse_config(os.path.join(arduino_home, 'hardware', 'arduino', 'boards.txt'))
+ env.PrependENVPath('PATH', os.path.join(arduino_home, 'hardware', 'tools', 'avr', 'bin'))
env.Replace(CC = 'avr-gcc')
env.Replace(CXX = 'avr-g++')
env.Replace(AR = 'avr-ar')
else:
is_1_0_x = False
if target_arch == 'avr':
- boards_info = __parse_config(arduino_home + '/hardware/arduino/avr/boards.txt')
- platform_info = __parse_config(arduino_home + '/hardware/arduino/avr/platform.txt')
+ boards_info = __parse_config(os.path.join(arduino_home, 'hardware', 'arduino', 'avr', 'boards.txt'))
+ platform_info = __parse_config(os.path.join(arduino_home, 'hardware', 'arduino', 'avr', 'platform.txt'))
elif target_arch == 'arm':
- boards_info = __parse_config(arduino_home + '/hardware/arduino/sam/boards.txt')
- platform_info = __parse_config(arduino_home + '/hardware/arduino/sam/platform.txt')
+ boards_info = __parse_config(os.path.join(arduino_home, 'hardware', 'arduino', 'sam', 'boards.txt'))
+ platform_info = __parse_config(os.path.join(arduino_home, 'hardware', 'arduino', 'sam', 'platform.txt'))
else:
print '''
************************************* Error ***********************************
usb_pid = __get_board_info(board, '.pid.0')
if is_1_0_x:
- core_base = arduino_home + '/hardware/arduino/'
+ core_base = os.path.join(arduino_home, 'hardware', 'arduino')
else:
if target_arch == 'avr':
- core_base = arduino_home + '/hardware/arduino/avr/'
+ core_base = os.path.join(arduino_home, 'hardware', 'arduino', 'avr')
else:
- core_base = arduino_home + '/hardware/arduino/sam/'
+ core_base = os.path.join(arduino_home, 'hardware', 'arduino', 'sam')
-variant_folder = core_base + 'variants/' + variant
+variant_folder = os.path.join(core_base, 'variants', variant)
env.AppendUnique(CPPPATH = [variant_folder])
core = __get_board_info(board, '.build.core')
-core_folder = core_base + 'cores/' + core + '/'
+core_folder = os.path.join(core_base, 'cores', core)
env.AppendUnique(CPPPATH = [core_folder])
if is_1_0_x:
env.Replace(CXX = platform_info.get('compiler.cpp.cmd'))
env.Replace(AR = platform_info.get('compiler.ar.cmd'))
if target_arch == 'arm':
- env.AppendUnique(CPPPATH = [arduino_home + '/hardware/arduino/sam/system/libsam',
- arduino_home + '/hardware/arduino/sam/system/CMSIS/CMSIS/Include/',
- arduino_home + '/hardware/arduino/sam/system//CMSIS/Device/ATMEL'])
+ env.AppendUnique(CPPPATH = [os.path.join(arduino_home, 'hardware', 'arduino', 'sam', 'system', 'libsam'),
+ os.path.join(arduino_home, 'hardware', 'arduino', 'sam', 'system', 'CMSIS', 'CMSIS', 'Include'),
+ os.path.join(arduino_home, 'hardware', 'arduino', 'sam', 'system', '', 'CMSIS', 'Device', 'ATMEL')])
env.AppendUnique(ASFLAGS = ['-x', 'assembler-with-cpp'])
env.AppendUnique(ASFLAGS = comm_flag)
env.AppendUnique(CFLAGS = Split(platform_info.get('compiler.c.flags')))
if target_arch == 'arm':
env.AppendUnique(LINKFLAGS = ['-Os', '-Wl,--gc-sections', cpu_flag,
- '-T' + variant_folder + '/' + __get_board_info(board, '.build.ldscript')])
+ '-T' + os.path.join(variant_folder, __get_board_info(board, '.build.ldscript'))])
env.AppendUnique(LINKFLAGS = Split('-lm -lgcc -mthumb -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group'))
variant_system_lib = __get_board_info(board, '.build.variant_system_lib')
if variant_folder.find(' ') >= 0:
variant_folder = '"' + variant_folder + '"'
env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS '
- + variant_folder + '/' + variant_system_lib + ' -Wl,--end-group')
+ + os.path.join(variant_folder, variant_system_lib) + ' -Wl,--end-group')
else:
env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS -Wl,--end-group')
else:
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:
void TemperatureSensor::onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep,
int eCode, int sequenceNumber)
{
- if (eCode == OC_STACK_OK)
+ if (eCode == OC_STACK_OK && sequenceNumber != OC_OBSERVE_NO_OPTION)
{
+ if(sequenceNumber == OC_OBSERVE_REGISTER)
+ {
+ cout << "Observe registration action is successful" << endl;
+ }
+ else if(sequenceNumber == OC_OBSERVE_DEREGISTER)
+ {
+ cout << "Observe De-registration action is successful" << endl;
+ }
double value;
rep.getValue(TEMPERATURE_RESOURCE_KEY, value);
cout << "Observing TemperatureSensor: Current temperature reading in Celsius is " << value << endl;
}
else
{
- cerr << "TemperatureSensor: Observer response error" << endl;
+ if(sequenceNumber == OC_OBSERVE_NO_OPTION)
+ {
+ cerr << "Observe registration or de-registration action is failed" << endl;
+ }
+ else
+ {
+ cerr << "TemperatureSensor: Observer response error" << endl;
+ }
}
}
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
+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);
}
}
#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);
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);
#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
CA_ADAPTER_RFCOMM_BTEDR = (1 << 2), // RFCOMM over Bluetooth EDR
#ifdef RA_ADAPTER
- CA_ADAPTER_REMOTE_ACCESS = (1 << 3) // Remote Access over XMPP.
+ CA_ADAPTER_REMOTE_ACCESS = (1 << 3), // Remote Access over XMPP.
#endif
+
+ CA_ALL_ADAPTERS = 0xffffffff
} CATransportAdapter_t;
typedef enum
{
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
} 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
*/
CAPayload_t payload; /**< payload of the request */
size_t payloadSize; /**< size in bytes of the 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;
+} CAHistoryItem_t;
+
+typedef struct
+{
+ 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;
- CATransportFlags_t serverFlags;
- bool client;
- bool server;
+ 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;
} CAGlobals_t;
#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
*
- * @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
*
- * @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);
#endif
/**
- * @brief Creates a new remote endpoint from the input endpoint
- * @param endpoint [IN] endpoint information where the data has to be sent
- * @return remote endpoint created
+ * Creates a new remote endpoint from the input endpoint.
+ * @param[in] endpoint endpoint information where the data has to be sent.
+ * @return remote endpoint created.
*/
CAEndpoint_t *CACloneEndpoint(const CAEndpoint_t *endpoint);
/**
- * @brief Allocate CAEndpoint_t instance.
- * @param flags [IN] Transport flag
- * @param adapter [IN] Adapter type
- * @param address [IN] Address
- * @param port [IN] Port
- * @return #CA_STATUS_OK or Appropriate error code
+ * Allocate CAEndpoint_t instance.
+ * @param[in] flags Transport flag.
+ * @param[in] adapter Adapter type.
+ * @param[in] address Address.
+ * @param[in] port Port.
+ * @return ::CA_STATUS_OK or Appropriate error code.
*/
CAEndpoint_t *CACreateEndpointObject(CATransportFlags_t flags, CATransportAdapter_t adapter,
const char *address, uint16_t port);
/**
- * @brief Destroy remote endpoint
- * @param endpoint [IN] endpoint information where the data has to be sent
- * @return none
+ * Destroy remote endpoint.
+ * @param[in] endpoint endpoint information where the data has to be sent.
*/
void CAFreeEndpoint(CAEndpoint_t *rep);
/**
- * @brief duplicates the given info.
+ * duplicates the given info.
* @param[in] info info object to be duplicated.
* @param[out] clone info object to be modified.
- * @return #CA_STATUS_OK or Appropriate error code if fail to clone.
+ * @return ::CA_STATUS_OK or Appropriate error code if fail to clone.
*/
CAResult_t CACloneInfo(const CAInfo_t *info, CAInfo_t *clone);
/**
- * @brief Creates a new request information
- * @param request [IN] request information that needs to be duplicated
- * @return duplicated request info object
+ * Creates a new request information.
+ * @param[in] request request information that needs to be duplicated.
+ * @return duplicated request info object.
*/
CARequestInfo_t *CACloneRequestInfo(const CARequestInfo_t *request);
/**
- * @brief Destroy the request information
- * @param request [IN] request information that needs to be destroyed
- * @return none
+ * Destroy the request information.
+ * @param[in] request request information that needs to be destroyed.
*/
void CADestroyRequestInfoInternal(CARequestInfo_t *request);
/**
- * @brief Creates a new response information
- * @param response [IN] response information that needs to be duplicated
- * @return duplicated response info object
+ * Creates a new response information.
+ * @param[in] response response information that needs to be duplicated.
+ * @return duplicated response info object.
*/
CAResponseInfo_t *CACloneResponseInfo(const CAResponseInfo_t *response);
/**
- * @brief Destroy the response information
- * @param response [IN] response information that needs to be destroyed
- * @return
+ * Destroy the response information.
+ * @param[in] response response information that needs to be destroyed.
*/
void CADestroyResponseInfoInternal(CAResponseInfo_t *response);
/**
- * @brief Free the error information
- * @param errorInfo [IN] error information to be freed
- * @return
+ * Free the error information.
+ * @param[in] errorInfo error information to be freed.
*/
void CADestroyErrorInfoInternal(CAErrorInfo_t *errorInfo);
-/******************************************************************
+/* ****************************************************************
*
* Copyright 2014 Samsung Electronics All Rights Reserved.
*
#define U_ARRAYLIST_H_
#include <stdint.h>
-#include "cacommon.h"
+#include <stdbool.h>
#ifdef __cplusplus
extern "C"
#endif
/**
- * @struct u_arraylist_t
- * @brief array list structure
+ * 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
{
} u_arraylist_t;
/**
- * @brief API to creates array list and initializes the elements.
- * @return u_arraylist_t if Success, NULL otherwise
+ * API to creates array list and initializes the elements.
+ * @return u_arraylist_t if Success, NULL otherwise.
*/
u_arraylist_t *u_arraylist_create();
/**
- * @brief Resets and deletes the array list
+ * Resets and deletes the array list.
* Arraylist elements are deleted. Calling function must take care of free
- * dynamic memory allocated before freeing the arraylist
- * @param list- u_arraylist pointer
- * @return CAResult_t
- * CA_STATUS_OK if Success, CA_STATUS_INVALID_PARAM if pointer to list is NULL
+ * dynamic memory allocated before freeing the arraylist.
+ * @param[in] list u_arraylist pointer
+ */
+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.
*/
-CAResult_t u_arraylist_free(u_arraylist_t **list);
+void u_arraylist_shrink_to_fit(u_arraylist_t *list);
/**
- * @brief Returns the data of the index from the array list
- * @param list
- * [IN] pointer of array list
- * @param index
- * [IN] index of array list
- * @return void pointer of data if success or NULL pointer otherwise
+ * Returns the data of the index from the array list.
+ * @param[in] list pointer of array list.
+ * @param[in] index index of array list.
+ * @return void pointer of data if success or NULL pointer otherwise.
*/
void *u_arraylist_get(const u_arraylist_t *list, uint32_t index);
/**
- * @brief Add data in the array list
- * @param list
- * [IN] pointer of array list
- * @param data
- * [IN] pointer of data
- * @return CAResult_t
- * CA_STATUS_OK if Success, CA_MEMORY_ALLOC_FAILED if memory allocation fails
+ * Add data in the array list.
+ * @param[in] list pointer of array list.
+ * @param[in] data pointer of data.
+ * @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);
/**
- * @brief Remove the data of the index from the array list
- * @param list
- * [IN] pointer of array list
- * @param index
- * [IN] index of array list
- * @return void pointer of the data if success or NULL pointer otherwise
+ * Remove the data of the index from the array list.
+ * @param[in] list pointer of array list.
+ * @param[in] index index of array list.
+ * @return void pointer of the data if success or NULL pointer otherwise.
*/
void *u_arraylist_remove(u_arraylist_t *list, uint32_t index);
/**
- * @brief Returns the length of the array list
- * @param list
- * [IN] pointer of array list
- * @return length of the array list
+ * Returns the length of the array list.
+ * @param[in] list pointer of array list.
+ * @return length of the array list.
*/
uint32_t u_arraylist_length(const u_arraylist_t *list);
/**
- * @brief Returns whether the data exists or not
- * @param list
- * [IN] pointer of array list
- * @param data
- * [IN] pointer of data
- * @return true if exists, false otherwise
+ * Returns whether the data exists or not.
+ * @param[in] list pointer of array list.
+ * @param[in] data pointer of data.
+ * @return true if exists, false otherwise.
*/
bool u_arraylist_contains(const u_arraylist_t *list,const void *data);
/**
- * @brief Destroys array list and elements (assuming elements are shallow)
- * @param list
- * [IN] pointer of array list
+ * Destroys array list and elements (assuming elements are shallow).
+ * @param[in] list pointer of array list.
*/
void u_arraylist_destroy(u_arraylist_t *list);
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)
- {
- // 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;
+ 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;
}
OIC_LOG(ERROR, TAG, "CACloneResponseInfo Out of memory");
return NULL;
}
- *clone = *rep;
-
- if (rep->info.token)
- {
- 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)
+ CAResult_t result = CACloneInfo(&rep->info, &clone->info);
+ if(CA_STATUS_OK != result)
{
- // 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)
- {
- // 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;
- }
-
- 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;
}
info->options = NULL;
info->numOptions = 0;
-
// free payload field
OICFree((char *) info->payload);
info->payload = NULL;
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)
+ 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;
}
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;
}
+ 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);
#ifndef __TIZEN__
static oic_log_ctx_t *logCtx = 0;
+#ifndef __ANDROID__
static oic_log_level LEVEL_XTABLE[] =
{ OIC_LOG_DEBUG, OIC_LOG_INFO, OIC_LOG_WARNING, OIC_LOG_ERROR, OIC_LOG_FATAL };
+#endif
#endif
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
- struct timespec when = {0};
+#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
+ struct timespec when = { 0, 0 };
clockid_t clk = CLOCK_REALTIME;
#ifdef CLOCK_REALTIME_COARSE
clk = CLOCK_REALTIME_COARSE;
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 *) OICMalloc(sizeof(u_arraylist_t));
if (!list)
{
+ OIC_LOG(DEBUG, TAG, "Out of memory");
return NULL;
}
list->size = U_ARRAYLIST_DEFAULT_SIZE;
list->length = 0;
- list->data = (void *) OICMalloc(list->size * sizeof(void *));
+ list->data = (void **) OICMalloc(list->size * 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;
+}
+
+void u_arraylist_reserve(u_arraylist_t *list, size_t count)
+{
+ if (list && (count > list->size))
+ {
+ 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->size = count;
+ }
+ }
+}
+
+void u_arraylist_shrink_to_fit(u_arraylist_t *list)
+{
+ if (!list)
+ {
+ return;
+ }
- return CA_STATUS_OK;
+ if ((list->size > list->length)
+ && (list->length >= U_ARRAYLIST_DEFAULT_SIZE))
+ {
+ 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->size = 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)
{
+ static const double GROWTH_FACTOR = 1.5;
if (!list)
{
- return CA_STATUS_INVALID_PARAM;
+ return false;
}
if (list->size <= list->length)
{
-
- uint32_t new_size = list->size + 1;
- if (!(list->data = (void **) realloc(list->data, new_size * sizeof(void *))))
+ uint32_t new_size = (list->size * GROWTH_FACTOR) + 0.5;
+ // 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_size * 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->data = (void **) tmp;
+ memset(list->data + list->size, 0,
+ (new_size - list->size) * sizeof(list->data[0]));
list->size = new_size;
}
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->size; 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);
}
-//* ****************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//******************************************************************/
+/* *****************************************************************
+ *
+ * Copyright 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
#endif
/**
- * @brief Starting connectivity adapters and each adapter have transport specific behavior.
+ * Starting connectivity adapters and each adapter have transport specific behavior.
* Transport Specific Behavior:
* WIFI/ETH connectivity Starts unicast server on all available IPs and defined
* port number as per specification.
* EDR will not start any specific servers.
* LE will not start any specific servers.
- * @return CA_STATUS_OK or CA_STATUS_FAILED
- * ERROR CODES (CAResult_t error codes in cacommon.h)
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED
+ * ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
typedef CAResult_t (*CAAdapterStart)();
/**
- * @brief Starting listening server for receiving multicast search requests
+ * Starting listening server for receiving multicast search requests
* Transport Specific Behavior:
* WIFI/ETH Starts multicast server on all available IPs and defined
* port number and as per specification.
* EDR Starts RFCOMM Server with prefixed UUID as per specification.
* LE Start GATT Server with prefixed UUID and Characteristics as per OIC Specification.
- * @return CA_STATUS_OK or CA_STATUS_FAILED
- * ERROR CODES (CAResult_t error codes in cacommon.h)
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED
+ * ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
typedef CAResult_t (*CAAdapterStartListeningServer)();
/**
- * @brief for starting discovery servers for receiving multicast advertisements
+ * for starting discovery servers for receiving multicast advertisements
* Transport Specific Behavior:
* WIFI/ETH Starts multicast server on all available IPs and defined port
* number as per OIC Specification.
* EDR Starts RFCOMM Server with prefixed UUID as per OIC Specification.
* LE Starts GATT Server with prefixed UUID and Characteristics as per OIC Specification.
- * @return CA_STATUS_OK or CA_STATUS_FAILED
- * ERROR CODES (CAResult_t error codes in cacommon.h)
+ * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED
+ * ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
typedef CAResult_t (*CAAdapterStartDiscoveryServer)();
/**
- * @brief Sends data to the endpoint using the adapter connectivity.
+ * Sends data to the endpoint using the adapter connectivity.
* Note: length must be > 0.
- * @param endpoint [IN] Remote Endpoint information (like ipaddress , port,
+ * @param[in] endpoint Remote Endpoint information (like ipaddress , port,
* reference uri and connectivity type) to which the unicast data has to be sent.
- * @param data [IN] Data which required to be sent.
- * @param dataLen [IN] Size of data to be sent.
+ * @param[in] data Data which required to be sent.
+ * @param[in] dataLen Size of data to be sent.
* @return The number of bytes sent on the network. Return value equal to -1 indicates error.
*/
typedef int32_t (*CAAdapterSendUnicastData)(const CAEndpoint_t *endpoint,
const void *data, uint32_t dataLen);
/**
- * @brief Sends Multicast data to the endpoint using the adapter connectivity.
+ * Sends Multicast data to the endpoint using the adapter connectivity.
* Note: length must be > 0.
- * @param endpoint [IN] Remote Endpoint information (like ipaddress , port,
- * @param data [IN] Data which required to be sent.
- * @param dataLen [IN] Size of data to be sent.
+ * @param[in] endpoint Remote Endpoint information (like ipaddress , port,
+ * @param[in] data Data which required to be sent.
+ * @param[in] dataLen Size of data to be sent.
* @return The number of bytes sent on the network. Return value equal to -1 indicates error.
*/
typedef int32_t (*CAAdapterSendMulticastData)(const CAEndpoint_t *endpoint,
const void *data, uint32_t dataLen);
/**
- * @brief Get Network Information
- * @param info [OUT] Local connectivity information structures
- * @param size [OUT] Number of local connectivity structures.
- * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
+ * Get Network Information.
+ * @param[out] info Local connectivity information structures
+ * @param[out] size Number of local connectivity structures.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h)
*/
typedef CAResult_t (*CAAdapterGetNetworkInfo)(CAEndpoint_t **info, uint32_t *size);
/**
- * @brief Read Synchronous API callback.
- * @return CA_STATUS_OK or ERROR CODES ( CAResult_t error codes in cacommon.h)
+ * Read Synchronous API callback.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h)
*/
typedef CAResult_t (*CAAdapterReadData)();
/**
- * @brief Stopping the adapters and close socket connections
+ * Stopping the adapters and close socket connections.
* Transport Specific Behavior:
* WIFI/ETH Stops all listening servers and close sockets.
* EDR Stops all RFCOMM servers and close sockets.
typedef CAResult_t (*CAAdapterStop)();
/**
- * @brief Terminate the connectivity adapter.Configuration information will be deleted from
+ * Terminate the connectivity adapter.Configuration information will be deleted from
* further use. Freeing Memory of threadpool and mutexs and cleanup will be done.
*/
typedef void (*CAAdapterTerminate)();
/**
- * @brief Connectivity handler information for adapter
+ * Connectivity handler information for adapter.
*/
typedef struct
{
- /** Start Transport specific functions*/
+ /** Start Transport specific functions. */
CAAdapterStart startAdapter;
- /** Listening Server function address*/
+ /** Listening Server function address. */
CAAdapterStartListeningServer startListenServer;
- /** Discovery Server function address **/
+ /** Discovery Server function address. **/
CAAdapterStartDiscoveryServer startDiscoveryServer;
- /** Unicast data function address**/
+ /** Unicast data function address. **/
CAAdapterSendUnicastData sendData;
- /** Multicast data function address**/
+ /** Multicast data function address. **/
CAAdapterSendMulticastData sendDataToAll;
- /** Get Networking information **/
+ /** Get Networking information. **/
CAAdapterGetNetworkInfo GetnetInfo;
- /** Read Data function address**/
+ /** Read Data function address. **/
CAAdapterReadData readData;
- /** Stop Transport specific functions*/
+ /** Stop Transport specific functions. */
CAAdapterStop stopAdapter;
- /** Terminate function address stored in this pointer**/
+ /** Terminate function address stored in this pointer. **/
CAAdapterTerminate terminate;
} CAConnectivityHandler_t;
/**
- * @brief This will be used during the registration of adapters call backs to the common logic
- * @see CAConnectivityHandler_t , CATransportAdapter_t
+ * This will be used during the registration of adapters call backs to the common logic.
+ * @see ::CAConnectivityHandler_t , ::CATransportAdapter_t
*/
typedef void (*CARegisterConnectivityCallback)(CAConnectivityHandler_t handler,
CATransportAdapter_t cType);
/**
- * @brief This will be used during the recive of network requests and response.
+ * 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);
/**
- * @brief This will be used to notify network changes to the connectivity common logic layer
+ * This will be used to notify network changes to the connectivity common logic layer.
* @see SendUnicastData(), SendMulticastData()
*/
typedef void (*CANetworkChangeCallback)(const CAEndpoint_t *info, CANetworkStatus_t status);
/**
- * @brief This will be used to notify error result to the connectivity common logic layer
+ * This will be used to notify error result to the connectivity common logic layer.
*/
typedef void (*CAErrorHandleCallback)(const CAEndpoint_t *endpoint,
const void *data, uint32_t dataLen,
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************/
+/* *****************************************************************
+ *
+ * Copyright 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 CA_ADAPTER_NET_DTLS_H_
#define CA_ADAPTER_NET_DTLS_H_
#include "cacommon.h"
/**
- * Currently DTLS supported adapters(2) WIFI and ETHENET for linux platform.
+ * Currently DTLS supported adapters(2) WIFI and ETHENET for linux platform.
*/
#define MAX_SUPPORTED_ADAPTERS 2
/**
- * @brief The implementation will be provided by OIC RI layer.
+ * The implementation will be provided by OIC RI layer.
*/
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,
const void *data, uint32_t dataLength);
/**
- * @struct stCAAdapterCallbacks_t
- * @brief Data structure for holding the send and recv callbacks.
+ * Data structure for holding the send and recv callbacks.
*/
typedef struct CAAdapterCallbacks
{
} stCAAdapterCallbacks_t;
/**
- * @struct stCADtlsContext_t
- * @brief Data structure for holding the tinyDTLS interface
- * related info.
+ * Data structure for holding the tinyDTLS interface related info.
*/
typedef struct stCADtlsContext
{
- u_arraylist_t *peerInfoList; /**< peerInfo list which holds the mapping between
- peer id to it's n/w address */
+ u_arraylist_t *peerInfoList; /**< peerInfo list which holds the mapping between
+ peer id to it's n/w address. */
u_arraylist_t *cacheList; /**< PDU's are cached until DTLS session is formed. */
struct dtls_context_t *dtlsContext; /**< Pointer to tinyDTLS context. */
struct stPacketInfo *packetInfo; /**< used by callback during
- decryption to hold address/length. */
+ decryption to hold address/length. */
dtls_handler_t callbacks; /**< Pointer to callbacks needed by tinyDTLS. */
stCAAdapterCallbacks_t adapterCallbacks[MAX_SUPPORTED_ADAPTERS];
} stCADtlsContext_t;
/**
- * @struct stPacketInfo_t
- * @brief Data structure for holding the decrypted data address
- * and length provided by tinyDTLS callback interface.
+ * Data structure for holding the decrypted data address
+ * and length provided by tinyDTLS callback interface.
*/
typedef struct stPacketInfo
{
} stPacketInfo_t;
/**
- * @enum eDtlsRet_t
- * @brief tinyDTLS library error codes.
+ * tinyDTLS library error codes.
*
*/
typedef enum
} eDtlsRet_t;
-/** Structure to have address information which will match with DTLS session_t struct.*/
+/** Structure to have address information which will match with DTLS session_t structure.*/
typedef struct
{
socklen_t size; /**< Size of address. */
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} addr; /**< Address information. */
- uint8_t ifIndex; /**< Holds adpater index to get callback info. */
+ uint8_t ifIndex; /**< Holds adapter index to get callback info. */
} stCADtlsAddrInfo_t;
/**
- * @struct stCACacheMessage_t
- * @brief structure to holds the information of cachemessage and address info.
- *
+ * structure to holds the information of cache message and address info.
*/
typedef struct CACacheMessage
{
/**
- * @fn CADTLSSetAdapterCallbacks
- * @brief Used set send and recv callbacks for different adapters(WIFI,EtherNet)
- *
- * @param[in] recvCallback packet received callback
- * @param[in] sendCallback packet sent callback
- * @param[in] type type of adapter
+ * Used set send and recv callbacks for different adapters(WIFI,EtherNet).
*
- * @retval void
+ * @param[in] recvCallback packet received callback.
+ * @param[in] sendCallback packet sent callback.
+ * @param[in] type type of adapter.
*
*/
void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
CATransportAdapter_t type);
/**
- * @brief Register callback to get DTLS PSK credentials.
- * @param credCallback [IN] callback to get DTLS credentials
- * @retval void
+ * Register callback to get DTLS PSK credentials.
+ * @param[in] credCallback callback to get DTLS credentials.
*/
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
*
- * @retval CA_STATUS_OK for success, otherwise some error value
+ * @retval ::CA_STATUS_OK for success, otherwise some error value
*/
CAResult_t CADtlsSelectCipherSuite(const dtls_cipher_t cipher);
*
* @param[in] enable TRUE/FALSE enables/disables anonymous cipher suite
*
- * @retval CA_STATUS_OK for success, otherwise some error value
+ * @retval ::CA_STATUS_OK for success, otherwise some error value
*/
CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable);
*
* @param[in] endpoint information of network address
*
- * @retval CA_STATUS_OK for success, otherwise some error value
+ * @retval ::CA_STATUS_OK for success, otherwise some error value
*/
CAResult_t CADtlsInitiateHandshake(const CAEndpoint_t *endpoint);
*
* @param[in] endpoint information of network address
*
- * @retval CA_STATUS_OK for success, otherwise some error value
+ * @retval ::CA_STATUS_OK for success, otherwise some error value
*/
CAResult_t CADtlsClose(const CAEndpoint_t *endpoint);
* @param[in,out] ownerPSK Output buffer for owner PSK
* @param[in] ownerPSKSize Byte length of the ownerPSK to be generated
*
- * @retval CA_STATUS_OK for success, otherwise some error value
+ * @retval ::CA_STATUS_OK for success, otherwise some error value
*/
CAResult_t CADtlsGenerateOwnerPSK(const CAEndpoint_t *endpoint,
const uint8_t* label, const size_t labelLen,
;
/**
- * @fn CAAdapterNetDtlsInit
- * @brief initialize tinyDTLS library and other necessary intialization.
+ * initialize tinyDTLS library and other necessary initialization.
*
* @return 0 on success otherwise a positive error value.
- * @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 CAAdapterNetDtlsInit();
/**
- * @fn CAAdapterNetDtlsDeInit
- * @brief de-inits tinyDTLS library and free the allocated memory.
- *
- * @return void
- *
+ * de-inits tinyDTLS library and free the allocated memory.
*/
void CAAdapterNetDtlsDeInit();
/**
- * @fn CAAdapterNetDtlsEncrypt
- * @brief Performs DTLS encryption of the CoAP PDU. If a
- * DTLS session does not exist yet with the @dst,
- * a DTLS handshake will be started. In case where
- * a new DTLS handshake is started, pdu info is
- * cached to be send when session setup is finished.
+ * Performs DTLS encryption of the CoAP PDU. If a DTLS session does not exist yet
+ * with the @dst, a DTLS handshake will be started. In case where a new DTLS handshake
+ * is started, pdu info is cached to be send when session setup is finished.
*
* @param[in] endpoint address to which data will be sent.
* @param[in] port port to which data will be sent.
* @param[in] dataLen length of given data
*
* @return 0 on success otherwise a positive error value.
- * @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.
*
*/
uint32_t dataLen);
/**
- * @fn CAAdapterNetDtlsDecrypt
- * @brief Performs DTLS decryption of the data received on
- * secure port. This method performs in-place decryption
- * of the cipher-text buffer. If a DTLS handshake message
- * is received or decryption failure happens, this method
- * returns -1. If a valid application PDU is decrypted, it
- * returns the length of the decrypted pdu.
+ * Performs DTLS decryption of the data received on
+ * secure port. This method performs in-place decryption
+ * of the cipher-text buffer. If a DTLS handshake message
+ * is received or decryption failure happens, this method
+ * returns -1. If a valid application PDU is decrypted, it
+ * returns the length of the decrypted pdu.
*
* @return 0 on success otherwise a positive error value.
- * @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 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.
#include "caprotocolmessage.h"
/**
- * Callback to send block data
- * @param[in] data send data
+ * Callback to send block data.
+ * @param[in] data send data.
*/
typedef void (*CASendThreadFunc)(CAData_t *data);
/**
- * Callback to notify received data from the remote endpoint
- * @param[in] data received data
+ * Callback to notify received data from the remote endpoint.
+ * @param[in] data received data.
*/
typedef void (*CAReceiveThreadFunc)(CAData_t *data);
+/**
+ * context of blockwise transfer.
+ */
typedef struct
{
- /** send method for block data **/
+ /** send method for block data. **/
CASendThreadFunc sendThreadFunc;
- /** callback function for received message **/
+ /** callback function for received message. **/
CAReceiveThreadFunc receivedThreadFunc;
/** array list on which the thread is operating. **/
u_arraylist_t *dataList;
- /** data list mutex for synchronization **/
+ /** data list mutex for synchronization. **/
ca_mutex blockDataListMutex;
- /** sender mutex for synchronization **/
+ /** sender mutex for synchronization. **/
ca_mutex blockDataSenderMutex;
} CABlockWiseContext_t;
+/**
+ * ID set of Blockwise transfer data set(::CABlockData_t).
+ */
typedef struct
{
- uint8_t* id; /**< blockData ID for CA */
- size_t idLength; /**< length of blockData ID */
+ uint8_t* id; /**< blockData ID for CA. */
+ size_t idLength; /**< length of blockData ID. */
} CABlockDataID_t;
+/**
+ * Block Data Set.
+ */
typedef struct
{
- coap_block_t block1; /**< block1 option */
- coap_block_t block2; /**< block2 option */
- uint16_t type; /**< block option type */
- CABlockDataID_t* blockDataId; /**< ID set of CABlockData */
- CAData_t *sentData; /**< sent request or response data information */
- CAPayload_t payload; /**< payload buffer */
- size_t payloadLength; /**< the total payload length to be received */
- size_t receivedPayloadLen; /**< currently received payload length */
+ coap_block_t block1; /**< block1 option. */
+ coap_block_t block2; /**< block2 option. */
+ uint16_t type; /**< block option type. */
+ CABlockDataID_t* blockDataId; /**< ID set of CABlockData. */
+ CAData_t *sentData; /**< sent request or response data information. */
+ CAPayload_t payload; /**< payload buffer. */
+ size_t payloadLength; /**< the total payload length to be received. */
+ size_t receivedPayloadLen; /**< currently received payload length. */
} CABlockData_t;
/**
- * CABlockState_t
- * state of received block message from remote endpoint
+ * state of received block message from remote endpoint.
*/
typedef enum
{
#endif
/**
- * Initializes the block-wise transfer context
- * @param[in] CASendThreadFunc function point to add data in send queue thread
- * @param[in] CAReceiveThreadFunc function point to add data in receive queue thread
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Initializes the block-wise transfer context.
+ * @param[in] CASendThreadFunc function point to add data in send queue thread.
+ * @param[in] CAReceiveThreadFunc function point to add data in receive queue thread.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAInitializeBlockWiseTransfer(CASendThreadFunc blockSendMethod,
CAReceiveThreadFunc receivedDataCallback);
/**
- * Terminate the block-wise transfer context
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Terminate the block-wise transfer context.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CATerminateBlockWiseTransfer();
/**
- * initialize mutex
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * initialize mutex.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAInitBlockWiseMutexVariables();
/**
- * terminate mutex
+ * terminate mutex.
*/
void CATerminateBlockWiseMutexVariables();
/**
* Pass the bulk data. if block-wise transfer process need,
* bulk data will be sent to block messages.
- * @param[in] data data for sending
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * @param[in] data data for sending.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CASendBlockWiseData(const CAData_t *data);
/**
- * Add the data to send thread queue
- * @param[in] sendData data for sending
- * @param[in] blockID ID set of CABlockData
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Add the data to send thread queue.
+ * @param[in] sendData data for sending.
+ * @param[in] blockID ID set of CABlockData.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAAddSendThreadQueue(const CAData_t *sendData, const CABlockDataID_t *blockID);
/**
* Check the block option type. If it has to be sent to a block,
* block option will be set.
- * @param[in] currData block data
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * @param[in] currData block data.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CACheckBlockOptionType(CABlockData_t *currData);
/**
* Pass the received pdu data. and check if block option is set.
- * @param[in] pdu received pdu binary data
- * @param[in] endpoint information of remote device
- * @param[in] receivedData received CAData
- * @param[in] dataLen received data length
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * @param[in] pdu received pdu binary data.
+ * @param[in] endpoint information of remote device.
+ * @param[in] receivedData received CAData.
+ * @param[in] dataLen received data length.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAReceiveBlockWiseData(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
const CAData_t *receivedData, size_t dataLen);
/**
- * process next step by block-wise state
- * @param[in] pdu received pdu binary data
- * @param[in] receivedData received CAData
- * @param[in] blockWiseStatus block-wise state to move next step
- * @param[in] blockID ID set of CABlockData
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * process next step by block-wise state.
+ * @param[in] pdu received pdu binary data.
+ * @param[in] receivedData received CAData.
+ * @param[in] blockWiseStatus block-wise state to move next step.
+ * @param[in] blockID ID set of CABlockData.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAProcessNextStep(const coap_pdu_t *pdu, const CAData_t *receivedData,
uint8_t blockWiseStatus, const CABlockDataID_t *blockID);
/**
- * send block message to remote device
- * @param[in] pdu received pdu binary data
- * @param[in] msgType the message type of the block
- * @param[in] status block-wise state to move next step
- * @param[in] blockID ID set of CABlockData
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send block message to remote device.
+ * @param[in] pdu received pdu binary data.
+ * @param[in] msgType the message type of the block.
+ * @param[in] status block-wise state to move next step.
+ * @param[in] blockID ID set of CABlockData.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CASendBlockMessage(const coap_pdu_t *pdu, CAMessageType_t msgType,
uint8_t status, const CABlockDataID_t *blockID);
/**
- * send error message to remote device
- * @param[in] pdu received pdu binary data
- * @param[in] status block-wise state to move next step
- * @param[in] responseResult response result code
- * @param[in] blockID ID set of CABlockData
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send error message to remote device.
+ * @param[in] pdu received pdu binary data.
+ * @param[in] status block-wise state to move next step.
+ * @param[in] responseResult response result code.
+ * @param[in] blockID ID set of CABlockData.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CASendErrorMessage(const coap_pdu_t *pdu, uint8_t status,
CAResponseResult_t responseResult,
const CABlockDataID_t *blockID);
/**
- * receive last block data
- * @param[in] blockID ID set of CABlockData
- * @param[in] receivedData received CAData
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * receive last block data.
+ * @param[in] blockID ID set of CABlockData.
+ * @param[in] receivedData received CAData.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAReceiveLastBlock(const CABlockDataID_t *blockID,
const CAData_t *receivedData);
/**
- * set next block option 1
- * @param[in] pdu received pdu binary data
- * @param[in] endpoint information of remote device
- * @param[in] receivedData received CAData
- * @param[in] block block option data
- * @param[in] dataLen received data length
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * set next block option 1.
+ * @param[in] pdu received pdu binary data.
+ * @param[in] endpoint information of remote device.
+ * @param[in] receivedData received CAData.
+ * @param[in] block block option data.
+ * @param[in] dataLen received data length.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CASetNextBlockOption1(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
const CAData_t *receivedData, coap_block_t block,
size_t dataLen);
/**
- * set next block option 2
- * @param[in] pdu received pdu binary data
- * @param[in] endpoint information of remote device
- * @param[in] receivedData received CAData
- * @param[in] block block option data
- * @param[in] dataLen received data length
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * set next block option 2.
+ * @param[in] pdu received pdu binary data.
+ * @param[in] endpoint information of remote device.
+ * @param[in] receivedData received CAData.
+ * @param[in] block block option data.
+ * @param[in] dataLen received data length.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CASetNextBlockOption2(coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
const CAData_t *receivedData, coap_block_t block,
size_t dataLen);
/**
- * Update the block option in block-wise transfer list
- * @param[in] currData stored block data information
- * @param[in] block block option to update
- * @param[in] msgType message type of pdu
- * @param[in] blockType block option type
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Update the block option in block-wise transfer list.
+ * @param[in] currData stored block data information.
+ * @param[in] block block option to update.
+ * @param[in] msgType message type of pdu.
+ * @param[in] blockType block option type.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CANegotiateBlockSize(CABlockData_t *currData, coap_block_t *block,
CAMessageType_t msgType, uint16_t blockType);
/**
- * Update the block option in block-wise transfer list
- * @param[in] currData stored block data information
- * @param[in] block block option of current message
- * @param[in] blockType block option type
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Update the block option in block-wise transfer list.
+ * @param[in] currData stored block data information.
+ * @param[in] block block option of current message.
+ * @param[in] blockType block option type.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAUpdateBlockData(CABlockData_t *currData, coap_block_t block,
uint16_t blockType);
/**
- * Update the messageId in block-wise transfer list
- * @param[in] pdu received pdu binary data
- * @param[in] blockID ID set of CABlockData
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Update the messageId in block-wise transfer list.
+ * @param[in] pdu received pdu binary data.
+ * @param[in] blockID ID set of CABlockData.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAUpdateMessageId(coap_pdu_t *pdu, const CABlockDataID_t *blockID);
/**
- * Update the block option items
- * @param[in] currData stored block data information
- * @param[in] pdu received pdu binary data
- * @param[in/out] block block option of current message
- * @param[in] blockType block option type
- * @param[in] status current flow status for block-wise transfer
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Update the block option items.
+ * @param[in] currData stored block data information.
+ * @param[in] pdu received pdu binary data.
+ * @param[in/out] block block option of current message.
+ * @param[in] blockType block option type.
+ * @param[in] status current flow status for block-wise transfer.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAUpdateBlockOptionItems(CABlockData_t *currData, const coap_pdu_t *pdu,
coap_block_t *block, uint16_t blockType,
uint32_t status);
/**
- * Set the M-bit of block option
- * @param[in] payloadLen payload length of current bulk data
- * @param[out] block block option
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Set the M-bit of block option.
+ * @param[in] payloadLen payload length of current bulk data.
+ * @param[out] block block option.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAGetMoreBitFromBlock(size_t payloadLen, coap_block_t *block);
/**
* check the block option what kind of option have to set.
- * @param[out] pdu pdu object
- * @param[in] info information of the request/response
- * @param[in] endpoint port of transport
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * @param[out] pdu pdu object.
+ * @param[in] info information of the request/response.
+ * @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,
const CAEndpoint_t *endpoint);
/**
* Write the block option2 in pdu binary data.
- * @param[out] pdu pdu object
- * @param[in] info information of the request/response
- * @param[in] dataLength length of payload
- * @param[in] blockID ID set of CABlockData
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * @param[out] pdu pdu object.
+ * @param[in] info information of the request/response.
+ * @param[in] dataLength length of payload.
+ * @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,
const CABlockDataID_t *blockID);
/**
* Write the block option1 in pdu binary data.
- * @param[out] pdu pdu object
- * @param[in] info information of the request/response
- * @param[in] dataLength length of payload
- * @param[in] blockID ID set of CABlockData
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * @param[out] pdu pdu object.
+ * @param[in] info information of the request/response.
+ * @param[in] dataLength length of payload.
+ * @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,
const CABlockDataID_t *blockID);
/**
- * Add the block option in pdu data
- * @param[in] pdu pdu object
- * @param[out] block block data
- * @param[in] blockType block option type
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Add the block option in pdu data.
+ * @param[in] pdu pdu object.
+ * @param[out] block block data.
+ * @param[in] blockType block option type.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAAddBlockOptionImpl(coap_pdu_t *pdu, coap_block_t *block, uint8_t blockType);
/**
- * Add the size option in pdu data
- * @param[in/out] pdu pdu object
- * @param[in] sizeType size option type
- * @param[in] dataLength the total payload length to be sent
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Add the size option in pdu data.
+ * @param[in/out] pdu pdu object.
+ * @param[in] sizeType size option type.
+ * @param[in] dataLength the total payload length to be sent.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAAddBlockSizeOption(coap_pdu_t *pdu, uint16_t sizeType, size_t dataLength);
/**
- * Get the size option from pdu data
- * @param[in] pdu pdu object
- * @param[in] sizeType size option type
- * @param[out] totalPayloadLen the total payload length to be received
- * @return true or false
+ * Get the size option from pdu data.
+ * @param[in] pdu pdu object.
+ * @param[in] sizeType size option type.
+ * @param[out] totalPayloadLen the total payload length to be received.
+ * @return true or false.
*/
bool CAIsPayloadLengthInPduWithBlockSizeOption(coap_pdu_t *pdu,
uint16_t sizeType,
size_t *totalPayloadLen);
/**
- * update the total payload with the received payload
- * @param[in] currData stored block data information
- * @param[in] receivedData received CAData
- * @param[in] status block-wise state
- * @param[in] isSizeOption size option
- * @param[in] blockType block option type
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * update the total payload with the received payload.
+ * @param[in] currData stored block data information.
+ * @param[in] receivedData received CAData.
+ * @param[in] status block-wise state.
+ * @param[in] isSizeOption size option.
+ * @param[in] blockType block option type.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAUpdatePayloadData(CABlockData_t *currData, const CAData_t *receivedData,
uint8_t status, bool isSizeOption, uint16_t blockType);
/**
* Generate CAData structure from the given information.
- * @param[in] pdu pdu object
- * @param[in] endpoint information of remote device
- * @return generated CAData
+ * @param[in] pdu pdu object.
+ * @param[in] endpoint information of remote device.
+ * @return generated CAData.
*/
CAData_t* CACreateNewDataSet(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint);
/**
- * Update the block option items
- * @param[in/out] blockblock option of current message
- * @param[in] blockType block option type
- * @param[in] responseResult result code of pdu
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Update the block option items.
+ * @param[in/out] blockblock option of current message.
+ * @param[in] blockType block option type.
+ * @param[in] responseResult result code of pdu.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAHandleBlockErrorResponse(coap_block_t *block, uint16_t blockType,
uint32_t responseResult);
/**
- * Check the received payload and if an error happens, return error type
- * @param[in/out] currData stored block data information
- * @param[in] receivedBlock received block option
- * @param[in] receivedData message type of pdu
- * @param[in] blockType block option type
- * @param[in] dataLen received data length
- * @return block state
+ * Check the received payload and if an error happens, return error type.
+ * @param[in/out] currData stored block data information.
+ * @param[in] receivedBlock received block option.
+ * @param[in] receivedData message type of pdu.
+ * @param[in] blockType block option type.
+ * @param[in] dataLen received data length.
+ * @return block state.
*/
uint8_t CACheckBlockErrorType(CABlockData_t *currData, coap_block_t *receivedBlock,
const CAData_t *receivedData, uint16_t blockType,
size_t dataLen);
/**
- * Destroys the given CAData
- * @param[in] data CAData to destroy
- * @return generated CAData
+ * Destroys the given CAData.
+ * @param[in] data CAData to destroy.
+ * @return generated CAData.
*/
void CADestroyDataSet(CAData_t* data);
/**
- * Create the blockId for CABlockData
- * @param[in] token token of current message
- * @param[in] tokenLength token length of current message
- * @param[in] portNumber port
- * @return ID set of CABlockData
+ * Create the blockId for CABlockData.
+ * @param[in] token token of current message.
+ * @param[in] tokenLength token length of current message.
+ * @param[in] portNumber port.
+ * @return ID set of CABlockData.
*/
CABlockDataID_t* CACreateBlockDatablockId(const CAToken_t token, uint8_t tokenLength,
uint16_t portNumber);
/**
- * Destroy the blockId set
- * @param[in] blockID ID set of CABlockData
+ * Destroy the blockId set.
+ * @param[in] blockID ID set of CABlockData.
*/
void CADestroyBlockID(CABlockDataID_t *blockID);
/**
- * check whether Block ID is matched or not
- * @param[in] currData block data
- * @param[in] blockID ID set of CABlockData
- * @return true or false
+ * check whether Block ID is matched or not.
+ * @param[in] currData block data.
+ * @param[in] blockID ID set of CABlockData.
+ * @return true or false.
*/
bool CABlockidMatches(const CABlockData_t *currData, const CABlockDataID_t *blockID);
/**
- * Print the given block option information
- * @param[in] block block option information
+ * Print the given block option information.
+ * @param[in] block block option information.
*/
void CALogBlockInfo(coap_block_t *block);
/**
- * Create new CAData structure from the input information
- * @param[in] data CAData information that needs to be duplicated
- * @return created CAData structure
+ * Create new CAData structure from the input information.
+ * @param[in] data CAData information that needs to be duplicated.
+ * @return created CAData structure.
*/
CAData_t *CACloneCAData(const CAData_t *data);
/**
- * Update payload from the input information
- * @param[in] data CAData information that needs to be updated
- * @param[in] payload received new payload from the remote endpoint
- * @param[in] payloadLen received full payload length
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Update payload from the input information.
+ * @param[in] data CAData information that needs to be updated.
+ * @param[in] payload received new payload from the remote endpoint.
+ * @param[in] payloadLen received full payload length.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAUpdatePayloadToCAData(CAData_t *data, const CAPayload_t payload,
size_t payloadLen);
/**
- * Get payload and payload length from the input information
- * @param[in] data CAData information
+ * Get payload and payload length from the input information.
+ * @param[in] data CAData information.
* @param[out] payloadLen The payload length is stored.
- * @return payload
+ * @return payload.
*/
CAPayload_t CAGetPayloadInfo(const CAData_t *data, size_t *payloadLen);
/**
- * Set the block option type
- * @param[in] blockID ID set of CABlockData
- * @param[in] blockType block option type
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Set the block option type.
+ * @param[in] blockID ID set of CABlockData.
+ * @param[in] blockType block option type.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAUpdateBlockOptionType(const CABlockDataID_t *blockID,
uint8_t blockType);
/**
- * Get the block option type from block-wise transfer list
- * @param[in] blockID ID set of CABlockData
- * @return block option type
+ * Get the block option type from block-wise transfer list.
+ * @param[in] blockID ID set of CABlockData.
+ * @return block option type.
*/
uint8_t CAGetBlockOptionType(const CABlockDataID_t *blockID);
/**
- * Get the block data from block-wise transfer list
- * @param[in] blockID ID set of CABlockData
- * @return CAData structure
+ * Get the block data from block-wise transfer list.
+ * @param[in] blockID ID set of CABlockData.
+ * @return CAData structure.
*/
CAData_t *CAGetDataSetFromBlockDataList(const CABlockDataID_t *blockID);
/**
- * Get token from block-wise transfer list
- * @param[in] pdu received pdu binary data
- * @param[in] endpoint remote endpoint information
- * @param[in] responseInfo received response information
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Get token from block-wise transfer list.
+ * @param[in] pdu received pdu binary data.
+ * @param[in] endpoint remote endpoint information.
+ * @param[in] responseInfo received response information.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAGetTokenFromBlockDataList(const coap_pdu_t *pdu, const CAEndpoint_t *endpoint,
CAResponseInfo_t *responseInfo);
/**
- * check whether the block data is valid or not
- * @param[in] sendData CAData information
- * @param[out] blockData block data when it is valid
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * check whether the block data is valid or not.
+ * @param[in] sendData CAData information.
+ * @param[out] blockData block data when it is valid.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CACheckBlockDataValidation(const CAData_t *sendData, CABlockData_t **blockData);
/**
- * Get the block data from block-wise transfer list
- * @param[in] blockID ID set of CABlockData
- * @return CABlockData_t structure
+ * Get the block data from block-wise transfer list.
+ * @param[in] blockID ID set of CABlockData.
+ * @return CABlockData_t structure.
*/
CABlockData_t *CAGetBlockDataFromBlockDataList(const CABlockDataID_t *blockID);
/**
- * Get the block option from block-wise transfer list
- * @param[in] blockID ID set of CABlockData
- * @param[in] blockType block option type
- * @return coap_block_t structure
+ * Get the block option from block-wise transfer list.
+ * @param[in] blockID ID set of CABlockData.
+ * @param[in] blockType block option type.
+ * @return coap_block_t structure.
*/
coap_block_t *CAGetBlockOption(const CABlockDataID_t *blockID,
uint16_t blockType);
/**
- * Get the full payload from block-wise list
- * @param[in] blockID ID set of CABlockData
- * @param[out] fullPayloadLen received full payload length
- * @return payload
+ * Get the full payload from block-wise list.
+ * @param[in] blockID ID set of CABlockData.
+ * @param[out] fullPayloadLen received full payload length.
+ * @return payload.
*/
CAPayload_t CAGetPayloadFromBlockDataList(const CABlockDataID_t *blockID,
size_t *fullPayloadLen);
/**
- * Create the block data from given data and add the data in block-wise transfer list
- * @param[in] sendData data to be added to a list
- * @return created CABlockData_t structure
- * and NULL point will be returned if there is error case.
+ * Create the block data from given data and add the data in block-wise transfer list.
+ * @param[in] sendData data to be added to a list.
+ * @return created CABlockData_t structure.
+ * and NULL point will be returned if there is error case..
*/
CABlockData_t *CACreateNewBlockData(const CAData_t *sendData);
/**
- * Remove the block data in block-wise transfer list
- * @param[in] blockID ID set of CABlockData
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Remove the block data in block-wise transfer list.
+ * @param[in] blockID ID set of CABlockData.
+ * @return ::CASTATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CARemoveBlockDataFromList(const CABlockDataID_t *blockID);
/**
* Check if data exist in block-wise transfer list.
- * @param[in] blockID ID set of CABlockData
- * @return true or false
+ * @param[in] blockID ID set of CABlockData.
+ * @return true or false.
*/
bool CAIsBlockDataInList(const CABlockDataID_t *blockID);
* @param[in] errorCallback errorCallback to notify error to connectivity common logic
* layer from adapter.
* @param[in] handle Threadpool Handle.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAInitializeEDR(CARegisterConnectivityCallback registerCallback,
CANetworkPacketReceivedCallback reqRespCallback,
/**
* Starts EDR connectivity adapters.
* As its peer to peer it does not require to start any servers.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAStartEDR();
* Starts listening server for receiving multicast search requests.
* Starts RFCOMM Server with prefixed UUID as per OIC specification.
*
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAStartEDRListeningServer();
* Starting discovery server for receiving multicast advertisements.
* Starts RFCOMM Server with prefixed UUID as per OIC specification.
*
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAStartEDRDiscoveryServer();
* @param[out] info Array of local connectivity information structures.
* @param[out] size Size of the array @info.
*
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAGetEDRInterfaceInformation(CAEndpoint_t **info, uint32_t *size);
/**
* Read Synchronous API callback.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAReadEDRData();
/**
* EDR Stops all RFCOMM servers and close sockets.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAStopEDR();
/**
* Initializes the adapter queues.
* This will initiates both server and receiver adapter queues.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAAdapterStartQueue();
typedef enum
{
STATE_DISCONNECTED, /**< State is Disconnected. */
- STATE_CONNECTED /**< State is Connected. */
+ STATE_CONNECTED /**< State is Connected. */
} CAConnectedState_t;
typedef struct connected_state
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);
/**
/**
* Callback to notify the error in the EDR adapter.
* @param[in] remoteAddress Remote EDR Address.
- * @param[in] serviceUUID Service UUID of the device.
* @param[in] data data containing token, uri and coap data.
* @param[in] dataLength length of data.
* @param[in] result error code as defined in ::CAResult_t.
* @pre Callback must be registered using CAEDRSetPacketReceivedCallback().
*/
-typedef void (*CAEDRErrorHandleCallback)(const char *remoteAddress, const char *serviceUUID,
- 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
*
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*
* @see CALocalConnectivity_t
/**
* Start RFCOMM server for given service UUID
*
- * @param[in] serviceUUID The UUID of service with which RFCOMM server
- * needs to be started.
- * @param[in] serverFD The RFCOMM server socket file descriptor.
* @param[in] handle Threadpool Handle.
*
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*
*/
-CAResult_t CAEDRServerStart(const char *serviceUUID, int *serverFD, ca_thread_pool_t handle);
+CAResult_t CAEDRServerStart(ca_thread_pool_t handle);
/**
* Stop RFCOMM server
*
- * @param[in] serverFD The RFCOMM server socket file descriptor which
- * needs to be stopped.
- *
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
-CAResult_t CAEDRServerStop(int serverFD);
+CAResult_t CAEDRServerStop();
/**
* Terminate server for EDR.
/**
* This function sends data to specified remote bluetooth device.
* @param[in] remoteAddress Remote EDR Address.
- * @param[in] serviceUUID Service UUID of the device.
* @param[in] data Data to be sent.
* @param[in] dataLength Length of the data to be sent.
- * @param[out] sentLength Length of the actual sent data.
* @return ::CA_STATUS_OK or Appropriate error code.
*/
-CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const char *serviceUUID,
- const void *data, uint32_t dataLength, uint32_t *sentLength);
+CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress,
+ const uint8_t *data,
+ uint32_t dataLength);
/**
* This function sends data to all bluetooth devices running OIC service.
- * @param[in] serviceUUID Service UUID of the device.
* @param[in] data Data to be sent.
* @param[in] dataLength Length of the data to be sent.
- * @param[out] sentLength Length of the actual sent data.
* @return ::CA_STATUS_OK or Appropriate error code.
*/
-CAResult_t CAEDRClientSendMulticastData(const char *serviceUUID, const void *data,
- uint32_t dataLength, uint32_t *sentLength);
+CAResult_t CAEDRClientSendMulticastData(const uint8_t *data,
+ uint32_t dataLength);
/**
* This function gets bonded bluetooth device list
#include "logger.h"
/**
- * @var MAX_DATA_LENGTH_SUPPORTED
- * @brief From the adapter level, this is the maximum data length is supported
- * for the data transmission.
+ * From the adapter level, this is the maximum data length is supported
+ * for the data transmission.
*/
#define MAX_DATA_LENGTH_SUPPORTED 4095
/**
- * @var NUMBER_OF_BITS_TO_IDENTIFY_DATA
- * @brief The number of bits allocated to represent data length in header.
+ * The number of bits allocated to represent data length in header.
*/
#define NUMBER_OF_BITS_TO_IDENTIFY_DATA 12
/**
- * @var NUMBER_OF_BITS_IN_CA_HEADER
- * @brief The length of the header in bits.
+ * The length of the header in bits.
*/
#define NUMBER_OF_BITS_IN_CA_HEADER 15
/**
- * @var CA_HEADER_LENGTH
- * @brief The length of the header in bytes.
+ * The length of the header in bytes.
*/
#define CA_HEADER_LENGTH 2
/**
- * @var CA_SUPPORTED_BLE_MTU_SIZE
- * @brief The MTU supported for BLE adapter
+ * The MTU supported for BLE adapter
*/
#define CA_SUPPORTED_BLE_MTU_SIZE 20
#ifdef __TIZEN__
/**
- * @var PLATFORM_IDENTIFIER_BIT
- * @brief Reserved bit to differentiating the platform. Currently not in use.
+ * Reserved bit to differentiating the platform. Currently not in use.
*/
#define PLATFORM_IDENTIFIER_BIT 1
/**
- * @var CA_SUPPORTED_EDR_MTU_SIZE
- * @brief The MTU supported from Tizen platform for EDR adapter.
+ * The MTU supported from Tizen platform for EDR adapter.
*/
#define CA_SUPPORTED_EDR_MTU_SIZE 512
#elif __ANDROID__
/**
- * @var PLATFORM_IDENTIFIER_BIT
- * @brief Reserved bit to differentiating the platform. Currently not in use.
+ * Reserved bit to differentiating the platform. Currently not in use.
*/
#define PLATFORM_IDENTIFIER_BIT 0
/**
- * @var CA_SUPPORTED_EDR_MTU_SIZE
- * @brief The MTU supported from Android platform for EDR adapter.
+ * The MTU supported from Android platform for EDR adapter.
*/
#define CA_SUPPORTED_EDR_MTU_SIZE 200
#elif __ARDUINO__
/**
- * @var PLATFORM_IDENTIFIER_BIT
- * @brief Reserved bit to differentiating the platform. Currently not in use.
+ * Reserved bit to differentiating the platform. Currently not in use.
*/
#define PLATFORM_IDENTIFIER_BIT 0
/**
- * @var CA_SUPPORTED_EDR_MTU_SIZE
- * @brief The MTU supported from Arduino platform for EDR adapter.
+ * The MTU supported from Arduino platform for EDR adapter.
*/
#define CA_SUPPORTED_EDR_MTU_SIZE 200
#else //Other Platforms
/**
- * @var PLATFORM_IDENTIFIER_BIT
- * @brief Reserved bit to differentiating the platform. Currently not in use.
+ * Reserved bit to differentiating the platform. Currently not in use.
*/
#define PLATFORM_IDENTIFIER_BIT 0
/**
- * @var CA_SUPPORTED_EDR_MTU_SIZE
- * @brief The MTU supported for EDR adapter
+ * The MTU supported for EDR adapter
*/
#define CA_SUPPORTED_EDR_MTU_SIZE 200
#endif
/**
- * @var HEADER_VERSION
- * @brief Current Header version.
+ * Current Header version.
*/
#define HEADER_VERSION 1
/*****************************************************************
* @file The CA Header format
- * @brief CA Header will be defined by 2 bytes of Header.
+ * CA Header will be defined by 2 bytes of Header.
* First two bits : Header version(Currently Its not being used)
* Third bit and fourth bit: Reserved bits for future use.
* 5th to 16th bit : 12 bits to provide the length of the data.
*****************************************************************/
/**
-* @fn CAGenerateHeader
-* @brief 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.
-*
-* @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).
-*
-* @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(char *header, uint32_t length);
-
-/**
-* @fn CAParseHeader
-* @brief 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
-* point to two bytes of data header which needs to
-* be parsed.
-*
-* @return Overall length of the data to be reassembled, or 0 on
-* failure.
-*/
-uint32_t CAParseHeader(const char *header);
+ * 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.
+ *
+ * @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 @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
+ * 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 uint8_t *header, size_t length);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* CA_FRAGMENTATION_H_ */
-
/**
* Starting different connectivity adapters based on the network selection.
* @param[in] transportType interested network for starting.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAStartAdapter(CATransportAdapter_t transportType);
* @param[out] info connectivity information
* such as ipaddress and mac information.
* @param[out] size number of connectivity information structures.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAGetNetworkInfo(CAEndpoint_t **info, uint32_t *size);
* @param[in] endpoint endpoint information where the data has to be sent.
* @param[in] data data that needs to be sent.
* @param[in] length length of the data that needs to be sent.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CASendUnicastData(const CAEndpoint_t *endpoint, const void *data, uint32_t length);
* @param[in] endpoint endpoint information where the data has to be sent.
* @param[in] data data that needs to be sent.
* @param[in] length length of the data that needs to be sent.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CASendMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t length);
/**
* Start listening servers to receive search requests from clients.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAStartListeningServerAdapters();
/**
* Start discovery servers to receive advertisements from server.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAStartDiscoveryServerAdapters();
#ifdef SINGLE_THREAD
/**
* Checks for available data and reads it.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAReadData();
#endif
} /* extern "C" */
#endif
-#endif // #ifndef CA_IP_ADAPTER_H_
+#endif // CA_IP_ADAPTER_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);
/**
******************************************************************/
/**
- * @file camessagehandler.h
+ * @file
* This file contains message functionality.
*/
CARequestInfo_t *requestInfo;
CAResponseInfo_t *responseInfo;
CAErrorInfo_t *errorInfo;
- CAHeaderOption_t *options;
CADataType_t dataType;
- uint8_t numOptions;
} CAData_t;
#ifdef __cplusplus
#endif
/**
- * Detaches control from the caller for sending unicast request
- * @param[IN] endpoint endpoint information where the data has to be sent
- * @param[IN] request request that needs to be sent
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Detaches control from the caller for sending unicast request.
+ * @param[in] endpoint endpoint information where the data has to be sent.
+ * @param[in] request request that needs to be sent.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CADetachRequestMessage(const CAEndpoint_t *endpoint,
const CARequestInfo_t *request);
/**
- * Detaches control from the caller for sending multicast request
- * @param[IN] object Group endpoint information where the data has to be sent
- * @param[IN] request request that needs to be sent
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Detaches control from the caller for sending multicast request.
+ * @param[in] object Group endpoint information where the data has to be sent.
+ * @param[in] request request that needs to be sent.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CADetachRequestToAllMessage(const CAEndpoint_t *object,
const CARequestInfo_t *request);
/**
- * Detaches control from the caller for sending response
- * @param[IN] endpoint endpoint information where the data has to be sent
- * @param[IN] response response that needs to be sent
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Detaches control from the caller for sending response.
+ * @param[in] endpoint endpoint information where the data has to be sent.
+ * @param[in] response response that needs to be sent.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CADetachResponseMessage(const CAEndpoint_t *endpoint,
const CAResponseInfo_t *response);
/**
- * Detaches control from the caller for sending request
- * @param[IN] resourceUri resource uri that needs to be sent in the request
- * @param[IN] token token information of the request
- * @param[IN] tokenLength length of the token
- * @param[IN] options header options that need to be append in the request
- * @param[IN] numOptions number of options be appended
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * Detaches control from the caller for sending request.
+ * @param[in] resourceUri resource uri that needs to be sent in the request.
+ * @param[in] token token information of the request.
+ * @param[in] tokenLength length of the token.
+ * @param[in] options header options that need to be append in the request.
+ * @param[in] numOptions number of options be appended.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CADetachMessageResourceUri(const CAURI_t resourceUri, const CAToken_t token,
uint8_t tokenLength, const CAHeaderOption_t *options,
uint8_t numOptions);
/**
- * Setting the request and response callbacks for network packets
- * @param[IN] ReqHandler callback for receiving the requests
- * @param[IN] RespHandler callback for receiving the response
- * @param[IN] ErrorHandler callback for receiving error response
+ * Setting the request and response callbacks for network packets.
+ * @param[in] ReqHandler callback for receiving the requests.
+ * @param[in] RespHandler callback for receiving the response.
+ * @param[in] ErrorHandler callback for receiving error response.
*/
void CASetInterfaceCallbacks(CARequestCallback ReqHandler, CAResponseCallback RespHandler,
CAErrorCallback ErrorHandler);
/**
* Initialize the message handler by starting thread pool and initializing the
- * send and receive queue
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send and receive queue.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAInitializeMessageHandler();
/**
- * Terminate the message handler by stopping the thread pool and destroying the queues
+ * Terminate the message handler by stopping the thread pool and destroying the queues.
*/
void CATerminateMessageHandler();
/**
- * Handler for receiving request and response callback in single thread model
+ * Handler for receiving request and response callback in single thread model.
*/
void CAHandleRequestResponseCallbacks();
/**
- * To log the PDU data
- * @param[IN] pdu pdu data
+ * To log the PDU data.
+ * @param[in] pdu pdu data.
*/
void CALogPDUInfo(coap_pdu_t *pdu);
#ifdef WITH_BWT
/**
- * Add the data to the send queue thread
- * @param[IN] data send data
+ * Add the data to the send queue thread.
+ * @param[in] data send data.
*/
void CAAddDataToSendThread(CAData_t *data);
/**
- * Add the data to the receive queue thread to notify received data
- * @param[IN] data received data
+ * Add the data to the receive queue thread to notify received data.
+ * @param[in] data received data.
*/
void CAAddDataToReceiveThread(CAData_t *data);
#endif
/**
* Add network type to the selected networks for network packets reception.
* @param[in] transportAdapter Adapter that needs to be added.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAAddNetworkType(CATransportAdapter_t transportAdapter);
/**
* Remove network type from the selected configuration.
* @param[in] transportAdapter Adapter that needs to be removed.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CARemoveNetworkType(CATransportAdapter_t transportAdapter);
u_arraylist_t *CAGetSelectedNetworkList();
/**
- * Getnetwork informations of the selected networks.
+ * Get network informations of the selected networks.
* @param[out] info LocalConnectivity objects.
* @param[out] size No Of Array objects.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CAGetNetworkInformationInternal(CAEndpoint_t **info, uint32_t *size);
/**
* Terminate network type from selected configuration.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CATerminateNetworkType();
*
******************************************************************/
/**
- * @file caprotocolmessage.h
- * @brief This file contains common function for handling protocol messages.
+ * @file
+ * This file contains common function for handling protocol messages.
*/
#ifndef CA_PROTOCOL_MESSAGE_H_
* generates pdu structure from the given information.
* @param[in] code code of the pdu packet.
* @param[in] info pdu information.
+ * @param[in] endpoint endpoint information.
* @return generated pdu.
*/
-coap_pdu_t *CAGeneratePDU(uint32_t code, const CAInfo_t *info);
-
-/**
- * function for generating
- */
+coap_pdu_t *CAGeneratePDU(uint32_t code, const CAInfo_t *info, const CAEndpoint_t *endpoint);
/**
* extracts request information from received pdu.
* @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] payload payload for the request or response consumed.
+ * @param[in] endpoint endpoint information.
* @return generated pdu.
*/
coap_pdu_t *CAGeneratePDUImpl(code_t code, coap_list_t *options, const CAInfo_t *info,
- const uint8_t *payload, size_t payloadSize);
+ const CAEndpoint_t *endpoint);
/**
* parse the URI and creates the options.
coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode);
/**
- * get Token fromn received data(pdu).
+ * get Token from received data(pdu).
* @param[in] pdu_hdr header of received pdu.
* @param[out] outInfo information with token received.
* @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
******************************************************************/
/**
- * @file caretransmission.h
- * @brief This file contains common function for retransmission messages.
+ * @file
+ * This file contains common function for retransmission messages.
*/
#ifndef CA_RETRANSMISSION_H_
* @param[in] timeoutCallback callback for retransmit timeout.
* @param[in] config configuration for retransmission.
* if NULL is coming, it will set default values.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CARetransmissionInitialize(CARetransmission_t *context,
ca_thread_pool_t handle,
/**
* Starting the retransmission context.
* @param[in] context context for retransmission.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CARetransmissionStart(CARetransmission_t *context);
* @param[in] endpoint endpoint information.
* @param[in] pdu sent pdu binary data.
* @param[in] size sent pdu binary data size.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CARetransmissionSentData(CARetransmission_t* context,
const CAEndpoint_t* endpoint,
* @param[in] pdu received pdu binary data.
* @param[in] size received pdu binary data size.
* @param[out] retransmissionPdu pdu data of the request for reset and ack.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CARetransmissionReceivedData(CARetransmission_t *context,
const CAEndpoint_t *endpoint, const void *pdu,
/**
* Stopping the retransmission context.
* @param[in] context context for retransmission.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CARetransmissionStop(CARetransmission_t *context);
/**
* Terminating the retransmission context.
* @param[in] context context for retransmission.
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CARetransmissionDestroy(CARetransmission_t *context);
print"Reading ca script %s"%ca_transport
app_env.AppendUnique(CPPPATH = [root_dir + '/api/'])
+app_env.AppendUnique(CPPPATH = [root_dir + '/inc/'])
+app_env.AppendUnique(CPPPATH = [root_dir + '/common/inc/'])
+app_env.AppendUnique(CPPPATH = [root_dir + 'lib/libcoap-4.1.1'])
print "Reading sample application build script"
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
} else if (subject.equals(getString(R.string.remote_port))) {
StringBuilder sb = new StringBuilder();
String uri = mReqData_ed.getText().toString();
+ sb.append(uri);
if (null != receivedData && uri.contains("."))
{
- sb.append(uri).append(":").append(receivedData);
+ sb.append(":").append(receivedData);
}
sb.append(getString(R.string.uri));
mReqData_ed.setText(sb.toString());
#include "cainterface.h"
#include "cacommon.h"
+#include "caadapterutils.h"
#include "org_iotivity_ca_service_RMInterface.h"
uint16_t port;
} addressSet_t;
-void request_handler(const CAEndpoint_t* object, const CARequestInfo_t* requestInfo);
-void response_handler(const CAEndpoint_t* object, const CAResponseInfo_t* responseInfo);
-void error_handler(const CAEndpoint_t *object, const CAErrorInfo_t* errorInfo);
-void get_resource_uri(const char *URI, char *resourceURI, uint32_t length);
-uint32_t get_secure_information(CAPayload_t payLoad);
-CAResult_t get_network_type(uint32_t selectedNetwork);
-void callback(char *subject, char *receivedData);
-CAResult_t get_remote_address(CATransportAdapter_t transportType, const char *address);
-void parsing_coap_uri(const char* uri, addressSet_t* address, CATransportFlags_t *flags);
+static void request_handler(const CAEndpoint_t* object, const CARequestInfo_t* requestInfo);
+static void response_handler(const CAEndpoint_t* object, const CAResponseInfo_t* responseInfo);
+static void error_handler(const CAEndpoint_t *object, const CAErrorInfo_t* errorInfo);
+static void get_resource_uri(const char *URI, char *resourceURI, int32_t length);
+static uint32_t get_secure_information(CAPayload_t payLoad);
+static CAResult_t get_network_type(uint32_t selectedNetwork);
+static void callback(char *subject, char *receivedData);
+static CAResult_t get_remote_address(const char *address);
+static void parsing_coap_uri(const char* uri, addressSet_t* address, CATransportFlags_t *flags);
+static void delete_global_references(JNIEnv *env, jobject obj);
+static int get_address_set(const char *pAddress, addressSet_t* outAddress);
uint16_t g_localSecurePort = SECURE_DEFAULT_PORT;
CATransportAdapter_t g_selectedNwType = CA_ADAPTER_IP;
jobject listener)
{
LOGI("setNativeResponseListener");
- g_responseListenerObject = (*env)->NewGlobalRef(env, obj);
+ if (!env || !obj || !listener)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
+
+ g_responseListenerObject = (*env)->NewGlobalRef(env, listener);
}
#ifdef __WITH_DTLS__
Java_org_iotivity_ca_service_RMInterface_RMInitialize(JNIEnv *env, jobject obj, jobject context)
{
LOGI("RMInitialize");
+ if (!env || !obj || !context)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
//Currently set context for Android Platform
CANativeJNISetContext(env, context);
Java_org_iotivity_ca_service_RMInterface_RMTerminate(JNIEnv *env, jobject obj)
{
LOGI("RMTerminate");
+ if (!env || !obj)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
+
CADestroyToken(g_lastRequestToken);
CATerminate();
+ delete_global_references(env, obj);
}
JNIEXPORT void JNICALL
Java_org_iotivity_ca_service_RMInterface_RMStartListeningServer(JNIEnv *env, jobject obj)
{
LOGI("RMStartListeningServer");
+ if (!env || !obj)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
if (CA_STATUS_OK != CAStartListeningServer())
{
Java_org_iotivity_ca_service_RMInterface_RMStartDiscoveryServer(JNIEnv *env, jobject obj)
{
LOGI("RMStartDiscoveryServer");
+ if (!env || !obj)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
if (CA_STATUS_OK != CAStartDiscoveryServer())
{
Java_org_iotivity_ca_service_RMInterface_RMRegisterHandler(JNIEnv *env, jobject obj)
{
LOGI("RMRegisterHandler");
+ if(!env || !obj)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
CARegisterHandler(request_handler, response_handler, error_handler);
}
jint isSecured, jint msgType)
{
LOGI("selectedNetwork - %d", selectedNetwork);
+ if (!env || !obj)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
+
+ if (!payload)
+ {
+ LOGE("payload is NULL");
+ }
+
+ if (!uri)
+ {
+ LOGE("Invalid input parameter : uri");
+ return;
+ }
+
CAResult_t res = get_network_type(selectedNetwork);
if (CA_STATUS_OK != res)
{
LOGI("RMSendRequest - %s", strUri);
CATransportFlags_t flags;
- addressSet_t address = {};
+ addressSet_t address = {{0}, 0};
parsing_coap_uri(strUri, &address, &flags);
//create remote endpoint
CAEndpoint_t* endpoint = NULL;
- res = CACreateEndpoint(flags, g_selectedNwType, (const char*)address.ipAddress,
+ res = CACreateEndpoint(flags, g_selectedNwType, (const char*)(address.ipAddress),
address.port, &endpoint);
if (CA_STATUS_OK != res)
{
CADestroyEndpoint(endpoint);
return;
}
- snprintf(requestData.payload, length, SECURE_INFO_DATA, resourceURI, g_localSecurePort);
+ snprintf((char *) requestData.payload, length, SECURE_INFO_DATA, resourceURI, g_localSecurePort);
requestData.payloadSize = length;
}
else
CADestroyEndpoint(endpoint);
return;
}
- snprintf(requestData.payload, length, NORMAL_INFO_DATA, resourceURI);
+ snprintf((char *) requestData.payload, length, NORMAL_INFO_DATA, resourceURI);
requestData.payloadSize = length;
}
jint selectedNetwork)
{
LOGI("selectedNetwork - %d", selectedNetwork);
+ if (!env || !obj)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
+
CAResult_t res = get_network_type(selectedNetwork);
if (CA_STATUS_OK != res)
{
jint responseValue)
{
LOGI("RMSendResponse");
+ if (!env || !obj)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
LOGI("selectedNetwork - %d", selectedNetwork);
{
uint32_t length = strlen(SECURE_INFO_DATA) + strlen(g_resourceUri) + 1;
responseData.payload = (CAPayload_t) malloc(length);
- sprintf(responseData.payload, SECURE_INFO_DATA, g_resourceUri,
+ sprintf((char *) responseData.payload, SECURE_INFO_DATA, g_resourceUri,
g_localSecurePort);
responseData.payloadSize = length;
}
{
uint32_t length = strlen(NORMAL_INFO_DATA) + strlen(g_resourceUri) + 1;
responseData.payload = (CAPayload_t) malloc(length);
- sprintf(responseData.payload, NORMAL_INFO_DATA, g_resourceUri);
+ sprintf((char *) responseData.payload, NORMAL_INFO_DATA, g_resourceUri);
responseData.payloadSize = length;
}
}
jint responseValue)
{
LOGI("selectedNetwork - %d", selectedNetwork);
+ if (!env || !obj)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
+
+ if (!payload)
+ {
+ LOGE("payload is NULL");
+ }
+
+ if (!uri)
+ {
+ LOGE("Invalid input parameter : uri");
+ return;
+ }
CAResult_t res = get_network_type(selectedNetwork);
if (CA_STATUS_OK != res)
LOGI("RMSendNotification - %s", strUri);
CATransportFlags_t flags;
- addressSet_t address = {};
+ addressSet_t address = {{0}, 0};
parsing_coap_uri(strUri, &address, &flags);
//create remote endpoint
free(responseData.resourceUri);
return;
}
- snprintf(responseData.payload, length, SECURE_INFO_DATA, resourceURI, g_localSecurePort);
+ snprintf((char *) responseData.payload, length, SECURE_INFO_DATA, resourceURI, g_localSecurePort);
+ responseData.payloadSize = length;
}
else
{
free(responseData.resourceUri);
return;
}
- snprintf(responseData.payload, length, NORMAL_INFO_DATA, resourceURI);
+ snprintf((char *) responseData.payload, length, NORMAL_INFO_DATA, resourceURI);
+ responseData.payloadSize = length;
}
responseData.type = messageType;
jint networkType)
{
LOGI("RMSelectNetwork Type : %d", networkType);
+ if (!env || !obj)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
if (CA_STATUS_OK != CASelectNetwork(networkType))
{
jint networkType)
{
LOGI("RMUnSelectNetwork Type : %d", networkType);
+ if (!env || !obj)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
if (CA_STATUS_OK != CAUnSelectNetwork(networkType))
{
Java_org_iotivity_ca_service_RMInterface_RMGetNetworkInfomation(JNIEnv *env, jobject obj)
{
LOGI("RMGetNetworkInfomation");
+ if (!env || !obj)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
CAEndpoint_t *tempInfo = NULL;
uint32_t tempSize = 0;
uint32_t index;
for (index = 0; index < tempSize; index++)
{
- res = get_remote_address(tempInfo[index].adapter, tempInfo[index].addr);
+ res = get_remote_address(tempInfo[index].addr);
if (CA_STATUS_OK != res)
{
free(tempInfo);
Java_org_iotivity_ca_service_RMInterface_RMHandleRequestResponse(JNIEnv *env, jobject obj)
{
LOGI("RMHandleRequestResponse");
+ if(!env || !obj)
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
if (CA_STATUS_OK != CAHandleRequestResponse())
{
return;
}
- CAResult_t res = get_remote_address(object->adapter, object->addr);
+ CAResult_t res = get_remote_address(object->addr);
if (CA_STATUS_OK != res)
{
return;
void response_handler(const CAEndpoint_t* object, const CAResponseInfo_t* responseInfo)
{
+ if (!object || !responseInfo)
+ {
+ LOGE("Invalid input parameter");
+ return;
+ }
- CAResult_t res = get_remote_address(object->adapter, object->addr);
+ CAResult_t res = get_remote_address(object->addr);
if (CA_STATUS_OK != res)
{
return;
void error_handler(const CAEndpoint_t *rep, const CAErrorInfo_t* errorInfo)
{
- printf("+++++++++++++++++++++++++++++++++++ErrorInfo+++++++++++++++++++++++++++++++++++");
+ LOGI("+++++++++++++++++++++++++++++++++++ErrorInfo+++++++++++++++++++++++++++++++++++");
- if(errorInfo)
+ if (rep)
+ {
+ LOGI("Error Handler, Adapter Type : %d", rep->adapter);
+ LOGI("Error Handler, Adapter Type : %s", rep->addr);
+ }
+
+ if (errorInfo)
{
const CAInfo_t *info = &errorInfo->info;
LOGI("Error Handler, ErrorInfo :");
return;
}
-void get_resource_uri(const char *URI, char *resourceURI, uint32_t length)
+void get_resource_uri(const char *URI, char *resourceURI, int32_t length)
{
const char *startPos = URI;
const char *temp = strstr(URI, "://");
}
const char *subString = NULL;
- if (NULL == (subString = strstr(payLoad, "\"sec\":1")))
+ if (NULL == (subString = strstr((const char *) payLoad, "\"sec\":1")))
{
LOGE("This is not secure resource");
return -1;
}
- if (NULL == (subString = strstr(payLoad, "\"port\":")))
+ if (NULL == (subString = strstr((const char *) payLoad, "\"port\":")))
{
LOGE("This secure resource does not have port information");
return -1;
void callback(char *subject, char *receivedData)
{
- JNIEnv* env = NULL;
- uint32_t status = (*g_jvm)->GetEnv(g_jvm, (void **) &env, JNI_VERSION_1_6);
- uint32_t res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
+ bool isAttached = false;
+ JNIEnv* env;
+
+ if (!g_responseListenerObject)
+ {
+ LOGE("g_responseListenerObject is NULL, cannot have callback");
+ return;
+ }
+
+ jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+ if (JNI_OK != res)
+ {
+ LOGI("Could not get JNIEnv pointer");
+ res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
+
+ if (JNI_OK != res)
+ {
+ LOGE("AttachCurrentThread has failed");
+ return;
+ }
+ isAttached = true;
+ }
jclass cls = (*env)->GetObjectClass(env, g_responseListenerObject);
+ if (!cls)
+ {
+ LOGE("could not get class");
+ goto detach_thread;
+ }
+
jmethodID mid = (*env)->GetMethodID(env, cls, "OnResponseReceived",
"(Ljava/lang/String;Ljava/lang/String;)V");
+ if (!mid)
+ {
+ LOGE("could not get Method ID");
+ goto detach_thread;
+ }
jstring jsubject = (*env)->NewStringUTF(env, (char*) subject);
+ if (!jsubject)
+ {
+ LOGE("NewStringUTF failed");
+ goto detach_thread;
+ }
+
jstring jreceivedData = (*env)->NewStringUTF(env, (char*) receivedData);
+ if (!jreceivedData)
+ {
+ LOGE("NewStringUTF failed");
+ goto detach_thread;
+ }
+
(*env)->CallVoidMethod(env, g_responseListenerObject, mid, jsubject, jreceivedData);
+detach_thread :
+ if (isAttached)
+ {
+ (*g_jvm)->DetachCurrentThread(g_jvm);
+ LOGI("DetachCurrentThread");
+ }
}
-CAResult_t get_remote_address(CATransportAdapter_t transportType, const char *address)
+CAResult_t get_remote_address(const char *address)
{
uint32_t len = strlen(address);
}
// #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;
- char *pResourceUri = NULL;
+ char *pstr = NULL;
+ //filter out the resource uri
+ char *pUrl = strtok_r(cloneUri, "/", &pstr);
- int32_t i = 0;
- for (i = 0; i < len; i++)
+ if (pUrl)
{
- if (cloneUri[i] == '/')
+ LOGI("pAddress : %s", pUrl);
+ int res = get_address_set(pUrl, address);
+ if (res == -1)
{
- // separate
- cloneUri[i] = 0;
- pResourceUri = &cloneUri[i + 1];
- break;
+ LOGE("address parse error");
+
+ return;
}
}
- LOGI("pAddress : %s", pAddress);
-
- int res = get_address_set(pAddress, address);
- if (res == -1)
+ else
{
- LOGE("address parse error");
-
- free(cloneUri);
- return;
+ LOGE("strtok_r error, could not get the address");
}
+
return;
}
return -1;
}
- int32_t len = strlen(pAddress);
- int32_t isIp = 0;
- int32_t ipLen = 0;
+ size_t len = strlen(pAddress);
+ int isIp = 0;
+ size_t ipLen = 0;
- int32_t i = 0;
- for (i = 0; i < len; i++)
+ for (size_t i = 0; i < len; i++)
{
if (pAddress[i] == '.')
{
if (isIp)
{
- if(ipLen && ipLen < sizeof(outAddress->ipAddress))
+ if(ipLen && (ipLen < sizeof(outAddress->ipAddress)))
{
strncpy(outAddress->ipAddress, pAddress, ipLen);
outAddress->ipAddress[ipLen] = '\0';
}
- else if (!ipLen && len < sizeof(outAddress->ipAddress))
+ else if (!ipLen && (len < sizeof(outAddress->ipAddress)))
{
strncpy(outAddress->ipAddress, pAddress, len);
outAddress->ipAddress[len] = '\0';
return isIp;
}
+
+void delete_global_references(JNIEnv *env, jobject obj)
+{
+ LOGI("delete_global_references");
+ if (!env || !obj )
+ {
+ LOGI("Invalid input parameter");
+ return;
+ }
+
+ (*env)->DeleteGlobalRef(env, g_responseListenerObject);
+}
printf("resourceURI : %s\n", resourceURI);
// create request data
- CAInfo_t requestData = { 0 };
- requestData.token = token;
- requestData.tokenLength = tokenLength;
- requestData.resourceUri = (CAURI_t)resourceURI;
+ CAInfo_t requestData = { .type = msgType,
+ .messageId = 0,
+ .token = token,
+ .tokenLength = tokenLength,
+ .options = NULL,
+ .numOptions = 0,
+ .payload = NULL,
+ .payloadSize = 0,
+ .resourceUri = (CAURI_t)resourceURI };
if (strcmp(secureRequest, "1") == 0)
{
requestData.payloadSize = length;
}
}
- requestData.type = msgType;
+
CAHeaderOption_t* headerOpt = get_option_data(&requestData);
- CARequestInfo_t requestInfo = { 0 };
- requestInfo.method = CA_GET;
- requestInfo.info = requestData;
- requestInfo.isMulticast = false;
+ CARequestInfo_t requestInfo = { .method = CA_GET,
+ .info = requestData,
+ .isMulticast = false };
// send request
res = CASendRequest(endpoint, &requestInfo);
printf("Generated token %s\n", token);
// create request data
- CAMessageType_t msgType = CA_MSG_NONCONFIRM;
- CAInfo_t requestData = { 0 };
- requestData.token = token;
- requestData.tokenLength = tokenLength;
- requestData.type = msgType;
-
- CARequestInfo_t requestInfo = { 0 };
- requestInfo.method = CA_GET;
- requestInfo.info = requestData;
- requestInfo.isMulticast = false;
+ CAInfo_t requestData = { .type = CA_MSG_NONCONFIRM,
+ .messageId = 0,
+ .token = token,
+ .tokenLength = tokenLength,
+ .options = NULL,
+ .numOptions = 0,
+ .payload = NULL,
+ .payloadSize = 0,
+ .resourceUri = NULL };
+
+ CARequestInfo_t requestInfo = { .method = CA_GET,
+ .info = requestData,
+ .isMulticast = false };
// send request
CASendRequest(endpoint, &requestInfo);
printf("generated token %s\n", token);
- CAInfo_t requestData = { 0 };
- requestData.token = token;
- requestData.tokenLength = tokenLength;
- requestData.payload = (CAPayload_t) "TempJsonPayload";
- requestData.payloadSize = strlen((const char *) requestData.payload);
- requestData.type = CA_MSG_NONCONFIRM;
- requestData.resourceUri = (CAURI_t)resourceURI;
+ // create request data
+ CAPayload_t payload = (CAPayload_t) "TempJsonPayload";
+ size_t payloadSize = strlen((const char *) payload);
+
+ CAInfo_t requestData = { .type = CA_MSG_NONCONFIRM,
+ .messageId = 0,
+ .token = token,
+ .tokenLength = tokenLength,
+ .options = NULL,
+ .numOptions = 0,
+ .payload = payload,
+ .payloadSize = payloadSize,
+ .resourceUri = (CAURI_t) resourceURI };
+
+ CARequestInfo_t requestInfo = { .method = CA_GET,
+ .info = requestData,
+ .isMulticast = true };
CAHeaderOption_t* headerOpt = get_option_data(&requestData);
- CARequestInfo_t requestInfo = { 0 };
- requestInfo.method = CA_GET;
- requestInfo.info = requestData;
- requestInfo.isMulticast = true;
-
// send request
res = CASendRequest(group, &requestInfo);
if (CA_STATUS_OK != res)
printf("Generated token %s\n", token);
- CAInfo_t respondData = { 0 };
- respondData.token = token;
- respondData.tokenLength = tokenLength;
- respondData.payload = (CAPayload_t) "TempNotificationData";
- respondData.payloadSize = strlen((const char *) respondData.payload);
- respondData.type = messageType;
- respondData.resourceUri = (CAURI_t)uri;
+ // create response data
+ CAPayload_t payload = (CAPayload_t) "TempNotificationData";
+ size_t payloadSize = strlen((const char *) payload);
- CAResponseInfo_t responseInfo = { 0 };
- responseInfo.result = CA_CONTENT;
- responseInfo.info = respondData;
+ CAInfo_t respondData = { .type = messageType,
+ .messageId = 0,
+ .token = token,
+ .tokenLength = tokenLength,
+ .options = NULL,
+ .numOptions = 0,
+ .payload = payload,
+ .payloadSize = payloadSize,
+ .resourceUri = (CAURI_t)uri };
+
+ CAResponseInfo_t responseInfo = { .result = CA_CONTENT,
+ .info = respondData };
// send request
res = CASendNotification(endpoint, &responseInfo);
}
responseCode = atoi(responseCodeBuf);
}
- CAInfo_t responseData = { 0 };
- responseData.type = messageType;
- responseData.messageId = (info != NULL) ? info->messageId : 0;
- responseData.resourceUri = (info != NULL) ? info->resourceUri : 0;
+
+ // create response data
+ uint16_t messageId = (info != NULL) ? info->messageId : 0;
+ CAURI_t resourceUri = (info != NULL) ? info->resourceUri : 0;
+
+ CAInfo_t responseData = { .type = messageType,
+ .messageId = messageId,
+ .token = NULL,
+ .tokenLength = 0,
+ .options = NULL,
+ .numOptions = 0,
+ .payload = NULL,
+ .payloadSize = 0,
+ .resourceUri = resourceUri };
if(CA_MSG_RESET != messageType)
{
}
}
- CAResponseInfo_t responseInfo = { 0 };
- responseInfo.result = responseCode;
- responseInfo.info = responseData;
+ CAResponseInfo_t responseInfo = { .result = responseCode,
+ .info = responseData };
// send response (transportType from remoteEndpoint of request Info)
CAResult_t res = CASendResponse(endpoint, &responseInfo);
{
if(ipLen && ipLen < sizeof(outAddress->ipAddress))
{
- OICStrcpy(outAddress->ipAddress, sizeof(outAddress->ipAddress), pAddress);
+ OICStrcpyPartial(outAddress->ipAddress, sizeof(outAddress->ipAddress),
+ pAddress, ipLen);
}
else if (!ipLen && len < sizeof(outAddress->ipAddress))
{
- OICStrcpy(outAddress->ipAddress, sizeof(outAddress->ipAddress), pAddress);
+ OICStrcpyPartial(outAddress->ipAddress, sizeof(outAddress->ipAddress),
+ pAddress, len);
}
else
{
*/
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;
}
}
static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port,
- const unsigned char *id, uint16_t id_length)
+ 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;
+ 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()
g_caDtlsContext->peerInfoList = NULL;
}
-static void CARemovePeerFromPeerInfoList(const char * addr, uint32_t port)
+static void CARemovePeerFromPeerInfoList(const char * addr, uint16_t port)
{
if (NULL == addr || 0 >= port)
{
int retLen = dtls_write(g_caDtlsContext->dtlsContext, (session_t *)dstSession, data,
dataLen);
OIC_LOG_V(DEBUG, NET_DTLS_TAG, "dtls_write retun len [%d]", retLen);
+ if (retLen < 0)
+ {
+ OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
+ return DTLS_FAIL;
+ }
if (0 == retLen)
{
// A new DTLS session was initiated by tinyDTLS library and wait for callback.
return DTLS_SESSION_INITIATED;
}
- else if (dataLen == retLen)
+ else if (dataLen != (uint32_t)retLen)
{
- OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
- return DTLS_OK;
+ OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
+ return DTLS_FAIL;
}
- OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT FAILURE");
- return DTLS_FAIL;
+ OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
+ return DTLS_OK;
}
static eDtlsRet_t CAAdapterNetDtlsDecryptInternal(const stCADtlsAddrInfo_t *srcSession,
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;
}
OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
}
-static int32_t CAReadDecryptedPayload(dtls_context_t *dtlsContext,
+static int32_t CAReadDecryptedPayload(dtls_context_t *context,
session_t *session,
uint8_t *buf,
size_t bufLen )
{
+ (void)context;
OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
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
{
return 0;
}
-static int32_t CASendSecureData(dtls_context_t *dtlsContext,
+static int32_t CASendSecureData(dtls_context_t *context,
session_t *session,
uint8_t *buf,
size_t bufLen)
{
+ (void)context;
OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", -1);
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.
return bufLen;
}
-static int32_t CAHandleSecureEvent(dtls_context_t *dtlsContext,
+static int32_t CAHandleSecureEvent(dtls_context_t *context,
session_t *session,
dtls_alert_level_t level,
unsigned short code)
{
+ (void)context;
OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
VERIFY_NON_NULL_RET(session, NET_DTLS_TAG, "Param Session is NULL", 0);
OIC_LOG(INFO, NET_DTLS_TAG, "Peer closing connection");
stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
- char *peerAddr = inet_ntoa(addrInfo->addr.sin.sin_addr);
- uint32_t port = ntohs(addrInfo->addr.sin.sin_port);
-
+ char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
+ uint16_t port = 0;
+ CAConvertAddrToName(&(addrInfo->addr.st), peerAddr, &port);
CARemovePeerFromPeerInfoList(peerAddr, port);
}
{
// Check if we have the credentials for the device with which we
// are trying to perform a handshake
- int index = 0;
- for (index = 0; index < credInfo->num; index++)
+ for (uint32_t index = 0; index < credInfo->num; index++)
{
if (memcmp(desc, credInfo->creds[index].id, DTLS_PSK_ID_LEN) == 0)
{
// 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 = inet_ntoa(addrInfo->addr.sin.sin_addr);
- uint32_t port = ntohs(addrInfo->addr.sin.sin_port);
+ char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 };
+ uint16_t port = 0;
+ CAConvertAddrToName(&(addrInfo->addr.st), peerAddr, &port);
- CAResult_t result = CAAddIdToPeerInfoList(peerAddress, port, desc, descLen);
+ 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");
CAResult_t CADtlsInitiateHandshake(const CAEndpoint_t *endpoint)
{
- stCADtlsAddrInfo_t dst = {};
+ stCADtlsAddrInfo_t dst = { 0 };
OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsInitiateHandshake");
CAResult_t CADtlsClose(const CAEndpoint_t *endpoint)
{
- stCADtlsAddrInfo_t dst = {};
+ stCADtlsAddrInfo_t dst = { 0 };
OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsDisconnect");
return CA_STATUS_INVALID_PARAM;
}
- stCADtlsAddrInfo_t dst = {};
+ stCADtlsAddrInfo_t dst = { 0 };
CAConvertNameToAddr(endpoint->addr, endpoint->port, &(dst.addr.st));
dst.ifIndex = 0;
OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Data to be encrypted dataLen [%d]", dataLen);
- stCADtlsAddrInfo_t addrInfo = {};
+ stCADtlsAddrInfo_t addrInfo = { 0 };
CAConvertNameToAddr(endpoint->addr, endpoint->port, &(addrInfo.addr.st));
addrInfo.ifIndex = 0;
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 = {};
+ 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)
VERIFY_NON_NULL_VOID(sockaddr, CA_ADAPTER_UTILS_TAG, "sockaddr is null");
struct addrinfo *addrs;
- struct addrinfo hints = { 0 };
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_flags = AI_NUMERICHOST;
+ struct addrinfo hints = { .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_DGRAM,
+ .ai_flags = AI_NUMERICHOST };
int r = getaddrinfo(host, NULL, &hints, &addrs);
if (r)
#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;
}
-
return CA_NOT_SUPPORTED;
}
-CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const char *serviceUUID,
- const void *data, uint32_t dataLength, uint32_t *sentLength)
+CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const uint8_t *data,
+ uint32_t dataLength)
{
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 char *serviceUUID, const void *data,
- uint32_t dataLength, uint32_t *sentLength)
+CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength)
{
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;
}
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);
return result;
}
-CAResult_t CAEDRSendMulticastMessage(const char* data, uint32_t dataLen)
+CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
{
OIC_LOG_V(DEBUG, TAG, "CAEDRSendMulticastMessage(%s)", data);
{
(*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)
{
OIC_LOG_V(DEBUG, TAG, "CAEDRSendUnicastMessageImpl, address: %s, data: %s", address, data);
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);
{
(*g_jvm)->DetachCurrentThread(g_jvm);
}
+
+ (*env)->DeleteLocalRef(env, j_str_address);
+ (*env)->DeleteLocalRef(env, j_obj_device);
+ (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
+ (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
return CA_STATUS_INVALID_PARAM;
}
if (!address)
(*g_jvm)->DetachCurrentThread(g_jvm);
}
(*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
+ (*env)->DeleteLocalRef(env, j_str_address);
+ (*env)->DeleteLocalRef(env, j_obj_device);
+ (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
+ (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
return CA_STATUS_INVALID_PARAM;
}
// find address
if (!strcmp(remoteAddress, address))
{
- CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen, i);
+ CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
if (CA_STATUS_OK != res)
{
(*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
+ (*env)->DeleteLocalRef(env, j_str_address);
+ (*env)->DeleteLocalRef(env, j_obj_device);
+ (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
+ (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
return res;
}
}
(*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
+ (*env)->DeleteLocalRef(env, j_str_address);
+ (*env)->DeleteLocalRef(env, j_obj_device);
}
+ (*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)
{
OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %s, %d", data, dataLen);
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);
"[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress);
// find address
- CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen, i);
+ 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",
remoteAddress);
- g_edrErrorHandler(remoteAddress, OIC_EDR_SERVICE_ID, data, dataLen, res);
+ g_edrErrorHandler(remoteAddress, data, dataLen, res);
continue;
}
}
+ (*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,
- uint32_t dataLength, uint32_t id)
+CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
+ uint32_t dataLength)
{
OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btSendData logic start : %s, %d", data, dataLength);
}
else
{
- CAResult_t res = CAEDRNativeConnect(env, address, id);
+ CAResult_t res = CAEDRNativeConnect(env, address);
if (CA_STATUS_OK != 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;
}
(*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!!!");
return CA_STATUS_OK;
}
-CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
+CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
{
OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect..");
return CA_STATUS_OK;
}
-void CAEDRNativeSocketClose(JNIEnv *env, const char *address, uint32_t id)
+void CAEDRNativeSocketClose(JNIEnv *env, const char *address)
{
jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
-/******************************************************************
+/* ****************************************************************
*
* Copyright 2014 Samsung Electronics All Rights Reserved.
*
#endif
/**
- * @brief Initialize context of application
- * @return None
+ * Initialize context of application.
*/
void CAEDRJniInitContext();
/**
- * @brief Create JNI Object
- * @param context [IN] context of application
- * @return #CA_STATUS_OK or Appropriate error code
+ * Create JNI Object.
+ * @param[in] context context of application.
+ * @return ::CA_STATUS_OK or Appropriate error code.
*/
CAResult_t CAEDRCreateJNIInterfaceObject(jobject context);
/**
- * @brief Initialize client for EDR
- * @param handle [IN] thread pool handle object
- * @return None
+ * Initialize client for EDR.
+ * @param[in] handle thread pool handle object.
*/
void CAEDRInitialize(ca_thread_pool_t handle);
/**
- * @brief Terminate server for EDR
- * @return None
+ * Terminate server for EDR.
*/
void CAEDRTerminate();
/**
- * @brief Initialize JNI object
- * @return None
+ * Initialize JNI object.
*/
void CAEDRCoreJniInit();
/**
- * @brief Send data for unicast
- * @param address [IN] remote address
- * @param data [IN] data for transmission
- * @param dataLen [IN] data length
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_FAILED Operation failed
+ * Send data for unicast.
+ * @param[in] address remote address.
+ * @param[in] data data for transmission.
+ * @param[in] dataLen data length.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @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);
/**
- * @brief Send data for multicast
- * @param data [IN] data for transmission
- * @param dataLen [IN] data length
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_FAILED Operation failed
+ * Send data for multicast.
+ * @param[in] data data for transmission.
+ * @param[in] dataLen data length.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @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);
/**
- * @brief Get Local EDR Address
- * @param address [OUT] local address
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_FAILED Operation failed
+ * Get Local EDR Address.
+ * @param[out] address local address.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CAEDRGetInterfaceInfo(char **address);
/**
- * @brief Get address from a local device
- * @param address [OUT] local address
- * @return None
+ * Get address from a local device.
+ * @param[out] address local address.
*/
void CAEDRGetLocalAddress(char **address);
/**
- * @brief Send data for unicast (implement)
- * @param address [IN] remote address
- * @param data [IN] data for transmission
- * @param dataLen [IN] data length
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_FAILED Operation failed
+ * Send data for unicast (implement).
+ * @param[in] address remote address.
+ * @param[in] data data for transmission.
+ * @param[in] dataLen data length.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @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);
/**
- * @brief Send data for multicast (implement)
- * @param env [IN] JNI interface pointer
- * @param data [IN] data for transmission
- * @param dataLen [IN] data length
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_FAILED Operation failed
+ * Send data for multicast (implement).
+ * @param[in] env JNI interface pointer.
+ * @param[in] data data for transmission.
+ * @param[in] dataLen data length.
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @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
*/
/**
- * @brief This function will send the data to remote device.
- * @param env [IN] JNI interface pointer
- * @param address [IN] Remote Address
- * @param data [IN] Data to be transmitted from EDR
- * @param dataLength [IN] Length of data
- * @param id [IN] index of remote address
- * @return #CA_STATUS_OK or Appropriate error code
+ * This function will send the data to remote device.
+ * @param[in] env JNI interface pointer.
+ * @param[in] address Remote Address.
+ * @param[in] data Data to be transmitted from EDR.
+ * @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,
- uint32_t dataLength, uint32_t id);
+CAResult_t CAEDRNativeSendData(JNIEnv *env, const char* address, const uint8_t* data,
+ uint32_t dataLength);
/**
- * @brief This function will connect to remote device.
- * @param env [IN] JNI interface pointer
- * @param address [IN] Remote Address
- * @param id [IN] index of remote address
- * @return #CA_STATUS_OK or Appropriate error code
+ * This function will connect to remote device.
+ * @param[in] env JNI interface pointer.
+ * @param[in] address Remote Address.
+ * @return ::CA_STATUS_OK or Appropriate error code.
*/
-CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id);
+CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address);
/**
- * @brief This function will close socket.
- * @param env [IN] JNI interface pointer
- * @param address [IN] Remote Address
- * @param id [IN] index of remote address
- * @return None
+ * This function will close socket.
+ * @param[in] env JNI interface pointer.
+ * @param[in] address Remote Address.
*/
-void CAEDRNativeSocketClose(JNIEnv *env, const char *address, uint32_t id);
+void CAEDRNativeSocketClose(JNIEnv *env, const char *address);
#ifdef __cplusplus
} /* extern "C" */
{
OIC_LOG(DEBUG, TAG, "IN");
- CAEDRNetworkMonitorJniInit();
- CANativeJNIGetJavaVM();
+ if (!threadPool)
+ {
+ return CA_STATUS_FAILED;
+ }
+ else
+ {
+ CAEDRNetworkMonitorJniInit();
+ CANativeJNIGetJavaVM();
+ }
OIC_LOG(DEBUG, TAG, "OUT");
return CA_STATUS_OK;
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaEdrInterface_caEdrStateChangedCallback(JNIEnv *env, jobject obj,
- jint status)
+ jint status)
{
+ if (!env || !obj)
+ {
+ OIC_LOG(ERROR, TAG, "parameter is null");
+ return;
+ }
+
// STATE_ON:12, STATE_OFF:10
OIC_LOG(DEBUG, TAG, "CaEdrInterface - Network State Changed");
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaEdrInterface_caEdrBondStateChangedCallback(JNIEnv *env, jobject obj,
- jstring addr)
+ jstring addr)
{
+ if (!env || !obj)
+ {
+ OIC_LOG(ERROR, TAG, "parameter is null");
+ return;
+ }
+
OIC_LOG(DEBUG, TAG, "CaEdrInterface - Bond State Changed");
if (addr)
-/******************************************************************
+/* ****************************************************************
*
* Copyright 2014 Samsung Electronics All Rights Reserved.
*
/**
* @file
- * @brief This file contains the APIs for BT LE communications.
+ * This file contains the APIs for BT LE communications.
*/
#ifndef CA_EDR_NW_MONITOR_H_
#define CA_EDR_NW_MONITOR_H_
#endif
/**
- * @brief Set context of application
- * @return None
+ * Set context of application.
*/
void CAEDRNetworkMonitorJNISetContext();
/**
- * @brief Initialize JNI object
- * @return None
+ * Initialize JNI object.
*/
void CAEDRNetworkMonitorJniInit();
******************************************************************/
#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);
+ }
}
}
/**
* implement for adapter common method.
*/
-CAResult_t CAEDRServerStart(const char *serviceUUID, int32_t *serverFD, ca_thread_pool_t handle)
+CAResult_t CAEDRServerStart(ca_thread_pool_t handle)
{
OIC_LOG(DEBUG, TAG, "IN");
CAEDRServerInitialize(handle);
return CA_STATUS_FAILED;
}
- *serverFD = 1;
OIC_LOG(DEBUG, TAG, "OUT");
return CA_STATUS_OK;
}
-CAResult_t CAEDRServerStop(int serverFD)
+CAResult_t CAEDRServerStop()
{
OIC_LOG(DEBUG, TAG, "IN");
- CAEDRStopUnicastServer(-1);
- CAEDRStopMulticastServer(-1);
+ CAEDRStopUnicastServer();
+ CAEDRStopMulticastServer();
ca_mutex_lock(g_mutexAcceptServer);
g_stopAccept = true;
return CA_STATUS_OK;
}
-CAResult_t CAEDRStartMulticastServer(bool isSecured)
+CAResult_t CAEDRStartMulticastServer()
{
OIC_LOG(DEBUG, TAG, "CAEDRStartMulticastServer");
return CA_STATUS_OK;
}
-CAResult_t CAEDRStopUnicastServer(int32_t serverID)
+CAResult_t CAEDRStopUnicastServer()
{
OIC_LOG(DEBUG, TAG, "CAEDRStopUnicastServer");
return CA_STATUS_OK;
}
-CAResult_t CAEDRStopMulticastServer(int32_t serverID)
+CAResult_t CAEDRStopMulticastServer()
{
OIC_LOG(DEBUG, TAG, "CAEDRStopMulticastServer");
CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
(*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+ (*env)->DeleteLocalRef(env, jni_str_address);
+
return CA_STATUS_FAILED;
}
jclass jni_cid_BTsocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
if (!jni_cid_BTsocket)
{
+ (*env)->DeleteLocalRef(env, jni_str_address);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] btReadData: jni_cid_BTsocket is null");
return CA_STATUS_FAILED;
}
if (!jni_obj_socket)
{
+ (*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;
}
jclass jni_cid_InputStream = (*env)->FindClass(env, "java/io/InputStream");
if (!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] btReadData: jni_cid_InputStream is null");
return CA_STATUS_FAILED;
}
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;
}
if (-1 == length)
{
+ (*env)->DeleteLocalRef(env, jni_cid_InputStream);
+ (*env)->DeleteLocalRef(env, jbuf);
+ (*env)->DeleteLocalRef(env, jni_obj_inputStream);
+ (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+ (*env)->DeleteLocalRef(env, jni_str_address);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] read buffer is empty...");
return CA_STATUS_FAILED;
}
CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
ca_mutex_unlock(g_mutexStateList);
(*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+
+ (*env)->DeleteLocalRef(env, jbuf);
+ (*env)->DeleteLocalRef(env, jni_cid_InputStream);
+ (*env)->DeleteLocalRef(env, jni_obj_inputStream);
+ (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+ (*env)->DeleteLocalRef(env, jni_str_address);
+
return CA_STATUS_FAILED;
}
jbyte* buf = (*env)->GetByteArrayElements(env, jbuf, NULL);
if (NULL == buf)
{
+ (*env)->DeleteLocalRef(env, jni_cid_InputStream);
+ (*env)->DeleteLocalRef(env, jbuf);
+ (*env)->DeleteLocalRef(env, jni_obj_inputStream);
+ (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+ (*env)->DeleteLocalRef(env, jni_str_address);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] btReadData: buf is null");
return CA_STATUS_FAILED;
}
}
(*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
(*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+
+ (*env)->DeleteLocalRef(env, jni_cid_InputStream);
+ (*env)->DeleteLocalRef(env, jbuf);
+ (*env)->DeleteLocalRef(env, jni_obj_inputStream);
+ (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+ (*env)->DeleteLocalRef(env, jni_str_address);
}
else
{
"()Z");
if (!jni_mid_isConnected)
{
+ (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] CAEDRIsConnectedForSocket \
- jni_mid_isConnected is null.");
return JNI_FALSE;
jboolean jni_isConnected = (*env)->CallBooleanMethod(env, socket, jni_mid_isConnected);
+ (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+
return jni_isConnected;
}
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");
}
/**
* Start multicast server.
- * @param[in] isSecured multicst server type.
* @return ::CA_STATUS_OK or Appropriate error code.
*/
-CAResult_t CAEDRStartMulticastServer(bool isSecured);
+CAResult_t CAEDRStartMulticastServer();
/**
* Stop unicast server.
- * @param[in] serverID unicast server id.
* @return ::CA_STATUS_OK or Appropriate error code.
*/
-CAResult_t CAEDRStopUnicastServer(int32_t serverID);
+CAResult_t CAEDRStopUnicastServer();
/**
* Stop multicast server.
- * @param[in] serverID multicast server id.
* @return ::CA_STATUS_OK or Appropriate error code.
*/
-CAResult_t CAEDRStopMulticastServer(int32_t serverID);
-
-// EDR Method
+CAResult_t CAEDRStopMulticastServer();
/**
* This function will read the data from remote device.
env, jni_cid_BTSocket, "getRemoteDevice", "()Landroid/bluetooth/BluetoothDevice;");
if (!jni_mid_getRemoteDevice)
{
+ (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
+
OIC_LOG(ERROR, TAG, "[EDR] getRemoteAddress: jni_mid_getRemoteDevice is null");
return NULL;
}
jni_mid_getRemoteDevice);
if (!jni_obj_remoteBTDevice)
{
+ (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
+
OIC_LOG(ERROR, TAG, "[EDR] getRemoteAddress: jni_obj_remoteBTDevice is null");
return NULL;
}
jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
if (!jni_cid_BTDevice)
{
+ (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
+ (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
+
OIC_LOG(ERROR, TAG, "[EDR] getRemoteAddress: jni_cid_BTDevice is null");
return NULL;
}
METHODID_STRINGNONPARAM);
if (!j_mid_getAddress)
{
+ (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
+ (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
+ (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
+
OIC_LOG(ERROR, TAG, "[EDR] getRemoteAddress: j_mid_getAddress is null");
return NULL;
}
jstring j_str_address = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice, j_mid_getAddress);
if (!j_str_address)
{
+ (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
+ (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
+ (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
+
OIC_LOG(ERROR, TAG, "[EDR] getRemoteAddress: j_str_address is null");
return NULL;
}
+ (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
+ (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
+ (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
+
return j_str_address;
}
METHODID_OBJECTNONPARAM);
if (!jni_mid_getDefaultAdapter)
{
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] getAddress: jni_mid_getDefaultAdapter is null");
return NULL;
}
METHODID_STRINGNONPARAM);
if (!jni_mid_getAddress)
{
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] getAddress: jni_mid_getAddress is null");
return NULL;
}
jni_mid_getDefaultAdapter);
if (!jni_obj_BTAdapter)
{
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] getAddress: jni_obj_BTAdapter is null");
return NULL;
}
jni_mid_getAddress);
if (!jni_str_address)
{
+ (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] getAddress: jni_str_address is null");
return NULL;
}
+ (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
return jni_str_address;
}
METHODID_OBJECTNONPARAM);
if (!jni_mid_getDefaultAdapter)
{
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: default adapter is null");
return NULL;
}
jni_mid_getDefaultAdapter);
if (!jni_obj_BTAdapter)
{
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: bluetooth adapter is null");
return NULL;
}
"()Ljava/util/Set;");
if (!jni_mid_getBondedDevices)
{
+ (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: jni_mid_getBondedDevicesr is null");
return NULL;
}
jni_mid_getBondedDevices);
if (!jni_obj_setPairedDevices)
{
+ (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: jni_obj_setPairedDevices is null");
return NULL;
}
jclass jni_cid_Set = (*env)->FindClass(env, "java/util/Set");
if (!jni_cid_Set)
{
+ (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: jni_cid_Set is null");
return NULL;
}
if (!jni_mid_toArray)
{
+ (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: jni_mid_toArray is null");
return NULL;
}
(*env)->CallObjectMethod(env, jni_obj_setPairedDevices, jni_mid_toArray));
if (!jni_arrayPairedDevices)
{
+ (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
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);
+
return jni_arrayPairedDevices;
}
jfieldID jni_fid_stateon = (*env)->GetStaticFieldID(env, jni_cid_BTAdapter, "STATE_ON", "I");
if (jni_fid_stateon == 0)
{
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] get_field_state is 0");
return ERROR_CODE;
}
OIC_LOG_V(DEBUG, TAG, "[EDR][Native] bluetooth state integer value : %d", jni_int_val);
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
return jni_int_val;
}
METHODID_OBJECTNONPARAM);
if (!jni_mid_getDefaultAdapter)
{
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] jni_mid_getDefaultAdapter is null");
return JNI_FALSE;
}
jni_mid_getDefaultAdapter);
if (!jni_obj_BTAdapter)
{
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] jni_obj_BTAdapter is null");
return JNI_FALSE;
}
jmethodID jni_mid_isEnable = (*env)->GetMethodID(env, jni_cid_BTAdapter, "isEnabled", "()Z");
if (!jni_mid_isEnable)
{
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+
OIC_LOG(ERROR, TAG, "[EDR][Native] jni_mid_isEnable is null");
return JNI_FALSE;
}
jboolean jni_isEnable = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter, jni_mid_isEnable);
OIC_LOG_V(DEBUG, TAG, "[EDR][Native] adapter state is %d", jni_isEnable);
+ (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+ (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
return jni_isEnable;
}
OIC_LOG(ERROR, TAG, "[EDR][Native] newstate is null");
return;
}
- OICStrcpy(newstate->address, sizeof(newstate->address), address);
+ OICStrcpy((char*) newstate->address, sizeof(newstate->address), address);
newstate->state = state;
CAEDRNativeAddDeviceStateToList(newstate);
return;
}
- if (CAEDRNativeIsDeviceInList(state->address))
+ if (CAEDRNativeIsDeviceInList((const char*) state->address))
{
- CAEDRNativeRemoveDevice(state->address); // delete previous state for update new state
+ // delete previous state for update new state
+ CAEDRNativeRemoveDevice((const char*) state->address);
}
u_arraylist_add(g_deviceStateList, state); // update new state
OIC_LOG_V(DEBUG, TAG, "Set State Info to List : %d", state->state);
return false;
}
- if (!strcmp(remoteAddress, state->address))
+ if (!strcmp(remoteAddress, (const char*) state->address))
{
OIC_LOG(DEBUG, TAG, "the device is already set");
return true;
continue;
}
- if (!strcmp(state->address, remoteAddress))
+ if (!strcmp((const char*) state->address, remoteAddress))
{
OIC_LOG_V(DEBUG, TAG, "[EDR][Native] remove state : %s", remoteAddress);
OICFree(state);
- CAEDRReorderingDeviceList(index);
+ u_arraylist_remove(g_deviceStateList, index);
break;
}
}
continue;
}
- if (!strcmp(state->address, remoteAddress))
+ if (!strcmp((const char*) state->address, remoteAddress))
{
OIC_LOG(DEBUG, TAG, "[EDR][Native] check whether it is connected or not");
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
*/
(*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--;
-}
-/******************************************************************
+/* ****************************************************************
*
* Copyright 2014 Samsung Electronics All Rights Reserved.
*
/**
* @file
- * @brief This file contains the APIs for BT communications.
+ * This file contains the APIs for BT communications.
*/
#ifndef CA_EDR_UTILS_H_
#define CA_EDR_UTILS_H_
#endif
/**
- * @brief Get address from device socket
- * @param env [IN] JNI interface pointer
- * @param bluetoothSocketObj [IN] bluetooth socket object
- * @return Bluetooth device address
+ * Get address from device socket.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothSocketObj bluetooth socket object.
+ * @return Bluetooth device address.
*/
jstring CAEDRNativeGetAddressFromDeviceSocket(JNIEnv *env, jobject bluetoothSocketObj);
/**
- * @brief Get local device address
- * @param env [IN] JNI interface pointer
- * @return Bluetooth device address
+ * Get local device address.
+ * @param[in] env JNI interface pointer.
+ * @return Bluetooth device address.
*/
jstring CAEDRNativeGetLocalDeviceAddress(JNIEnv *env);
/**
- * @brief Get bonded devices list
- * @param env [IN] JNI interface pointer
- * @return Bonded devices list
+ * Get bonded devices list.
+ * @param[in] env JNI interface pointer.
+ * @return Bonded devices list.
*/
jobjectArray CAEDRNativeGetBondedDevices(JNIEnv *env);
/**
- * @brief Get Bluetooth device state
- * @param env [IN] JNI interface pointer
- * @return Bluetooth device state
+ * Get Bluetooth device state.
+ * @param[in] env JNI interface pointer.
+ * @return Bluetooth device state.
*/
jint CAEDRNativeGetBTStateOnInfo(JNIEnv *env);
/**
- * @brief Check the BT Adapter enable
- * @param env [IN] JNI interface pointer
- * @return JNI_TRUE or JNI_FALSE
+ * Check the BT Adapter enable.
+ * @param[in] env JNI interface pointer.
+ * @return JNI_TRUE or JNI_FALSE.
*/
jboolean CAEDRNativeIsEnableBTAdapter(JNIEnv *env);
/**
- * @brief Get address from BT device
- * @param env [IN] JNI interface pointer
- * @param bluetoothSocketObj [IN] bluetooth socket object
- * @return Bluetooth device address
+ * Get address from BT device.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothDevice bluetooth socket object.
+ * @return Bluetooth device address.
*/
jstring CAEDRNativeGetAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice);
/**
- * BT State Info List
- */
-
-/**
- * @brief This function will create the device state list.
- * @return None
+ * This function will create the device state list.
*/
void CAEDRNativeCreateDeviceStateList();
/**
- * @brief Update connection state of device
- * @param state [IN] connection state
- * @param address [IN] remote address
- * @return None
+ * Update connection state of device.
+ * @param[in] state connection state.
+ * @param[in] address remote address.
*/
void CAEDRUpdateDeviceState(CAConnectedState_t state, const char *address);
/**
- * @brief Add device object to the list
- * @param state [IN] connection state object
- * @return None
+ * Add device object to the list.
+ * @param[in] state connection state object.
*/
void CAEDRNativeAddDeviceStateToList(state_t *state);
/**
- * @brief Check whether the device exist in the list or not
- * @param remoteAddress [IN] remote address
- * @return true or false
+ * Check whether the device exist in the list or not.
+ * @param[in] remoteAddress remote address.
+ * @return true or false.
*/
bool CAEDRNativeIsDeviceInList(const char *remoteAddress);
/**
- * @brief Close all socket
- * @param env [IN] JNI interface pointer
- * @return NONE
+ * Close all socket.
+ * @param[in] env JNI interface pointer.
*/
void CAEDRNativeSocketCloseToAll(JNIEnv *env);
/**
- * @brief Remove all device objects in the list
- * @return None
+ * Remove all device objects in the list.
*/
void CAEDRNativeRemoveAllDeviceState();
/**
- * @brief Remove target device in the list
- * @param remoteAddress [IN] remote address
- * @return None
+ * Remove target device in the list.
+ * @param[in] remoteAddress remote address.
*/
void CAEDRNativeRemoveDevice(const char *remoteAddress);
/**
- * @brief Get current device connection state
- * @param remoteAddress [IN] remote address
- * @return STATE_DISCONNECTED or STATE_CONNECTED
+ * Get current device connection state.
+ * @param[in] remoteAddress remote address.
+ * @return STATE_DISCONNECTED or STATE_CONNECTED.
*/
CAConnectedState_t CAEDRIsConnectedDevice(const char *remoteAddress);
/**
- * @brief Reordering for the list
- * @param index [IN] index of device list that want to reordering
- * @return None
- */
-void CAEDRReorderingDeviceList(uint32_t index);
-
-/**
- * Bluetooth Socket Object List
- */
-
-/**
- * @brief This function will create the device socket list.
- * @return None
+ * This function will create the device socket list.
*/
void CAEDRNativeCreateDeviceSocketList();
/**
- * @brief Add device object to the list
- * @param env [IN] JNI interface pointer
- * @param deviceSocket [IN] device socket object
- * @return None
+ * Add device object to the list.
+ * @param[in] env JNI interface pointer.
+ * @param[in] deviceSocket device socket object.
*/
void CAEDRNativeAddDeviceSocketToList(JNIEnv *env, jobject deviceSocket);
/**
- * @brief Add device object to the list
- * @param env [IN] JNI interface pointer
- * @param remoteAddress [IN] remote address
- * @return true or false
+ * Add device object to the list.
+ * @param[in] env JNI interface pointer.
+ * @param[in] remoteAddress remote address.
+ * @return true or false.
*/
bool CAEDRNativeIsDeviceSocketInList(JNIEnv *env, const char *remoteAddress);
/**
- * @brief Add device object to the list
- * @param env [IN] JNI interface pointer
- * @return None
+ * Add device object to the list.
+ * @param[in] env JNI interface pointer.
*/
void CAEDRNativeRemoveAllDeviceSocket(JNIEnv *env);
/**
- * @brief Add device object to the list
- * @param env [IN] JNI interface pointer
- * @param deviceSocket [IN] device socket object
- * @return None
+ * Add device object to the list.
+ * @param[in] env JNI interface pointer.
+ * @param[in] deviceSocket device socket object.
*/
void CAEDRNativeRemoveDeviceSocket(JNIEnv *env, jobject deviceSocket);
/**
- * @brief Remove device socket
- * @param env [IN] JNI interface pointer
- * @param address [IN] remote address
- * @return NONE
+ * Remove device socket.
+ * @param[in] env JNI interface pointer.
+ * @param[in] address remote address.
*/
void CAEDRNativeRemoveDeviceSocketBaseAddr(JNIEnv *env, jstring address);
/**
- * @brief Get device socket object from the list
- * @param idx [IN] index of device list
- * @return Device socket object or NULL
+ * Get device socket object from the list.
+ * @param[in] idx index of device list.
+ * @return Device socket object or NULL.
*/
jobject CAEDRNativeGetDeviceSocket(uint32_t idx);
/**
- * @brief Get device socket address
- * @param env [IN] JNI interface pointer
- * @param remoteAddress [IN] remote address
- * @return Device socket object or NULL
+ * Get device socket address.
+ * @param[in] env JNI interface pointer.
+ * @param[in] remoteAddress remote address.
+ * @return Device socket object or NULL.
*/
jobject CAEDRNativeGetDeviceSocketBaseAddr(JNIEnv *env, const char* remoteAddress);
/**
- * @brief Get length of device socket list
- * @return length of list
+ * Get length of device socket list.
+ * @return length of list.
*/
uint32_t CAEDRGetSocketListLength();
-/**
- * @brief Reordering for the list
- * @param index [IN] index of device list that want to reordering
- * @return None
- */
-void CAEDRReorderingDeviceSocketList(uint32_t index);
#ifdef __cplusplus
} /* extern "C" */
#endif
static CAQueueingThread_t *g_recvQueueHandle = NULL;
/**
- * @var g_isHeaderAvailable
- * @brief to differentiate btw header and data packet.
- */
-static bool g_isHeaderAvailable = false;
-
-/**
* @var g_adapterState
* @brief Storing Adapter state information
*/
static CAEndpoint_t *g_localConnectivity = NULL;
/**
- * @var g_serverId
- * @brief Storing RfcommserverUUID
- */
-static int g_serverId = -1;
-
-/**
* @var g_serverState
* @brief Storing Rfcommserver state information
*/
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 char *serviceUUID,
- const void *data, uint32_t dataLength, uint32_t *sentLength);
+
+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 char *serviceUUID, const void *data,
+static void CAEDRErrorHandler(const char *remoteAddress, const uint8_t *data,
uint32_t dataLength, CAResult_t result);
CAResult_t CAInitializeEDR(CARegisterConnectivityCallback registerCallback,
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
// Stop RFComm server if it is running
- if (-1 != g_serverId)
- {
- CAEDRServerStop(g_serverId);
- g_serverId = -1;
- }
+ CAEDRServerStop();
// Stop network monitor
CAEDRStopNetworkMonitor();
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
- // Stop EDR adapter
- CAStopEDR();
// Terminate EDR Network Monitor
CAEDRTerminateNetworkMonitor();
return CA_STATUS_OK;
}
- if (-1 < g_serverId)
- {
- OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Server is already in running state.");
- return CA_SERVER_STARTED_ALREADY;
- }
-
- if (CA_STATUS_OK != (err = CAEDRServerStart(OIC_EDR_SERVICE_ID, &g_serverId, g_edrThreadPool)))
+ if (CA_STATUS_OK != (err = CAEDRServerStart(g_edrThreadPool)))
{
OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to start RFCOMM server!, error num [%d]",
err);
}
const char *remoteAddress = NULL;
- const char *serviceUUID = OIC_EDR_SERVICE_ID;
- uint32_t sentLength = 0;
if (NULL == message->remoteEndpoint)
{
remoteAddress = message->remoteEndpoint->addr;
}
- if(!remoteAddress || !serviceUUID)
+ if(!remoteAddress)
{
OIC_LOG(ERROR, EDR_ADAPTER_TAG, "EDR Send Message error");
//Error cannot be sent if remote address is NULL
return;
}
- CAResult_t result = CAEDRClientSendData(remoteAddress, serviceUUID, message->data,
- message->dataLen, &sentLength);
+ CAResult_t result = CAEDRClientSendData(remoteAddress, message->data,
+ message->dataLen);
if(CA_STATUS_OK != result)
{
OIC_LOG(ERROR, EDR_ADAPTER_TAG, "CAEDRClientSendData API failed");
- CAEDRErrorHandler(remoteAddress, serviceUUID, message->data, message->dataLen, result);
+ CAEDRErrorHandler(remoteAddress, message->data, message->dataLen, result);
return;
}
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
}
-CAResult_t CAEDRClientSendData(const char *remoteAddress, const char *serviceUUID,
- const void *data, uint32_t dataLength, uint32_t *sentLength)
+CAResult_t CAEDRClientSendData(const char *remoteAddress,
+ const uint8_t *data,
+ uint32_t dataLength)
{
CAResult_t result = CA_SEND_FAILED;
// Send the first segment with the header.
if ((NULL != remoteAddress) && (0 < strlen(remoteAddress))) //Unicast data
{
- result = CAEDRClientSendUnicastData(remoteAddress, serviceUUID, data,
- dataLength, sentLength);
+ result = CAEDRClientSendUnicastData(remoteAddress, data, dataLength);
if (CA_STATUS_OK != result)
{
OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to send unicast data !");
else
{
OIC_LOG_V(DEBUG, EDR_ADAPTER_TAG, "sending multicast data : %s", data);
- result = CAEDRClientSendMulticastData(serviceUUID, data, dataLength,
- sentLength);
+ result = CAEDRClientSendMulticastData(data, dataLength);
if (CA_STATUS_OK != result)
{
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 char *serviceUUID, const void *data,
+void CAEDRErrorHandler(const char *remoteAddress, const uint8_t *data,
uint32_t dataLength, CAResult_t result)
{
- (void)serviceUUID;
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
// Input validation
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)
device->socketFD = connection->socket_fd;
while (device->pendingDataList)
{
- uint32_t sentData = 0;
EDRData *edrData = device->pendingDataList->data;
res = CAEDRSendData(device->socketFD, edrData->data,
- edrData->dataLength, &sentData);
+ edrData->dataLength);
if (CA_STATUS_OK != res)
{
OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to send pending data [%s]",
}
-CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const char *serviceUUID,
- const void *data, uint32_t dataLength, uint32_t *sentLength)
+CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress,
+ const uint8_t *data,
+ uint32_t dataLength)
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
// Input validation
VERIFY_NON_NULL(remoteAddress, EDR_ADAPTER_TAG, "Remote address is null");
- VERIFY_NON_NULL(serviceUUID, EDR_ADAPTER_TAG, "service UUID is null");
VERIFY_NON_NULL(data, EDR_ADAPTER_TAG, "Data is null");
- VERIFY_NON_NULL(sentLength, EDR_ADAPTER_TAG, "Sent data length holder is null");
if (0 >= dataLength)
{
// Make a rfcomm connection with remote BT Device
if (device->serviceSearched &&
- CA_STATUS_OK != CAEDRClientConnect(remoteAddress, serviceUUID))
+ CA_STATUS_OK != CAEDRClientConnect(remoteAddress, OIC_EDR_SERVICE_ID))
{
OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to make RFCOMM connection!");
CARemoveEDRDeviceFromList(&g_edrDeviceList, remoteAddress);
return CA_STATUS_FAILED;
}
- *sentLength = dataLength;
}
else
{
- result = CAEDRSendData(device->socketFD, data, dataLength, sentLength);
+ result = CAEDRSendData(device->socketFD, data, dataLength);
if (CA_STATUS_OK != result)
{
OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to send data!");
return CA_STATUS_OK;
}
-CAResult_t CAEDRClientSendMulticastData(const char *serviceUUID, const void *data,
- uint32_t dataLength, uint32_t *sentLength)
+CAResult_t CAEDRClientSendMulticastData(const uint8_t *data,
+ uint32_t dataLength)
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
// Input validation
- VERIFY_NON_NULL(serviceUUID, EDR_ADAPTER_TAG, "service UUID is null");
VERIFY_NON_NULL(data, EDR_ADAPTER_TAG, "Data is null");
- VERIFY_NON_NULL(sentLength, EDR_ADAPTER_TAG, "Sent data length holder is null");
if (0 >= dataLength)
{
return CA_STATUS_INVALID_PARAM;
}
- *sentLength = dataLength;
-
// Send the packet to all OIC devices
ca_mutex_lock(g_edrDeviceListMutex);
EDRDeviceList *curList = g_edrDeviceList;
else
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN3");
- result = CAEDRSendData(device->socketFD, data, dataLength, sentLength);
+ result = CAEDRSendData(device->socketFD, data, dataLength);
if (CA_STATUS_OK != result)
{
OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to send data to [%s] !",
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");
}
#endif
/**
- * @struct EDRData
- * @brief Structure to maintain the data needs to send to peer Bluetooth device.
+ * Structure to maintain the data needs to send to peer Bluetooth device.
*/
typedef struct
{
} EDRData;
/**
- * @struct EDRDataList
- * @brief Structure to maintain list of data needs to send to peer Bluetooth device.
+ * Structure to maintain list of data needs to send to peer Bluetooth device.
*/
typedef struct _EDRDataList
{
} EDRDataList;
/**
- * @struct EDRDevice
- * @brief Structure to maintain information of peer Bluetooth device.
+ * Structure to maintain information of peer Bluetooth device.
*/
typedef struct
{
} EDRDevice;
/**
- * @struct EDRDeviceList
- * @brief Structure to maintain list of peer Bluetooth device information.
+ * Structure to maintain list of peer Bluetooth device information.
*/
typedef struct _EDRDeviceList
{
} EDRDeviceList;
/**
- * @brief Creates #EDRDevice for specified remote address and uuid and to device list.
+ * Creates ::EDRDevice for specified remote address and uuid and to device list.
*
- * @param deviceList [IN,OUT] Device list which created device add to.
- * @param deviceAddress [IN] Bluetooth device address.
- * @param uuid [IN] Service uuid.
- * @param device [IN] Created #EDRDevice.
+ * @param[in/out] deviceList Device list which created device add to.
+ * @param[in] deviceAddress Bluetooth device address.
+ * @param[in] uuid Service uuid.
+ * @param[in] device Created ::EDRDevice.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input parameters
- * @retval #CA_STATUS_FAILED Failed to create device and add to list
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input parameters.
+ * @retval ::CA_STATUS_FAILED Failed to create device and add to list.
*/
CAResult_t CACreateAndAddToDeviceList(EDRDeviceList **deviceList, const char *deviceAddress,
const char *uuid, EDRDevice **device);
/**
- * @brief Insert device to specified list.
+ * Insert device to specified list.
*
- * @param deviceList [IN,OUT] Device list to which specifed @device to be added.
- * @param device [IN] Device to be added to list.
+ * @param[in/out] deviceList Device list to which specifed @device to be added.
+ * @param[in] device Device to be added to list.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input parameters
- * @retval #CA_MEMORY_ALLOC_FAILED Memory allocation failed
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input parameters.
+ * @retval ::CA_MEMORY_ALLOC_FAILED Memory allocation failed.
*/
CAResult_t CAAddEDRDeviceToList(EDRDeviceList **deviceList, EDRDevice *device);
/**
- * @brief Get the device from list which matches specified device address.
+ * Get the device from list which matches specified device address.
*
- * @param deviceList [IN] Device list to search for the device.
- * @param deviceAddress [IN] Device address used for matching.
- * @param device [OUT] #EDRDevice which has matching device address.
+ * @param[in] deviceList Device list to search for the device.
+ * @param[in] deviceAddress Device address used for matching.
+ * @param[out] device ::EDRDevice which has matching device address.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input parameters
- * @retval #CA_STATUS_FAILED Device is not found in the list
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input parameters.
+ * @retval ::CA_STATUS_FAILED Device is not found in the list.
*/
CAResult_t CAGetEDRDevice(EDRDeviceList *deviceList,
const char *deviceAddress, EDRDevice **device);
/**
- * @brief Get the device from list which matches specified RFCOMM socket id.
+ * Get the device from list which matches specified RFCOMM socket id.
*
- * @param deviceList [IN] Device list to search for the device.
- * @param socketID [IN] RFCOMM socket id.
- * @param device [OUT] #EDRDevice which has matching RFCOMM socket id .
+ * @param[in] deviceList Device list to search for the device.
+ * @param[in] socketID RFCOMM socket id.
+ * @param[out] device ::EDRDevice which has matching RFCOMM socket id .
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input parameters
- * @retval #CA_STATUS_FAILED Device is not found in the list
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input parameters.
+ * @retval ::CA_STATUS_FAILED Device is not found in the list.
*/
CAResult_t CAGetEDRDeviceBySocketId(EDRDeviceList *deviceList, int32_t socketID,
EDRDevice **device);
/**
- * @brief Remove and delete the device matching specified device address from list.
+ * Remove and delete the device matching specified device address from list.
*
- * @param deviceList [IN,OUT] Device list to search for the device.
- * @param deviceAddress [IN] Bluetooth device address.
+ * @param[in/out] deviceList Device list to search for the device.
+ * @param[in] deviceAddress Bluetooth device address.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input parameters
- * @retval #CA_STATUS_FAILED Device is not found in the list
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input parameters.
+ * @retval ::CA_STATUS_FAILED Device is not found in the list.
*/
CAResult_t CARemoveEDRDeviceFromList(EDRDeviceList **deviceList,
const char *deviceAddress);
/**
- * @brief Destroy the specified device list. Removes and delete all the devices in the list.
- * @param deviceList [IN,OUT] Device list to be destroyed.
- * @return NONE
+ * Destroy the specified device list. Removes and delete all the devices in the list.
+ * @param[in/out] deviceList Device list to be destroyed.
*/
void CADestroyEDRDeviceList(EDRDeviceList **deviceList);
/**
- * @brief Insert data to specified list.
+ * Insert data to specified list.
*
- * @param dataList [IN,OUT] Data list to which data will be add.
- * @param data [IN] Data to be stored.
- * @param dataLength [IN] Length of the data.
+ * @param[in] dataList Data list to which data will be add.
+ * @param[in] data Data to be stored.
+ * @param[in] dataLength Length of the data.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input parameters
- * @retval #CA_MEMORY_ALLOC_FAILED Memory allocation failed
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input parameters.
+ * @retval ::CA_MEMORY_ALLOC_FAILED Memory allocation failed.
*/
CAResult_t CAAddEDRDataToList(EDRDataList **dataList, const void *data, uint32_t dataLength);
/**
- * @brief Remove and delete data from front end of list.
- * @param dataList [IN,OUT] Data list from which data will be removed.
+ * Remove and delete data from front end of list.
+ * @param[in/out] dataList Data list from which data will be removed.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input parameters
+ * @return ::CA_STATUS_OK or Appropriate error code.
+ * @retval ::CA_STATUS_OK Successful.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input parameters.
*/
CAResult_t CARemoveEDRDataFromList(EDRDataList **dataList);
/**
- * @brief Destroy the specified data list. Removes and deletes all the data in the list.
- * @param dataList [IN] Data list to be destroyed.
- * @return NONE
+ * Destroy the specified data list. Removes and deletes all the data in the list.
+ * @param[in] dataList Data list to be destroyed.
*/
void CADestroyEDRDataList(EDRDataList **dataList);
#include "caedrutils.h"
#include "logger.h"
-CAResult_t CAEDRSendData(int serverFD, const void *data, uint32_t dataLength,
- uint32_t *sentDataLen)
+CAResult_t CAEDRSendData(int serverFD, const void *data, uint32_t dataLength)
{
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 (dataLen == -1)
{
OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "sending data failed!, soketid [%d]", serverFD);
- *sentDataLen = 0;
return CA_SOCKET_OPERATION_FAILED;
}
- *sentDataLen = dataLen;
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
#endif
/**
- * @brief Send data over RFCOMM connection.
+ * Send data over RFCOMM connection.
*
- * @param serverFD [IN] The RFCOMM connection socket file descriptor.
- * @param data [IN] The data needs to be sent.
- * @param dataLength [IN] The length of data.
- * @param sentDataLength [IN] The length of data which actually sent successful.
+ * @param[in] serverFD The RFCOMM connection socket file descriptor.
+ * @param[in] data The data needs to be sent.
+ * @param[in] dataLength The length of data.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @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 CAEDRSendData(int serverFD, const void *data, uint32_t dataLength,
- uint32_t *sentDataLength);
+CAResult_t CAEDRSendData(int serverFD, const void *data, uint32_t dataLength);
#ifdef __cplusplus
} /* extern "C" */
static void CAEDRAdapterStateChangeCallback(int result, bt_adapter_state_e adapterState,
void *userData);
-void *GMainLoopThread (void *param)
+void GMainLoopThread (void *param)
{
g_main_loop_run(g_mainloop);
- return NULL;
}
CAResult_t CAEDRInitializeNetworkMonitor(const ca_thread_pool_t threadPool)
static int32_t g_maxPendingConnections = 10;
-CAResult_t CAEDRServerStart(const char *serviceUUID, int *serverFD, ca_thread_pool_t handle)
+/**
+ * Storing RfcommserverUUID
+ */
+static int g_serverFD = -1;
+
+CAResult_t CAEDRServerStart(ca_thread_pool_t handle)
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
- VERIFY_NON_NULL(serviceUUID, EDR_ADAPTER_TAG, "Service UUID is null");
- VERIFY_NON_NULL(serverFD, EDR_ADAPTER_TAG, "Server fd holder is null");
-
- if (!serviceUUID[0])
- {
- OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Invalid input: Empty service uuid!");
- return CA_STATUS_INVALID_PARAM;
- }
-
bool isRunning = false;
- bt_error_e err = bt_adapter_is_service_used(serviceUUID, &isRunning);
+ bt_error_e err = bt_adapter_is_service_used(OIC_EDR_SERVICE_ID, &isRunning);
if (BT_ERROR_NONE != err)
{
OIC_LOG_V(ERROR, EDR_ADAPTER_TAG,
int socketFD = 0;
// Registers a rfcomm socket with a specific service_uuid.
- err = bt_socket_create_rfcomm(serviceUUID, &socketFD);
+ err = bt_socket_create_rfcomm(OIC_EDR_SERVICE_ID, &socketFD);
if (BT_ERROR_NONE != err)
{
OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to create rfcomm socket!, error num [%x]", err);
return CA_STATUS_FAILED;
}
- *serverFD = socketFD;
+ g_serverFD = socketFD;
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
-CAResult_t CAEDRServerStop(int serverFD)
+CAResult_t CAEDRServerStop()
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
- bt_error_e err = bt_socket_destroy_rfcomm(serverFD);
- if (BT_ERROR_NONE != err)
+ if (-1 < g_serverFD)
{
- OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed close server socket!, error num [%x]", err);
- return CA_STATUS_FAILED;
+ bt_error_e err = bt_socket_destroy_rfcomm(g_serverFD);
+
+ if (BT_ERROR_NONE != err)
+ {
+ OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed close server socket!, error num [%x]", err);
+ return CA_STATUS_FAILED;
+ }
+ g_serverFD = -1;
}
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
return CA_NOT_SUPPORTED;
}
-
#include "oic_malloc.h"
/**
- * @var EDR_ADAPTER_TAG
- * @brief Logging tag for module name.
+ * Logging tag for module name.
*/
#ifndef EDR_ADAPTER_TAG
#define EDR_ADAPTER_TAG "CA_EDR_ADAPTER"
#endif
/**
- * @brief Checks if the specified list of service UUIDs contains OIC service UUID.
+ * Checks if the specified list of service UUIDs contains OIC service UUID.
*
- * @param serviceUUID [IN] Array of service UUIDs
- * @param serviceCount [IN] Size of the service UUIDs array.
- * @param matchService [IN] Service UUID to be checked in the given array of service UUIDs
+ * @param[in] serviceUUID Array of service UUIDs.
+ * @param[in] serviceCount Size of the service UUIDs array.
+ * @param[in] matchService Service UUID to be checked in the given array of service UUIDs.
*
* @return true if match service UUID found otherwise false.
*
#include "logger.h"
#include "oic_malloc.h"
+#include "oic_string.h"
#include "cathreadpool.h" /* for thread pool */
#include "camutex.h"
#include "uarraylist.h"
#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;
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;
}
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 CALEClientGetInterfaceInfo(char **address)
-{
- OIC_LOG(INFO, TAG, "CALEClientGetInterfaceInfo is not supported");
- return CA_NOT_SUPPORTED;
-}
-
-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");
{
OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
ca_mutex_unlock(g_threadSendMutex);
+ if (isAttached)
+ {
+ (*g_jvm)->DetachCurrentThread(g_jvm);
+ }
return res;
}
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 int 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);
{
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
*/
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)
{
VERIFY_NON_NULL(data, TAG, "data is null");
VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
+ if (LE_UNICAST != type || position < 0)
+ {
+ OIC_LOG(ERROR, TAG, "this request is not unicast");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
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");
CAResult_t CAGetLEAddress(char **local_address)
{
- OIC_LOG(DEBUG, TAG, "IN");
-
- VERIFY_NON_NULL(local_address, TAG, "local_address is null");
- CAResult_t res = CALEClientGetInterfaceInfo(local_address);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(INFO, TAG, "it didn't get local address");
- }
-
- OIC_LOG(DEBUG, TAG, "OUT");
- return CA_STATUS_OK;
+ VERIFY_NON_NULL(local_address, TAG, "local_address");
+ OIC_LOG(INFO, TAG, "CAGetLEAddress is not support");
+ return CA_NOT_SUPPORTED;
}
JNIEXPORT void JNICALL
{
OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
g_leScanCallback = (*env)->NewGlobalRef(env, callback);
{
OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
g_leGattCallback = (*env)->NewGlobalRef(env, callback);
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
- jobject device, jint rssi,
- jbyteArray scanRecord)
+ jobject device)
{
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(device, TAG, "device is null");
CAResult_t res = CALEClientAddScanDeviceToList(env, device);
OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
newstate);
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
if (GATT_SUCCESS == status && STATE_CONNECTED == newstate) // le connected
{
OIC_LOG_V(DEBUG, TAG, "CALeGattServicesDiscoveredCallback - status %d: ", status);
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
if (0 != status) // discovery error
/*
* Class: org_iotivity_ca_jar_caleinterface
- * Method: CALeGattCharacteristicReadCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicReadCallback(JNIEnv *env,
- jobject obj,
- jobject gatt,
- jobject characteristic,
- jbyteArray data,
- jint status)
-{
- OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicReadCallback - status : %d", status);
-}
-
-/*
- * Class: org_iotivity_ca_jar_caleinterface
* Method: CALeGattCharacteristicWritjclasseCallback
* Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
*/
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
- JNIEnv *env, jobject obj, jobject gatt, jobject characteristic, jbyteArray data,
+ JNIEnv *env, jobject obj, jobject gatt, jbyteArray data,
jint status)
{
OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
jboolean isCopy;
*/
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
- JNIEnv *env, jobject obj, jobject gatt, jobject characteristic, jbyteArray data)
+ JNIEnv *env, jobject obj, jobject gatt, jbyteArray data)
{
OIC_LOG(DEBUG, TAG, "CALeGattCharacteristicChangedCallback");
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
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);
/*
* Class: org_iotivity_ca_jar_caleinterface
- * Method: CALeGattDescriptorReadCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorReadCallback(JNIEnv *env, jobject obj,
- jobject gatt,
- jobject descriptor,
- jint status)
-{
- OIC_LOG_V(DEBUG, TAG, "CALeGattDescriptorReadCallback - status %d: ", status);
-}
-
-/*
- * Class: org_iotivity_ca_jar_caleinterface
* Method: CALeGattDescriptorWriteCallback
* Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
*/
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
- jobject gatt,
- jobject descriptor,
- jint status)
+ jobject gatt,
+ jint status)
{
OIC_LOG_V(DEBUG, TAG, "CALeGattDescriptorWriteCallback - status %d: ", status);
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
CALEClientSendFinish(env, gatt);
return;
}
-
-/*
- * Class: org_iotivity_ca_jar_caleinterface
- * Method: CALeGattReliableWriteCompletedCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeGattReliableWriteCompletedCallback(JNIEnv *env,
- jobject obj,
- jobject gatt,
- jint status)
-{
- OIC_LOG_V(DEBUG, TAG, "CALeGattReliableWriteCompletedCallback - status %d: ", status);
-}
-
-/*
- * Class: org_iotivity_ca_jar_caleinterface
- * Method: CALeGattReadRemoteRssiCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeGattReadRemoteRssiCallback(JNIEnv *env, jobject obj,
- jobject gatt, jint rssi,
- jint status)
-{
- OIC_LOG_V(DEBUG, TAG, "CALeGattReadRemoteRssiCallback - rssi %d, status %d: ", rssi, status);
-}
-/******************************************************************
+/* ****************************************************************
*
* Copyright 2014 Samsung Electronics All Rights Reserved.
*
******************************************************************/
/**
- * @file caleclient.h
- * @brief This file contains the APIs for BT LE communications.
+ * @file
+ * This file contains the APIs for BT LE communications.
*/
#ifndef CA_LECLIENT_H_
#define CA_LECLIENT_H_
static const uint16_t STATE_SEND_SUCCESS = 1;
static const uint16_t STATE_SEND_FAILED = 2;
-static const uint32_t STATE_CONNECTED = 2;
-static const uint32_t STATE_DISCONNECTED = 0;
+static const jint STATE_CONNECTED = 2;
+static const jint STATE_DISCONNECTED = 0;
typedef struct le_state_info
{
char address[CA_MACADDR_SIZE];
- uint32_t connectedState;
+ jint connectedState;
uint16_t notificationState;
uint16_t sendState;
} CALEState_t;
/**
- * @brief Callback to be notified on reception of any data from remote devices.
- * @param address [IN] MAC address of remote device.
- * @param data [IN] Data received from remote device.
- * @return None
+ * Callback to be notified on reception of any data from remote devices.
+ * @param[in] address MAC address of remote device.
+ * @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);
/**
- * @brief initialize JNI object
- * @return None
+ * initialize JNI object.
*/
void CALEClientJniInit();
/**
- * @brief set context of application
- * @return None
+ * set context of application.
*/
void CALEClientJNISetContext();
/**
- * @brief create interface object and initialize the object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * create interface object and initialize the object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientCreateJniInterfaceObject();
/**
- * @brief initialize client for BLE
- * @param handle [IN] thread pool handle object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * initialize client for BLE.
+ * @param[in] handle thread pool handle object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientInitialize(ca_thread_pool_t handle);
/**
- * @brief terminate client for BLE
- * @return None
+ * terminate client for BLE.
*/
void CALEClientTerminate();
/**
- * @brief for destroy sending routine
- * @param env [IN] JNI interface pointer
- * @param gatt [IN] Gatt profile object
- * @return None
+ * for destroy sending routine.
+ * @param[in] env JNI interface pointer.
+ * @param[in] gatt Gatt profile object.
*/
void CALEClientSendFinish(JNIEnv *env, jobject gatt);
/**
- * @brief send data for unicast (interface)
- * @param address [IN] remote address
- * @param data [IN] data for transmission
- * @param dataLen [IN] data length
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send data for unicast (interface).
+ * @param[in] address remote address.
+ * @param[in] data data for transmission.
+ * @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);
/**
- * @brief send data for multicast (interface)
- * @param data [IN] data for transmission
- * @param dataLen [IN] data length
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send data for multicast (interface).
+ * @param[in] data data for transmission.
+ * @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);
/**
- * @brief start unicast server
- * @param address [IN] remote address
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * start unicast server.
+ * @param[in] address remote address.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientStartUnicastServer(const char *address);
/**
- * @brief start multicast server (start discovery)
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * start multicast server (start discovery).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientStartMulticastServer();
/**
- * @brief stop unicast server
- * @return None
+ * stop unicast server.
*/
void CALEClientStopUnicastServer();
/**
- * @brief stop multicast server (stop discovery)
- * @return None
+ * stop multicast server (stop discovery).
*/
void CALEClientStopMulticastServer();
/**
- * @brief set this callback for receiving data packets from peer devices.
- * @param callback [IN] callback to be notified on reception of
- * unicast/multicast data packets.
- * @return None
+ * set this callback for receiving data packets from peer devices.
+ * @param[in] callback callback to be notified on reception of
+ * unicast/multicast data packets.
*/
void CALEClientSetCallback(CAPacketReceiveCallback callback);
/**
- * @brief get local address (interface)
- * @param address [OUT] local address
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send data for unicast (implement).
+ * @param[in] address remote address.
+ * @param[in] data data for transmission.
+ * @param[in] dataLen data length.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
-CAResult_t CALEClientGetInterfaceInfo(char **address);
-
-/**
- * @brief get local address (implement)
- * @param address [OUT] local address
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
- */
-CAResult_t CALEClientGetLocalAddress(char** address);
-
-/**
- * @brief send data for unicast (implement)
- * @param address [IN] remote address
- * @param data [IN] data for transmission
- * @param dataLen [IN] 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);
/**
- * @brief send data for multicast (implement)
- * @param env [IN] JNI interface pointer
- * @param data [IN] data for transmission
- * @param dataLen [IN] data length
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send data for multicast (implement).
+ * @param[in] env JNI interface pointer.
+ * @param[in] data data for transmission.
+ * @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);
/**
- * @brief check whether it is connected or not with remote address.
- * @param address [IN] remote address
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * check whether it is connected or not with remote address.
+ * @param[in] address remote address.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALECheckSendState(const char* address);
/**
- * @brief send data to remote device.
- * if it isn't connected yet. connect LE before try to send data
- * @param env [IN] JNI interface pointer
- * @param device [IN] bluetooth device object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send data to remote device.
+ * if it isn't connected yet. connect LE before try to send data.
+ * @param[in] env JNI interface pointer.
+ * @param[in] device bluetooth device object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientSendData(JNIEnv *env, jobject device);
/**
- * @brief get address from bluetooth gatt object
- * @param env [IN] JNI interface pointer
- * @param gatt [IN] Gatt profile object
- * @return bluetooth address
+ * get address from bluetooth gatt object.
+ * @param[in] env JNI interface pointer.
+ * @param[in] gatt Gatt profile object.
+ * @return bluetooth address.
*/
jstring CALEClientGetAddressFromGattObj(JNIEnv *env, jobject gatt);
/**
- * @brief get remote address from bluetooth socket object
- * @param env [IN] JNI interface pointer
- * @param bluetoothSocketObj [IN] bluetooth socket
- * @return bluetooth address
+ * get remote address from bluetooth socket object.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothSocketObj bluetooth socket.
+ * @return bluetooth address.
*/
jstring CALEClientGetRemoteAddress(JNIEnv *env, jobject bluetoothSocketObj);
/**
- * @brief close gatt
- * @param env [IN] JNI interface pointer
- * @param bluetoothGatt [IN] gatt profile object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * close gatt.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothGatt gatt profile object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientGattClose(JNIEnv *env, jobject bluetoothGatt);
/**
- * @brief start to scan whole bluetooth devices (interface)
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * start to scan whole bluetooth devices (interface).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientStartScan();
/**
- * @brief start to scan whole bluetooth devices (implement)
- * @param env [IN] JNI interface pointer
- * @param callback [IN] callback to receive device object by scanning
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * start to scan whole bluetooth devices (implement).
+ * @param[in] env JNI interface pointer.
+ * @param[in] callback callback to receive device object by scanning.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback);
/**
- * @brief start to scan target bluetooth devices for service uuid (implement)
- * @param env [IN] JNI interface pointer
- * @param uuids [IN] target UUID
- * @param callback [IN] callback to receive device object by scanning
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * start to scan target bluetooth devices for service uuid (implement).
+ * @param[in] env JNI interface pointer.
+ * @param[in] uuids target UUID.
+ * @param[in] callback callback to receive device object by scanning.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids,
jobject callback);
/**
- * @brief get uuid object
- * @param env [IN] JNI interface pointer
- * @param uuid [IN] uuid
- * @return uuid object
+ * get uuid object.
+ * @param[in] env JNI interface pointer.
+ * @param[in] uuid uuid.
+ * @return uuid object.
*/
jobject CALEClientGetUUIDObject(JNIEnv *env, const char *uuid);
/**
- * @brief stop scan (interface)
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * stop scan (interface).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientStopScan();
/**
- * @brief stop scan (implement)
- * @param env [IN] JNI interface pointer
- * @param callback [IN] callback to receive device object by scanning
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * stop scan (implement).
+ * @param[in] env JNI interface pointer.
+ * @param[in] callback callback to receive device object by scanning.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback);
/**
- * @brief connect to gatt server hosted
- * @param env [IN] JNI interface pointer
- * @param bluetoothDevice [IN] bluetooth Device object
- * @param autoconnect [IN] whether to directly connect to the remote device(false) or
+ * connect to gatt server hosted.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothDevice bluetooth Device object.
+ * @param[in] autoconnect whether to directly connect to the remote device(false) or
* to automatically connect as soon as the remote device
- * becomes available
- * @param callback [IN] callback for connection state change
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * becomes available.
+ * @param[in] callback callback for connection state change.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect,
jobject callback);
/**
- * @brief disconnect to gatt server by a target device
- * @param env [IN] JNI interface pointer
- * @param bluetoothGatt [IN] Gatt profile object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * disconnect to gatt server by a target device.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothGatt Gatt profile object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientDisconnect(JNIEnv *env, jobject bluetoothGatt);
/**
- * @brief disconnect to gatt server by whole devices
- * @param env [IN] JNI interface pointer
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * disconnect to gatt server by whole devices.
+ * @param[in] env JNI interface pointer.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientDisconnectAll(JNIEnv *env);
/**
- * @brief start discovery server
- * @param env [IN] JNI interface pointer
- * @param bluetoothGatt [IN] Gatt profile object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * start discovery server.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothGatt Gatt profile object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientDiscoverServices(JNIEnv *env, jobject bluetoothGatt);
/**
- * @brief create GattCharacteristic and call CALEClientWriteCharacteristicImpl
- * for request to write gatt characteristic
- * @param env [IN] JNI interface pointer
- * @param gatt [IN] Gatt profile object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * create GattCharacteristic and call CALEClientWriteCharacteristicImpl
+ * for request to write gatt characteristic.
+ * @param[in] env JNI interface pointer.
+ * @param[in] gatt Gatt profile object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt);
/**
- * @brief request to write gatt characteristic
- * @param env [IN] JNI interface pointer
- * @param bluetoothGatt [IN] Gatt profile object
- * @param gattCharacteristic [IN] characteristic object that contain data to send
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * request to write gatt characteristic.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothGatt Gatt profile object.
+ * @param[in] gattCharacteristic characteristic object that contain data to send.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientWriteCharacteristicImpl(JNIEnv *env, jobject bluetoothGatt,
jobject gattCharacteristic);
/**
- * @brief request to read gatt characteristic
- * @param env [IN] JNI interface pointer
- * @param bluetoothGatt [IN] Gatt profile object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * request to read gatt characteristic.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothGatt Gatt profile object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientReadCharacteristic(JNIEnv *env, jobject bluetoothGatt);
/**
- * @brief enable notification for a target device
- * @param env [IN] JNI interface pointer
- * @param bluetoothGatt [IN] Gatt profile object
- * @param characteristic [IN] Characteristic object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * enable notification for a target device.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothGatt Gatt profile object.
+ * @param[in] characteristic Characteristic object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientSetCharacteristicNotification(JNIEnv *env, jobject bluetoothGatt,
jobject characteristic);
/**
- * @brief create gatt characteristic object
- * @param env [IN] JNI interface pointer
- * @param bluetoothGatt [IN] Gatt profile object
- * @param data [IN] for make Characteristic with data
- * @return Gatt Characteristic object
+ * create gatt characteristic object.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothGatt Gatt profile object.
+ * @param[in] data for make Characteristic with data.
+ * @return Gatt Characteristic object.
*/
jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, jbyteArray data);
/**
- * @brief get gatt service
- * @param env [IN] JNI interface pointer
- * @param bluetoothGatt [IN] Gatt profile object
- * @param characterUUID [IN] for make BluetoothGattCharacteristic object
- * @return Gatt Service
+ * get gatt service.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothGatt Gatt profile object.
+ * @param[in] characterUUID for make BluetoothGattCharacteristic object.
+ * @return Gatt Service.
*/
jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring characterUUID);
/**
- * @brief get value from characteristic
- * @param env [IN] JNI interface pointer
- * @param characteristic [IN] Characteristic object
- * @return value in characteristic
+ * get value from characteristic.
+ * @param[in] env JNI interface pointer.
+ * @param[in] characteristic Characteristic object.
+ * @return value in characteristic.
*/
jbyteArray CALEClientGetValueFromCharacteristic(JNIEnv *env, jobject characteristic);
/**
- * @brief create UUID List
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * create UUID List.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientCreateUUIDList();
/**
- * @brief set UUID to descriptor
- * @param env [IN] JNI interface pointer
- * @param bluetoothGatt [IN] Gatt profile object
- * @param characteristic [IN] Characteristic object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * set UUID to descriptor.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothGatt Gatt profile object.
+ * @param[in] characteristic Characteristic object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt,
jobject characteristic);
/**
- * BluetoothDevice List
- */
-/**
- * @brief add device object to scan device list
- * @param env [IN] JNI interface pointer
- * @param device [IN] bluetooth device object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * add device object to scan device list.
+ * @param[in] env JNI interface pointer.
+ * @param[in] device bluetooth device object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device);
/**
- * @brief check whether the device exist in list or not
- * @param env [IN] JNI interface pointer
- * @param remoteAddress [IN] remote address
- * @return true or false
+ * check whether the device exist in list or not.
+ * @param[in] env JNI interface pointer.
+ * @param[in] remoteAddress remote address.
+ * @return true or false.
*/
bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char *remoteAddress);
/**
- * @brief remove all devices in scan device list
- * @param env [IN] JNI interface pointer
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * remove all devices in scan device list.
+ * @param[in] env JNI interface pointer.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env);
/**
- * @brief remove target device in scan device list
- * @param env [IN] JNI interface pointer
- * @param remoteAddress [IN] remote address
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * remove target device in scan device list.
+ * @param[in] env JNI interface pointer.
+ * @param[in] remoteAddress remote address.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring remoteAddress);
/**
- * BluetoothGatt List
- */
-
-/**
- * @brief add gatt object to gatt object list
- * @param env [IN] JNI interface pointer
- * @param gatt [IN] Gatt profile object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * add gatt object to gatt object list.
+ * @param[in] env JNI interface pointer.
+ * @param[in] gatt Gatt profile object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt);
/**
- * @brief check whether the gatt object exist in list or not
- * @param env [IN] JNI interface pointer
- * @param remoteAddress [IN] remote address
- * @return true or false
+ * check whether the gatt object exist in list or not.
+ * @param[in] env JNI interface pointer.
+ * @param[in] remoteAddress remote address.
+ * @return true or false.
*/
bool CALEClientIsGattObjInList(JNIEnv *env, const char *remoteAddress);
/**
- * @brief get the gatt object
- * @param env [IN] JNI interface pointer
- * @param remoteAddress [IN] remote address
- * @return gatt object
+ * get the gatt object.
+ * @param[in] env JNI interface pointer.
+ * @param[in] remoteAddress remote address.
+ * @return gatt object.
*/
jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress);
/**
- * @brief remove all gatt objects in gatt object list
- * @param env [IN] JNI interface pointer
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * remove all gatt objects in gatt object list.
+ * @param[in] env JNI interface pointer.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env);
/**
- * @brief remove target device in gatt object list
- * @param env [IN] JNI interface pointer
- * @param gatt [IN] Gatt profile object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * remove target device in gatt object list.
+ * @param[in] env JNI interface pointer.
+ * @param[in] gatt Gatt profile object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt);
/**
- * @brief remove gatt object of target device for address in gatt object list
- * @param env [IN] JNI interface pointer
- * @param gatt [IN] Gatt profile object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * remove gatt object of target device for address in gatt object list.
+ * @param[in] env JNI interface pointer.
+ * @param[in] gatt Gatt profile object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr);
/**
- * BT State Info List
- */
-
-/**
- * @brief update new state information
- * @param address [IN] remote address
- * @param connectedState [IN] connection state
- * @param notificationState [IN] whether characteristic notification already set or not
- * @param sendState [IN] whether sending was success or not
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * update new state information.
+ * @param[in] address remote address.
+ * @param[in] connectedState connection state.
+ * @param[in] notificationState whether characteristic notification already set or not.
+ * @param[in] sendState whether sending was success or not.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientUpdateDeviceState(const char* address, uint32_t connectedState,
uint16_t notificationState, uint16_t sendState);
/**
- * @brief add new state to state list
- * @param state [IN] new state
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * add new state to state list.
+ * @param[in] state new state.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientAddDeviceStateToList(CALEState_t* state);
/**
- * @brief check whether the remote address is existed or not.
- * @param address [IN] remote address
- * @return true or false
+ * check whether the remote address is existed or not.
+ * @param[in] address remote address.
+ * @return true or false.
*/
bool CALEClientIsDeviceInList(const char *remoteAddress);
/**
- * @brief remove all device states
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * remove all device states.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientRemoveAllDeviceState();
/**
- * @brief remove the device state for a remote device
- * @param remoteAddress [IN] remote address
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * remove the device state for a remote device.
+ * @param[in] remoteAddress remote address.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress);
/**
- * @brief get state information for a remote device
- * @param remoteAddress [IN] remote address
- * @return CALEState_t
+ * get state information for a remote device.
+ * @param[in] remoteAddress remote address.
+ * @return CALEState_t.
*/
CALEState_t* CALEClientGetStateInfo(const char* remoteAddress);
/**
- * @brief check whether the remote address is connected or not.
- * @param remoteAddress [IN] remote address
- * @return true or false
+ * check whether the remote address is connected or not.
+ * @param[in] remoteAddress remote address.
+ * @return true or false.
*/
bool CALEClientIsConnectedDevice(const char* remoteAddress);
/**
- * @brief check whether the remote address set CharacteristicNotification or not
- * @param remoteAddress [IN] remote address
- * @return true or false
+ * check whether the remote address set CharacteristicNotification or not.
+ * @param[in] remoteAddress remote address.
+ * @return true or false.
*/
bool CALEClientIsSetCharacteristic(const char* remoteAddress);
/**
- * @brief create scan device list
- * @return None
+ * create scan device list.
*/
void CALEClientCreateDeviceList();
/**
- * @brief Reordering for device state list
- * @param index [IN] index of device list that want to reordering
- * @param list [IN] 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);
-
-/**
- * @brief update the counter which data is sent to remote device
- * @param env [IN] JNI interface pointer
- * @return None
+ * update the counter which data is sent to remote device.
+ * @param[in] env JNI interface pointer.
*/
void CALEClientUpdateSendCnt(JNIEnv *env);
/**
- * @brief initialize mutex
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * initialize mutex.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEClientInitGattMutexVaraibles();
/**
- * @brief terminate mutex
- * @return None
+ * terminate mutex.
*/
void CALEClientTerminateGattMutexVariables();
/**
- * @brief set send finish flag
- * @param flag [IN] flag
- * @return None
+ * set send finish flag.
+ * @param[in] flag finish flag.
*/
void CALEClientSetSendFinishFlag(bool flag);
jint status)
{
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
-
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
OIC_LOG(DEBUG, TAG, "CaLeClientInterface - Network State Changed");
{
OIC_LOG(DEBUG, TAG, "CaLeClientInterface - Bond State Changed");
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(addr, TAG, "addr is null");
// remove obj for client
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************/
+/* ****************************************************************
+ *
+ * Copyright 2014 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
/**
-* @file calenwmonitor.h
-* @brief This file contains the APIs for BT LE communications.
+* @file
+* This file contains the APIs for BT LE communications.
*/
#ifndef CA_LENWMONITOR_H_
#define CA_LENWMONITOR_H_
#endif
/**
- * @brief set context of application
- * @return None
+ * set context of application.
*/
void CALENetworkMonitorJNISetContext();
/**
- * @brief initialize JNI object
- * @return None
+ * initialize JNI object.
*/
void CALENetworkMonitorJniInit();
/**
- * @brief Set this callback for receiving network information from BT stack.
- * @param callback [IN] Callback to be notified on reception of BT state information
- * @return NONE
+ * Set this callback for receiving network information from BT stack.
+ * @param[in] callback Callback to be notified on reception of BT state information.
+
*/
void CALESetNetStateCallback(CALEDeviceStateChangedCallback callback);
return NULL;
}
-#ifdef USE_PROPERTY_WRITE_RESPONSE
- jfieldID jni_fid_writeProperties = (*env)->GetStaticFieldID(env,
- jni_cid_bluetoothGattCharacteristic,
- "PROPERTY_WRITE", "I");
-#else
jfieldID jni_fid_writeProperties = (*env)->GetStaticFieldID(env,
jni_cid_bluetoothGattCharacteristic,
"PROPERTY_WRITE_NO_RESPONSE", "I");
-#endif
-
if (!jni_fid_writeProperties)
{
OIC_LOG(ERROR, TAG, "jni_fid_writeProperties is null");
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)
+ jobject callback)
{
- OIC_LOG(DEBUG, TAG, "CaLeServerInterface - Register Le Gatt Server Callback");
- VERIFY_NON_NULL_VOID(env, TAG, "env is null");
- VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
+ OIC_LOG(DEBUG, TAG, "Register Le Gatt Server Callback");
+ VERIFY_NON_NULL_VOID(env, TAG, "env");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj");
+ VERIFY_NON_NULL_VOID(callback, TAG, "callback");
g_bluetoothGattServerCallback = (*env)->NewGlobalRef(env, callback);
}
jobject obj,
jobject callback)
{
- OIC_LOG(DEBUG, TAG, "CaLeServerInterface - Register Le Advertise Callback");
- VERIFY_NON_NULL_VOID(env, TAG, "env is null");
- VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
+ OIC_LOG(DEBUG, TAG, "Register Le Advertise Callback");
+ VERIFY_NON_NULL_VOID(env, TAG, "env");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj");
+ VERIFY_NON_NULL_VOID(callback, TAG, "callback");
g_leAdvertiseCallback = (*env)->NewGlobalRef(env, callback);
}
Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerConnectionStateChangeCallback(
JNIEnv *env, jobject obj, jobject device, jint status, jint newState)
{
- OIC_LOG(DEBUG, TAG, "CaLeServerInterface - Gatt Server ConnectionStateChange Callback");
+ OIC_LOG(DEBUG, TAG, " Gatt Server ConnectionStateChange Callback");
OIC_LOG_V(DEBUG, TAG, "New connection State: %d", newState);
- VERIFY_NON_NULL_VOID(env, TAG, "env is null");
- VERIFY_NON_NULL_VOID(device, TAG, "device is null");
+ VERIFY_NON_NULL_VOID(env, TAG, "env");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj");
+ VERIFY_NON_NULL_VOID(device, TAG, "device");
jclass jni_cid_bluetoothProfile = (*env)->FindClass(env, "android/bluetooth/BluetoothProfile");
if (!jni_cid_bluetoothProfile)
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerServiceAddedCallback(JNIEnv *env,
- jobject obj,
- jint status,
- jobject gattService)
+ jobject obj,
+ jint status,
+ jobject gattService)
{
- OIC_LOG_V(DEBUG, TAG, "CaLeServerInterface - Gatt Service Added Callback(%d)", status);
+ VERIFY_NON_NULL_VOID(env, TAG, "env");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj");
+ VERIFY_NON_NULL_VOID(gattService, TAG, "gattService");
+
+ OIC_LOG_V(DEBUG, TAG, "Gatt Service Added Callback(%d)", status);
}
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerCharacteristicReadRequestCallback(
- JNIEnv *env, jobject obj, jobject device, jint requestId, jint offset,
- jobject characteristic, jbyteArray data)
+ JNIEnv *env, jobject obj, jobject device, jbyteArray data)
{
- OIC_LOG(DEBUG, TAG, "CaLeServerInterface - Gatt Server Characteristic Read Request Callback");
- VERIFY_NON_NULL_VOID(env, TAG, "env is null");
- VERIFY_NON_NULL_VOID(device, TAG, "device is null");
-
-#ifdef USE_PROPERTY_WRITE_RESPONSE
- CALEServerSendResponse(env, device, requestId, 0, offset, NULL);
-#endif
-
+ OIC_LOG(DEBUG, TAG, " Gatt Server Characteristic Read Request Callback");
+ VERIFY_NON_NULL_VOID(env, TAG, "env");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj");
+ VERIFY_NON_NULL_VOID(device, TAG, "device");
+ VERIFY_NON_NULL_VOID(data, TAG, "data");
}
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerCharacteristicWriteRequestCallback(
- JNIEnv *env, jobject obj, jobject device, jint requestId, jobject characteristic,
- jbyteArray data, jboolean preparedWrite, jboolean responseNeeded, jint offset,
- jbyteArray value)
+ JNIEnv *env, jobject obj, jobject device, jbyteArray data)
{
- OIC_LOG(DEBUG, TAG, "CaLeServerInterface - Gatt Server Characteristic Write Request Callback");
- VERIFY_NON_NULL_VOID(env, TAG, "env is null");
- VERIFY_NON_NULL_VOID(device, TAG, "device is null");
- VERIFY_NON_NULL_VOID(value, TAG, "value is null");
- VERIFY_NON_NULL_VOID(data, TAG, "data is null");
-
-#ifdef USE_PROPERTY_WRITE_RESPONSE
- CALEServerSendResponse(env, device, requestId, 0, offset, value);
-#endif
+ OIC_LOG_V(DEBUG, TAG, "Gatt Server Characteristic Write Request Callback");
+ VERIFY_NON_NULL_VOID(env, TAG, "env");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj");
+ 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;
}
JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerDescriptorReadRequestCallback(
- JNIEnv *env, jobject obj, jobject device, jint requestId, jint offset, jobject descriptor)
-{
- OIC_LOG(DEBUG, TAG, "CaLeServerInterface_CALeGattServerDescriptorReadRequestCallback");
-}
-
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerDescriptorWriteRequestCallback(
- JNIEnv *env, jobject obj, jobject device, jint requestId, jobject descriptor,
- jboolean preparedWrite, jboolean responseNeeded, jint offset, jbyteArray value)
-{
- OIC_LOG(DEBUG, TAG, "CaLeServerInterface_CALeGattServerDescriptorWriteRequestCallback");
-}
-
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerExecuteWriteCallback(JNIEnv *env,
- jobject obj,
- jobject device,
- jint requestId,
- jboolean execute)
+Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerNotificationSentCallback(JNIEnv *env,
+ jobject obj,
+ jobject device,
+ jint status)
{
- OIC_LOG(DEBUG, TAG, "CaLeServerInterface_CALeGattServerExecuteWriteCallback");
- VERIFY_NON_NULL_VOID(env, TAG, "env is null");
- VERIFY_NON_NULL_VOID(device, TAG, "device is null");
+ VERIFY_NON_NULL_VOID(env, TAG, "env");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj");
+ VERIFY_NON_NULL_VOID(device, TAG, "device");
-// CALEServerSendResponse(env, device, requestId, 0, 0, NULL);
+ OIC_LOG_V(DEBUG, TAG, "Gatt Server Notification Sent Callback(%d)",
+ status);
}
JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerNotificationSentCallback(JNIEnv *env,
- jobject obj,
- jobject device,
- jint status)
+Java_org_iotivity_ca_CaLeServerInterface_caLeAdvertiseStartSuccessCallback(JNIEnv *env,
+ jobject obj,
+ jobject settingsInEffect)
{
- OIC_LOG(DEBUG, TAG, "CaLeServerInterface - Gatt Server Notification Sent Callback");
-}
+ VERIFY_NON_NULL_VOID(env, TAG, "env");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj");
+ VERIFY_NON_NULL_VOID(settingsInEffect, TAG, "settingsInEffect");
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeServerInterface_caLeAdvertiseStartSuccessCallback(
- JNIEnv *env, jobject obj, jobject settingsInEffect)
-{
- OIC_LOG(DEBUG, TAG, "CaLeServerInterface - LE Advertise Start Success Callback");
+ OIC_LOG(DEBUG, TAG, "LE Advertise Start Success Callback");
}
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeServerInterface_caLeAdvertiseStartFailureCallback(JNIEnv *env,
- jobject obj,
- jint errorCode)
+ jobject obj,
+ jint errorCode)
{
- OIC_LOG_V(ERROR, TAG, "CaLeServerInterface - LE Advertise Start Failure Callback(%)",
+ 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);
}
}
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");
-/******************************************************************
+/* ****************************************************************
*
* Copyright 2014 Samsung Electronics All Rights Reserved.
*
******************************************************************/
/**
- * @file caleserver.h
- * @brief This file contains the APIs for BT LE communications.
+ * @file
+ * This file contains the APIs for BT LE communications.
*/
#ifndef CA_LESERVER_H_
#define CA_LESERVER_H_
#endif
/**
- * @brief Callback to be notified on reception of any data from remote devices.
- * @param address [IN] MAC address of remote device.
- * @param data [IN] Data received from remote device.
- * @return None
- * @pre Callback must be registered using CALEServerSetCallback(CAPacketReceiveCallback callback)
+ * Callback to be notified on reception of any data from remote devices.
+ * @param[in] address MAC address of remote device.
+ * @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);
/**
- * @brief initialize server for BLE
- * @param handle [IN] thread pool handle object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * initialize server for BLE.
+ * @param[in] handle thread pool handle object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerInitialize(ca_thread_pool_t handle);
/**
- * @brief terminate client for BLE
- * @return None
+ * terminate client for BLE.
*/
void CALEServerTerminate();
/**
- * @brief send data for unicast (interface)
- * @param address [IN] remote address
- * @param data [IN] data for transmission
- * @param dataLen [IN] data length
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send data for unicast (interface).
+ * @param[in] address remote address.
+ * @param[in] data data for transmission.
+ * @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);
/**
- * @brief send data for multicast (interface)
- * @param data [IN] data for transmission
- * @param dataLen [IN] data length
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send data for multicast (interface).
+ * @param[in] data data for transmission.
+ * @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);
/**
- * @brief start multicast server (start advertise)
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * start multicast server (start advertise).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerStartMulticastServer();
/**
- * @brief stop multicast server (stop discovery)
+ * stop multicast server (stop discovery).
* @return None
*/
CAResult_t CALEServerStopMulticastServer();
/**
- * @brief set this callback for receiving data packets from peer devices.
- * @param callback [IN] callback to be notified on reception of
- * unicast/multicast data packets.
- * @return None
+ * set this callback for receiving data packets from peer devices.
+ * @param[in] callback callback to be notified on reception of
+ * unicast/multicast data packets.
*/
void CALEServerSetCallback(CAPacketReceiveCallback callback);
/**
- * @brief send data for unicast (implement)
- * @param env [IN] JNI interface pointer
- * @param address [IN] remote address
- * @param data [IN] data for transmission
- * @param dataLen [IN] data length
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send data for unicast (implement).
+ * @param[in] env JNI interface pointer.
+ * @param[in] address remote address.
+ * @param[in] data data for transmission.
+ * @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);
/**
- * @brief send data for multicast (implement)
- * @param env [IN] JNI interface pointer
- * @param data [IN] data for transmission
- * @param dataLen [IN] data length
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send data for multicast (implement)
+ * @param[in] env JNI interface pointer
+ * @param[in] data data for transmission
+ * @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);
-/* Android BLE Server Functions */
/**
- * @brief set context of application
- * @return None
+ * set context of application.
*/
void CALEServerJNISetContext();
/**
- * @brief initialize JNI object
- * @return None
+ * initialize JNI object.
*/
void CALeServerJniInit();
/**
- * @brief create interface object and initialize the object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * create interface object and initialize the object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerCreateJniInterfaceObject();
/**
- * @brief start advertise in gatt server
- * @param env [IN] JNI interface pointer
- * @param advertiseCallback [IN] callback to be notified on reception of
- * advertisement result
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * start advertise in gatt server.
+ * @param[in] env JNI interface pointer.
+ * @param[in] advertiseCallback callback to be notified on reception of
+ * advertisement result.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerStartAdvertise(JNIEnv *env, jobject advertiseCallback);
/**
- * @brief stop advertise in gatt server
- * @param env [IN] JNI interface pointer
- * @param advertiseCallback [IN] callback to be notified on reception of
- * advertisement result
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * stop advertise in gatt server.
+ * @param[in] env JNI interface pointer.
+ * @param[in] advertiseCallback callback to be notified on reception of
+ * advertisement result.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerStopAdvertise(JNIEnv *env, jobject advertiseCallback);
/**
- * @brief open a gatt server
- * @param env [IN] JNI interface pointer
- * @return gatt server object
+ * open a gatt server.
+ * @param[in] env JNI interface pointer.
+ * @return gatt server object.
*/
jobject CALEServerOpenGattServer(JNIEnv *env);
/**
- * @brief create gatt service
- * @param env [IN] JNI interface pointer
+ * create gatt service
+ * @param[in] env JNI interface pointer
* @return gatt service object
*/
jobject CALEServerCreateGattService(JNIEnv *env);
/**
- * @brief add a descriptor to the characteristic
- * @param env [IN] JNI interface pointer
- * @param characteristic [IN] Characteristic object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * add a descriptor to the characteristic.
+ * @param[in] env JNI interface pointer.
+ * @param[in] characteristic Characteristic object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerAddDescriptor(JNIEnv *env, jobject characteristic);
/**
- * @brief create gatt service
- * @param env [IN] JNI interface pointer
- * @param bluetoothGattServer [IN] Bluetooth Gatt Server object
- * @param bluetoothGattService [IN] Bluetooth Gatt Service object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * create gatt service.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothGattServer Bluetooth Gatt Server object.
+ * @param[in] bluetoothGattService Bluetooth Gatt Service object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerAddGattService(JNIEnv *env, jobject bluetoothGattServer,
jobject bluetoothGattService);
/**
- * @brief start gatt server
- * @param env [IN] JNI interface pointer
- * @param gattServerCallback [IN] callback to be notified on reception of
- * state change of gatt server
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * start gatt server.
+ * @param[in] env JNI interface pointer.
+ * @param[in] gattServerCallback callback to be notified on reception of
+ * state change of gatt server.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerStartGattServer(JNIEnv *env, jobject gattServerCallback);
/**
- * @brief close gatt server
- * @param env [IN] JNI interface pointer
- * @param bluetoothGattServer [IN] Gatt Server object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * close gatt server.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothGattServer Gatt Server object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerGattClose(JNIEnv *env, jobject bluetoothGattServer);
/**
- * @brief send data
- * @param env [IN] JNI interface pointer
- * @param bluetoothDevice [IN] bluetooth device object
- * @param data [IN] data which send
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send data.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothDevice bluetooth device object.
+ * @param[in] data data which send.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerSend(JNIEnv *env, jobject bluetoothDevice, jstring data);
/**
- * @brief set data in BluetoothGattCharacteristic
- * @param env [IN] JNI interface pointer
- * @param responseData [IN] data to set in characteristic object
- * @return BluetoothGattCharacteristic object
+ * set data in BluetoothGattCharacteristic.
+ * @param[in] env JNI interface pointer.
+ * @param[in] responseData data to set in characteristic object.
+ * @return BluetoothGattCharacteristic object.
*/
jobject CALEServerSetResponseData(JNIEnv *env, jbyteArray responseData);
/**
- * @brief send data through notifyCharacteristicChanged api of android
- * @param env [IN] JNI interface pointer
- * @param device [IN] bluetooth device object
- * @param responseData [IN] data which send
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send data through notifyCharacteristicChanged api of android.
+ * @param[in] env JNI interface pointer.
+ * @param[in] device bluetooth device object.
+ * @param[in] responseData data which send.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerSendResponseData(JNIEnv *env, jobject device, jobject responseData);
/**
- * @brief send a response to a write request to a remote device
- * @param env [IN] JNI interface pointer
- * @param device [IN] bluetooth device object
- * @param requestId [IN] the id of request
- * @param status [IN] the status of the request to be sent to the remote devices
- * @param offset [IN] value offset for partial write response
- * @param value [IN] the value of the attribute that written (optional)
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * send a response to a write request to a remote device.
+ * @param[in] env JNI interface pointer.
+ * @param[in] device bluetooth device object.
+ * @param[in] requestId the id of request.
+ * @param[in] status the status of the request to be sent to the remote devices.
+ * @param[in] offset value offset for partial write response.
+ * @param[in] value the value of the attribute that written (optional).
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerSendResponse(JNIEnv *env, jobject device, jint requestId, jint status,
jint offset, jbyteArray value);
/**
- * @brief connect BLE to remote device form gatt server
- * @param env [IN] JNI interface pointer
- * @param bluetoothDevice [IN] bluetooth device object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * connect BLE to remote device form gatt server.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothDevice bluetooth device object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerConnect(JNIEnv *env, jobject bluetoothDevice);
/**
- * @brief disconnect LE for all devices
- * @param env [IN] JNI interface pointer
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * disconnect LE for all devices.
+ * @param[in] env JNI interface pointer.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerDisconnectAllDevices(JNIEnv *env);
/**
- * @brief disconnect LE to remote device form gatt server
- * @param env [IN] JNI interface pointer
- * @param bluetoothDevice [IN] bluetooth device object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * disconnect LE to remote device form gatt server.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothDevice bluetooth device object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerDisconnect(JNIEnv *env, jobject bluetoothDevice);
-/* BLE Server Utils */
/**
- * @brief create connected device list
- * @return None
+ * create connected device list.
*/
void CALEServerCreateCachedDeviceList();
/**
- * @brief check whether the device exist in the list or not
- * @param env [IN] JNI interface pointer
- * @param remoteAddress [IN] remote address
- * @return true or false
+ * check whether the device exist in the list or not.
+ * @param[in] env JNI interface pointer.
+ * @param[in] remoteAddress remote address.
+ * @return true or false.
*/
bool CALEServerIsDeviceInList(JNIEnv *env, const char* remoteAddress);
/**
- * @brief add device object to the list (connected device list)
- * @param env [IN] JNI interface pointer
- * @param device [IN] bluetooth device object
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * add device object to the list (connected device list).
+ * @param[in] env JNI interface pointer.
+ * @param[in] device bluetooth device object.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerAddDeviceToList(JNIEnv *env, jobject device);
/**
- * @brief remove all devices objects in the list (connected device list)
- * @param env [IN] JNI interface pointer
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * remove all devices objects in the list (connected device list).
+ * @param[in] env JNI interface pointer.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerRemoveAllDevices(JNIEnv *env);
/**
- * @brief remove target device in the list (connected device list)
- * @param env [IN] JNI interface pointer
- * @param address [IN] target address to remove
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * remove target device in the list (connected device list).
+ * @param[in] env JNI interface pointer.
+ * @param[in] address target address to remove.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerRemoveDevice(JNIEnv *env, jstring address);
/**
- * @brief Reordering for the list (connected device list)
- * @param index [IN] 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);
-
-/**
- * @brief initialize mutex
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * initialize mutex.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerInitMutexVaraibles();
/**
- * @brief terminate mutex
- * @return None
+ * terminate mutex.
*/
void CALEServerTerminateMutexVaraibles();
/**
- * @brief initialize condition
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * initialize condition.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALEServerInitConditionVaraibles();
/**
- * @brief terminate condition
- * @return None
+ * terminate condition.
*/
void CALEServerTerminateConditionVaraibles();
-/******************************************************************
+/* ****************************************************************
*
* Copyright 2014 Samsung Electronics All Rights Reserved.
*
******************************************************************/
/**
- * @file caleutils.h
- * @brief This file contains the APIs for BT LE communications.
+ * @file
+ * This file contains the APIs for BT LE communications.
*/
#ifndef CA_LE_UTILS_H_
#define CA_LE_UTILS_H_
static const char OIC_GATT_CHARACTERISTIC_RESPONSE_UUID[] = CA_GATT_RESPONSE_CHRC_UUID;
static const char OIC_GATT_CHARACTERISTIC_CONFIG_UUID[] = "00002902-0000-1000-8000-00805f9b34fb";
-static const uint32_t GATT_SUCCESS = 0;
+static const jint GATT_SUCCESS = 0;
-static const uint32_t BOND_BONDED = 12;
-static const uint32_t BOND_BONDING = 11;
-static const uint32_t BOND_NONE = 10;
+static const jint BOND_BONDED = 12;
+static const jint BOND_BONDING = 11;
+static const jint BOND_NONE = 10;
/**
- * @brief get uuid(jni object) from uuid(character)
- * @param env [IN] JNI interface pointer
- * @param uuid [IN] uuid(character)
- * @return uuid(jni object)
+ * get uuid(jni object) from uuid(character).
+ * @param[in] env JNI interface pointer.
+ * @param[in] uuid uuid(character).
+ * @return uuid(jni object).
*/
jobject CALEGetUuidFromString(JNIEnv *env, const char* uuid);
/**
- * @brief get parcel uuid object
- * @param env [IN] JNI interface pointer
- * @param uuid [IN] uuid (jni object)
- * @return parcel uuid object
+ * get parcel uuid object.
+ * @param[in] env JNI interface pointer.
+ * @param[in] uuid uuid (jni object).
+ * @return parcel uuid object.
*/
jobject CALEGetParcelUuid(JNIEnv *env, jobject uuid);
/**
- * @brief get address from a local device
- * @param env [IN] JNI interface pointer
- * @return local address
+ * get address from a local device.
+ * @param[in] env JNI interface pointer.
+ * @return local address.
*/
jstring CALEGetLocalDeviceAddress(JNIEnv *env);
/**
- * @brief get bonded list
- * @param env [IN] JNI interface pointer
- * @return bonded list
+ * get bonded list.
+ * @param[in] env JNI interface pointer.
+ * @return bonded list.
*/
jobjectArray CALEGetBondedDevices(JNIEnv *env);
/**
- * @brief get constants information of bluetooth state-on
- * @param env [IN] JNI interface pointer
- * @return constants information of bluetooth state-on
+ * get constants information of bluetooth state-on.
+ * @param[in] env JNI interface pointer.
+ * @return constants information of bluetooth state-on.
*/
jint CALEGetBTStateOnInfo(JNIEnv *env);
/**
- * @brief check this device can be supported as BLE client or server
- * @param env [IN] JNI interface pointer
- * @param level [IN] Android API Level to support
- * @return CA_STATUS_OK or ERROR CODES (CAResult_t error codes in cacommon.h)
+ * check this device can be supported as BLE client or server.
+ * @param[in] env JNI interface pointer.
+ * @param[in] level Android API Level to support.
+ * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
*/
CAResult_t CALECheckPlatformVersion(JNIEnv *env, uint16_t level);
/**
- * @brief get constants information of android.os.Build.VERSION.SDK_INT
- * @param env [IN] JNI interface pointer
- * @return constants information of android.os.Build.VERSION.SDK_INT
+ * get constants information of android.os.Build.VERSION.SDK_INT.
+ * @param[in] env JNI interface pointer.
+ * @return constants information of android.os.Build.VERSION.SDK_INT.
*/
jint CALEGetBuildVersion(JNIEnv *env);
/**
- * @brief get constants information of android.os.Build.VERSION_CODES.[VersionName]
- * @param env [IN] JNI interface pointer
- * @param versionName [IN] version name (.., KITKAT, LOLLIPOP, ..)
- * @return constants information of android.os.Build.VERSION_CODES.[VersionName]
+ * get constants information of android.os.Build.VERSION_CODES.[VersionName].
+ * @param[in] env JNI interface pointer.
+ * @param[in] versionName version name (.., KITKAT, LOLLIPOP, ..).
+ * @return constants information of android.os.Build.VERSION_CODES.[VersionName].
*/
jint CALEGetBuildVersionCodeForName(JNIEnv *env, const char* versionName);
/**
- * @brief get bluetooth adapter state information
- * @param env [IN] JNI interface pointer
- * @return JNI_TRUE if the local adapter is turned on
+ * get bluetooth adapter state information.
+ * @param[in] env JNI interface pointer.
+ * @return JNI_TRUE if the local adapter is turned on.
*/
jboolean CALEIsEnableBTAdapter(JNIEnv *env);
/**
- * @brief get address from remote device
- * @param env [IN] JNI interface pointer
- * @param bluetoothDevice [IN] bluetooth device object
- * @return remote address
+ * get address from remote device.
+ * @param[in] env JNI interface pointer.
+ * @param[in] bluetoothDevice bluetooth device object.
+ * @return remote address.
*/
jstring CALEGetAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice);
*/
JNIEXPORT void JNICALL
Java_org_iotivity_ca_caLeClientInterface_caLeScanCallback
-(JNIEnv *, jobject, jobject, jint, jbyteArray);
+(JNIEnv *, jobject, jobject);
/*
* Class: org_iotivity_ca_caLeClientInterface
/*
* Class: org_iotivity_ca_caLeClientInterface
- * Method: caLeGattCharacteristicReadCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_caLeClientInterface_caLeGattCharacteristicReadCallback
-(JNIEnv *, jobject, jobject, jobject, jbyteArray, jint);
-
-/*
- * Class: org_iotivity_ca_caLeClientInterface
* Method: caLeGattCharacteristicWritjclasseCallback
* Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
*/
JNIEXPORT void JNICALL
Java_org_iotivity_ca_caLeClientInterface_caLeGattCharacteristicWriteCallback
-(JNIEnv *, jobject, jobject, jobject, jbyteArray, jint);
+(JNIEnv *, jobject, jobject, jbyteArray, jint);
/*
* Class: org_iotivity_ca_caLeClientInterface
*/
JNIEXPORT void JNICALL
Java_org_iotivity_ca_caLeClientInterface_caLeGattCharacteristicChangedCallback
-(JNIEnv *, jobject, jobject, jobject, jbyteArray);
-
-/*
- * Class: org_iotivity_ca_caLeClientInterface
- * Method: caLeGattDescriptorReadCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_caLeClientInterface_caLeGattDescriptorReadCallback
-(JNIEnv *, jobject, jobject, jobject, jint);
+(JNIEnv *, jobject, jobject, jbyteArray);
/*
* Class: org_iotivity_ca_caLeClientInterface
*/
JNIEXPORT void JNICALL
Java_org_iotivity_ca_caLeClientInterface_caLeGattDescriptorWriteCallback
-(JNIEnv *, jobject, jobject, jobject, jint);
-
-/*
- * Class: org_iotivity_ca_caLeClientInterface
- * Method: caLeGattReliableWriteCompletedCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_caLeClientInterface_caLeGattReliableWriteCompletedCallback
(JNIEnv *, jobject, jobject, jint);
/*
* Class: org_iotivity_ca_caLeClientInterface
- * Method: caLeGattReadRemoteRssiCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_caLeClientInterface_caLeGattReadRemoteRssiCallback
-(JNIEnv *, jobject, jobject, jint, jint);
-
-/*
- * Class: org_iotivity_ca_caLeClientInterface
* Method: caLeStateChangedCallback
* Signature: (I)V
*/
*/
JNIEXPORT void JNICALL
Java_org_iotivity_ca_caLeServerInterface_caLeGattServerCharacteristicReadRequestCallback
-(JNIEnv *, jobject, jobject, jint, jint, jobject, jbyteArray);
+(JNIEnv *, jobject, jobject, jbyteArray);
/*
* Class: org_iotivity_ca_caLeServerInterface
*/
JNIEXPORT void JNICALL
Java_org_iotivity_ca_caLeServerInterface_caLeGattServerCharacteristicWriteRequestCallback
-(JNIEnv *, jobject, jobject, jint, jobject, jbyteArray, jboolean, jboolean, jint, jbyteArray);
-
-/*
- * Class: org_iotivity_ca_caLeServerInterface
- * Method: caLeGattServerDescriptorReadRequestCallback
- * Signature: (Landroid/bluetooth/BluetoothDevice;IILandroid/bluetooth/
- * BluetoothGattDescriptor;)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_caLeServerInterface_caLeGattServerDescriptorReadRequestCallback
-(JNIEnv *, jobject, jobject, jint, jint, jobject);
-
-/*
- * Class: org_iotivity_ca_caLeServerInterface
- * Method: caLeGattServerDescriptorWriteRequestCallback
- * Signature: (Landroid/bluetooth/BluetoothDevice;ILandroid/bluetooth/
- * BluetoothGattDescriptor;ZZI[B)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_caLeServerInterface_caLeGattServerDescriptorWriteRequestCallback
-(JNIEnv *, jobject, jobject, jint, jobject, jboolean, jboolean, jint, jbyteArray);
-
-/*
- * Class: org_iotivity_ca_caLeServerInterface
- * Method: caLeGattServerExecuteWriteCallback
- * Signature: (Landroid/bluetooth/BluetoothDevice;IZ)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_caLeServerInterface_caLeGattServerExecuteWriteCallback
-(JNIEnv *, jobject, jobject, jint, jboolean);
+(JNIEnv *, jobject, jobject, jbyteArray);
/*
* Class: org_iotivity_ca_caLeServerInterface
#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
/* ****************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************/
+ *
+ * Copyright 2014 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
/**
* @file
* This file contains the APIs related to the GATT Server functionalities.
* Creation of the GATT Server with the characteristics. Enabling the
* advertisement and updating the characteristics for the response and
- * notifying the change of characteristcs for the request will be done here.
+ * notifying the change of characteristics for the request will be done here.
*/
#ifndef BLE_ADAPTER_ARDUINO_H_
#endif
/**
- * @brief API to initialize Arduino BLE module and advertise the service
- * @return #CA_STATUS_OK or Appropriate error code
+ * API to initialize Arduino BLE module and advertise the service.
+ * @return ::CA_STATUS_OK or Appropriate error code.
*/
CAResult_t CALEInitialize();
/**
- * @brief API to check whether data is available in BLE shield
- * @return - Received buffer length
+ * API to check whether data is available in BLE shield.
+ * @return - Received buffer length.
*/
unsigned char CAIsLEDataAvailable();
/**
- * @brief API to check whether client is connected with BLE Shield
- * @return - Connection state
+ * API to check whether client is connected with BLE Shield.
+ * @return - Connection state.
*/
unsigned char CAIsLEConnected();
/**
- * @brief API to read data from BLE shield
- * @return - Data read
+ * API to read data from BLE shield.
+ * @return - Data read.
*/
-char CALEReadData();
+uint8_t CALEReadData();
/**
- * @brief API to perform BLE events
- * @return #CA_STATUS_OK or Appropriate error code
+ * API to perform BLE events.
+ * @return ::CA_STATUS_OK or Appropriate error code.
*/
CAResult_t CALEDoEvents();
*/
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)
{
{
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();
}
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;
+ CAEndpoint_t endPoint =
+ { .adapter = CA_ADAPTER_GATT_BTLE }; // will be filled by
+ // upper layer
+
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");
}
char const * signal_name,
GVariant * parameters)
{
+ (void)sender_name;
+ (void)object_path;
+ (void)interface_name;
+ (void)signal_name;
+ (void)parameters;
#ifdef TB_LOG
gchar * const param_dump =
g_variant_print(parameters, TRUE);
gchar const * const * invalidated_properties,
gpointer user_data)
{
+ (void)manager;
+ (void)object_proxy;
+ (void)invalidated_properties;
OIC_LOG_V(DEBUG,
TAG,
"Properties Changed on %s:\n",
GVariant * parameters,
gpointer user_data)
{
+ (void)connection;
+ (void)user_data;
CALEDumpDBusSignalParameters(sender_name,
object_path,
interface_name,
GVariant * parameters,
gpointer user_data)
{
+ (void)connection;
+ (void)user_data;
CALEDumpDBusSignalParameters(sender_name,
object_path,
interface_name,
}
if (iter != NULL)
+ {
g_variant_iter_free(iter);
+ }
}
static void CALEOnPropertiesChanged(GDBusConnection * connection,
GVariant * parameters,
gpointer user_data)
{
+ (void)connection;
+ (void)user_data;
CALEDumpDBusSignalParameters(sender_name,
object_path,
interface_name,
GVariant * parameters,
gpointer user_data)
{
+ (void)connection;
+ (void)user_data;
CALEDumpDBusSignalParameters(sender_name,
object_path,
interface_name,
return accepted;
}
- char const ** const UUIDs = g_variant_get_strv(prop, NULL);
+ 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.
- */
- for (char const * const * u = UUIDs; u != NULL; ++u)
+ /*
+ 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)
{
if (strcasecmp(*u, CA_GATT_SERVICE_UUID) == 0)
{
// 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)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)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)
{
+ (void)remoteAddress;
+ (void)data;
+ (void)dataLen;
+ (void)type;
+ (void)position;
/**
* @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 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;
bool CAGattClientsDestroy(CALEContext * context)
{
+ (void)context;
/* g_hash_table_destroy(...); */ // FIXME
return false;
}
*/
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);
}
GVariant * parameters,
gpointer user_data)
{
+ (void)connection;
+ (void)sender_name;
+ (void)object_path;
+ (void)interface_name;
+ (void)signal_name;
/*
This handler is only trigged in a GATT client when receiving
data sent by a GATT server through a notification, e.g. such as
* @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);
GDBusMethodInvocation * invocation,
gpointer user_data)
{
+ (void)user_data;
/**
* @todo The @c GattDescriptor1 object still owns the returned
* variant when using the below call. Should be we use
char const * descriptor_path,
char const * value)
{
+ (void)s;
CAGattDescriptor * const d = &c->descriptor;
// Path of the form /org/iotivity/gatt/hci0/service0/char0/desc0.
-/******************************************************************
+/* ****************************************************************
*
* Copyright 2015 Intel Corporation All Rights Reserved.
*
gchar const * name,
gpointer user_data)
{
+ (void)connection;
+ (void)name; // needed when logging is a noop
+ (void)user_data;
OIC_LOG_V(DEBUG,
TAG,
"Name \"%s\" acquired on D-Bus.", name);
gchar const * name,
gpointer user_data)
{
+ (void)connection;
+ (void)name; // needed when logging is a noop
+ (void)user_data;
/*
This can happen if the appropriate D-Bus policy is not
installed, for example.
* advertising actually exists.
*/
if (result == CA_STATUS_OK
- && !(CAPeripheralRegisterGattServices(context)
+ && !(CAPeripheralRegisterGattServices(&g_context)
&& CAPeripheralRegisterAdvertisements(&g_context)))
{
result = CA_STATUS_FAILED;
*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.
*
*
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CAInitGattClientMutexVariables();
*
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CABleGattSetScanParameter();
*
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CABleGattSetCallbacks();
*
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CABleGattWatchCharacteristicChanges(bt_gatt_attribute_h service);
*
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CABleGattStartDeviceDiscovery();
*
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CABleGattConnect(const char *remoteAddress);
*
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CABleGattDisConnect(const char *remoteAddress);
/**
* Used to discover the services that is advertised by Gatt Server
- * asynchrounously.
+ * asynchronously.
*
* @param[in] remoteAddress MAC address of remote device in which we want
* to discover the services.
*
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CABleGattDiscoverServices(const char *remoteAddress);
* characteristics of given service handle.
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CABleGattDiscoverCharacteristics(bt_gatt_attribute_h service,
* descriptor of given char handle.
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CABleGattDiscoverDescriptor(bt_gatt_attribute_h service,
*
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CASetCharacteristicDescriptorValue
*
* @return ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
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 ::CA_STATUS_OK or Appropriate error code.
* @retval ::CA_STATUS_OK Successful.
- * @retval ::CA_STATUS_INVALID_PARAM Invalid input argumets.
+ * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments.
* @retval ::CA_STATUS_FAILED Operation failed.
*/
CAResult_t CALEReadDataFromLEClient();
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,
/* ****************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************/
+ *
+ * Copyright 2014 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
/**
* @file
#include "caleinterface.h"
/**
- * @brief This is thread which will be used for creating ble service and advertise ble service.
- * 1. Create New OIC Service 2. Add two read & write characteristics to service.
- * 3. Register Service 4. Advertise service.
+ * This is thread which will be used for creating ble service and advertise ble service.
+ * 1. Create New OIC Service 2. Add two read & write characteristics to service.
+ * 3. Register Service 4. Advertise service.
*
- * @param data [IN] Currently it will be NULL.
- * @return NONE
+ * @param[in] data Currently it will be NULL.
*/
void CAStartBleGattServerThread(void *data);
/**
- * @brief Used to initialize gatt service using _bt_gatt_init_service api.
+ * Used to initialize gatt service using _bt_gatt_init_service api.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @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 CAInitBleGattService();
/**
- * @brief Used to de-initialize gatt service using _bt_gatt_deinit_service api.
+ * Used to de-initialize gatt service using _bt_gatt_deinit_service api.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @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 CADeInitBleGattService();
/**
- * @brief Used to initialize all required mutex variables for GATT server implementation.
+ * Used to initialize all required mutex variables for GATT server implementation.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @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 CAInitGattServerMutexVariables();
/**
- * @brief Used to terminate all required mutex variables for GATT server implementation.
- * @return NONE
+ * Used to terminate all required mutex variables for GATT server implementation.
*/
void CATerminateGattServerMutexVariables();
/**
- * @brief Used to add new OIC service in GATT server using bt_gatt_add_service api and
- * internally store service path(outparam) in global variable.
+ * Used to add new OIC service in GATT server using bt_gatt_add_service api and
+ * internally store service path(outparam) in global variable.
*
- * @param serviceUUID [IN] unique identifier for BLE OIC service.
+ * @param[in] serviceUUID unique identifier for BLE OIC service.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @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 CAAddNewBleServiceInGattServer(const char *serviceUUID);
/**
- * @brief Used to remove already registered service from Gatt Server using
- * bt_gatt_remove_service api.
- * @param svcPath [IN] unique identifier for BLE OIC service which is outparam of
+ * Used to remove already registered service from Gatt Server using
+ * bt_gatt_remove_service api.
+ * @param[in] svcPath unique identifier for BLE OIC service which is outparam of
* bt_gatt_add_service api.
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @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 CARemoveBleServiceFromGattServer(const char *svcPath);
/**
- * @brief Used to remove all the registered service from Gatt Server using
- * bt_gatt_delete_services api.
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * Used to remove all the registered service from Gatt Server using
+ * bt_gatt_delete_services api.
+ * @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 CARemoveAllBleServicesFromGattServer();
/**
- * @brief Used to register the service in Gatt Server using bt_gatt_register_service api.
+ * Used to register the service in Gatt Server using bt_gatt_register_service api.
*
- * @param svcPath [IN] unique identifier for BLE OIC service which is outparam of
+ * @param[in] svcPath unique identifier for BLE OIC service which is outparam of
* bt_gatt_add_service api.
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @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 CARegisterBleServicewithGattServer(const char *svcPath);
/**
- * @brief Used to add new characteristics(Read/Write) to the service in Gatt Server using
- * bt_gatt_add_characteristic api.
- * @param svcPath [IN] Service path to which this characteristic belongs to.
- * @param charUUID [IN] Gatt characteristic uuid.
- * @param charValue [IN] Gatt characteristic value.
- * @param charValueLen [IN] Characteristic value length.
- * @param read [IN] Boolean variable for checking whether read characteristics or
+ * Used to add new characteristics(Read/Write) to the service in Gatt Server using
+ * bt_gatt_add_characteristic api.
+ * @param[in] svcPath Service path to which this characteristic belongs to.
+ * @param[in] charUUID Gatt characteristic uuid.
+ * @param[in] charValue Gatt characteristic value.
+ * @param[in] charValueLen Characteristic value length.
+ * @param[in] read Boolean variable for checking whether read characteristics or
* write characteristics.
- * @return #CA_STATUS_OK or Appropriate error code
+ * @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);
/**
- * @brief Used to remove characteristics(Read/Write) from the service in Gatt Server.
+ * Used to remove characteristics(Read/Write) from the service in Gatt Server.
*
- * @param charPath [IN] Characteristic path registered on the interface and unique identifier
+ * @param[in] charPath Characteristic path registered on the interface and unique identifier
* for added characteristics.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @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 CARemoveCharacteristicsFromGattServer(const char *charPath);
/**
- * @brief This is the callback which will be called when client update one of the characteristics
- * with data.
- * @param charPath [IN] characteristic path registered on the interface and unique
+ * This is the callback which will be called when client update one of the characteristics
+ * with data.
+ * @param[in] charPath characteristic path registered on the interface and unique
* identifier for added characteristics.
- * @param charValue [IN] data which is send by client.
- * @param charValueLen [IN] length of the data.
- * @param remoteAddress [IN] remote device bluetooth address in which data is received.
- * @param userData [IN] user data
- *
- * @return NONE
+ * @param[in] charValue data which is send by client.
+ * @param[in] charValueLen length of the data.
+ * @param[in] remoteAddress remote device bluetooth address in which data is received.
+ * @param[in] userData user data.
+
*/
void CABleGattRemoteCharacteristicWriteCb(char *charPath, unsigned char *charValue,
int charValueLen, const char *remoteAddress,
void *userData);
/**
- * @brief This is the callback which will be called whenever there is change in gatt connection
- * with Client(Connected/Disconnected).
+ * This is the callback which will be called whenever there is change in gatt connection
+ * with Client(Connected/Disconnected).
*
- * @param result [IN] The result of discovering.
- * @param connected [IN] State of connection.
- * @param remoteAddress [IN] Mac address of the remote device in which we made connection.
- * @param userData [IN] The user data passed from the request function.
- *
- * @return NONE
+ * @param[in] result The result of discovering.
+ * @param[in] connected State of connection.
+ * @param[in] remoteAddress Mac address of the remote device in which we made connection.
+ * @param[in] userData The user data passed from the request function.
+
*/
void CABleGattServerConnectionStateChangedCb(int result, bool connected,
const char *remoteAddress, void *userData);
/**
- * @brief Synchronous function for reading characteristic value.
+ * Synchronous function for reading characteristic value.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @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 CALEReadDataFromLEServer();
/**
- * @brief Used to enqueue the message into sender queue using CAAdapterEnqueueMessage and make
- * signal to the thread to process.
+ * Used to enqueue the message into sender queue using CAAdapterEnqueueMessage and make
+ * signal to the thread to process.
*
- * @param remoteEndpoint [IN] Remote device information.
- * @param data [IN] Data to be sent to remote device.
- * @param dataLen [IN] Length of data.
+ * @param[in] remoteEndpoint Remote device information.
+ * @param[in] data Data to be sent to remote device.
+ * @param[in] dataLen Length of data.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @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 CABleServerSenderQueueEnqueueMessage
- (const CAEndpoint_t *remoteEndpoint, const void *data, uint32_t dataLen);
+ (const CAEndpoint_t *remoteEndpoint, const uint8_t *data, uint32_t dataLen);
/**
- * @brief This is the thread which will be used for processing receiver queue.
- * @return NONE
+ * This is the thread which will be used for processing receiver queue.
*/
void *CABleServerSenderQueueProcessor();
/* ****************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************/
+ *
+ * Copyright 2014 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
/**
* @file
#include "cacommon.h"
/**
- * @struct BLEServiceInfo
- * @brief Information regarding the GATTServer
+ * Information regarding the GATTServer.
*
* This structure holds the infomation about the GATTServer
- * in the service and the characteristic level
+ * in the service and the characteristic level.
*/
typedef struct
{
} BLEServiceInfo;
/**
- * @struct BLEServiceList
- * @brief List of the BLEServiceInfo structures.
+ * List of the BLEServiceInfo structures.
*
* A list of BLEServiceInfo and gives the info about all the
* the registered services from the client side.
*/
typedef struct _BLEServiceList
{
- BLEServiceInfo *serviceInfo; /**< BLEServiceInfo structure from an OIC Server */
- struct _BLEServiceList *next; /**< Next reference to the List*/
+ BLEServiceInfo *serviceInfo; /**< BLEServiceInfo structure from an OIC Server. */
+ struct _BLEServiceList *next; /**< Next reference to the List. */
} BLEServiceList;
/**
- * @enum CHAR_TYPE
- * @brief Different characteristics types.
+ * Different characteristics types.
*
- * This provides information of different characteristics
- * which will be added to OIC service.
+ * This provides information of different characteristics
+ * which will be added to OIC service.
*/
typedef enum
{
- BLE_GATT_WRITE_CHAR = 0, /**< write_char This will be used to get the unicast response */
- BLE_GATT_READ_CHAR, /**< read_char This will be used update value to OIC server */
+ BLE_GATT_WRITE_CHAR = 0, /**< write_char This will be used to get the unicast response. */
+ BLE_GATT_READ_CHAR, /**< read_char This will be used update value to OIC server. */
BLE_GATT_NOTIFY_CHAR /**< Reserved char for the time being. */
} CHAR_TYPE;
/**
- * @struct stGattCharDescriptor_t
- * @brief Stores the information required to set the descriptor value of the Service.
+ * Stores the information required to set the descriptor value of the Service.
*/
typedef struct gattCharDescriptor
{
- bt_gatt_attribute_h characteristic; /**< The attribute handle of descriptor */
- uint8_t *desc; /**< Descriptor handle of characteristic, in byte array*/
- int total; /**< The total number of descriptor in a characteristic */
+ bt_gatt_attribute_h characteristic; /**< The attribute handle of descriptor. */
+ uint8_t *desc; /**< Descriptor handle of characteristic, in byte array. */
+ int total; /**< The total number of descriptor in a characteristic. */
} stGattCharDescriptor_t;
/**
- * @brief Used to increment the registered service count.
- * @return NONE
+ * Used to increment the registered service count.
*/
void CAIncrementRegisteredServiceCount();
/**
- * @brief Used to decrement the registered service count.
- *
- * @return NONE.
+ * Used to decrement the registered service count.
*/
void CADecrementRegisteredServiceCount();
/**
- * @brief Used to reset the registered service count.
- * @return NONE
+ * Used to reset the registered service count.
*/
void CAResetRegisteredServiceCount();
/**
- * @brief Used to get the total registered service count.
+ * Used to get the total registered service count.
* @return Total registered service count.
*/
int32_t CAGetRegisteredServiceCount();
/**
- * @brief Used to create BLEServiceInfo structure with server handler and BD address will be
- * created.
- * @param bdAddress [IN] BD address of the device where GATTServer is running.
- * @param service [IN] service attribute handler.
- * @param bleServiceInfo [IN] Pointer where serviceInfo structure needs to be stored.
- * Memory will be allocated here and needs to be cleared by caller.
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * Used to create BLEServiceInfo structure with server handler and BD address will be
+ * created.
+ * @param[in] bdAddress BD address of the device where GATTServer is running.
+ * @param[in] service service attribute handler.
+ * @param[in] bleServiceInfo Pointer where serviceInfo structure needs to be stored.
+ * Memory will be allocated here and needs to be cleared by caller.
+ * @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 CACreateBLEServiceInfo(const char *bdAddress, bt_gatt_attribute_h service,
BLEServiceInfo **bleServiceInfo);
/**
- * @brief Used to append the characteristic info to the already created serviceInfo structure.
+ * Used to append the characteristic info to the already created serviceInfo structure.
*
- * @param characteristic [IN] Charecteristic attribute handler.
- * @param type [IN] Specifies whether its BLE_GATT_READ_CHAR or BLE_GATT_WRITE_CHAR
- * @param bleServiceInfo [IN] Pointer where serviceInfo structure needs to be appended with
- * char info.
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @param[in] characteristic Charecteristic attribute handler.
+ * @param[in] type Specifies whether its BLE_GATT_READ_CHAR or BLE_GATT_WRITE_CHAR
+ * @param[in] bleServiceInfo Pointer where serviceInfo structure needs to be appended with
+ * char info.
+ * @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 CAAppendBLECharInfo(bt_gatt_attribute_h characteristic, CHAR_TYPE type,
BLEServiceInfo *bleServiceInfo);
/**
- * @brief Used to add the ServiceInfo structure to the Service List.
+ * Used to add the ServiceInfo structure to the Service List.
*
- * @param serviceList [IN] Pointer to the ble service list which holds the info of list of
- * service registered from client.
- * @param bleServiceInfo [IN] Pointer where serviceInfo structure needs to be appended with
- * char info.
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @param[in] serviceList Pointer to the ble service list which holds the info of list of
+ * service registered from client.
+ * @param[in] bleServiceInfo Pointer where serviceInfo structure needs to be appended with
+ * char info.
+ * @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 CAAddBLEServiceInfoToList(BLEServiceList **serviceList,
BLEServiceInfo *bleServiceInfo);
/**
- * @brief Used to remove the ServiceInfo structure from the Service List.
+ * Used to remove the ServiceInfo structure from the Service List.
*
- * @param serviceList [IN] Pointer to the ble service list which holds the info of list of
- * service registered from client.
- * @param bleServiceInfo [IN] Pointer where serviceInfo structure needs to be appended with
- * char info.
- * @param bdAddress [IN] BD address of the device where GATTServer is disconnected.
+ * @param[in] serviceList Pointer to the ble service list which holds the info of list of
+ * service registered from client.
+ * @param[in] bleServiceInfo Pointer where serviceInfo structure needs to be appended with
+ * char info.
+ * @param[in] bdAddress BD address of the device where GATTServer is disconnected.
*
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @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 CARemoveBLEServiceInfoToList(BLEServiceList **serviceList,
BLEServiceInfo *bleServiceInfo,
const char *bdAddress);
/**
- * @brief Used to get the serviceInfo from the list.
+ * Used to get the serviceInfo from the list.
*
- * @param serviceList [IN] Pointer to the ble service list which holds the info of list
- * of service registered from client.
- * @param bdAddress [IN] BD address of the device where GATTServer information is required.
- * @param bleServiceInfo [OUT] Pointer where serviceInfo structure needs to provide the service
- * and char info.
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @param[in] serviceList Pointer to the ble service list which holds the info of list
+ * of service registered from client.
+ * @param[in] bdAddress BD address of the device where GATTServer information is required.
+ * @param[out] bleServiceInfo Pointer where serviceInfo structure needs to provide the service
+ * and char info.
+ * @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 CAGetBLEServiceInfo(BLEServiceList *serviceList, const char *bdAddress,
BLEServiceInfo **bleServiceInfo);
/**
- * @brief Used to get the serviceInfo from the list by position.
+ * Used to get the serviceInfo from the list by position.
*
- * @param serviceList [IN] Pointer to the ble service list which holds the info of list
+ * @param[in] serviceList Pointer to the ble service list which holds the info of list
* of service registered from client.
- * @param position [IN] The service information of particular position in the list.
- * @param bleServiceInfo [OUT] Pointer where serviceInfo structure needs to provide the service
+ * @param[in] position The service information of particular position in the list.
+ * @param[out] bleServiceInfo Pointer where serviceInfo structure needs to provide the service
* and char info.
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @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 CAGetBLEServiceInfoByPosition(BLEServiceList *serviceList, int32_t position,
BLEServiceInfo **bleServiceInfo);
/**
- * @brief Used to clear BLE service list
+ * Used to clear BLE service list.
*
- * @param serviceList [IN] Pointer to the ble service list which holds the info of list of
- * service registered from client.
- * @return NONE
+ * @param[in] serviceList Pointer to the ble service list which holds the info of list of
+ * service registered from client.
*/
void CAFreeBLEServiceList(BLEServiceList *serviceList);
/**
- * @brief Used to get remove particular BLE service info from list
- * @param serviceinfo [IN] Pointer to the structure which needs to be cleared.
- *
- * @return NONE
+ * Used to get remove particular BLE service info from list.
+ * @param[in] serviceinfo Pointer to the structure which needs to be cleared.
*/
void CAFreeBLEServiceInfo(BLEServiceInfo *bleServiceInfo);
/**
- * @brief Used to check whether found handle is OIC service handle or not.
+ * Used to check whether found handle is OIC service handle or not.
*
- * @param serviceHandle [IN] Discovered service handle(unique identifier for service)
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @param[in] serviceHandle Discovered service handle(unique identifier for service).
+ * @return 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 CAVerifyOICServiceByServiceHandle(bt_gatt_attribute_h serviceHandle);
/**
- * @brief Used to check whether UUID of the discovered device is OIC service or not.
+ * Used to check whether UUID of the discovered device is OIC service or not.
*
- * @param serviceUUID [IN] Service UUID
- * @return #CA_STATUS_OK or Appropriate error code
- * @retval #CA_STATUS_OK Successful
- * @retval #CA_STATUS_INVALID_PARAM Invalid input argumets
- * @retval #CA_STATUS_FAILED Operation failed
+ * @param[in] serviceUUID Service UUID.
+ * @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 CAVerifyOICServiceByUUID(const char* serviceUUID);
/**
- * @brief Used to get the Error message.
- * @param err [IN] Error code(#bt_error_e)
+ * Used to get the Error message.
+ * @param[in] err Error code(::bt_error_e).
* @return Error string corresponding to the BT error code.
*/
const char *CABTGetErrorMsg(bt_error_e err);
}
// check if block option is set and get block data
- coap_block_t block = {0};
+ coap_block_t block = {0, 0, 0};
// get block1 option
int isBlock1 = coap_get_block(pdu, COAP_OPTION_BLOCK1, &block);
OIC_LOG(DEBUG, TAG, "allocate memory for the received block payload");
size_t totalPayloadLen = prePayloadLen + blockPayloadLen + 1;
- void *newPayload = realloc(currData->payload, totalPayloadLen);
+ CAPayload_t newPayload = OICRealloc(currData->payload, totalPayloadLen);
if (NULL == newPayload)
{
OIC_LOG(ERROR, TAG, "out of memory");
VERIFY_NON_NULL_RET(pdu->hdr, TAG, "pdu->hdr", NULL);
VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", NULL);
- CAInfo_t responseData = { 0 };
- responseData.token = (CAToken_t) OICMalloc(pdu->hdr->token_length);
+ CAInfo_t responseData = { .tokenLength = pdu->hdr->token_length };
+ responseData.token = (CAToken_t) OICMalloc(responseData.tokenLength);
if (NULL == responseData.token)
{
OIC_LOG(ERROR, TAG, "out of memory");
return NULL;
}
- memcpy(responseData.token, pdu->hdr->token, pdu->hdr->token_length);
- responseData.tokenLength = pdu->hdr->token_length;
+ memcpy(responseData.token, pdu->hdr->token, responseData.tokenLength);
+
CAResponseInfo_t* responseInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t));
if (NULL == responseInfo)
{
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;
}
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);
CAFreeEndpoint(data->remoteEndpoint);
CADestroyRequestInfoInternal(data->requestInfo);
CADestroyResponseInfoInternal(data->responseInfo);
- OICFree(data->options);
OICFree(data);
}
{
OIC_LOG(DEBUG, TAG, "CAGenerateToken");
- if(!g_isInitialized)
- {
- return CA_STATUS_NOT_INITIALIZED;
- }
return CAGenerateTokenInternal(token, tokenLength);
}
}
return CADetachResponseMessage(object, responseInfo);
-
}
CAResult_t CASendResponse(const CAEndpoint_t *object, const CAResponseInfo_t *responseInfo)
}
return CADetachResponseMessage(object, responseInfo);
-
}
CAResult_t CASelectNetwork(CATransportAdapter_t interestedNetwork)
}
#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
{
OIC_LOG(DEBUG, TAG, "IN");
u_arraylist_t *list = CAGetSelectedNetworkList();
-
if (!list)
{
OIC_LOG(DEBUG, TAG, "No selected network");
return CA_SEND_FAILED;
}
+ CATransportFlags_t requestedAdapter = endpoint->adapter ? endpoint->adapter : CA_ALL_ADAPTERS;
+
for (uint32_t i = 0; i < u_arraylist_length(list); i++)
{
void* ptrType = u_arraylist_get(list, i);
}
CATransportAdapter_t connType = *(CATransportAdapter_t *)ptrType;
+ if ((connType & requestedAdapter) == 0)
+ {
+ continue;
+ }
int index = CAGetAdapterIndex(connType);
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);
#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;
}
cadata->responseInfo = resInfo;
info = &resInfo->info;
+ if (identity)
+ {
+ info->identity = *identity;
+ }
OIC_LOG(DEBUG, TAG, "Response Info :");
CALogPayloadInfo(info);
}
return NULL;
}
- if (CADropSecondRequest(endpoint, reqInfo->info.messageId))
+ if (CADropSecondMessage(&caglobals.ca.requestHistory, endpoint, reqInfo->info.messageId))
{
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);
}
cadata->errorInfo = errorInfo;
info = &errorInfo->info;
+ if (identity)
+ {
+ info->identity = *identity;
+ }
OIC_LOG(DEBUG, TAG, "error Info :");
CALogPayloadInfo(info);
}
CADestroyErrorInfoInternal(cadata->errorInfo);
}
- OICFree(cadata->options);
OICFree(cadata);
OIC_LOG(DEBUG, TAG, "CADestroyData OUT");
}
OIC_LOG(DEBUG, TAG, "requestInfo is available..");
info = &data->requestInfo->info;
- pdu = CAGeneratePDU(data->requestInfo->method, info);
+ pdu = CAGeneratePDU(data->requestInfo->method, info, data->remoteEndpoint);
}
else if (NULL != data->responseInfo)
{
OIC_LOG(DEBUG, TAG, "responseInfo is available..");
info = &data->responseInfo->info;
- pdu = CAGeneratePDU(data->responseInfo->result, info);
+ pdu = CAGeneratePDU(data->responseInfo->result, info, data->remoteEndpoint);
}
else
{
OIC_LOG(DEBUG, TAG, "requestInfo is available..");
info = &data->requestInfo->info;
- pdu = CAGeneratePDU(CA_GET, info);
+ pdu = CAGeneratePDU(CA_GET, info, data->remoteEndpoint);
if (NULL != pdu)
{
#ifdef WITH_BWT
}
}
#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..");
- res = CASendMulticastData(data->remoteEndpoint, pdu->hdr, pdu->length);
- if (CA_STATUS_OK != res)
+ info = &data->responseInfo->info;
+ pdu = CAGeneratePDU(data->responseInfo->result, info, data->remoteEndpoint);
+
+ if (NULL != pdu)
+ {
+#ifdef WITH_BWT
+ if (CA_ADAPTER_GATT_BTLE != data->remoteEndpoint->adapter)
{
- 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);
+
+ 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;
}
/*
* If a second message arrives with the same 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)
{
- 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;
}
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)
{
- 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 (++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");
uint32_t code = CA_NOT_FOUND;
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!");
CAProcessReceivedData(cadata);
#else
#ifdef WITH_BWT
- if (CA_ADAPTER_GATT_BTLE != remoteEndpoint->adapter)
+ if (CA_ADAPTER_GATT_BTLE != sep->endpoint.adapter)
+ {
+ 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)
{
{
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,
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!");
return CA_MEMORY_ALLOC_FAILED;
}
}
- CAResult_t res = CA_STATUS_OK;
+ bool res = true;
switch (transportType)
{
case CA_ADAPTER_IP:
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");
return ret;
}
-coap_pdu_t *CAGeneratePDU(uint32_t code, const CAInfo_t *info)
+coap_pdu_t *CAGeneratePDU(uint32_t code, const CAInfo_t *info, const CAEndpoint_t *endpoint)
{
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, NULL, 0)))
+ if (!(pdu = CAGeneratePDUImpl((code_t) code, NULL, info, endpoint)))
{
OIC_LOG(ERROR, TAG, "pdu NULL");
return NULL;
coap_delete_list(optlist);
return NULL;
}
- pdu = CAGeneratePDUImpl((code_t) code, optlist, info, info->payload, info->payloadSize);
+
+ pdu = CAGeneratePDUImpl((code_t) code, optlist, info, endpoint);
if (NULL == pdu)
{
OIC_LOG(ERROR, TAG, "pdu NULL");
return NULL;
}
+ if (outpdu->hdr->version != COAP_DEFAULT_VERSION)
+ {
+ OIC_LOG_V(ERROR, TAG, "coap version is not available : %d",
+ outpdu->hdr->version);
+ coap_delete_pdu(outpdu);
+ return NULL;
+ }
+
+ if (outpdu->hdr->token_length > CA_MAX_TOKEN_LEN)
+ {
+ OIC_LOG_V(ERROR, TAG, "token length has been exceed : %d",
+ outpdu->hdr->token_length);
+ coap_delete_pdu(outpdu);
+ return NULL;
+ }
+
if (outCode)
{
(*outCode) = (uint32_t) CA_RESPONSE_CODE(outpdu->hdr->code);
}
coap_pdu_t *CAGeneratePDUImpl(code_t code, coap_list_t *options, const CAInfo_t *info,
- const uint8_t *payload, size_t payloadSize)
+ const CAEndpoint_t *endpoint)
{
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_pdu_t *pdu = coap_new_pdu();
}
}
+ bool enabledPayload = false;
#ifndef WITH_BWT
- if (NULL != payload)
+ enabledPayload = true;
+#endif
+
+ if (enabledPayload || CA_ADAPTER_GATT_BTLE == endpoint->adapter)
{
- coap_add_data(pdu, payloadSize, (const unsigned char *) payload);
+ if (NULL != info->payload && 0 < info->payloadSize)
+ {
+ OIC_LOG(DEBUG, TAG, "payload is added");
+ coap_add_data(pdu, info->payloadSize, (const unsigned char *) info->payload);
+ }
}
-#else
- (void)payload;
- (void)payloadSize;
-#endif
OIC_LOG(DEBUG, TAG, "OUT");
return pdu;
outInfo->payloadSize = dataSize;
}
- uint32_t length = strlen(optionResult);
- OIC_LOG_V(DEBUG, TAG, "URL length:%d", length);
-
- outInfo->resourceUri = OICMalloc(length + 1);
- if (!outInfo->resourceUri)
+ if (optionResult[0] != '\0')
{
- OIC_LOG(ERROR, TAG, "Out of memory");
- OICFree(outInfo->options);
- OICFree(outInfo->token);
- return CA_MEMORY_ALLOC_FAILED;
+ OIC_LOG_V(DEBUG, TAG, "URL length:%d", strlen(optionResult));
+ outInfo->resourceUri = OICStrdup(optionResult);
+ if (!outInfo->resourceUri)
+ {
+ OIC_LOG(ERROR, TAG, "Out of memory");
+ OICFree(outInfo->options);
+ OICFree(outInfo->token);
+ return CA_MEMORY_ALLOC_FAILED;
+ }
}
- OICStrcpy(outInfo->resourceUri, length + 1, optionResult);
- OIC_LOG_V(DEBUG, TAG, "made URL : %s, %s", optionResult, outInfo->resourceUri);
OIC_LOG(DEBUG, TAG, "OUT");
return CA_STATUS_OK;
memset(context, 0, sizeof(CARetransmission_t));
- CARetransmissionConfig_t cfg = { 0 };
+ CARetransmissionConfig_t cfg = { .supportType = DEFAULT_RETRANSMISSION_TYPE,
+ .tryingCount = DEFAULT_RETRANSMISSION_COUNT };
- if (NULL == config)
- {
- // setDefault
- cfg.supportType = DEFAULT_RETRANSMISSION_TYPE;
- cfg.tryingCount = DEFAULT_RETRANSMISSION_COUNT;
- }
- else
+ if (config)
{
cfg = *config;
}
#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;
+
+ 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++)
+ {
+ 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)
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);
+}
/* ****************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************/
+ *
+ * Copyright 2014 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
/**
* @file
#endif
/**
- * @brief Get available UDP socket
- * @param sockID [OUT] Available UDP socket ID
- * @return #CA_STATUS_OK or Appropriate error code
+ * Get available UDP socket.
+ * @param[out] sockID Available UDP socket ID.
+ * @return ::CA_STATUS_OK or Appropriate error code.
*/
CAResult_t CAArduinoGetAvailableSocket(int *sockID);
/**
- * @brief Initialize Unicast UDP socket
- * @param port [INOUT] Port to start the unicast server
- * @param socketID [OUT Unicast socket ID
- * @return #CA_STATUS_OK or Appropriate error code
+ * Initialize Unicast UDP socket.
+ * @param[in/out] port Port to start the unicast server.
+ * @param[out] socketID Unicast socket ID.
+ * @return ::CA_STATUS_OK or Appropriate error code.
*/
CAResult_t CAArduinoInitUdpSocket(uint16_t *port, int *socketID);
/**
- * @brief Initialize Multicast UDP socket
- * @param mcastAddress [IN] Port to start the unicast server
- * @param mport [IN] Multicast port
- * @param lport [IN] Local port on which the server is started
- * @param socketID [OUT] Multicast socket ID
- * @return #CA_STATUS_OK or Appropriate error code
+ * Initialize Multicast UDP socket.
+ * @param[in] mcastAddress Port to start the unicast server.
+ * @param[in] mport Multicast port.
+ * @param[in] lport Local port on which the server is started.
+ * @param[out] socketID Multicast socket ID.
+ * @return ::CA_STATUS_OK or Appropriate error code.
*/
CAResult_t CAArduinoInitMulticastUdpSocket(const char *mcastAddress,
uint16_t mport, uint16_t lport,
// 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;
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");
}
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");
*/
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);
+ }
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);
}
}
#endif
struct sockaddr_storage sa = { .ss_family = family };
+ socklen_t socklen;
+
if (family == AF_INET6)
{
int on = 1;
OIC_LOG_V(ERROR, TAG, "IPV6_V6ONLY failed: %s", strerror(errno));
}
((struct sockaddr_in6 *)&sa)->sin6_port = htons(*port);
+ socklen = sizeof (struct sockaddr_in6);
}
else
{
((struct sockaddr_in *)&sa)->sin_port = htons(*port);
+ socklen = sizeof (struct sockaddr_in);
}
if (*port) // use the given port
}
}
- if (-1 == bind(fd, (struct sockaddr *)&sa, sizeof(sa)))
+ if (-1 == bind(fd, (struct sockaddr *)&sa, socklen))
{
OIC_LOG_V(ERROR, TAG, "bind socket failed: %s", strerror(errno));
close(fd);
if (!*port) // return the assigned port
{
- struct sockaddr_storage sa;
- socklen_t socklen = sizeof (sa);
if (-1 == getsockname(fd, (struct sockaddr *)&sa, &socklen))
{
OIC_LOG_V(ERROR, TAG, "getsockname failed: %s", strerror(errno));
NEWSOCKET(AF_INET6, u6s)
NEWSOCKET(AF_INET6, m6)
NEWSOCKET(AF_INET6, m6s)
+ OIC_LOG_V(INFO, TAG, "IPv6 unicast port: %u", caglobals.ip.u6.port);
}
if (caglobals.ip.ipv4enabled)
{
NEWSOCKET(AF_INET, u4s)
NEWSOCKET(AF_INET, m4)
NEWSOCKET(AF_INET, m4s)
+ OIC_LOG_V(INFO, TAG, "IPv4 unicast port: %u", caglobals.ip.u4.port);
}
OIC_LOG_V(DEBUG, TAG,
// 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 };
-
-int 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)
+ 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 };
+
+ 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)
+ {
+ continue;
+ }
+
struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh);
- if ((ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING))
+ if (!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING))
{
continue;
}
return;
}
- uint32_t len = u_arraylist_length(iflist);
- for (uint32_t i = 0; i < len; i++)
+ 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)
continue;
}
- applyMulticastToInterface6(newIndex);
- struct in_addr inaddr;
- inaddr.s_addr = ifitem->ipv4addr;
- applyMulticastToInterface4(inaddr);
- break; // we found the one we were looking for
+ 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.
}
else
{
+ if (!endpoint->port) // unicast discovery
+ {
+ endpoint->port = isSecure ? CA_SECURE_COAP : CA_COAP;
+ }
+
int fd;
- if (endpoint->flags & CA_IPV6)
+ if (caglobals.ip.ipv6enabled && (endpoint->flags & CA_IPV6))
{
fd = isSecure ? caglobals.ip.u6s.fd : caglobals.ip.u6.fd;
#ifndef __WITH_DTLS__
#endif
sendData(fd, endpoint, data, datalen, "unicast", "ipv6");
}
- if (endpoint->flags & CA_IPV4)
+ if (caglobals.ip.ipv4enabled && (endpoint->flags & CA_IPV4))
{
fd = isSecure ? caglobals.ip.u4s.fd : caglobals.ip.u4.fd;
#ifndef __WITH_DTLS__
#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)
+ {
+ OIC_LOG_V(ERROR, TAG, "invalid index : %d", desiredIndex);
+ return NULL;
+ }
+
u_arraylist_t *iflist = u_arraylist_create();
if (!iflist)
{
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");
+}
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])
CAResult_t checkGetNetworkInfo();
CAResult_t checkSelectNetwork();
-void request_handler(const CAEndpoint_t *object, const CARequestInfo_t *requestInfo)
+void request_handler(const CAEndpoint_t * /*object*/,
+ const CARequestInfo_t * /*requestInfo*/)
{
}
-void response_handler(const CAEndpoint_t *object, const CAResponseInfo_t *responseInfo)
+void response_handler(const CAEndpoint_t * /*object*/,
+ const CAResponseInfo_t * /*responseInfo*/)
{
}
EXPECT_EQ(CA_STATUS_OK, ca_thread_pool_init(3, &mythreadpool));
- _func1_struct pData = {};
+ _func1_struct pData = {0, false, false};
pData.mutex = ca_mutex_new();
--- /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->size, list->length);
+ u_arraylist_shrink_to_fit(list);
+ EXPECT_EQ(list->size, 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));
+ }
+}
if (min && sec && ms)
{
#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
- struct timespec when = {};
+ struct timespec when = {0};
clockid_t clk = CLOCK_REALTIME;
#ifdef CLOCK_REALTIME_COARSE
clk = CLOCK_REALTIME_COARSE;
######################################################################
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')
--- /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
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 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
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;
};
/**
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, PCF(#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, PCF(#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.
+
'../../ocmalloc/include',
'include',
'include/internal',
+ 'include/oxm',
'../../resource/csdk/security/include',
'../../../../extlibs/cjson/',
- '../../../../../extlibs/tinydtlsra/',
+ '../../../../../extlibs/tinydtls/',
'../../connectivity/inc',
'../../connectivity/external/inc',
'../../connectivity/common/inc',
+ '../../connectivity/lib/libcoap-4.1.1',
'../../connectivity/api',
'../include',
'../include/internal'
# 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' ]
+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 tempCredId;\r
+}OTMContext_t;\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] selectedDeviceInfo selected device information\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* selectedDeviceInfo, 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_
\ 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 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 SP_SUCCESS 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);
+#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
+ * 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 OCProvisionInit(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
+ * API to delete memory allocated to linked list created by OCDiscover_XXX_Devices API.\r
+ *\r
+ * @param[in] ppList Pointer to OCProvisionDev_t which should be deleted.\r
+ */\r
+void OCDeleteDiscoveredDevices(OCProvisionDev_t **ppList);\r
+\r
+/**\r
+ * API to delete memory allocated to OCProvisionResult_t list in callback function.\r
+ *\r
+ * @note: This function must be called in the callback implementation after checking results.\r
+ *\r
+ * @param[in] pList Pointer to OCProvisionResult_t list which should be deleted.\r
+ */\r
+void OCDeleteProvisionResults(OCProvisionResult_t *pList);\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
+
+/**
+ * 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 **/
+ 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
\ 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 _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 DeleteDeviceList(OCProvisionDev_t **pList);
+
+
+/**
+ * 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);
+
+#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(RPATH = [env.get('BUILD_DIR')])
provisioning_env.AppendUnique(LIBS = ['-lpthread'])
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"
+ ],
+ "perms": 2,
+ "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+ },
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/sec/doxm",
+ "/oic/sec/pstat",
+ "/oic/sec/acl",
+ "/oic/sec/cred"
+ ],
+ "perms": 7,
+ "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+ }
+ ],
+ "pstat": {
+ "isop": true,
+ "deviceid": "YWRtaW5EZXZpY2VVVUlEMA==",
+ "ch": 0,
+ "cm": 0,
+ "tm": 0,
+ "om": 3,
+ "sm": [3]
+ },
+ "doxm": {
+ "oxm": [0],
+ "oxmsel": 0,
+ "owned": true,
+ "deviceid": "YWRtaW5EZXZpY2VVVUlEMA==",
+ "ownr": "YWRtaW5EZXZpY2VVVUlEMA=="
+ }
+}
--- /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,
+ "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,
+ "owned": false,
+ "deviceid": "cmFuZG9tUGluRGV2VVVJRA=="
+ }
+}
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-#include <getopt.h>
+
#include "logger.h"
#include "oic_malloc.h"
#include "utlist.h"
-#include "securevirtualresourcetypes.h"
-#include "provisioningmanager.h"
+#include "ocprovisioningmanager.h"
+#include "secureresourceprovider.h"
+#include "oxmjustworks.h"
+#include "oxmrandompin.h"
+#include "pinoxmcommon.h"
+#include "oic_string.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 PREDEFINED_TIMEOUT (10)
+#define MAX_OWNED_DEVICE (10)
#define TAG "provisioningclient"
-static OicSecAcl_t *gAcl = NULL;
-static char PROV_TOOL_DB_FILE[] = "oic_svr_db_prov_tool.json";
+static char CRED_FILE[] = "oic_svr_db_client.json";
+static OicSecAcl_t *gAcl1 = NULL;
+static OicSecAcl_t *gAcl2 = NULL;
+static int gOwnershipState = 0;
+
+typedef enum
+{
+ ownershipDone = 1 << 1,
+ finalizeDone = 1 << 2,
+ provisionCredDone = 1 << 3,
+ provisionAclDone = 1 << 4
+} StateManager;
+
/**
- * Perform cleanup for ACL list
- *
- * @param[in] ACL list
+ * Perform cleanup for ACL
+ * @param[in] ACL
*/
-static void DeleteACLList(OicSecAcl_t *acl)
+static void deleteACL(OicSecAcl_t *acl)
{
if (acl)
{
- OicSecAcl_t *aclTmp1 = NULL;
- OicSecAcl_t *aclTmp2 = NULL;
- LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
+ /* Clean Resources */
+ for (size_t i = 0; i < (acl)->resourcesLen; i++)
{
- LL_DELETE(acl, aclTmp1);
+ OICFree((acl)->resources[i]);
+ }
+ OICFree((acl)->resources);
- /* Clean Resources */
- for (int i = 0; i < aclTmp1->resourcesLen; i++)
- {
- OICFree(aclTmp1->resources[i]);
- }
- OICFree(aclTmp1->resources);
+ /* Clean Owners */
+ OICFree((acl)->owners);
- /* Clean Owners */
- OICFree(aclTmp1->owners);
+ /* Clean ACL node itself */
+ OICFree((acl));
- /* Clean ACL node itself */
- OICFree(aclTmp1);
- }
acl = NULL;
}
}
*
* @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
+ * @return 0 on success otherwise -1.
*/
-static SPResult CalculateAclPermission(const char *temp_pms, uint16_t *pms)
+static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
{
int i = 0;
if (NULL == temp_pms || NULL == pms)
{
- return SP_RESULT_INVALID_PARAM;
+ return -1;
}
*pms = 0;
while (temp_pms[i] != '\0')
}
default:
{
- return SP_RESULT_INVALID_PARAM;
+ return -1;
}
}
}
- return SP_RESULT_SUCCESS;
+ return 0;
}
/**
* 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
+ * @return 0 on success otherwise -1.
*/
-static SPResult InputACL(OicSecAcl_t *acl)
+static int InputACL(OicSecAcl_t *acl)
{
- int unused __attribute__((unused));
- char temp_id [MAX_INPUT_ID_LENGTH + 4] = {0,};
+ int ret;
+ char temp_id [UUID_LENGTH + 4] = {0,};
char temp_rsc[MAX_URI_LENGTH + 1] = {0,};
char temp_pms[MAX_PERMISSION_LENGTH + 1] = {0,};
printf("******************************************************************************\n");
printf("-URN identifying the subject\n");
printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
printf("Subject : ");
- unused = scanf("%19s", temp_id);
+ char *ptr = NULL;
+ ret = scanf("%19ms", &ptr);
+ if(1==ret)
+ {
+ OICStrcpy(temp_id, sizeof(temp_id), ptr);
+ OICFree(ptr);
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
int j = 0;
for (int i = 0; temp_id[i] != '\0'; i++)
{
if (DASH != temp_id[i])
+ {
+ if(j>UUID_LENGTH)
+ {
+ printf("Invalid input\n");
+ return -1;
+ }
acl->subject.id[j++] = temp_id[i];
+ }
}
//Set Resource.
- printf("Num. of Resource : ");
- unused = scanf("%zu", &acl->resourcesLen);
+ printf("Num. of Resource : \n");
+ 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 **)OICMalloc(acl->resourcesLen * sizeof(char *));
+ acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
if (NULL == acl->resources)
{
OC_LOG(ERROR, TAG, "Error while memory allocation");
- return SP_RESULT_MEM_ALLOCATION_FAIL;
+ return -1;
}
- for (int i = 0; i < acl->resourcesLen; i++)
+ for (size_t 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));
+ printf("[%zu]Resource : ", i + 1);
+ char *ptr_tempRsc = NULL;
+ ret = scanf("%64ms", &ptr_tempRsc);
+ if (1==ret)
+ {
+ OICStrcpy(temp_rsc, sizeof(temp_rsc), ptr_tempRsc);
+ OICFree(ptr_tempRsc);
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+ acl->resources[i] = OICStrdup(temp_rsc);
+
if (NULL == acl->resources[i])
{
OC_LOG(ERROR, TAG, "Error while memory allocation");
- return SP_RESULT_MEM_ALLOCATION_FAIL;
+ return -1;
}
- 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);
+ char *ptr_temp_pms = NULL;
+ ret = scanf("%5ms", &ptr_temp_pms);
+ if(1 == ret)
+ {
+ OICStrcpy(temp_pms, sizeof(temp_pms), ptr_temp_pms);
+ OICFree(ptr_temp_pms);
+
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
}
- while (SP_RESULT_SUCCESS != CalculateAclPermission(temp_pms, &(acl->permission)) );
+ while (0 != CalculateAclPermission(temp_pms, &(acl->permission)) );
// Set Rowner
printf("Num. of Rowner : ");
- unused = scanf("%zu", &acl->ownersLen);
+ 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 SP_RESULT_MEM_ALLOCATION_FAIL;
+ return -1;
}
- for (int i = 0; i < acl->ownersLen; i++)
+ for (size_t i = 0; i < acl->ownersLen; i++)
{
- printf("[%d]Rowner : ", i + 1);
- unused = scanf("%19s", temp_id);
+ printf("[%zu]Rowner : ", i + 1);
+ char *ptr_temp_id = NULL;
+ ret = scanf("%19ms", &ptr_temp_id);
+ if (1 == ret)
+ {
+ OICStrcpy(temp_id, sizeof(temp_id), ptr_temp_id);
+ OICFree(ptr_temp_id);
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
j = 0;
for (int k = 0; temp_id[k] != '\0'; k++)
{
}
}
}
- return SP_RESULT_SUCCESS;
+ return 0;
+}
+
+
+//FILE *client_fopen(const char *path, const char *mode)
+FILE *client_fopen(const char* UNUSED_PARAM , const char *mode)
+{
+ (void)UNUSED_PARAM;
+ return fopen(CRED_FILE, mode);
+}
+
+void PrintfResult(const char* procName, void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ printf("-----------------------------------------------------------\n");
+ if(!hasError)
+ {
+ printf("%s was successfully done.\n", procName);
+ }
+ else
+ {
+ for(int i = 0; i < nOfRes; i++)
+ {
+ printf("UUID : ");
+ for(int j = 0; j < UUID_LENGTH; i++)
+ {
+ printf("%c", arr[i].deviceId.id[j]);
+ }
+ printf("\t");
+ printf("Result=%d\n", arr[i].res);
+ }
+ }
+
+ if(ctx)
+ {
+ printf("Context is %s\n", (char*)ctx);
+ }
+ printf("-----------------------------------------------------------\n");
+}
+
+void ProvisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ if(!hasError)
+ {
+ gOwnershipState = 1;
+ PrintfResult("Provision Credential", ctx, nOfRes, arr, hasError);
+ }
+}
+
+void ProvisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ if(!hasError)
+ {
+ gOwnershipState = 1;
+ PrintfResult("Provision ACL", ctx, nOfRes, arr, hasError);
+ }
}
-FILE* client_fopen(const char *path, const char *mode)
+void ProvisionPairwiseCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
{
- (void)path;
- return fopen(PROV_TOOL_DB_FILE, mode);
+ if(!hasError)
+ {
+ gOwnershipState = 1;
+ PrintfResult("Provision Pairwise Credential", ctx, nOfRes, arr, hasError);
+ }
+}
+
+void OwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ if(!hasError)
+ {
+ gOwnershipState = 1;
+ PrintfResult("Ownership transfer", ctx, nOfRes, arr, hasError);
+ }
+}
+
+void InputPinCB(char* pinBuf, size_t bufSize)
+{
+ if(pinBuf)
+ {
+ printf("INPUT PIN : ");
+ char *ptr = NULL;
+ int ret = scanf("%ms", &ptr);
+ if(1 == ret)
+ {
+ OICStrcpy(pinBuf, bufSize, ptr);
+ OICFree(ptr);
+ }
+ else
+ {
+ printf("Error in input\n");
+ return;
+ }
+ }
}
/**
- * Provisioning client sample using ProvisioningAPI on provisioningmanager.c
- * To change network type use command line option -w for Wifi and -e for Ethernet
+ * Provisioning client sample using ProvisioningAPI
*/
-int main(int argc, char **argv)
+int main()
{
- SPResult res = SP_RESULT_SUCCESS;
- SPTargetDeviceInfo_t *pDeviceList = NULL;
- gAcl = (OicSecAcl_t *)OICMalloc(sizeof(OicSecAcl_t));
+ OCStackResult res = OC_STACK_OK;
+ int unused;
+ (void)unused;
// Initialize Persistent Storage for SVR database
- OCPersistentStorage ps = {};
+ OCPersistentStorage ps = { .open = NULL,
+ .read = NULL,
+ .write = NULL,
+ .close = NULL,
+ .unlink = NULL };
ps.open = client_fopen;
ps.read = fread;
ps.write = fwrite;
ps.unlink = unlink;
OCRegisterPersistentStorageHandler(&ps);
- if (OCInit(NULL, 0, OC_CLIENT_SERVER) != OC_STACK_OK)
+ if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
{
OC_LOG(ERROR, TAG, "OCStack init error");
- return 0;
+ goto error;
}
- if (NULL == gAcl)
+ OCProvisionDev_t* pDeviceList = NULL;
+ res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
+ if(OC_STACK_OK != res)
{
- OC_LOG(ERROR, TAG, "Error while memory allocation");
- return SP_RESULT_MEM_ALLOCATION_FAIL;
+ OC_LOG_V(ERROR, TAG, "Failed to PMDeviceDiscovery : %d", res);
+ goto error;
+ }
+
+ OCProvisionDev_t* pCurDev = pDeviceList;
+ int i;
+ while(pCurDev !=NULL)
+ {
+ for(i = 0; i < UUID_LENGTH; i++)
+ printf("%c", pCurDev->doxm->deviceID.id[i]);
+ printf("\n");
+ pCurDev = pCurDev->next;
+ }
+
+ //Register callback function to each OxM
+ OTMCallbackData_t justWorksCBData = {.loadSecretCB=NULL,
+ .createSecureSessionCB=NULL,
+ .createSelectOxmPayloadCB=NULL,
+ .createOwnerTransferPayloadCB=NULL};
+ justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+ justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+ justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+ justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+ OTMSetOwnershipTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData);
+
+ OTMCallbackData_t pinBasedCBData = {.loadSecretCB=NULL,
+ .createSecureSessionCB=NULL,
+ .createSelectOxmPayloadCB=NULL,
+ .createOwnerTransferPayloadCB=NULL};
+ pinBasedCBData.loadSecretCB = InputPinCodeCallback;
+ pinBasedCBData.createSecureSessionCB = CreateSecureSessionRandomPinCallbak;
+ pinBasedCBData.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
+ pinBasedCBData.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
+ OTMSetOwnershipTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &pinBasedCBData);
+
+ SetInputPinCB(&InputPinCB);
+
+ char* myContext = "OTM Context";
+ //Perform ownership transfer
+ res = OCDoOwnershipTransfer((void*)myContext, pDeviceList, OwnershipTransferCB);
+ if(OC_STACK_OK == res)
+ {
+ OC_LOG(INFO, TAG, "Request for ownership transfer is sent successfully.");
+ }
+ else
+ {
+ OC_LOG_V(ERROR, TAG, "Failed to OCDoOwnershipTransfer : %d", res);
+ }
+
+ gOwnershipState = 0;
+ while ( gOwnershipState == 0 )
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+ sleep(1);
}
- res = SPProvisioningDiscovery(PREDEFINED_TIMEOUT, &pDeviceList);
- if (SP_RESULT_SUCCESS == res)
+// Credential & ACL provisioning between two devices.
+
+ OCProvisionDev_t *pOwnedList = NULL;
+ OCProvisionDev_t *pOwnedDevices [MAX_OWNED_DEVICE] = {0,};
+ int nOwnedDevice = 0;
+
+ res = OCDiscoverOwnedDevices(PREDEFINED_TIMEOUT, &pOwnedList);
+ if (OC_STACK_OK == res)
{
- while (pDeviceList != NULL)
+ printf("################## Owned Device List #######################\n");
+ while (pOwnedList != NULL)
{
- printf("-Provisioning device ID : ");
- for (int i = 0; i < MAX_INPUT_ID_LENGTH; i++)
+ nOwnedDevice ++;
+ printf(" %d : ", nOwnedDevice);
+ for (int i = 0; i < UUID_LENGTH; i++)
{
- if (pDeviceList->doxm->deviceID.id[i] == '\0')
- {
- break;
- }
- printf("%c", pDeviceList->doxm->deviceID.id[i]);
+ printf("%c", pOwnedList->doxm->deviceID.id[i]);
}
printf("\n");
- res = SPInitProvisionContext(PREDEFINED_TIMEOUT, pDeviceList);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Error while init provisioning Context");
- goto error;
- }
- res = InputACL(gAcl);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Error while user ACL input ");
- goto error;
- }
- res = SPProvisionACL(PREDEFINED_TIMEOUT, pDeviceList, gAcl);
- if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Error while provisioning ACL");
- goto error;
- }
- res = SPFinalizeProvisioning(PREDEFINED_TIMEOUT, pDeviceList);
- if (SP_RESULT_SUCCESS == res)
- {
- printf("Provisioning Success~!!\n");
- }
- else if (SP_RESULT_SUCCESS != res)
- {
- OC_LOG(ERROR, TAG, "Error while Finalize Provisioning");
- goto error;
- }
- pDeviceList = pDeviceList->next;
+ pOwnedDevices[nOwnedDevice] = pOwnedList;
+ pOwnedList = pOwnedList->next;
}
}
else
{
- OC_LOG(ERROR, TAG, "Error while Provisioning Discovery");
+ OC_LOG(ERROR, TAG, "Error while Owned Device Discovery");
+ }
+
+ int Device1 = 0;
+ int Device2 = 0;
+
+ printf("Select 2 devices for Credential & ACL provisioning\n");
+ printf("Device 1: ");
+ unused = scanf("%d", &Device1);
+ printf("Device 2: ");
+ unused = scanf("%d", &Device2);
+
+
+ gAcl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+ if (NULL == gAcl1)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ goto error;
+ }
+
+ gAcl2 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+ if (NULL == gAcl2)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ goto error;
+ }
+
+ printf("Input ACL for Device1\n");
+ if ( 0 == InputACL(gAcl1))
+ {
+ printf("Success Input ACL\n");
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "InputACL error");
+ goto error;
+ }
+
+ printf("Input ACL for Device2\n");
+ if (0 == InputACL(gAcl2))
+ {
+ printf("Success Input ACL\n");
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "InputACL error");
+ goto error;
+ }
+ char *ctx = "DUMMY";
+ OCProvisionPairwiseDevices(ctx,SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128, pOwnedDevices[Device1],
+ gAcl1, pOwnedDevices[Device2], gAcl2, ProvisionPairwiseCB);
+
+ gOwnershipState = 0;
+ while ( gOwnershipState == 0 )
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+ sleep(1);
+ }
+
+ if (OCStop() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
goto error;
}
error:
- DeleteACLList(gAcl);
- SPTerminateProvisioning();
+ deleteACL(gAcl1);
+ deleteACL(gAcl2);
+ OCDeleteDiscoveredDevices(&pDeviceList);
+ OCDeleteDiscoveredDevices(&pOwnedList);
+
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"
+
+#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, PCF("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, PCF("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, PCF("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, PCF("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, PCF(#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, PCF(#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"
+
+#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 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 **ppList)
+{
+ DeleteDeviceList(ppList);
+}
+
+/**
+ * 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);
+
+}
+
+/**
+ * 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;
+
+}
--- /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"
+
+// TODO: Not yet supported.
+//#include "oxmrandompin.h"
+
+#define DEFAULT_CONTEXT_VALUE 0x99
+#define DEFAULT_SECURE_PORT 5684
+
+#define TAG "OTM"
+
+OCProvisionResultCB g_resultCallback;
+OCProvisionResult_t* g_resultArray = NULL;
+size_t g_resultArraySize = 0;
+bool g_hasError = false;
+
+/**
+ * Possible states of ownership transfer manager module.
+ */
+typedef enum
+{
+ SP_NO_MASK = (0 ),
+ SP_DISCOVERY_STARTED = (0x1 << 1),
+ SP_DISCOVERY_ERROR = (0x1 << 2),
+ SP_DISCOVERY_DONE = (0x1 << 3),
+ SP_UP_OWN_TR_METH_STARTED = (0x1 << 4),
+ SP_UP_OWN_TR_METH_ERROR = (0x1 << 5),
+ SP_UP_OWN_TR_METH_DONE = (0x1 << 6),
+ SP_LIST_METHODS_STARTED = (0x1 << 7),
+ SP_LIST_METHODS_ERROR = (0x1 << 8),
+ SP_LIST_METHODS_DONE = (0x1 << 9),
+ SP_UPDATE_OP_MODE_STARTED = (0x1 << 10),
+ SP_UPDATE_OP_MODE_ERROR = (0x1 << 11),
+ SP_UPDATE_OP_MODE_DONE = (0x1 << 12),
+ SP_UPDATE_OWNER_STARTED = (0x1 << 13),
+ SP_UPDATE_OWNER_ERROR = (0x1 << 14),
+ SP_UPDATE_OWNER_DONE = (0x1 << 15)
+} OTMStates;
+
+
+
+/**
+ * Array to store the callbacks for each owner transfer method.
+ */
+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 SP_SUCCESS 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 SP_SUCCESS 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()
+{
+ for(size_t i = 0; i < g_resultArraySize; i++)
+ {
+ if(OC_STACK_CONTINUE == g_resultArray[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 < g_resultArraySize; i++)
+ {
+ if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
+ g_resultArray[i].deviceId.id, UUID_LENGTH) == 0)
+ {
+ g_resultArray[i].res = res;
+ if(OC_STACK_OK != res)
+ {
+ g_hasError = true;
+ }
+ }
+ }
+
+ //If all request is completed, invoke the user callback.
+ if(IsComplete())
+ {
+ g_resultCallback(otmCtx->userCtx, g_resultArraySize, g_resultArray, g_hasError);
+ }
+ else
+ {
+ if(OC_STACK_OK != StartOwnershipTransfer(otmCtx->userCtx,
+ otmCtx->selectedDeviceInfo->next))
+ {
+ OC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
+ }
+ }
+ }
+
+ OC_LOG(DEBUG, TAG, "OUT SetResult");
+
+ OICFree(otmCtx);
+}
+
+
+/**
+ * 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->tempCredId);
+ 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, "Invailed 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, "DeviceDiscoveryHandler : 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, "DeviceDiscoveryHandler : 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, "DeviceDiscoveryHandler : 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, "DeviceDiscoveryHandler : 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*)OICMalloc(sizeof(OTMContext_t));
+ if(!otmCtx)
+ {
+ OC_LOG(ERROR, TAG, "Failed to create OTM Context");
+ return OC_STACK_NO_MEMORY;
+ }
+ otmCtx->userCtx = 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;
+ }
+
+ g_resultCallback = resultCallback;
+ g_hasError = false;
+
+ OCProvisionDev_t* pCurDev = selectedDevicelist;
+
+ //Counting number of selected devices.
+ g_resultArraySize = 0;
+ while(NULL != pCurDev)
+ {
+ g_resultArraySize++;
+ pCurDev = pCurDev->next;
+ }
+
+ if(g_resultArray)
+ {
+ OICFree(g_resultArray);
+ }
+ g_resultArray =
+ (OCProvisionResult_t*)OICMalloc(sizeof(OCProvisionResult_t) * g_resultArraySize);
+ if(NULL == g_resultArray)
+ {
+ OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ pCurDev = selectedDevicelist;
+ //Fill the device UUID for result array.
+ for(size_t devIdx = 0; devIdx < g_resultArraySize; devIdx++)
+ {
+ memcpy(g_resultArray[devIdx].deviceId.id,
+ pCurDev->doxm->deviceID.id,
+ UUID_LENGTH);
+ g_resultArray[devIdx].res = OC_STACK_CONTINUE;
+ pCurDev = pCurDev->next;
+ }
+
+ StartOwnershipTransfer(ctx, selectedDevicelist);
+
+ OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
+
+ return (g_hasError ? OC_STACK_ERROR : 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)
+ {
+ SetResult(otmCtx, OC_STACK_OK);
+ }
+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, "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 = &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, "DeviceDiscoveryHandler : 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->tempCredId);
+ 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"
+
+#define TAG ("PM-UTILITY")
+
+/**
+ * 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;
+
+ 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] pList List of OCProvisionDev_t.
+ */
+void DeleteDeviceList(OCProvisionDev_t **ppDevicesList)
+{
+ if(*ppDevicesList)
+ {
+ OCProvisionDev_t *del = NULL, *tmp = NULL;
+ LL_FOREACH_SAFE(*ppDevicesList, del, tmp)
+ {
+ LL_DELETE(*ppDevicesList, del);
+
+ DeleteDoxmBinData(del->doxm);
+ DeletePstatBinData(del->pstat);
+ OICFree(del);
+ }
+ }
+}
+
+/**
+ * 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.
+ * @return OC_STACK_OK on success otherwise error.
+ */
+OCStackResult PMTimeout(unsigned short waittime)
+{
+ 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;
+ }
+ 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, ERROR, "Unknown address format.");
+ return false;
+ }
+ if(snRet >= bufferSize)
+ {
+ OC_LOG(ERROR, INFO, "PMGenerateQuery : URI is too long");
+ 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, ERROR, "Not supported connectivity adapter.");
+ return false;
+ break;
+ default:
+ OC_LOG(ERROR, ERROR, "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;
+ }
+
+ OCProvisionDev_t** ppDevicesList = (OCProvisionDev_t**) ctx;
+
+ 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.");
+
+ OCProvisionDev_t **ppDevicesList = (OCProvisionDev_t**) ctx;
+
+ OCStackResult 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_ERROR;
+ }
+ 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_GET, 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_DELETE_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";
+
+ OCCallbackData cbData;
+ cbData.cb = &DeviceDiscoveryHandler;
+ cbData.context = (void *)ppDevicesList;
+ 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);
+ 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:
+ 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.
- *
- * *****************************************************************/
-
-// 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"
+
+#define SRP_MAX_URI_LENGTH 512
+#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.**/
+};
+
+/**
+ * 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);
+ ((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;
+}
'../../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(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'])
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 "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 **ppList, const char* addr, const uint16_t port,
+ OCTransportAdapter adapter, 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, pDoxm);
+ EXPECT_TRUE(OC_STACK_OK == res);
+ EXPECT_TRUE(NULL != gList);
+
+ LL_FOREACH(gList,el){ ++cnt; };
+ //LL_COUNT(gList, el, cnt);
+ EXPECT_TRUE(1 == cnt);
+
+ // Same node must not be inserted
+ res = AddDevice(&gList, "10.20.30.40", 5684, OC_ADAPTER_IP, pDoxm);
+ EXPECT_TRUE(OC_STACK_OK == res);
+ EXPECT_TRUE(NULL != gList);
+
+ cnt = 0;
+ LL_FOREACH(gList,el){ ++cnt; };
+ //LL_COUNT(gList, el, cnt);
+ EXPECT_TRUE(1 == cnt);
+
+ // Differnet node must be inserted
+ res = AddDevice(&gList, "110.120.130.140", 6789, OC_DEFAULT_ADAPTER, pDoxm);
+ EXPECT_TRUE(OC_STACK_OK == res);
+ EXPECT_TRUE(NULL != gList);
+
+ cnt = 0;
+ LL_FOREACH(gList,el){ ++cnt; };
+ //LL_COUNT(gList, el, cnt);
+ EXPECT_TRUE(2 == cnt);
+}
+
+// List Delete Tests
+TEST(ProvisionListTest, Deletion)
+{
+ OCProvisionDev_t* el = NULL;
+ int cnt =0;
+
+ // Delete whole
+ DeleteDeviceList(&gList);
+ gList = NULL;
+
+ LL_FOREACH(gList,el){ ++cnt; };
+ //LL_COUNT(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 "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));
+}
\ No newline at end of file
#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")
-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, PCF("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)
{
- OicSecAcl_t *aclTmp1 = NULL, *aclTmp2 = NULL;
+ OicSecAcl_t *aclTmp1 = NULL;
+ OicSecAcl_t *aclTmp2 = NULL;
LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
{
- int i = 0;
-
LL_DELETE(acl, aclTmp1);
-
- // Clean Resources
- for (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);
}
}
}
cJSON *jsonRsrcArray = NULL;
cJSON_AddItemToObject (jsonAcl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray = cJSON_CreateArray());
VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);
- for (int i = 0; i < acl->resourcesLen; i++)
+ for (size_t i = 0; i < acl->resourcesLen; i++)
{
cJSON_AddItemToArray (jsonRsrcArray, cJSON_CreateString(acl->resources[i]));
}
// 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());
VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
- for (int i = 0; i < acl->ownersLen; i++)
+ for (size_t i = 0; i < acl->ownersLen; i++)
{
outLen = 0;
acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
- int idxx = 0;
+ size_t idxx = 0;
do
{
cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx);
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, PCF("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, PCF("%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)
+ {
+ 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;
+}
+
static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest)
{
// Convert ACL data into JSON for transmission
// 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;
}
}
return ehRet;
}
+static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest)
+{
+ OC_LOG (INFO, TAG, PCF("Processing ACLDeleteRequest"));
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+ if(NULL == ehRequest->query)
+ {
+ return ehRet;
+ }
+ OicParseQueryIter_t parseIter = {.attrPos=NULL};
+ OicUuid_t subject = {.id={0}};
+ char * resource = NULL;
+
+ //Parsing REST query to get subject & resource
+ 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(strncasecmp((char *)parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen) == 0)
+ {
+ resource = (char *)OICMalloc(parseIter.valLen);
+ VERIFY_NON_NULL(TAG, resource, ERROR);
+ OICStrcpy(resource, sizeof(resource), (char *)parseIter.valPos);
+ }
+ }
+
+ if(OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
+ {
+ ehRet = OC_EH_RESOURCE_DELETED;
+ }
+ OICFree(resource);
+
+ // Send payload to request originator
+ SendSRMResponse(ehRequest, ehRet, NULL);
+
+exit:
+ return ehRet;
+}
+
/*
* This internal method is the entity handler for ACL resources and
* will handle REST request (GET/PUT/POST/DEL) for them.
OCEntityHandlerRequest * ehRequest,
void* callbackParameter)
{
+ OC_LOG(INFO, TAG, PCF("Received request ACLEntityHandler"));
+ (void)callbackParameter;
OCEntityHandlerResult ehRet = OC_EH_ERROR;
if (!ehRequest)
ehRet = HandleACLPostRequest(ehRequest);
break;
+ case OC_REST_DELETE:
+ ehRet = HandleACLDeleteRequest(ehRequest);
+ break;
+
default:
ehRet = OC_EH_ERROR;
SendSRMResponse(ehRequest, ehRet, NULL);
{
OCStackResult ret = OC_STACK_ERROR;
- OicUuid_t ownerId = {};
+ OicUuid_t ownerId = {.id = {0}};
/*
* TODO In future, when new virtual resources will be added in OIC
acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
- for (int i = 0; i < acl->resourcesLen; i++)
+ for (size_t i = 0; i < acl->resourcesLen; i++)
{
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 PCF("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, PCF("%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, PCF("%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, PCF("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, PCF("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 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, PCF("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(credTmp1->privateData.data);
+ //Clean PrivateData
+ OICFree(cred->privateData.data);
- //Clean Period
- OICFree(credTmp1->period);
+ //Clean Period
+ OICFree(cred->period);
- //Clean Owners
- OICFree(credTmp1->owners);
+ //Clean Owners
+ OICFree(cred->owners);
- //Clean Cred node itself
- OICFree(credTmp1);
+ //Clean Cred node itself
+ OICFree(cred);
+}
+
+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);
}
}
}
//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));
const char * publicData, const char * privateData,
size_t ownersLen, const OicUuid_t * owners)
{
+ (void)publicData;
OCStackResult ret = OC_STACK_ERROR;
OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_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;
+}
- if((jsonCred) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
+OCStackResult RemoveCredential(const OicUuid_t *subject)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ OicSecCred_t *cred = NULL;
+ OicSecCred_t *tempCred = NULL;
+ bool deleteFlag = false;
+
+ 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_V (INFO, TAG, PCF("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)
OCEntityHandlerRequest * ehRequest,
void* callbackParameter)
{
+ (void)callbackParameter;
OCEntityHandlerResult ret = OC_EH_ERROR;
if(!ehRequest)
case OC_REST_POST:
ret = HandlePostRequest(ehRequest);
break;
+ case OC_REST_DELETE:
+ ret = HandleDeleteRequest(ehRequest);
+ break;
default:
ret = OC_EH_ERROR;
break;
{
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>
1, /* size_t oxmLen */
OIC_JUST_WORKS, /* uint16_t oxmSel */
false, /* bool owned */
- {}, /* OicUuid_t deviceID */
- {}, /* OicUuid_t owner */
+ {.id = {0}}, /* OicUuid_t deviceID */
+ {.id = {0}}, /* OicUuid_t owner */
};
void DeleteDoxmBinData(OicSecDoxm_t* doxm)
if (doxm)
{
//Clean oxmType
- for(int i = 0; i < doxm->oxmTypeLen; i++)
+ for (size_t i = 0; i < doxm->oxmTypeLen; i++)
{
OICFree(doxm->oxmType[i]);
}
doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(char *));
VERIFY_NON_NULL(TAG, (doxm->oxmType), ERROR);
- for(int i = 0; i < doxm->oxmTypeLen ; i++)
+ for (size_t i = 0; i < doxm->oxmTypeLen ; i++)
{
cJSON *jsonOxmTy = cJSON_GetArrayItem(jsonObj, i);
VERIFY_NON_NULL(TAG, jsonOxmTy, ERROR);
doxm->oxm = (OicSecOxm_t*)OICCalloc(doxm->oxmLen, sizeof(OicSecOxm_t));
VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
- for(int i = 0; i < doxm->oxmLen ; i++)
+ for (size_t i = 0; i < doxm->oxmLen ; i++)
{
cJSON *jsonOxm = cJSON_GetArrayItem(jsonObj, i);
VERIFY_NON_NULL(TAG, jsonOxm, ERROR);
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
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 false;
}
- OicParseQueryIter_t parseIter = {};
+ OicParseQueryIter_t parseIter = {.attrPos = NULL};
ParseQueryIterInit(query, &parseIter);
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, PCF("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"));
OCEntityHandlerResult ehRet = OC_EH_ERROR;
- OicUuid_t emptyOwner = {};
+ OicUuid_t emptyOwner = {.id = {0}};
/*
* Convert JSON Doxm data into binary. This will also validate
*
*/
#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);
-
- //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, 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);
+ //Generate new credential for provisioning tool
+ ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm,
+ (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS));
- gDoxm->owned = true;
- memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
+ VERIFY_SUCCESS(TAG, ehRet = OC_EH_OK, 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:
OCEntityHandlerRequest * ehRequest,
void* callbackParam)
{
+ (void)callbackParam;
OCEntityHandlerResult ehRet = OC_EH_ERROR;
if(NULL == ehRequest)
* 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++)
{
- OCFillRandomMem(gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id));
- UpdatePersistentStorage(gDoxm);
+ if (gDoxm->deviceID.id[i] != 0)
+ {
+ validId = true;
+ break;
+ }
}
+
+ if (!validId)
+ {
+ if (OCGenerateUuid(gDoxm->deviceID.id) != RAND_UUID_OK)
+ {
+ OC_LOG(FATAL, TAG, PCF("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, PCF("UpdatePersistentStorage failed!"));
+ }
+ }
+ else
+ {
+ ret = OC_STACK_OK;
+ }
+ return ret;
}
/**
{
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, PCF("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 PCF("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")
}
/**
- * 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, PCF("Access request is in allowed time period"));
return true;
}
}
+ OC_LOG(INFO, TAG, PCF("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.
OC_LOG(INFO, TAG, PCF("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;
+ }
}
}
}
{
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, 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!! "));
}
}
PROVISION_CREDENTIALS | PROVISION_ACLS), // OicSecDpm_t cm
(OicSecDpm_t)(TAKE_OWNER | BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES |
PROVISION_CREDENTIALS | PROVISION_ACLS), // OicSecDpm_t tm
- {}, // OicUuid_t deviceID
+ {.id = {0}}, // OicUuid_t deviceID
SINGLE_SERVICE_CLIENT_DRIVEN, // OicSecDpom_t om */
1, // the number of elts in Sms
&gSm, // OicSecDpom_t *sm
cJSON_AddItemToObject(jsonPstat, OIC_JSON_SM_NAME, jsonSmArray = cJSON_CreateArray());
VERIFY_NON_NULL(TAG, jsonSmArray, INFO);
- for (int i = 0; i < pstat->smLen; i++)
+ for (size_t i = 0; i < pstat->smLen; i++)
{
cJSON_AddItemToArray(jsonSmArray, cJSON_CreateNumber((int )pstat->sm[i]));
}
if (cJSON_Array == jsonObj->type)
{
pstat->smLen = cJSON_GetArraySize(jsonObj);
- int idxx = 0;
+ size_t idxx = 0;
VERIFY_SUCCESS(TAG, pstat->smLen != 0, ERROR);
pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
VERIFY_NON_NULL(TAG, pstat->sm, ERROR);
*/
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;
OCEntityHandlerRequest * ehRequest,
void *callbackParam)
{
+ (void)callbackParam;
OCEntityHandlerResult ehRet = OC_EH_ERROR;
// This method will handle REST request (GET/POST) for /oic/sec/pstat
if (flag & OC_REQUEST_FLAG)
#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"
OCEntityHandlerResult ehRet, const char *rspPayload)
{
OC_LOG (INFO, TAG, PCF("SRM sending SRM response"));
- OCEntityHandlerResponse response = {};
+ OCEntityHandlerResponse response = {.requestHandle = NULL};
if (ehRequest)
{
- OCSecurityPayload ocPayload = {};
+ OCSecurityPayload ocPayload = {.base = {.type = PAYLOAD_TYPE_INVALID}};
response.requestHandle = ehRequest->requestHandle;
response.resourceHandle = ehRequest->resource;
{
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
}
// Copy the subjectID
- OicUuid_t subjectId = {};
- memcpy(subjectId.id, endPoint->identity.id, sizeof(subjectId.id));
+ OicUuid_t subjectId = {.id = {0}};
+ 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, "?");
}
// Form a 'access deny' or 'Error' response and send to peer
- CAResponseInfo_t responseInfo = {};
+ CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
memcpy(&responseInfo.info, &(requestInfo->info), sizeof(responseInfo.info));
responseInfo.info.payload = NULL;
if (!gRequestHandler)
OCPersistentStorage* SRMGetPersistentStorageHandler()
{
- OC_LOG(INFO, TAG, PCF("SRMGetPersistentStorageHandler !!"));
return gPersistentStorageHandler;
}
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";
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")
(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
}
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 PCF("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, PCF("%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, PCF("%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, PCF("Unable to instantiate SVC resource"));
+ DeInitSVCResource();
+ }
+ return ret;
+}
+
+
+OCStackResult InitSVCResource()
+{
+ OCStackResult ret = OC_STACK_ERROR;
+
+ OC_LOG_V (INFO, TAG, PCF("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, PCF("%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 PCF("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
OICFree(jsonStr);
}
}
+//'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);
+
+ //ACE to POST
+ memcpy(acl.subject.id, "2222222222222222", sizeof(acl.subject.id));
+ acl.resourcesLen = 1;
+ 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");
+ 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));
+
+ //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);
+
+ memcpy(acl.subject.id, "2222222222222222", sizeof(acl.subject.id));
+ acl.resourcesLen = 2;
+ 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");
+ 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));
+
+ 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);
+}
#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")
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->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");
+ 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;
}
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, PCF("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 = {};
+ 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 = {};
+ 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 PCF("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));
TEST(DoxmEntityHandlerTest, DoxmEntityHandlerValidRequest)
{
EXPECT_EQ(OC_STACK_INVALID_PARAM, InitDoxmResource());
- char query[] = "oxm=0&owned=false&owner=owner1";
- OCEntityHandlerRequest req = {};
+ 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));
OicSecDoxm_t * doxm = getBinDoxm();
char * json = BinToDoxmJSON(doxm);
+ OC_LOG_V(INFO, TAG, PCF("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 PCF("CALENDAR-UT")
+
+static void printPeriod(IotvtICalPeriod_t *period)
+{
+ if(NULL == period)
+ {
+ return;
+ }
+
+ OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_year = %d"),period->startDateTime.tm_year);
+ OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_mon = %d"),period->startDateTime.tm_mon);
+ OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_mday = %d"),period->startDateTime.tm_mday);
+ OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_hour = %d"),period->startDateTime.tm_hour);
+ OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_min = %d"),period->startDateTime.tm_min);
+ OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_sec = %d"),period->startDateTime.tm_sec);
+
+ OC_LOG_V(INFO, TAG, PCF("period->endDateTime.tm_year = %d"),period->endDateTime.tm_year);
+ OC_LOG_V(INFO, TAG, PCF("period->endDateTime.tm_mon = %d"),period->endDateTime.tm_mon);
+ OC_LOG_V(INFO, TAG, PCF("period->endDateTime.tm_mday = %d"),period->endDateTime.tm_mday);
+ OC_LOG_V(INFO, TAG, PCF("period->endDateTime.tm_hour = %d"),period->endDateTime.tm_hour);
+ OC_LOG_V(INFO, TAG, PCF("period->endDateTime.tm_min = %d"),period->endDateTime.tm_min);
+ OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_sec = %d"),period->endDateTime.tm_sec);
+}
+
+
+static void printRecur(IotvtICalRecur_t *recur)
+{
+ OC_LOG_V(INFO, TAG, PCF("recur->freq = %d"), recur->freq);
+ OC_LOG_V(INFO, TAG, PCF("recur->until.tm_year = %d"), recur->until.tm_year);
+ OC_LOG_V(INFO, TAG, PCF("recur->until.tm_mon = %d"), recur->until.tm_mon);
+ OC_LOG_V(INFO, TAG, PCF("recur->until.tm_mday = %d"), recur->until.tm_mday);
+
+ if(recur->byDay & SUNDAY)
+ {
+ OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Sunday");
+ }
+ if(recur->byDay & MONDAY)
+ {
+ OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Monday");
+ }
+ if(recur->byDay & TUESDAY)
+ {
+ OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Tuesday");
+ }
+ if(recur->byDay & WEDNESDAY)
+ {
+ OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Wednesday");
+ }
+ if(recur->byDay & THURSDAY)
+ {
+ OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Thursday");
+ }
+ if(recur->byDay & FRIDAY)
+ {
+ OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Friday");
+ }
+ if(recur->byDay & SATURDAY)
+ {
+ OC_LOG_V(INFO, TAG, PCF("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, PCF("t1 = %02d:%02d:%02d"), t1.tm_hour, t1.tm_min, t1.tm_sec );
+ OC_LOG_V(INFO, TAG, PCF("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
"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
}
using namespace std;
// Helper Methods
-void UTRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requestInfo)
+void UTRequestHandler(const CAEndpoint_t * /*endPoint*/,
+ const CARequestInfo_t * /*requestInfo*/)
{
EXPECT_TRUE(true) << "UTRequestHandler\n";
}
-void UTResponseHandler(const CAEndpoint_t *endPoint, const CAResponseInfo_t *responseInfo)
+void UTResponseHandler(const CAEndpoint_t * /*endPoint*/,
+ const CAResponseInfo_t * /*responseInfo*/)
{
EXPECT_TRUE(true) << "UTResponseHandler\n";
}
-void UTErrorHandler(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo)
+void UTErrorHandler(const CAEndpoint_t * /*endPoint*/,
+ const CAErrorInfo_t * /*errorInfo*/)
{
EXPECT_TRUE(true) << "UTErrorHandler\n";
}
--- /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 = {};
+ 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 = {};
+ 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 = {};
+ OicParseQueryIter_t parseIter = OicParseQueryIter_t();
ParseQueryIterInit(query, &parseIter);
printf("\n");
while(GetNextQuery(&parseIter))
}
printf("\n");
}
-
--- /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);
+ }
+}
+
#include "cacommon.h"
#include "cainterface.h"
+#include "securevirtualresourcetypes.h"
#ifdef __cplusplus
extern "C" {
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;
*
* @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);
typedef struct OCResource OCResource;
-#ifdef TB_LOG
- #define OC_LOG_PAYLOAD(level, tag, payload) OCPayloadLog((level),(tag),(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)
-{
- OC_LOG(level, tag, PCF("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:"));
- OCStringLL* strll = rep->types;
- while(strll)
- {
- OC_LOG_V(level, tag, "\t\t%s", strll->value);
- strll = strll->next;
- }
- OC_LOG(level, tag, PCF("\tInterfaces:"));
- strll = rep->interfaces;
- while(strll)
- {
- OC_LOG_V(level, tag, "\t\t%s", strll->value);
- strll = strll->next;
- }
-
- // TODO Finish Logging: Values
- OCRepPayloadValue* val = rep->values;
-
- OC_LOG(level, tag, PCF("\tValues:"));
-
- while(val)
- {
- switch(val->type)
- {
- case OCREP_PROP_NULL:
- OC_LOG_V(level, 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);
- break;
- case OCREP_PROP_DOUBLE:
- OC_LOG_V(level, 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");
- break;
- case OCREP_PROP_STRING:
- OC_LOG_V(level, 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);
- 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",
- 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",
- 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",
- 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",
- 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",
- 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!",
- val->name);
- break;
- }
- break;
- default:
- OC_LOG_V(ERROR, tag, "\t\t%s <-- Unknown type!", val->name);
- break;
- }
- val = val -> next;
- }
-
- ++i;
- rep = rep->next;
- }
-
-}
-
-static inline void OCPayloadLogDiscovery(LogLevel level, const char* tag,
- OCDiscoveryPayload* payload)
-{
- OC_LOG(level, tag, PCF("Payload Type: Discovery"));
- int i = 1;
-
- if(!payload->resources)
- {
- OC_LOG(level, tag, PCF("\tNO Resources"));
- return;
- }
-
- OCResourcePayload* res = payload->resources;
-
- 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:"));
- OCStringLL* strll = res->types;
- while(strll)
- {
- OC_LOG_V(level, tag, "\t\t%s", strll->value);
- strll = strll->next;
- }
- OC_LOG(level, tag, PCF("\tInterfaces:"));
- strll = res->interfaces;
- while(strll)
- {
- OC_LOG_V(level, 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(""));
- res = res->next;
- ++i;
- }
-}
-
-static inline void OCPayloadLogDevice(LogLevel level, const char* tag, 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);
-}
-
-static inline void OCPayloadLogPlatform(LogLevel level, const char* tag, 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);
-}
-
-static inline void OCPayloadLogPresence(LogLevel level, const char* tag, 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);
-}
-
-static inline void OCPayloadLogSecurity(LogLevel level, const char* tag,
- OCSecurityPayload* payload)
-{
- OC_LOG(level, tag, PCF("Payload Type: Security"));
- OC_LOG_V(level, tag, "\tSecurity Data: %s", payload->securityData);
-}
-
-static inline void OCPayloadLog(LogLevel level, const char* tag, OCPayload* payload)
-{
- if(!payload)
- {
- OC_LOG(level, tag, PCF("NULL Payload"));
- return;
- }
- switch(payload->type)
- {
- case PAYLOAD_TYPE_REPRESENTATION:
- OCPayloadLogRep(level, tag, (OCRepPayload*)payload);
- break;
- case PAYLOAD_TYPE_DISCOVERY:
- OCPayloadLogDiscovery(level, tag, (OCDiscoveryPayload*)payload);
- break;
- case PAYLOAD_TYPE_DEVICE:
- OCPayloadLogDevice(level, tag, (OCDevicePayload*)payload);
- break;
- case PAYLOAD_TYPE_PLATFORM:
- OCPayloadLogPlatform(level, tag, (OCPlatformPayload*)payload);
- break;
- case PAYLOAD_TYPE_PRESENCE:
- OCPayloadLogPresence(level, tag, (OCPresencePayload*)payload);
- break;
- case PAYLOAD_TYPE_SECURITY:
- OCPayloadLogSecurity(level, tag, (OCSecurityPayload*)payload);
- break;
- default:
- OC_LOG_V(level, tag, "Unknown Payload Type: %d", payload->type);
- break;
- }
-}
-#else
- #define OC_LOG_PAYLOAD(level, tag, payload)
-#endif
-
void OCPayloadDestroy(OCPayload* payload);
// Representation Payload
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);
/** 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;
} OCDevAddr;
/**
/** 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;
--- /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 PAYLOAD_LOGGING_H_
+#define PAYLOAD_LOGGING_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef TB_LOG
+ #define OC_LOG_PAYLOAD(level, tag, payload) OCPayloadLog((level),(tag),(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)
+{
+ OC_LOG(level, tag, PCF("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:"));
+ OCStringLL* strll = rep->types;
+ while(strll)
+ {
+ OC_LOG_V(level, tag, "\t\t%s", strll->value);
+ strll = strll->next;
+ }
+ OC_LOG(level, tag, PCF("\tInterfaces:"));
+ strll = rep->interfaces;
+ while(strll)
+ {
+ OC_LOG_V(level, tag, "\t\t%s", strll->value);
+ strll = strll->next;
+ }
+
+ // TODO Finish Logging: Values
+ OCRepPayloadValue* val = rep->values;
+
+ OC_LOG(level, tag, PCF("\tValues:"));
+
+ while(val)
+ {
+ switch(val->type)
+ {
+ case OCREP_PROP_NULL:
+ OC_LOG_V(level, 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);
+ break;
+ case OCREP_PROP_DOUBLE:
+ OC_LOG_V(level, 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");
+ break;
+ case OCREP_PROP_STRING:
+ OC_LOG_V(level, 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);
+ 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",
+ 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",
+ 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",
+ 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",
+ 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",
+ 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!",
+ val->name);
+ break;
+ }
+ break;
+ default:
+ OC_LOG_V(ERROR, tag, "\t\t%s <-- Unknown type!", val->name);
+ break;
+ }
+ val = val -> next;
+ }
+
+ ++i;
+ rep = rep->next;
+ }
+
+}
+
+static inline void OCPayloadLogDiscovery(LogLevel level, const char* tag,
+ OCDiscoveryPayload* payload)
+{
+ OC_LOG(level, tag, PCF("Payload Type: Discovery"));
+ int i = 1;
+
+ if(!payload->resources)
+ {
+ OC_LOG(level, tag, PCF("\tNO Resources"));
+ return;
+ }
+
+ OCResourcePayload* res = payload->resources;
+
+ 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:"));
+ OCStringLL* strll = res->types;
+ while(strll)
+ {
+ OC_LOG_V(level, tag, "\t\t%s", strll->value);
+ strll = strll->next;
+ }
+ OC_LOG(level, tag, PCF("\tInterfaces:"));
+ strll = res->interfaces;
+ while(strll)
+ {
+ OC_LOG_V(level, 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(""));
+ res = res->next;
+ ++i;
+ }
+}
+
+static inline void OCPayloadLogDevice(LogLevel level, const char* tag, 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);
+}
+
+static inline void OCPayloadLogPlatform(LogLevel level, const char* tag, 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);
+}
+
+static inline void OCPayloadLogPresence(LogLevel level, const char* tag, 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);
+}
+
+static inline void OCPayloadLogSecurity(LogLevel level, const char* tag,
+ OCSecurityPayload* payload)
+{
+ OC_LOG(level, tag, PCF("Payload Type: Security"));
+ OC_LOG_V(level, tag, "\tSecurity Data: %s", payload->securityData);
+}
+
+static inline void OCPayloadLog(LogLevel level, const char* tag, OCPayload* payload)
+{
+ if(!payload)
+ {
+ OC_LOG(level, tag, PCF("NULL Payload"));
+ return;
+ }
+ switch(payload->type)
+ {
+ case PAYLOAD_TYPE_REPRESENTATION:
+ OCPayloadLogRep(level, tag, (OCRepPayload*)payload);
+ break;
+ case PAYLOAD_TYPE_DISCOVERY:
+ OCPayloadLogDiscovery(level, tag, (OCDiscoveryPayload*)payload);
+ break;
+ case PAYLOAD_TYPE_DEVICE:
+ OCPayloadLogDevice(level, tag, (OCDevicePayload*)payload);
+ break;
+ case PAYLOAD_TYPE_PLATFORM:
+ OCPayloadLogPlatform(level, tag, (OCPlatformPayload*)payload);
+ break;
+ case PAYLOAD_TYPE_PRESENCE:
+ OCPayloadLogPresence(level, tag, (OCPresencePayload*)payload);
+ break;
+ case PAYLOAD_TYPE_SECURITY:
+ OCPayloadLogSecurity(level, tag, (OCSecurityPayload*)payload);
+ break;
+ default:
+ OC_LOG_V(level, tag, "Unknown Payload Type: %d", payload->type);
+ break;
+ }
+}
+#else
+ #define OC_LOG_PAYLOAD(level, tag, payload)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
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
#include "logger.h"
#include "occlient.h"
#include "ocpayload.h"
+#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 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)
{
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)
{
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);
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)
{
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);
}
OCStackApplicationResult deleteReqCB(void *ctx,
- OCDoHandle handle, OCClientResponse *clientResponse)
+ 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);
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)
{
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_PAYLOAD(INFO, TAG, clientResponse->payload);
OC_LOG(INFO, TAG, PCF("=============> 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 );
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)
{
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);
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;
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)
{
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);
#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)
{
clientResponse->devAddr.port);
OC_LOG_PAYLOAD(INFO, TAG, 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_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_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)
+ if (Connectivity == CT_ADAPTER_DEFAULT || Connectivity == CT_IP)
{
- OC_CONNTYPE = CT_ADAPTER_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);
}
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);
}
-
#include "logger.h"
#include "occlientbasicops.h"
#include "ocpayload.h"
+#include "payload_logging.h"
#include "oic_malloc.h"
#include "oic_string.h"
#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)
{
return ret;
}
-OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle,
- OCClientResponse * clientResponse)
+OCStackApplicationResult putReqCB(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
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)
{
return OC_STACK_DELETE_TRANSACTION;
}
-OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle,
- OCClientResponse * clientResponse)
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
{
/*
* 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)
{
{
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 <iostream>
#include <sstream>
#include "ocpayload.h"
+#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")
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;
"unavailable resource using link list interface.");
}
-OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+OCStackApplicationResult putReqCB(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
if(clientResponse == NULL)
{
return OC_STACK_KEEP_TRANSACTION;
}
-OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
OC_LOG_V(INFO, TAG, "StackResult: %s",
getResult(clientResponse->result));
}
}
}
- 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)
+OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
{
OC_LOG(INFO, TAG,
"Entering discoveryReqCB (Application Layer CB)");
clientResponse->devAddr.port);
OC_LOG_PAYLOAD(INFO, TAG, 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_PAYLOAD(INFO, TAG, 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_PAYLOAD(INFO, TAG, 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 "occlientslow.h"
#include "oic_string.h"
#include "ocpayload.h"
+#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)
{
}
// 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)
clientResponse->devAddr.addr, clientResponse->devAddr.port);
OC_LOG_PAYLOAD (INFO, TAG, 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);
-}
-
#include "ocstack.h"
#include "logger.h"
#include "ocpayload.h"
+#include "payload_logging.h"
#include "ocremoteaccessclient.h"
// Tracking user input
return ehResult;
}
-OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest * /*ehRequest*/)
{
OC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
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
-OCNOPEntityHandlerCb (OCEntityHandlerFlag flag,
- OCEntityHandlerRequest *entityHandlerRequest, void* callbackParam)
+OCNOPEntityHandlerCb (OCEntityHandlerFlag /*flag*/,
+ OCEntityHandlerRequest * /*entityHandlerRequest*/,
+ void* /*callbackParam*/)
{
// This is callback is associated with the 2 presence notification
// resources. They are non-operational.
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)
OCEntityHandlerResult
OCEntityHandlerCb (OCEntityHandlerFlag flag,
- OCEntityHandlerRequest *entityHandlerRequest,void* callbackParam)
+ OCEntityHandlerRequest *entityHandlerRequest,
+ 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)
}
}
-int main(int argc, char* argv[])
+int main(int /*argc*/, char* /*argv*/[])
{
OC_LOG(DEBUG, TAG, "OCServer is starting...");
if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
//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;
#include "cJSON.h"
#include "ocserverslow.h"
#include "ocpayload.h"
+#include "payload_logging.h"
volatile sig_atomic_t gQuitFlag = 0;
}
OCEntityHandlerResult OCEntityHandlerCb (OCEntityHandlerFlag flag,
- OCEntityHandlerRequest *entityHandlerRequest, void* callbackParam)
+ OCEntityHandlerRequest *entityHandlerRequest, void* /*callbackParam*/)
{
OCEntityHandlerResult result = OC_EH_ERROR;
OCEntityHandlerRequest *request = NULL;
}
}
-int main(int argc, char* argv[])
+int main(int /*argc*/, char** /*argv[]*/)
{
OC_LOG(DEBUG, TAG, "OCServer is starting...");
#include "logger.h"
#include "occlientbasicops.h"
#include "ocpayload.h"
+#include "payload_logging.h"
#include "oic_string.h"
#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");
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");
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");
}
// 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");
OC_LOG_PAYLOAD(INFO, TAG, 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=="]
"/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=="]
}
],
"oxmsel": 0,
"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=="]
}]
}
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 extlibs/cjson/cJSON.h %{DEST_INC_DIR}
cp -rf %{ROOTDIR}/com.oic.ri.pc %{DEST_LIB_DIR}/pkgconfig/
#include "oic_malloc.h"
#include "oic_string.h"
#include "ocpayload.h"
+#include "payload_logging.h"
/// Module Name
#include <stdio.h>
}
static OCStackResult
-HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, uint8_t filterOn, char *filterValue)
+HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest,
+ uint8_t filterOn,
+ char *filterValue)
{
+ (void)filterOn;
+ (void)filterValue;
if(!ehRequest)
{
return OC_STACK_INVALID_PARAM;
if(ret == OC_STACK_OK)
{
- OCEntityHandlerResponse response = {};
+ OCEntityHandlerResponse response = {0};
response.ehResult = OC_EH_OK;
response.payload = (OCPayload*)payload;
response.persistentBufferFlag = 0;
if(stackRet == OC_STACK_OK)
{
- OCEntityHandlerResponse response = {};
+ OCEntityHandlerResponse response = {0};
response.ehResult = OC_EH_OK;
response.payload = (OCPayload*)payload;
response.persistentBufferFlag = 0;
return HandleBatchInterface(ehRequest);
case STACK_IF_GROUP:
- return BuildCollectionGroupActionJSONResponse(OC_REST_GET/*flag*/,
+ return BuildCollectionGroupActionCBORResponse(OC_REST_GET/*flag*/,
(OCResource *) ehRequest->resource, ehRequest);
default:
return OC_STACK_ERROR;
{
OC_LOG(INFO, TAG, PCF("IF_COLLECTION PUT with request ::\n"));
OC_LOG_PAYLOAD(INFO, TAG, ehRequest->payload);
- return BuildCollectionGroupActionJSONResponse(OC_REST_PUT/*flag*/,
+ return BuildCollectionGroupActionCBORResponse(OC_REST_PUT/*flag*/,
(OCResource *) ehRequest->resource, ehRequest);
}
default:
{
OC_LOG(INFO, TAG, PCF("IF_COLLECTION POST with request ::\n"));
OC_LOG_PAYLOAD(INFO, TAG, ehRequest->payload);
- return BuildCollectionGroupActionJSONResponse(OC_REST_POST/*flag*/,
+ return BuildCollectionGroupActionCBORResponse(OC_REST_POST/*flag*/,
(OCResource *) ehRequest->resource, ehRequest);
}
default:
{
OC_LOG(INFO, TAG, PCF("IF_COLLECTION POST with request ::\n"));
OC_LOG_PAYLOAD(INFO, TAG, ehRequest->payload);
- return BuildCollectionGroupActionJSONResponse(OC_REST_POST/*flag*/,
+ return BuildCollectionGroupActionCBORResponse(OC_REST_POST/*flag*/,
(OCResource *) ehRequest->resource, ehRequest);
}
else
ResourceObserver * resourceObserver = serverObsList;
uint8_t numObs = 0;
OCServerRequest * request = NULL;
- OCEntityHandlerRequest ehRequest = {};
+ OCEntityHandlerRequest ehRequest = {0};
OCEntityHandlerResult ehResult = OC_EH_ERROR;
bool observeErrorFlag = false;
}
else
{
- OCEntityHandlerResponse ehResponse = {};
+ OCEntityHandlerResponse ehResponse = {0};
//This is effectively the implementation for the presence entity handler.
OC_LOG(DEBUG, TAG, PCF("This notification is for Presence"));
uint32_t maxAge,
OCQualityOfService qos)
{
+ (void)maxAge;
if(!resource || !obsIdList || !payload)
{
return OC_STACK_INVALID_PARAM;
request->observeResult = OC_STACK_OK;
if(result == OC_STACK_OK)
{
- OCEntityHandlerResponse ehResponse = {};
+ OCEntityHandlerResponse ehResponse = {0};
ehResponse.ehResult = OC_EH_OK;
ehResponse.payload = (OCPayload*)OCRepPayloadCreate();
if(!ehResponse.payload)
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)
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include "ocpayloadcbor.h"
+#include "platform_features.h"
#include <stdlib.h>
#include "oic_malloc.h"
#include "logger.h"
#include "cbor.h"
#define TAG PCF("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);
+#define STRINGIFY(s) XSTRINGIFY(s)
+#define XSTRINGIFY(s) #s
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, PCF("Payload parameter NULL"));
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ if (!outPayload || !size)
+ {
+ OC_LOG(ERROR, TAG, PCF("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, 2);
+ err = err | cbor_encode_uint(&rootArray, PAYLOAD_TYPE_SECURITY);
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 = {};
- bool err = false;
+ CborEncoder encoder = {0};
+ 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, 1 + resourceCount);
+ err = err | cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DISCOVERY);
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);
+ err = err | cbor_encoder_close_container(&encoder, &rootArray);
- 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 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 = {};
- bool err = false;
+ CborEncoder encoder = {0};
+ 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, 2);
+ err = err | cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DEVICE);
{
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);
-
- 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;
- }
+ err = err | cbor_encoder_close_container(&encoder, &rootArray);
- *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 = {};
- bool err = false;
+ CborEncoder encoder = {0};
+ 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, 2);
+ err = err | cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PLATFORM);
{
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;
- }
-
- *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 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, CborIndefiniteLength);
- err = err || cbor_encode_uint(&array, valArray->type);
+ 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)
{
- err = err || cbor_encode_uint(&array, valArray->dimensions[i]);
+ err = err | cbor_encode_uint(&array, valArray->dimensions[i]);
}
size_t dimTotal = calcDimTotal(valArray->dimensions);
err = CborUnknownError;
break;
case OCREP_PROP_INT:
- err = err || cbor_encode_int(&array, valArray->iArray[i]);
+ err = err | cbor_encode_int(&array, valArray->iArray[i]);
break;
case OCREP_PROP_DOUBLE:
- err = err || cbor_encode_double(&array, valArray->dArray[i]);
+ err = err | cbor_encode_double(&array, valArray->dArray[i]);
break;
case OCREP_PROP_BOOL:
- err = err || cbor_encode_boolean(&array, valArray->bArray[i]);
+ err = err | cbor_encode_boolean(&array, valArray->bArray[i]);
break;
case OCREP_PROP_STRING:
- err = err || cbor_encode_text_string(&array, valArray->strArray[i],
+ err = err | cbor_encode_text_string(&array, valArray->strArray[i],
strlen(valArray->strArray[i]));
break;
case OCREP_PROP_OBJECT:
}
}
- 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);
if(payload->types || payload->interfaces)
{
OC_LOG_V(INFO, TAG, "Payload has types or interfaces");
- err = err || cbor_encode_text_string(&map,
+ 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 = {};
- bool err = false;
+ CborEncoder encoder = {0};
+ 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);
+ err = err | cbor_encode_uint(&rootArray, PAYLOAD_TYPE_REPRESENTATION);
- 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;
- }
+ err = err | cbor_encoder_close_container(&encoder, &rootArray);
- *outPayload = tempPayload;
-
- 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};
+ int64_t err = 0;
- CborEncoder encoder = {};
- bool err = false;
-
- 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, 2);
+ err = err | cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PRESENCE);
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;
}
if(cbor_value_is_map(arrayVal))
{
char* uri = NULL;
- OCPlatformInfo info = {};
+ OCPlatformInfo info = {0};
CborValue curVal;
err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_HREF, &curVal);
size_t len;
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))
+ if(err || !OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions))
{
OICFree(arr);
err = true;
err = err || cbor_value_map_find_value(repParent, OC_RSRVD_PROPERTY, &curVal);
if(cbor_value_is_valid(&curVal))
{
- CborValue insidePropArray = {};
+ CborValue insidePropArray = {0};
err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_RESOURCE_TYPE,
&insidePropArray);
if(err)
{
OCRepPayloadDestroy(*outPayload);
+ *outPayload = NULL;
}
return err;
TAG, PCF(#arg " is NULL")); return (retVal); } }
extern OCResource *headResource;
-static OCPlatformInfo savedPlatformInfo = {};
-static OCDeviceInfo savedDeviceInfo = {};
+static OCPlatformInfo savedPlatformInfo = {0};
+static OCDeviceInfo savedDeviceInfo = {0};
//-----------------------------------------------------------------------------
// Default resource entity handler function
OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
{
- OCEntityHandlerResponse response = {};
+ OCEntityHandlerResponse response = {0};
response.ehResult = ehResult;
response.payload = discoveryPayload;
}
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)
OCStackResult result = OC_STACK_OK;
OCEntityHandlerResult ehResult = OC_EH_ERROR;
- OCEntityHandlerRequest ehRequest = {};
+ OCEntityHandlerRequest ehRequest = {0};
OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
result = FormOCEntityHandlerRequest(&ehRequest,
OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
ResourceObserver *resObs = NULL;
- OCEntityHandlerRequest ehRequest = {};
+ OCEntityHandlerRequest ehRequest = {0};
OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler"));
}
OCStackResult result = OC_STACK_ERROR;
- OCEntityHandlerRequest ehRequest = {};
+ OCEntityHandlerRequest ehRequest = {0};
result = FormOCEntityHandlerRequest(&ehRequest,
(OCRequestHandle)request,
OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
{
OCStackResult result = OC_STACK_ERROR;
- CAEndpoint_t responseEndpoint = {};
- CAResponseInfo_t responseInfo = {};
+ CAEndpoint_t responseEndpoint = {.adapter = CA_DEFAULT_ADAPTER};
+ CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
CAHeaderOption_t* optionsPointer = NULL;
if(!ehResponse || !ehResponse->requestHandle)
// Put the JSON prefix and suffix around the payload
if(ehResponse->payload)
{
+ if (ehResponse->payload->type == PAYLOAD_TYPE_PRESENCE)
+ {
+ responseInfo.isMulticast = true;
+ }
+ else
+ {
+ responseInfo.isMulticast = false;
+ }
+
OCStackResult result;
if((result = OCConvertPayload(ehResponse->payload, &responseInfo.info.payload,
&responseInfo.info.payloadSize))
OICFree(responseInfo.info.options);
return result;
}
-
- if(responseInfo.info.payloadSize > MAX_RESPONSE_LENGTH)
- {
- OICFree(responseInfo.info.payload);
- OC_LOG(ERROR, TAG, "Payload too long!");
- OICFree(responseInfo.info.options);
- return OC_STACK_INVALID_PARAM;
- }
}
else
{
+ responseInfo.isMulticast = false;
responseInfo.info.payload = NULL;
responseInfo.info.payloadSize = 0;
}
#include "oic_string.h"
#include "ocserverrequest.h"
#include "secureresourcemanager.h"
+#include "doxmresource.h"
#include "cacommon.h"
#include "cainterface.h"
#include "ocpayload.h"
out->flags = CAToOCTransportFlags(in->flags);
OICStrcpy(out->addr, sizeof(out->addr), in->addr);
out->port = in->port;
+ out->interface = in->interface;
}
void CopyDevAddrToEndpoint(const OCDevAddr *in, CAEndpoint_t *out)
out->flags = OCToCATransportFlags(in->flags);
OICStrcpy(out->addr, sizeof(out->addr), in->addr);
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)
{
OCStackResult result = OC_STACK_ERROR;
ResourceObserver * observer = NULL;
- OCEntityHandlerRequest ehRequest = {};
+ OCEntityHandlerRequest ehRequest = {0};
switch(status)
{
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]))
OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
ClientCB * cbNode = NULL;
char *resourceTypeName = NULL;
- OCClientResponse response = {};
+ OCClientResponse response = {.devAddr = {.adapter = OC_DEFAULT_ADAPTER}};
OCStackResult result = OC_STACK_ERROR;
uint32_t maxAge = 0;
int uriLen;
// 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;
}
else
{
// check for multiicast presence
- CAEndpoint_t ep = { endpoint->adapter, endpoint->flags };
- OICStrcpy(ep.addr, sizeof(ep.addr), OC_MULTICAST_IP);
- ep.port = OC_MULTICAST_PORT;
+ CAEndpoint_t ep = { .adapter = endpoint->adapter,
+ .flags = endpoint->flags };
uriLen = FormCanonicalPresenceUri(&ep, OC_RSRVD_PRESENCE_URI, presenceUri);
}
exit:
- OICFree(resourceTypeName);
OCPayloadDestroy(response.payload);
return result;
}
OC_LOG(INFO, TAG, PCF("Receiving A Timeout for this token"));
OC_LOG(INFO, TAG, PCF("Calling into application address space"));
- OCClientResponse response = {};
+ 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,
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"));
- OCClientResponse response = {};
+ OCClientResponse response =
+ {.devAddr = {.adapter = OC_DEFAULT_ADAPTER}};
response.sequenceNumber = OC_OBSERVE_NO_OPTION;
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 &&
const uint8_t numOptions, const CAHeaderOption_t *options,
CAToken_t token, uint8_t tokenLength)
{
- CAResponseInfo_t respInfo = {};
- respInfo.result = responseResult;
+ CAResponseInfo_t respInfo = {
+ .result = responseResult
+ };
respInfo.info.messageId = coapID;
respInfo.info.numOptions = numOptions;
respInfo.info.options = (CAHeaderOption_t*)options;
return;
}
- OCServerProtocolRequest serverRequest = {};
+ OCServerProtocolRequest serverRequest = {0};
OC_LOG_V(INFO, TAG, PCF("Endpoint URI : %s"), requestInfo->info.resourceUri);
}
}
- 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
requestInfo->info.type, requestInfo->info.numOptions,
requestInfo->info.options, requestInfo->info.token,
requestInfo->info.tokenLength);
+ OICFree(serverRequest.payload);
return;
}
requestInfo->info.type, requestInfo->info.numOptions,
requestInfo->info.options, requestInfo->info.token,
requestInfo->info.tokenLength);
+ OICFree(serverRequest.payload);
return;
}
memcpy(serverRequest.requestToken, requestInfo->info.token, requestInfo->info.tokenLength);
requestInfo->info.type, requestInfo->info.numOptions,
requestInfo->info.options, requestInfo->info.token,
requestInfo->info.tokenLength);
+ OICFree(serverRequest.payload);
OICFree(serverRequest.requestToken);
return;
}
}
// 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"));
}
{
(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);
}
return OC_STACK_OK;
}
+#ifdef RA_ADAPTER
+ if(!gRASetInfo)
+ {
+ OC_LOG(ERROR, TAG, PCF("Need to call OCSetRAInfo before calling OCInit"));
+ return OC_STACK_ERROR;
+ }
+#endif
+
OCStackResult result = OC_STACK_ERROR;
OC_LOG(INFO, TAG, PCF("Entering OCInit"));
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);
+ caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4|CA_IPV6);
}
defaultDeviceHandler = NULL;
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
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;
- }
+ if (start[0] == '[')
+ { // ipv6 address
+ char *close = strchr(++start, ']');
+ if (!close || close > slash)
+ {
+ return OC_STACK_INVALID_URI;
}
- else
+ end = close;
+ if (close[1] == ':')
+ {
+ colon = close + 1;
+ }
+ adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
+ flags = (OCTransportFlags)(flags | OC_IP_USE_V6);
+ }
+ else
+ {
+ char *dot = strchr(start, '.');
+ if (dot && dot < slash)
{ // ipv4 address
- end = slash;
colon = strchr(start, ':');
end = (colon && colon < slash) ? colon : slash;
+ adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
+ flags = (OCTransportFlags)(flags | OC_IP_USE_V4);
}
- len = end - start;
- if (len >= sizeof(da->addr))
- {
- return OC_STACK_INVALID_URI;
+ else
+ { // MAC address
+ end = slash;
}
- // use standard multicast port
- 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))
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;
OCTransportFlags flags;
// the request contents are put here
- CARequestInfo_t requestInfo = { CA_GET };
+ CARequestInfo_t requestInfo = {.method = CA_GET};
// requestUri will be parsed into the following three variables
OCDevAddr *devAddr = NULL;
char *resourceUri = NULL;
break;
case OC_REST_DISCOVER:
qos = OC_LOW_QOS;
- if (!destination && !devAddr)
+ if (destination || devAddr)
+ {
+ requestInfo.isMulticast = false;
+ }
+ else
{
+ tmpDevAddr.adapter = adapter;
+ tmpDevAddr.flags = flags;
destination = &tmpDevAddr;
+ requestInfo.isMulticast = true;
}
// CA_DISCOVER will become GET and isMulticast
requestInfo.method = CA_GET;
- requestInfo.isMulticast = true;
break;
#ifdef WITH_PRESENCE
case OC_REST_PRESENCE:
requestInfo.info.numOptions = numOptions;
}
- // create remote endpoint
- result = OCCreateEndpoint(devAddr, &endpoint);
+ CopyDevAddrToEndpoint(devAddr, &endpoint);
+
if(payload)
{
if((result =
requestInfo.info.payloadSize = 0;
}
-
-
if (result != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, PCF("CACreateEndpoint error"));
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;
resourceType = NULL; // Client CB list entry now owns it
// send request
- caResult = CASendRequest(endpoint, &requestInfo);
+ caResult = CASendRequest(&endpoint, &requestInfo);
if (caResult != CA_STATUS_OK)
{
OC_LOG(ERROR, TAG, PCF("CASendRequest"));
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;
+ CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
CAResult_t caResult;
- CAInfo_t requestData = {};
- CARequestInfo_t requestInfo = {};
+ CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
+ CARequestInfo_t requestInfo = {.method = CA_GET};
if(!handle)
{
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);
+ caResult = CASendRequest(&endpoint, &requestInfo);
if (caResult != CA_STATUS_OK)
{
OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
}
Error:
- OCDestroyEndpoint(endpoint);
if (requestData.numOptions > 0)
{
OICFree(requestData.options);
{
OICFree (requestData.resourceUri);
}
-
return ret;
}
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"));
}
CAResult_t caResult = CA_STATUS_OK;
- CAEndpoint_t* endpoint = NULL;
- CAInfo_t requestData ={};
- CARequestInfo_t requestInfo = {};
+ 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"));
- 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);
+ caResult = CASendRequest(&endpoint, &requestInfo);
if (caResult != CA_STATUS_OK)
{
{
OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
}
+
return result;
}
#endif // WITH_PRESENCE
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);
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!"));
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!"));
return NULL;
#include "oicgroup.h"
#include "cJSON.h"
+#include "cbor.h"
+#include "ocpayload.h"
#include "oic_malloc.h"
#include "oic_string.h"
#include "occollection.h"
#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) \
{\
}
-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)
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,
OCClientResponse* clientResponse)
{
- OC_LOG(INFO, TAG, PCF("Entering BuildActionJSON"));
+ (void)context;
+ (void)clientResponse;
+ OC_LOG(INFO, TAG, PCF("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;
void ActionSetCD(void *context)
{
+ (void)context;
}
OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr,
return ret;
}
+OCPayload* BuildActionCBOR(OCAction* action)
+{
+ OCRepPayload* payload = OCRepPayloadCreate();
+
+ if (!payload)
+ {
+ OC_LOG(INFO, TAG, PCF("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)
-{
- // 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);
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 };
-
- OCResource * collResource = (OCResource *) ehRequest->resource;
- char *jsonResponse;
+ char *doWhat = NULL;
+ char *details = NULL;
- stackRet = OC_STACK_NOTIMPL;
- // TODO: Fix?
- //stackRet = ExtractKeyValueFromRequest((char *) ehRequest->reqJSONPayload,
- // &doWhat, &details);
+ stackRet = ExtractKeyValueFromRequest(ehRequest, &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, PCF("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());
+ OCActionSet *actionSet = NULL;
+ stackRet = BuildActionSetFromString(&actionSet, details);
- OC_LOG(INFO, TAG, PCF("Group Action[PUT]."));
-
- 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, PCF("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, PCF("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;
+
+ OCRepPayload* payload = OCRepPayloadCreate();
+ OCRepPayloadSetUri(payload, resource->uri);
- if (method == OC_REST_POST)
+ 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, PCF("ERROR"));
+ stackRet = OC_STACK_ERROR;
}
- else
+
+ if (actionset == NULL)
{
- stackRet = OC_STACK_OK;
+ OC_LOG(INFO, TAG, PCF("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, PCF("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(
+ ScheduledResourceInfo *schedule;
+ schedule = (ScheduledResourceInfo *) OICMalloc(
+ sizeof(ScheduledResourceInfo));
+
+ if (schedule)
+ {
+ OC_LOG(INFO, TAG, PCF("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(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;
- }
+ 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;
}
}
}
}
}
- 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, PCF("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;
}
+
//-----------------------------------------------------------------------------
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 {
// 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
{
- if(eCode == OC_STACK_OK)
+ if(eCode == OC_STACK_OK && sequenceNumber != OC_OBSERVE_NO_OPTION)
{
+ if(sequenceNumber == OC_OBSERVE_REGISTER)
+ {
+ std::cout << "Observe registration action is successful" << std::endl;
+ }
+ else if(sequenceNumber == OC_OBSERVE_DEREGISTER)
+ {
+ std::cout << "Observe De-registration action is successful" << std::endl;
+ }
+
std::cout << "OBSERVE RESULT:"<<std::endl;
std::cout << "\tSequenceNumber: "<< sequenceNumber << std::endl;
rep.getValue("state", mylight.m_state);
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();
}
else
{
- std::cout << "onObserve Response error: " << eCode << std::endl;
- std::exit(-1);
+ if(sequenceNumber == OC_OBSERVE_NO_OPTION)
+ {
+ std::cout << "Observe registration or de-registration action is failed" << std::endl;
+ }
+ else
+ {
+ std::cout << "onObserve Response error: " << eCode << std::endl;
+ std::exit(-1);
+ }
}
}
catch(std::exception& e)
}
-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";
OutOfProc
};
+ /**
+ * Host Mode of Operation.
+ */
enum class ModeType
{
Server,
Both
};
+ /**
+ * Quality of Service attempts to abstract the guarantees provided by the underlying transport
+ * protocol. The precise definitions of each quality of service level depend on the
+ * implementation. In descriptions below are for the current implementation and may changed
+ * over time.
+ */
enum class QualityOfService : uint8_t
{
+ /** Packet delivery is best effort. */
LowQos = OC_LOW_QOS,
+
+ /** Packet delivery is best effort. */
MidQos = OC_MEDIUM_QOS,
+
+ /** Acknowledgments are used to confirm delivery. */
HighQos = OC_HIGH_QOS,
- NaQos = OC_NA_QOS // No Quality is defined, let the stack decide
+
+ /** No Quality is defined, let the stack decide. */
+ NaQos = OC_NA_QOS
};
/**
- * Data structure to provide the configuration.
- * ServiceType: indicate InProc or OutOfProc
- * ModeType : indicate whether we want to do server, client or both
- * ServerConnectivity : default flags for server
- * ClientConnectivity : default flags for client
- * QoS : indicate Quality of Service : LowQos, MidQos,HighQos and NaQos(No quality Defined).
- * ps : persistant storage Handler structure (open/read/write/close/unlink)
- */
+ * Data structure to provide the configuration.
+ */
struct PlatformConfig
{
+ /** indicate InProc or OutOfProc. */
ServiceType serviceType;
+
+ /** indicate whether we want to do server, client or both. */
ModeType mode;
+
+ /** default flags for server. */
OCConnectivityType serverConnectivity;
+
+ /** default flags for client. */
OCConnectivityType clientConnectivity;
- std::string ipAddress; // not used
- uint16_t port; // not used
+
+ /** not used. */
+ std::string ipAddress;
+
+ /** not used. */
+ uint16_t port;
+
+ /** indicate Quality of Service : LowQos, MidQos,HighQos and NaQos(No quality Defined). */
QualityOfService QoS;
+
+ /** persistant storage Handler structure (open/read/write/close/unlink). */
OCPersistentStorage *ps;
public:
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.
- * Above relative URI will be prepended (by core) with a host IP + namespace "oc"
+ * @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:
* //192.168.1.1/oic/a/light"
* 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 addedResourceHandle - 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 resourceTypeName - 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
- *
- * @return OCStackResult return value of the API. Returns OC_STACK_OK if success
+ * @param deviceInfo Structure containing all the device related information
*
- * 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);
* 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;
throw OCException(OC::Exception::NIL_GUARD_NULL, OC_STACK_INVALID_PARAM);
}
- // Note that although parameters are being forwarded, std::bind() will make a single copy:
- return std::bind(fn, p, std::forward<ParamTs>(params)...)();
+ // Note that the parameters are being passed by reference to std::bind. This is not an
+ // issue, as it is this function's parameters that are being passed by reference. So,
+ // unless the parameters are being passed by reference to here (or to checked_guard),
+ // they won't be modified.
+ return std::bind(fn, p, std::ref(params)...)();
}
/* Check for nullptr and forward the result of an OC function call on success; raise
int oc_console_logger_init(oc_log_ctx_t *ctx, void *world)
{
+ (void)world;
oc_console_logger_ctx *my_ctx;
my_ctx = (oc_console_logger_ctx *)malloc(sizeof(oc_console_logger_ctx));
void oc_console_logger_set_level(oc_log_ctx_t *ctx, const int level)
{
+ (void)ctx;
+ (void)level;
/* We don't have any special thing we need to do when a log level changes. */
return;
}
int oc_console_logger_set_module(oc_log_ctx_t *ctx, const char *module_name)
{
+ (void)ctx;
+ (void)module_name;
/* We don't do anything special when the module name changes: */
return 1;
}
{
}
-void oc_ostream_log_set_level(oc_log_ctx_t *ctx, const int level)
+void oc_ostream_log_set_level(oc_log_ctx_t * /*ctx*/, const int /*level*/)
try
{
/* We don't have any special thing we need to do when a log level changes. */
return 0;
}
-int oc_ostream_log_set_module(oc_log_ctx_t *ctx, const char *module_name)
+int oc_ostream_log_set_module(oc_log_ctx_t * /*ctx*/,
+ const char * /*module_name*/)
try
{
// Nothing special needs to happen for a module name change:
}
- OCStackApplicationResult listenCallback(void* ctx, OCDoHandle handle,
+ OCStackApplicationResult listenCallback(void* ctx, OCDoHandle /*handle*/,
OCClientResponse* clientResponse)
{
ClientCallbackContext::ListenContext* context =
}
OCStackResult InProcClientWrapper::ListenForResource(
- const std::string& serviceUrl, // unused
+ const std::string& serviceUrl,
const std::string& resourceType,
OCConnectivityType connectivityType,
FindCallback& callback, QualityOfService QoS)
}
OCStackResult result;
+ ostringstream resourceUri;
+ resourceUri << serviceUrl << resourceType;
ClientCallbackContext::ListenContext* context =
new ClientCallbackContext::ListenContext(callback, shared_from_this());
{
std::lock_guard<std::recursive_mutex> lock(*cLock);
result = OCDoResource(nullptr, OC_REST_DISCOVER,
- resourceType.c_str(),
+ resourceUri.str().c_str(),
nullptr, nullptr, connectivityType,
static_cast<OCQualityOfService>(QoS),
&cbdata,
return result;
}
- OCStackApplicationResult listenDeviceCallback(void* ctx, OCDoHandle handle,
+ OCStackApplicationResult listenDeviceCallback(void* ctx,
+ OCDoHandle /*handle*/,
OCClientResponse* clientResponse)
{
ClientCallbackContext::DeviceListenContext* context =
}
OCStackResult InProcClientWrapper::ListenForDevice(
- const std::string& serviceUrl, // unused
+ const std::string& serviceUrl,
const std::string& deviceURI,
OCConnectivityType connectivityType,
FindDeviceCallback& callback,
return OC_STACK_INVALID_PARAM;
}
OCStackResult result;
+ ostringstream deviceUri;
+ deviceUri << serviceUrl << deviceURI;
ClientCallbackContext::DeviceListenContext* context =
new ClientCallbackContext::DeviceListenContext(callback, shared_from_this());
{
std::lock_guard<std::recursive_mutex> lock(*cLock);
result = OCDoResource(nullptr, OC_REST_DISCOVER,
- deviceURI.c_str(),
+ deviceUri.str().c_str(),
nullptr, nullptr, connectivityType,
static_cast<OCQualityOfService>(QoS),
&cbdata,
}
}
- OCStackApplicationResult getResourceCallback(void* ctx, OCDoHandle handle,
+ OCStackApplicationResult getResourceCallback(void* ctx,
+ OCDoHandle /*handle*/,
OCClientResponse* clientResponse)
{
ClientCallbackContext::GetContext* context =
}
- OCStackApplicationResult setResourceCallback(void* ctx, OCDoHandle handle,
+ OCStackApplicationResult setResourceCallback(void* ctx,
+ OCDoHandle /*handle*/,
OCClientResponse* clientResponse)
{
ClientCallbackContext::SetContext* context =
return result;
}
- OCStackApplicationResult deleteResourceCallback(void* ctx, OCDoHandle handle,
+ OCStackApplicationResult deleteResourceCallback(void* ctx,
+ OCDoHandle /*handle*/,
OCClientResponse* clientResponse)
{
ClientCallbackContext::DeleteContext* context =
OCStackResult InProcClientWrapper::DeleteResource(
const OCDevAddr& devAddr,
const std::string& uri,
- const HeaderOptions& headerOptions, DeleteCallback& callback, QualityOfService QoS)
+ const HeaderOptions& headerOptions,
+ DeleteCallback& callback,
+ QualityOfService /*QoS*/)
{
if(!callback)
{
return result;
}
- OCStackApplicationResult observeResourceCallback(void* ctx, OCDoHandle handle,
+ OCStackApplicationResult observeResourceCallback(void* ctx,
+ OCDoHandle /*handle*/,
OCClientResponse* clientResponse)
{
ClientCallbackContext::ObserveContext* context =
OCStackResult InProcClientWrapper::CancelObserveResource(
OCDoHandle handle,
- const std::string& host, // unused
- const std::string& uri, // unused
+ const std::string& /*host*/,
+ const std::string& /*uri*/,
const HeaderOptions& headerOptions,
QualityOfService QoS)
{
return result;
}
- OCStackApplicationResult subscribePresenceCallback(void* ctx, OCDoHandle handle,
+ OCStackApplicationResult subscribePresenceCallback(void* ctx,
+ OCDoHandle /*handle*/,
OCClientResponse* clientResponse)
{
ClientCallbackContext::SubscribePresenceContext* context =
{
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());
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;
}
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);
+ }
+
// 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);
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);
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));
}
EXPECT_ANY_THROW(ConstructResourceObject(std::string(""), std::string("")));
}
+ 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(ResourceGetTest, DISABLED_ResourceGetForValidUri)
{
OCResource::Ptr resource = ConstructResourceObject("coap://192.168.1.2:5000", "/resource");
SConscript('notification-manager/SConscript')
# Build resource-encapsulation project
- if target_os not in ['android', 'tizen']:
- SConscript('resource-encapsulation/SConscript')
+ SConscript('resource-encapsulation/SConscript')
# Build simulator module
if target_os in ['linux']:
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)
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);
}
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')
######################################################################
# 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 exported="true" kind="lib" path="E:/Projects/Mixed_backup/master_22_aug/android/android_api/base/build/intermediates/bundles/release/classes.jar"/>
+ <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>SampleResourceClientApp</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.ConfigurationApiActivity"
+ 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/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">RESampleClient</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.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
+ */
+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 API's");
+ 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);
+ }
+ }
+ });
+
+ // 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.*;
+import org.iotivity.ResourceEncapsulation.client.RCSRemoteResourceObject;
+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 RemoteAttributeListener remoteAttributeListener;
+ static boolean monitoringState = false;
+ static boolean cachingState = false;
+
+ // constructor
+ public ResourceClient() {
+ discoveyManagerObj = RCSDiscoveryManager.getInstance();
+ discoverResourceListener = new DiscoverResourceListener();
+ stateChangedListener = new StateChangedListener();
+ cacheUpdateListener = new CacheUpdateListener();
+ remoteAttributeListener = new RemoteAttributeListener();
+
+ 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;
+
+ msg = Message.obtain();
+ msg.what = 0;
+ resourcClientActivityObj.getHandler().sendMessage(msg);
+
+ logMessage = "URI : " + resourceURI + "\n";
+ logMessage = logMessage + "Host : " + hostAddress + "\n";
+ for (int i = 0; i < resourceTypes.size(); i++) {
+ logMessage = logMessage + "resourceType : "
+ + resourceTypes.get(i) + "\n";
+ }
+
+ for (int i = 0; i < resourceInterfaces.size(); i++) {
+ logMessage = logMessage + "resourceInterfaces : "
+ + resourceInterfaces.get(i) + "\n";
+ }
+ logMessage = logMessage + "isObservable : " + isObservableflag
+ + "\n";
+
+ resourcClientActivityObj.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 = 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() and setRemoteAttributes() API
+ */
+ private class RemoteAttributeListener implements IRemoteAttributeListener {
+ @Override
+ public void onRemoteAttributesGetCallback(
+ RCSResourceAttributes attributes) {
+
+ Log.i(LOG_TAG, "onRemoteAttributesGetCallback invoked");
+ printAttributes(attributes);
+ }
+ };
+
+ public void disocverResources() {
+ Log.d(LOG_TAG, "discover resources entry");
+ RCSAddress address = RCSAddress.multicast();
+ try {
+ discoveyManagerObj.discoverResource(address);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ Log.d(LOG_TAG, "discover resources exit");
+ }
+
+ 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");
+ }
+
+ 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);
+ }
+
+ public void getRemoteAttributes() {
+ Log.d(LOG_TAG, "getRemoteAttributes entry");
+
+ if (null == remoteResourceObj) {
+ Log.e(LOG_TAG, "Remote Resource object NULL");
+ return;
+ }
+
+ try {
+ remoteResourceObj
+ .setRemoteAttributesListener(remoteAttributeListener);
+
+ if (null != remoteAttributeListener) {
+ remoteResourceObj.getRemoteAttributes();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return;
+ }
+
+ Log.d(LOG_TAG, "getRemoteAttributes exit");
+ }
+
+ 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
+ .setRemoteAttributesListener(remoteAttributeListener);
+
+ if (null != remoteAttributeListener) {
+ RCSResourceAttributes attr = new RCSResourceAttributes();
+ attr.setValueInt("Temperature", value);
+ remoteResourceObj.setRemoteAttributes(attr);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return;
+ }
+
+ Log.d(LOG_TAG, "setRemoteAttributes exit");
+ }
+
+ 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");
+ }
+
+ 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");
+ }
+
+ 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");
+ }
+
+ 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 = 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");
+ }
+
+ 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");
+ }
+
+ 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 java.util.Calendar;
+
+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 ResourceClient resourceClientObj;
+ private static Handler mHandler;
+
+ private static EditText logs;
+ private static String logMessage;
+
+ public static Context mcontext;
+ public static Calendar scheduleTime;
+
+ 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"); // 0
+ clientApisList.add("2. Stop Monitoring"); // 1
+
+ clientApisList.add("3. Get Remote Attributes"); // 2
+ clientApisList.add("4. Set Remote Attributes"); // 3
+
+ clientApisList.add("5. Start Caching without callback"); // 4
+ clientApisList.add("6. Start Caching with callback"); // 5
+
+ clientApisList.add("7. Get Cache State"); // 6
+ clientApisList.add("8. Get All Cached Attributes"); // 7
+ clientApisList.add("9. Get Cached Attribute"); // 8
+
+ clientApisList.add("10. Stop Caching"); // 9
+
+ // 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 regionValue = (EditText) dialog
+ .findViewById(R.id.attributeValue);
+ String value = regionValue.getText().toString();
+ if (value.equalsIgnoreCase("")) {
+ String toastmessage = "Please enter the Temperature Value";
+ displayToastMessage(toastmessage);
+ } else {
+ dialog.dismiss();
+ int val = Integer.parseInt(value);
+ resourceClientObj.setRemoteAttributes(val);
+ }
+ }
+ });
+ 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);
+ }
+}
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'):
+//******************************************************************
+//
+// 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<iostream>
+#include "mutex"
+#include "condition_variable"
#include "RCSDiscoveryManager.h"
#include "RCSRemoteResourceObject.h"
#include "RCSResourceAttributes.h"
-#include "OCPlatform.h"
#include "RCSAddress.h"
-using namespace std;
+#include "OCPlatform.h"
+
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;
-RCSResourceAttributes resourceAttributes;
-bool startCachingFlag;
-bool isReady;
-//callback function for discoverResource()
-void OnResourceDiscovered(std::shared_ptr<RCSRemoteResourceObject> foundResource)
+const std::string defaultKey = "Temperature";
+const std::string resourceType = "core.TemperatureSensor";
+const std::string relativetUri = OC_RSRVD_WELL_KNOWN_URI;
+
+std::mutex mtx;
+std::condition_variable cond;
+
+void startMonitoring();
+void startMonitoring();
+void stopMonitoring();
+void getAttributeFromRemoteServer();
+void setAttributeToRemoteServer();
+void startCachingWithoutCallback();
+void startCachingWithCallback();
+void getResourceCacheState();
+void getCachedAttributes();
+void getCachedAttribute();
+void stopCaching();
+
+enum Menu
+{
+ START_MONITORING = 1,
+ STOP_MONITORING,
+ GET_ATTRIBUTE,
+ SET_ATTRIBUTE,
+ START_CACHING_NO_UPDATE,
+ START_CACHING_UPDATE,
+ GET_RESOURCE_CACHE_STATE,
+ GET_CACHED_ATTRIBUTES,
+ GET_CACHED_ATTRIBUTE,
+ STOP_CACHING,
+ QUIT,
+ END_OF_MENU
+};
+
+typedef void(*ClientMenuHandler)();
+typedef int ReturnValue;
+
+struct ClientMenu
{
+ Menu m_menu;
+ ClientMenuHandler m_handler;
+ ReturnValue m_result;
+};
- cout << "\nOnResourceDiscovered callback" << std::endl;
+ClientMenu clientMenu[] = {
+ {Menu::START_MONITORING, startMonitoring, CORRECT_INPUT},
+ {Menu::STOP_MONITORING, stopMonitoring, CORRECT_INPUT},
+ {Menu::GET_ATTRIBUTE, getAttributeFromRemoteServer, CORRECT_INPUT},
+ {Menu::SET_ATTRIBUTE, setAttributeToRemoteServer, CORRECT_INPUT},
+ {Menu::START_CACHING_NO_UPDATE, startCachingWithoutCallback, CORRECT_INPUT},
+ {Menu::START_CACHING_UPDATE, startCachingWithCallback, CORRECT_INPUT},
+ {Menu::GET_RESOURCE_CACHE_STATE, getResourceCacheState, CORRECT_INPUT},
+ {Menu::GET_CACHED_ATTRIBUTES, getCachedAttributes, CORRECT_INPUT},
+ {Menu::GET_CACHED_ATTRIBUTE, getCachedAttribute, CORRECT_INPUT},
+ {Menu::STOP_CACHING, stopCaching, CORRECT_INPUT},
+ {Menu::QUIT, [](){}, QUIT_INPUT},
+ {Menu::END_OF_MENU, nullptr, INCORRECT_INPUT}
+ };
+
+void onResourceDiscovered(std::shared_ptr<RCSRemoteResourceObject> foundResource)
+{
+ std::cout << "onResourceDiscovered callback" << std::endl;
std::string resourceURI = foundResource->getUri();
std::string hostAddress = foundResource->getAddress();
- cout << "\tResource URI : " << resourceURI << std::endl;
- cout << "\tResource Host : " << hostAddress << std::endl;
+ std::cout << "\t\tResource URI : " << resourceURI << std::endl;
+ std::cout << "\t\tResource Host : " << hostAddress << std::endl;
resource = foundResource;
- isReady = true;
+
+ cond.notify_all();
}
-//callback for StartMonitoring()
-void OnResourceStateChanged(ResourceState resourceState)
+void onResourceStateChanged(const ResourceState& resourceState)
{
+ std::cout << "onResourceStateChanged callback" << std::endl;
- cout << "\nOnResourceStateChanged callback" << std::endl;
+ switch(resourceState)
+ {
+ case ResourceState::NONE:
+ std::cout << "\tState changed to : NOT_MONITORING" << std::endl;
+ break;
+
+ case ResourceState::ALIVE:
+ std::cout << "\tState changed to : ALIVE" << std::endl;
+ break;
+
+ case ResourceState::REQUESTED:
+ std::cout << "\tState changed to : REQUESTED" << std::endl;
+ break;
- if (resourceState == ResourceState::NONE)
- cout << "State changed to : NONE" << std::endl;
- else if (resourceState == ResourceState::ALIVE)
- cout << "State changed to : ALIVE" << std::endl;
- else if (resourceState == ResourceState::REQUESTED)
- cout << "State changed to : REQUESTED" << std::endl;
- else if (resourceState == ResourceState::LOST_SIGNAL)
+ case ResourceState::LOST_SIGNAL:
+ std::cout << "\tState changed to : LOST_SIGNAL" << std::endl;
+ resource = nullptr;
+ break;
+
+ case ResourceState::DESTROYED:
+ std::cout << "\tState changed to : DESTROYED" << std::endl;
+ break;
+ }
+}
+
+void onCacheUpdated(const RCSResourceAttributes& attributes)
+{
+ std::cout << "onCacheUpdated callback" << std::endl;
+
+ if (attributes.empty())
+ {
+ std::cout << "\tAttribute is Empty" << std::endl;
+ return;
+ }
+
+ for(const auto& attr : attributes)
{
- cout << "State changed to : LOST_SIGNAL" << std::endl;
- resource = NULL;
+ std::cout << "\tkey : " << attr.key() << std::endl
+ << "\tvalue : " << attr.value().toString() << std::endl;
}
- else if (resourceState == ResourceState::DESTROYED)
- cout << "State changed to : DESTROYED" << std::endl;
}
-//callback for startCaching() [uptodate]
-void OnCacheUpdated(const RCSResourceAttributes atttribute )
+void onRemoteAttributesReceivedCallback(const RCSResourceAttributes& attributes)
{
- cout << "\nOnCacheUpdated callback" << std::endl;
- if (atttribute.empty())
+ std::cout << "onRemoteAttributesReceivedCallback callback" << std::endl;
+
+ if (attributes.empty())
{
- std::cout << "Attribute is Empty" << std::endl;
+ std::cout << "\tAttribute is Empty" << std::endl;
+ return;
+ }
+
+ for(const auto& attr : attributes)
+ {
+ std::cout << "\tkey : " << attr.key() << std::endl
+ << "\tvalue : " << attr.value().toString() << std::endl;
+ }
+}
+
+void displayMenu()
+{
+ std::cout << std::endl;
+ std::cout << "1 :: Start Monitoring" << std::endl;
+ std::cout << "2 :: Stop Monitoring" << std::endl;
+ std::cout << "3 :: Get Attribute" << std::endl;
+ std::cout << "4 :: Set Attribute" << std::endl;
+ std::cout << "5 :: Start Caching (No update to Application)" << std::endl;
+ std::cout << "6 :: Start Caching (Update the application when data change)"<< std::endl;
+ std::cout << "7 :: Get Resource cache State" << std::endl;
+ std::cout << "8 :: Get Cached Attributes" << std::endl;
+ std::cout << "9 :: Get Cached Attribute" << std::endl;
+ std::cout << "10 :: Stop Caching" << std::endl;
+ std::cout << "11 :: Stop Server" << std::endl;
+}
+
+int processUserInput()
+{
+ int userInput;
+ std::cin >> userInput;
+ if (std::cin.fail())
+ {
+ std::cin.clear();
+ std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+ return -1;
+ }
+ return userInput;
+}
+
+void startMonitoring()
+{
+ if (!resource->isMonitoring())
+ {
+ resource->startMonitoring(&onResourceStateChanged);
+ std::cout << "\tHosting Started..." << std::endl;
}
else
{
- RCSResourceAttributes::const_iterator iter = atttribute.begin();
- for (unsigned int i = 0; i < atttribute.size(); ++i)
- {
- std::cout << "key : " << iter->key() << "\nvalue : " << iter->value().toString() << std::endl;
- ++iter;
- }
+ std::cout << "\tAlready Started..." << std::endl;
}
+}
+void stopMonitoring()
+{
+ if (resource->isMonitoring())
+ {
+ resource->stopMonitoring();
+ std::cout << "\tHosting stopped..." << std::endl;
+ }
+ else
+ {
+ std::cout << "\tHosting not started..." << std::endl;
+ }
}
-//callback for getRemoteAttributes()
-void OnRemoteAttributesReceivedCallback(const RCSResourceAttributes &atttribute)
+
+void getAttributeFromRemoteServer()
+{
+ resource->getRemoteAttributes(&onRemoteAttributesReceivedCallback);
+}
+
+void setAttributeToRemoteServer()
{
+ std::string key;
+ int value;
- std::cout << "\nOnRemoteAttributesReceivedCallback callback" << std::endl;
- if (atttribute.empty())
+ RCSResourceAttributes setAttribute;
+
+ std::cout << "\tEnter the Key you want to set : ";
+ std::cin >> key;
+ std::cout << "\tEnter the value you want to set :";
+ std::cin >> value;
+
+ setAttribute[key] = value;
+ resource->setRemoteAttributes(setAttribute,
+ &onRemoteAttributesReceivedCallback);
+}
+
+void startCaching(std::function <void (const RCSResourceAttributes&)>cb)
+{
+ if (!resource->isCaching())
{
- std::cout << "Got empty attribute " << std::endl;
+ if(cb) resource->startCaching(&onCacheUpdated);
+
+ else resource->startCaching();
+
+ std::cout << "\tCaching Started..." << std::endl;
}
else
{
- resourceAttributes = atttribute;
- RCSResourceAttributes::const_iterator iter = atttribute.begin();
- for (unsigned int i = 0; i < atttribute.size(); ++i)
+ std::cout << "\tAlready Started Caching..." << std::endl;
+ }
+}
+
+void startCachingWithoutCallback()
+{
+ startCaching(nullptr);
+}
+
+void startCachingWithCallback()
+{
+ startCaching(onCacheUpdated);
+}
+
+void getResourceCacheState()
+{
+ switch(resource->getCacheState())
+ {
+ case CacheState::READY:
+ std::cout << "\tCurrent Cache State : " << "CACHE_STATE ::READY" << std::endl;
+ break;
+
+ case CacheState::UNREADY:
+ std::cout << "\tCurrent Cache State : " << "CACHE_STATE ::UNREADY" << std::endl;
+ break;
+
+ case CacheState::LOST_SIGNAL:
+ std::cout << "\tCurrent Cache State : " << "CACHE_STATE ::LOST_SIGNAL" << std::endl;
+ break;
+
+ case CacheState::NONE:
+ std::cout << "\tCurrent Cache State : " << "CACHE_STATE ::NONE" << std::endl;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void getCachedAttributes()
+{
+ try
+ {
+ if (resource->getCachedAttributes().empty())
{
- std::cout << "key : " << iter->key() << "\nvalue : " << iter->value().toString() << std::endl;
- ++iter;
+ std::cout << "\tReceived cached attribute is empty" << std::endl;
}
+ else
+ {
+ for(const auto& attr : resource->getCachedAttributes())
+ {
+ std::cout << "\tkey : " << attr.key() << std::endl
+ << "\tvalue : " << attr.value().toString() << std::endl;
+ }
+ }
+ }
+ catch (const BadRequestException& e)
+ {
+ std::cout << "Exception in getCachedAttributes : " << e.what() << std::endl;
}
}
-//callback for setRemoteAttributes()
-void OnRemoteAttributesSetCallback(const RCSResourceAttributes &atttribute)
+void getCachedAttribute()
{
+ try
+ {
+ std::cout << "\tkey : " << defaultKey << std::endl
+ << "\tvalue : " << resource->getCachedAttribute(defaultKey).get< int >()
+ << std::endl;
+ }
+ catch (const BadRequestException& e)
+ {
+ std::cout << "Exception in getCachedAttribute : " << e.what() << std::endl;
+ }
+ catch (const BadGetException& e)
+ {
+ std::cout << "Exception in getCachedAttribute : " << e.what() << std::endl;
+ }
+}
- std::cout << "\nOnRemoteAttributesSetCallback callback" << std::endl;
- if (atttribute.empty())
+void stopCaching()
+{
+ if(resource->isCaching())
{
- std::cout << "Got empty attribute " << std::endl;
+ resource->stopCaching();
+ std::cout << "\tCaching stopped..." << std::endl;
}
else
{
- resourceAttributes = atttribute;
- RCSResourceAttributes::const_iterator iter = atttribute.begin();
- for (unsigned int i = 0; i < atttribute.size(); ++i)
+ std::cout << "\tCaching not started..." << std::endl;
+ }
+}
+
+int selectClientMenu(int selectedMenu)
+{
+ for(int i = 0; clientMenu[i].m_menu != Menu::END_OF_MENU; i++)
+ {
+ if(clientMenu[i].m_menu == selectedMenu)
{
- std::cout << "key : " << iter->key() << "\nvalue : " << iter->value().toString() << std::endl;
- ++iter;
+ clientMenu[i].m_handler();
+ return clientMenu[i].m_result;
}
}
+
+ std::cout << "Invalid input, please try again" << std::endl;
+
+ return INCORRECT_INPUT;
}
-int main()
+void process()
{
+ while(true)
+ {
+ displayMenu();
- RCSDiscoveryManager *discoveryManagerInstance = RCSDiscoveryManager::getInstance();
- bool cachingFlag = false;
- bool startMonitoringFlag= false;
+ if(selectClientMenu(processUserInput()) == QUIT_INPUT) break;
+ }
+}
- //configuring the platform
+void platFormConfigure()
+{
PlatformConfig config
{
OC::ServiceType::InProc, ModeType::Client, "0.0.0.0", 0, OC::QualityOfService::LowQos
};
OCPlatform::Configure(config);
+}
+
+bool discoverResource()
+{
+ std::cout << "Wait 2 seconds until discovered." << std::endl;
- std::cout << "\nPlatform configured successfully" << std::endl;
- std::string uri = "";
- std::string address = "";
- std::string rt = "core.TemperatureSensor";
+ RCSDiscoveryManager::getInstance()->discoverResourceByType(RCSAddress::multicast(),
+ relativetUri, resourceType, &onResourceDiscovered);
- try
- {
+ std::unique_lock<std::mutex> lck(mtx);
+ cond.wait_for(lck,std::chrono::seconds(2));
- uri = OC_RSRVD_WELL_KNOWN_URI + uri + "?rt=" + rt;
+ return resource != nullptr;
+}
- //getting the object of RCSAddress for multicast discovery
- RCSAddress rcsAddress = RCSAddress::multicast();
+int main()
+{
+ platFormConfigure();
- //discover the resource in the network
- discoveryManagerInstance->discoverResource(rcsAddress, uri , &OnResourceDiscovered);
- }
- catch (InvalidParameterException e)
+ if (!discoverResource())
{
- cout << "Exeception in discoverResource" << e.what() << std::endl;
+ std::cout << "Can't discovered Server... Exiting the Client." << std::endl;
+ return -1;
}
- bool isRun = true;
- int userInput;
- while (isRun)
+ try
{
- while (isReady)
- {
- cout << endl;
- cout << "1 :: Start Hosting" << endl;
- cout << "2 :: Stop Hosting" << endl;
- cout << "3 :: Get Attribute" << endl;
- cout << "4 :: Set Attribute" << endl;
- cout << "5 :: Start caching (No update to Application)" << endl;
- cout << "6 :: Start caching (Update the application when data change)" <<
- endl; //look for the datachange on server
- cout << "7 :: Get Resource cache State" << endl;
- cout << "8 :: Get Cached Attributes" << endl;
- cout << "9 :: Get Cached Attribute" << endl;
- cout << "10 :: Stop caching" << endl;
- cout << "11 :: QUIT" << endl;
-
- cin >> userInput;
-
- if (userInput == 1)
- {
- if(NULL == resource)
- {
- cout << "\n\n******No Resource found :-> Run the Server and Restart this App******" << std::endl;
- }
- else
- {
- try
- {
- if(false == startMonitoringFlag)
- {
- resource->startMonitoring(&OnResourceStateChanged);
- startMonitoringFlag = true;
- cout << "\n\n********** Hosting Started ***********" << std::endl;
- }
- else
- {
- cout << "\n\n********** Already Started ***********" << std::endl;
- }
- }
-
- catch (InvalidParameterException e)
- {
- cout << "Exeception in startMonitoring :: " << e.what() << std::endl;
- }
- }
- }
- else if (userInput == 2)
- {
- if(NULL == resource)
- {
- cout << "\n\n******No Resource found :-> Run the Server and Restart this App******" << std::endl;
- }
- else
- {
- if(true == startMonitoringFlag)
- {
- resource->stopMonitoring();
- cout << "\n\n****** Hosting stopped******" << std::endl;
- startMonitoringFlag = false;
- }
- else
- {
- cout << "\n\n******Hosting not started : press 1 to start Hosting******" << std::endl;
- }
- }
- }
- else if (userInput == 3)
- {
- if(NULL == resource)
- {
- cout << "\n\n******No Resource found :-> Run the Server and Restart this App******" << std::endl;
- }
- else
- {
- resource->getRemoteAttributes(&OnRemoteAttributesReceivedCallback);
- }
- }
- else if (userInput == 4)
- {
- int temperatureValue;
- if(NULL == resource)
- {
- cout << "\n\n******No Resource found :-> Run the Server and Restart this App******" << std::endl;
- }
- else
- {
- if (0 == resourceAttributes.size())
- {
- cout << "\n***First Get the Attributes from Remote Device : press 3 to get attributes***" <<
- std::endl;
- }
- else
- {
- RCSResourceAttributes::const_iterator iter = resourceAttributes.begin();
- for (unsigned int i = 0; i < resourceAttributes.size(); ++i)
- {
- if ( iter->key() == "Temperature")
- {
- cout << "Enter the value you want to set :";
- cin >> temperatureValue;
- resourceAttributes["Temperature"] = temperatureValue;
- resource->setRemoteAttributes(resourceAttributes, &OnRemoteAttributesSetCallback);
- }
- ++iter;
- }
- }
- }
- }
- else if (userInput == 5)
- {
- if(NULL == resource)
- {
- cout << "\n\n******No Resource found :-> Run the Server and Restart this app******" << std::endl;
- }
- else
- {
- if (false == cachingFlag)
- {
- resource->startCaching();
- cout << "********** caching Started ***********" << std::endl;
- cachingFlag = true;
- }
- else
- {
- cout << "*** Already Started... To start it again first stop it : press 10 ***" << std::endl;
- }
- }
- }
- else if (userInput == 6)
- {
-
- if(NULL == resource)
- {
- cout << "\n\n******No Resource found :-> Run the Server and Restart this app******" << std::endl;
- }
- else
- {
- try
- {
- if (false == cachingFlag)
- {
- resource->startCaching(&OnCacheUpdated);
- cout << "********** caching Started ***********" << std::endl;
- cachingFlag = true;
- }
- else
- {
- cout << "*** Already Started... To start it again first stop it : press 10 ***" << std::endl;
- }
- }
- catch (InvalidParameterException e)
- {
- cout << "Exeception in startCaching :: " << e.what() << std::endl;
- }
- }
- }
- else if (userInput == 7)
- {
- if(NULL == resource)
- {
- cout << "\n\n******No Resource found :-> Run the Server and Restart this app******" << std::endl;
- }
- else
- {
- CacheState state = resource->getCacheState();
- if (state == CacheState ::READY)
- cout << "Current Cache State : " << "CACHE_STATE ::READY" << std::endl;
- else if (state == CacheState ::UNREADY)
- cout << "Current Cache State : " << "CACHE_STATE ::UNREADY" << std::endl;
- else if (state == CacheState ::LOST_SIGNAL)
- cout << "Current Cache State : " << "CACHE_STATE ::LOST_SIGNAL" << std::endl;
- else if (state == CacheState ::NONE)
- cout << "Current Cache State : " << "CACHE_STATE ::NONE" << std::endl;
- }
- }
- else if (userInput == 8)
- {
- if(NULL == resource)
- {
- cout << "\n\n******No Resource found :-> Run the Server and Restart this app******" << std::endl;
- }
- else
- {
- try
- {
- RCSResourceAttributes atttribute = resource->getCachedAttributes();
- if (atttribute.empty())
- {
- cout << "Received cached attribute is empty" << std::endl;
- }
- else
- {
- RCSResourceAttributes::const_iterator iter = atttribute.begin();
- for (unsigned int i = 0; i < atttribute.size(); ++i)
- {
- std::cout << "\nkey : " << iter->key() << "\nvalue : " << iter->value().toString() << std::endl;
- ++iter;
- }
- }
- }
- catch (BadRequestException e)
- {
- cout << "getCachedAttributes exception : " << e.what() << std::endl;
- }
- }
- }
- else if (userInput == 9)
- {
- std::string key = "Temperature";
- if(NULL == resource)
- {
- cout << "\n\n******No Resource found :-> Run the Server and Restart this app******" << std::endl;
- }
- else
- {
- try
- {
- RCSResourceAttributes::Value valueObj = resource->getCachedAttribute(key);
- int value = valueObj.get< int >();
- cout << "\nkey : " << key << "\nValue : " << value << std::endl;
- }
- catch (BadRequestException e)
- {
- cout << "getCachedAttribute exception : " << e.what() << std::endl;
- }
- catch (BadGetException e)
- {
- cout << "Exeception in getCachedAttribute BadGetException:: " << e.what() << std::endl;
- }
- }
- }
- else if (userInput == 10)
- {
- if(NULL == resource)
- {
- cout << "\n\n******No Resource found :-> Run the Server and Restart this app******" << std::endl;
- }
- else
- {
- if(true == cachingFlag)
- {
- resource->stopCaching();
- cachingFlag = false;
- cout << "****** Caching stopped ******" << std::endl;
- }
- else
- {
- cout << "****** Caching not started : press 5 or 6 to start Caching ******" << std::endl;
- }
- }
- }
- else if (userInput == 11)
- {
- isReady = false;
- isRun = false;
- }
- else
- {
- cout << "*** Please enter the number between 1-11 ***" << std::endl;
- }
- }
+ process();
}
+ catch (const std::exception& e)
+ {
+ std::cout << "main exception : " << e.what() << std::endl;
+ }
+
+ std::cout << "Stopping the Client" << std::endl;
+
return 0;
}
#include "OCPlatform.h"
#include "OCApi.h"
-using namespace std;
using namespace OC;
using namespace OC::OCPlatform;
using namespace OIC::Service;
+constexpr int DEFALUT_VALUE = 0;
+
+constexpr int DEFALUT_SERVER = 1;
+constexpr int CUSTOM_SERVER = 2;
+constexpr int STOP = 3;
+
+constexpr int INCREASE_TEMPERATURE = 1;
+constexpr int DECREASE_TEMPERATURE = 2;
+constexpr int STOP_SENSOR = 3;
+
+constexpr int CORRECT_INPUT = 1;
+constexpr int INCORRECT_INPUT = 2;
+constexpr int QUIT = 3;
+
std::string resourceUri = "/a/TempSensor";
std::string resourceType = "core.TemperatureSensor";
std::string resourceInterface = "oic.if.";
std::string attributeKey = "Temperature";
+
RCSResourceObject::Ptr server;
-//display the menu on the screen
+enum class Control{
+ INCREASE,
+ DECREASE
+};
+
void displayMenu()
{
- std::cout << "=====================================================================\n\n";
+ std::cout << "====================================================================="
+ << std::endl;
std::cout << " 1 - Creation of Resource [Auto control for requests]" << std::endl;
- std::cout << " 2 - Creation of Resource [Developer control for Get and Set requests]" <<std::endl;
+ std::cout << " 2 - Creation of Resource [Developer control for Get and Set requests]"
+ << std::endl;
std::cout << " 3 - Quit" << std::endl;
- std::cout << "=====================================================================\n\n";
+ std::cout << "====================================================================="
+ << std::endl;
}
-//hander for get request (if developer choose second option for resource Creation)
-RCSGetResponse RequestHandlerForGet(const RCSRequest &request,
- RCSResourceAttributes &attrs)
+void displayControlTemperatureMenu()
{
- cout << "Recieved a Get request from Client" << std::endl;
- RCSResourceObject::LockGuard lock(*server);
- RCSResourceAttributes attr = server->getAttributes();
- RCSResourceAttributes::const_iterator iter = attr.begin();
- cout << "\nSending response to Client : " << std::endl;
- for (unsigned int i = 0; i < attr.size(); ++i)
+ std::cout << "========================================================" << std::endl;
+ std::cout << "1. Increase Temperature by 10 degree" << std::endl;
+ std::cout << "2. Decrease Temperature by 10 degree" << std::endl;
+ std::cout << "3. Stop the Sensor" << std::endl;
+ std::cout << "========================================================" << std::endl;
+}
+
+void printAttribute(const RCSResourceAttributes& attrs)
+{
+ for(const auto& attr : attrs)
{
- std::cout << "\tkey : " << iter->key() << "\n\tvalue : " << iter->value().toString() << std::endl;
- ++iter;
+ std::cout << "\tkey : " << attr.key() << "\n\tvalue : "
+ << attr.value().toString() << std::endl;
}
- return RCSGetResponse::create(attr);
+}
+
+//hander for get request (if developer choose second option for resource Creation)
+RCSGetResponse requestHandlerForGet(const RCSRequest& request,
+ RCSResourceAttributes& attrs)
+{
+ std::cout << "Recieved a Get request from Client" << std::endl;
+
+ RCSResourceObject::LockGuard lock(*server);
+ RCSResourceAttributes attributes = server->getAttributes();
+
+ std::cout << "\nSending response to Client : " << std::endl;
+ printAttribute(attributes);
+
+ return RCSGetResponse::defaultAction();
}
//hander for set request (if developer choose second option for resource Creation)
-RCSSetResponse RequestHandlerForSet(const RCSRequest &request,
- RCSResourceAttributes &attrs)
+RCSSetResponse requestHandlerForSet(const RCSRequest& request,
+ RCSResourceAttributes& attrs)
+{
+ std::cout << "Recieved a Set request from Client" << std::endl;
+
+ std::cout << "\n\nSending response to Client : " << std::endl;
+ RCSResourceObject::LockGuard lock(*server);
+ printAttribute(attrs);
+ return RCSSetResponse::defaultAction();
+}
+
+void createResource()
+{
+ server = RCSResourceObject::Builder(resourceUri, resourceType,
+ resourceInterface).setDiscoverable(true).setObservable(true).build();
+}
+
+void initServer()
{
- cout << "Recieved a Set request from Client" << std::endl;
- RCSResourceAttributes::const_iterator iter = attrs.begin();
- for (unsigned int i = 0; i < attrs.size(); ++i)
+ try
{
- std::cout << "\tkey : " << iter->key() << "\n\tvalue : " << iter->value().toString() << std::endl;
- ++iter;
+ createResource();
}
- iter = attrs.begin();
- cout << "\n\nSending response to Client : " << std::endl;
- for (unsigned int i = 0; i < attrs.size(); ++i)
+ catch (const PlatformException& e)
{
- std::cout << "\tkey : " << iter->key() << "\n\tvalue : " << iter->value().toString() << std::endl;
- ++iter;
+ std::cout << "Exception in initServer : " << e.what() << std::endl;
}
- return RCSSetResponse::create(attrs);
+
+ server->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
+ server->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::NEVER);
+ server->setAttribute(attributeKey, DEFALUT_VALUE);
}
-int main(void)
+void changeTemperature(Control control)
{
+ RCSResourceObject::LockGuard lock(server);
+ if(Control::INCREASE == control)
+ {
+ server->getAttributes()[attributeKey] =
+ server->getAttribute<int>(attributeKey) + 10;
+ std::cout << "\nTemperature increased by 10 degree" << std::endl;
+ }
+ else if(Control::DECREASE == control)
+ {
+ server->getAttributes()[attributeKey] =
+ server->getAttribute<int>(attributeKey) - 10;
+ std::cout << "\nTemperature Decreased by 10 degree" << std::endl;
+ }
+ std::cout << "\nCurrent Temperature : "
+ << server->getAttributeValue(attributeKey).get<int>() << std::endl;
+}
+int processUserInput()
+{
int userInput;
- int initialTemperature = 0;
- int temperatureInput;
- bool flag = true;
- startPresence(3);
+ std::cin >> userInput;
+ if (std::cin.fail())
+ {
+ std::cin.clear();
+ std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+ return -1;
+ }
+ return userInput;
+}
- displayMenu();
+int selectServerMenu()
+{
+ switch (processUserInput())
+ {
+ case DEFALUT_SERVER: // Creation of Resource & Auto control for all requests from Client.
+ initServer();
+ return CORRECT_INPUT;
+
+ case CUSTOM_SERVER:
+ // Creation of Resource & setting get and set handler for handling get and
+ // set request from client in application.
+ initServer();
+
+ server->setGetRequestHandler(requestHandlerForGet);
+ server->setSetRequestHandler(requestHandlerForSet);
+ return CORRECT_INPUT;
+ case STOP :
+ return QUIT;
+
+ default :
+ std::cout << "Invalid input, please try again" << std::endl;
+ return INCORRECT_INPUT;
+ }
+}
+
+int selectControlTemperatureMenu()
+{
+ switch (processUserInput())
+ {
+ case INCREASE_TEMPERATURE:
+ changeTemperature(Control::INCREASE);
+ return CORRECT_INPUT;
+
+ case DECREASE_TEMPERATURE:
+ changeTemperature(Control::DECREASE);
+ return CORRECT_INPUT;
+
+ case STOP_SENSOR:
+ return QUIT;
+
+ default:
+ std::cout << "Invalid input. Please try again." << std::endl;
+ return INCORRECT_INPUT;
+ }
+}
+
+void process()
+{
+ while(true)
+ {
+ displayMenu();
+
+ int ret = selectServerMenu();
+
+ if(ret == QUIT) return;
+ if(ret == CORRECT_INPUT) break;
+ }
+
+ while(true)
+ {
+ displayControlTemperatureMenu();
+
+ if (selectControlTemperatureMenu() == QUIT) return;
+ }
+}
+
+int main(void)
+{
+ startPresence(3);
- //userInput for creation of Resource
- std::cin >> userInput;
- std::cin.clear();
- std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
try
{
- while (flag)
- {
-
- switch (userInput)
- {
-
- case 1:
- //Creation of Resource & Auto control for all requests from Client
- {
- //creation of Resource
- server = RCSResourceObject::Builder(resourceUri, resourceType,
- resourceInterface).setDiscoverable(true).setObservable(false).build();
- std::cout << "Resource created successfully " << std::endl;
-
- //setting attribute for the Created Resource
- server->setAttribute(attributeKey, initialTemperature);
- flag = false;
- break;
- }
-
- case 2:
- //Creation of Resource & setting get and set handler for handling get and set request from client in application
- {
- server = RCSResourceObject::Builder(resourceUri, resourceType,
- resourceInterface).setDiscoverable(true).setObservable(false).build();
- std::cout << "Resource created successfully " << std::endl;
-
- //setting attribute for the Created Resource
- server->setAttribute(attributeKey, initialTemperature);
-
- //setting handler for handling get request from the client
- server->setGetRequestHandler(RequestHandlerForGet);
-
- // setting handler for handling set request from the client
- server->setSetRequestHandler(RequestHandlerForSet);
- flag = false;
- break;
- }
- case 3:
- return 0;
- default :
- std::cout << "Invalid Input" << std::endl;
- break;
- }
- }
-
- while (true)
- {
- bool end = false;
- cout << endl;
- cout << "========================================================" << endl;
- cout << "1. Increase Temperature by 10 degree" << endl;
- cout << "2. Decrease Temperature by 10 degree" << endl;
- cout << "3. Stop the Sensor" << endl;
- cout << "========================================================" << endl;
-
- //user Input for increasing/decreasing the temperature
- cin >> temperatureInput;
- if (std::cin.fail())
- {
- std::cin.clear();
- std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
- std::cout << "Invalid input type, please try again" << std::endl;
- continue;
- }
-
- switch (temperatureInput)
- {
- case 1:
- {
- RCSResourceObject::LockGuard lock(*server);
- RCSResourceAttributes attrs = server->getAttributes();
-
- attrs[attributeKey] = (server->getAttribute<int>(attributeKey) + 10);
- server->setAttribute(attributeKey, attrs[attributeKey]);
- cout << "\nTemperature increased by 10 degree" << endl;
-
- //getting the current attribute and priniting it on the console
- attrs = server->getAttributes();
- cout << "\nCurrent Temperature : ";
- RCSResourceAttributes::const_iterator iter = attrs.begin();
- for (unsigned int i = 0; i < attrs.size(); ++i)
- {
- std::cout << iter->value().toString() << std::endl;
- ++iter;
- }
- break;
- }
- case 2:
- {
- RCSResourceObject::LockGuard lock(*server);
- RCSResourceAttributes attrs = server->getAttributes();
- attrs[attributeKey] = (server->getAttribute<int>(attributeKey) - 10);
- server->setAttribute(attributeKey, attrs[attributeKey]);
- cout << "\nTemperature decreased by 10 degree" << endl;
-
- //getting the current attribute and priniting it on the console
- attrs = server->getAttributes();
- cout << "\nCurrent Temperature : ";
- RCSResourceAttributes::const_iterator iter = attrs.begin();
- for (unsigned int i = 0; i < attrs.size(); ++i)
- {
- std::cout << iter->value().toString() << std::endl;
- ++iter;
- }
- break;
- }
- case 3:
- {
- cout << "Stopping the Resource" << endl;
- end = true;
- break;
- }
- default:
- {
- cout << "Invalid input. Please try again." << endl;
- break;
- }
- }
- if (end == true)
- {
- server=NULL;
- break;
- }
- }
+ process();
+ server = NULL;
}
- catch (exception &e)
+ catch (const std::exception& e)
{
- cout << "main exception : " << e.what() << endl;
+ std::cout << "main exception : " << e.what() << std::endl;
}
+
+ std::cout << "Stopping the Server" << std::endl;
}
--- /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>
/**
* @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;
+
+ /**
+ * 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 any parameter is invalid.
- *
- * @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;
};
}
}
namespace Service
{
/**
- * @class RCSRequest
- * @brief This class describes the resource request.
- * It provides API to get the resource URI from the request.
+ * This class describes the request.
+ *
*/
class RCSRequest
{
RCSRequest &operator=(RCSRequest &) = delete;
/**
- * API to get the URI from the request.
+ * Returns the URI of the request.
*
- * @return string - uri of resource.
*/
std::string getResourceUri() const;
private:
- /**
- * resource uri value stored as a string.
- * value set once during request initialization.
- */
std::string m_resourceUri;
};
#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;
#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();
{
namespace Service
{
- //forward declaration of classes
class RCSResourceAttributes;
class RequestHandler;
class SetRequestHandler;
/**
- * @class RCSGetResponse
- * @brief This class provides APIs to create the response for the recieved Get request.
+ * This class provides factory methods to create the response for a received get request.
+ * The response consists of a result code, an error code and result attributes.
+ *
+ * @see RCSResourceObject
*/
class RCSGetResponse
{
public:
/**
- * Create RCSGetResponse with default response.
+ * 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 - instance of RCSGetResponse
*/
static RCSGetResponse defaultAction();
/**
- * Create RCSGetResponse using OCEntityHandlerResult value and error code provided.
+ * Creates a RCSGetResponse with a result and error code passed.
+ * The attributes of the RCSResourceObject will be set as the result attributes.
*
- * @param result -OCEntityHandlerResult
+ * @param result The response result.
+ * @param errorCode The error code to set in response.
*
- * @param errorCode - error code to set in response
- *
- * @return RCSGetResponse - instance of RCSGetResponse
- *
- * NOTE : OCEntityHandlerResult is defined in octypes.h
*/
- static RCSGetResponse create(const OCEntityHandlerResult &result, int errorCode);
+ static RCSGetResponse create(const OCEntityHandlerResult& result, int errorCode);
/**
- * Create RCSGetResponse using resource attributes.
- *
- * @param attrs -RCSResourceAttributes to set
+ * Creates a RCSGetResponse with custom attributes.
+ * This sends the passed attributes as the result attributes
+ * instead of the one the RCSResourceObject holds.
*
- * @return RCSGetResponse - instance of RCSGetResponse
+ * @param attrs The attributes to set.
*
* @see RCSResourceAttributes
*
- * NOTE : RCSResourceAttributes is defined in RCSResourceAttributes.h
*/
- static RCSGetResponse create(const RCSResourceAttributes &attrs);
- /**
- * Create RCSGetResponse using RCSResourceAttributes, OCEntityHandlerResult and error code.
- *
- * @param attrs - RCSResourceAttributes to set
- *
- * @param result - OCEntityHandlerResult
- *
- * @param errorCode - error code for response
- *
- * @return RCSGetResponse - instance of RCSGetResponse
- *
- * @see RCSResourceAttributes
- *
- *NOTE : OCEntityHandlerResult is defined in octypes.h.
- * RCSResourceAttributes is defined in RCSResourceAttributes.h.
- */
- static RCSGetResponse create(const RCSResourceAttributes &attrs,
- const OCEntityHandlerResult &result, int errorCode);
+ static RCSGetResponse create(const RCSResourceAttributes& attrs);
/**
- * Create RCSGetResponse using RCSResourceAttributes value.
- *
- * @param attrs - RCSResourceAttributes to set
- *
- * @return RCSGetResponse - instance of RCSGetResponse
- *
- * @see RCSResourceAttributes
- *
- *NOTE : RCSResourceAttributes is defined in RCSResourceAttributes.h.
+ * @override
*/
- static RCSGetResponse create(RCSResourceAttributes &&attrs);
+ static RCSGetResponse create(RCSResourceAttributes&& attrs);
+
/**
- * Create RCSGetResponse using RCSResourceAttributes value.
+ * Creates a RCSGetResponse with a result and error code passed.
+ * This sends the passed attributes as the result attributes
+ * instead of the one the RCSResourceObject holds.
*
- * @param attrs - RCSResourceAttributes to set
- *
- * @param result - OCEntityHandlerResult
- *
- * @param errorCode - error code for response
- *
- * @return RCSGetResponse - instance of RCSGetResponse
+ * @param attrs The attributes to set.
+ * @param result The response result.
+ * @param errorCode The error code for response.
*
* @see RCSResourceAttributes
*
- *NOTE : OCEntityHandlerResult is defined in octypes.h.
- * RCSResourceAttributes is defined in RCSResourceAttributes.h.
*/
- static RCSGetResponse create(RCSResourceAttributes &&attrs,
- const OCEntityHandlerResult &result, int errorCode);
+ static RCSGetResponse create(const RCSResourceAttributes& attrs,
+ const OCEntityHandlerResult& result, int errorCode);
/**
- * Get the request handler.
- *
- * @return RequestHandler - RequestHandler pointer.
- *
+ * @override
*/
+ static RCSGetResponse create(RCSResourceAttributes&& attrs,
+ const OCEntityHandlerResult& result, int errorCode);
+
+ //! @cond
RequestHandler* getHandler() const;
+ //! @endcond
private:
RCSGetResponse(std::shared_ptr< RequestHandler >&&);
};
/**
- * @class RCSSetResponse
- * @brief This class provides API to create a response for received Set request.
+ * This class provides factory methods to create the response for a received set request.
+ * The response consists of a result code, an error code and result attributes.
+ *
+ * AcceptanceMethod provides ways how to handle attributes from a request.
+ *
+ * @see RCSResourceObject
*/
class RCSSetResponse
{
public:
/**
- * AcceptanceMethod enum provides values for different acceptance method policy to be
- * used in setting response.
+ * Options for handling a set request.
+ *
+ * This overrides SetRequestHandlerPolicy.
+ *
+ * @see SetRequestHandlerPolicy
+ *
*/
enum class AcceptanceMethod
{
- DEFAULT, ACCEPT, IGNORE
+ /**
+ * Follow SetRequestHandlerPolicy of the RCSResourceObject.
+ */
+ DEFAULT,
+
+ /**
+ * Accept the request attributes even if there is an unknown key or mismatched type.
+ */
+ ACCEPT,
+
+ /**
+ * Ignore the request attributes.
+ */
+ IGNORE
};
/**
- * Create default RCSSetResponse with default response.
+ * Creates a default RCSSetResponse that has AcceptanceMethod::DEFAULT.
+ * 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 RCSSetResponse - instance of RCSSetResponse
*/
static RCSSetResponse defaultAction();
/**
- * Internally it invokes the defaultAction() API.
- * It sets the AcceptanceMethod as ACCEPT.
- *
- * @return RCSSetResponse - instance of RCSSetResponse
+ * Creates a default RCSSetResponse that has AcceptanceMethod::ACCEPT.
+ * 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.
*
- * @see AcceptanceMethod
*/
static RCSSetResponse accept();
+
/**
- * Internally it invokes the create(const OCEntityHandlerResult&, int errorCode) API.
- * It sets the AcceptanceMethod as ACCEPT.
+ * Creates a RCSSetResponse that has AcceptanceMethod::ACCEPT
+ * with a result and error code passed.
+ * The attributes of the RCSResourceObject will be set as the result attributes.
*
- * @param result - OCEntityHandlerResult value.
- *
- * @param errorCode - error code for the response
- *
- * @return RCSSetResponse - instance of RCSSetResponse
- *
- * @see AcceptanceMethod
+ * @param result The response result.
+ * @param errorCode The error code to set in response.
*
- *NOTE : OCEntityHandlerResult is defined in octypes.h
*/
- static RCSSetResponse accept(const OCEntityHandlerResult &result, int errorCode);
+ static RCSSetResponse accept(const OCEntityHandlerResult& result, int errorCode);
/**
- * Internally it invokes the defaultAction() API.
- * It sets the AcceptanceMethod as IGNORE.
+ * Creates a default RCSSetResponse that has AcceptanceMethod::IGNORE.
+ * 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 RCSSetResponse - instance of RCSSetResponse.
- *
- * @see AcceptanceMethod
*/
static RCSSetResponse ignore();
- /**
- * Internaly it invokes the create(const OCEntityHandlerResult&, int errorCode) API.
- * It sets the AcceptanceMethod as IGNORE.
- *
- * @param result - OCEntityHandlerResult value.
- *
- * @param errorCode - error code for the response.
- *
- * @return RCSSetResponse - instance of RCSSetResponse.
- *
- * @see AcceptanceMethod
- *
- *NOTE : OCEntityHandlerResult is defined in octypes.h
- */
- static RCSSetResponse ignore(const OCEntityHandlerResult &result, int errorCode);
/**
- * Create RCSSetResponse with OCEntityHandlerResult and errorCode.
- *
- * @param result - OCEntityHandlerResult value
- *
- * @param errorCode - error code for the response
+ * Creates a RCSSetResponse that has AcceptanceMethod::IGNORE
+ * with a result and error code passed.
+ * The attributes of the RCSResourceObject will be set as the result attributes.
*
- * @return RCSSetResponse - instance of RCSSetResponse
+ * @param result The response result.
+ * @param errorCode The error code to set in response.
*
- *NOTE : OCEntityHandlerResult is defined in octypes.h
*/
- static RCSSetResponse create(const OCEntityHandlerResult &result, int errorCode);
+ static RCSSetResponse ignore(const OCEntityHandlerResult& result, int errorCode);
/**
- * Create RCSSetResponse with RCSResourceAttributes.
+ * Creates a RCSSetResponse that has AcceptanceMethod::DEFAULT
+ * with a result and error code passed.
+ * The attributes of the RCSResourceObject will be set as the result attributes.
*
- * @param attrs - RCSResourceAttributes to set
+ * @param result The response result.
+ * @param errorCode The error code to set in response.
*
- * @return RCSSetResponse - instance of RCSSetResponse
- *
- * @see RCSResourceAttributes
*/
- static RCSSetResponse create(const RCSResourceAttributes &attrs);
+ static RCSSetResponse create(const OCEntityHandlerResult& result, int errorCode);
+
/**
- * Create RCSSetResponse with RCSResourceAttributes, OCEntityHandlerResult and errorCode.
- *
- * @param attrs - RCSResourceAttributes to set.
- *
- * @param result - OCEntityHandlerResult value
+ * Creates a RCSSetResponse that has AcceptanceMethod::DEFAULT with custom attributes.
+ * This sends the passed attributes as the result attributes
+ * instead of the one the RCSResourceObject holds.
*
- * @param errorCode - error code for the response
- *
- * @return RCSSetResponse - instance of RCSSetResponse
+ * @param attrs The attributes to set.
*
* @see RCSResourceAttributes
*
- *NOTE : OCEntityHandlerResult is defined in octypes.h.
*/
- static RCSSetResponse create(const RCSResourceAttributes &attrs,
- const OCEntityHandlerResult &result, int errorCode);
+ static RCSSetResponse create(const RCSResourceAttributes& attrs);
/**
- * Create RCSSetResponse with RCSResourceAttributes.
- *
- * @param attrs - RCSResourceAttributes value to set
- *
- * @return RCSSetResponse - instance of RCSSetResponse
- *
- * @see RCSResourceAttributes
+ * @override
*/
static RCSSetResponse create(RCSResourceAttributes &&attrs);
+
/**
- * Create RCSSetResponse with RCSResourceAttributes, OCEntityHandlerResult and errorCode.
- *
- * @param attrs - RCSResourceAttributes value to set
- *
- * @param result - OCEntityHandlerResult value
+ * Creates a RCSSetResponse with a result and error code passed.
+ * This sends the passed attributes as the result attributes
+ * instead of the one the RCSResourceObject holds.
*
- * @param errorCode - error code for the response
- *
- * @return RCSSetResponse - instance of RCSSetResponse
+ * @param attrs The attributes to set.
+ * @param result The response result.
+ * @param errorCode The error code for response.
*
* @see RCSResourceAttributes
*
- *NOTE : OCEntityHandlerResult is defined in octypes.h.
*/
- static RCSSetResponse create(RCSResourceAttributes &&attrs,
- const OCEntityHandlerResult &result, int errorCode);
+ static RCSSetResponse create(const RCSResourceAttributes& attrs,
+ const OCEntityHandlerResult& result, int errorCode);
+
/**
- * API to get the set request handler.
- *
- * @return SetRequestHandler - pointer to SetRequestHandler.
- *
+ * @override
*/
+ static RCSSetResponse create(RCSResourceAttributes &&attrs,
+ const OCEntityHandlerResult &result, int errorCode);
+
+
+ //! @cond/
SetRequestHandler* getHandler() const;
+ //! @endcond
/**
- * API to get the acceptance method of the RCSSetResponse.
- *
- * @return AcceptanceMethod - acceptance methods enum value.
- *
- * @see AcceptanceMethod
+ * Returns the acceptance method.
*
*/
AcceptanceMethod getAcceptanceMethod() const;
/**
- * API to get the acceptance method of the RCSSetResponse.
+ * Sets the acceptance method for the RCSSetResponse.
*
* @param method - AcceptanceMethod value to set
*
- * @return RCSSetResponse - reference to RCSSetResponse
+ * @return The reference to this RCSSetResponse
*
* @see AcceptanceMethod
*
*/
- RCSSetResponse &setAcceptanceMethod(AcceptanceMethod method);
+ RCSSetResponse& setAcceptanceMethod(AcceptanceMethod method);
private:
RCSSetResponse(std::shared_ptr< SetRequestHandler >&&);
--- /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-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_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-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_RCSRemoteResourceObject;
+extern jclass g_cls_RCSRemoteResourceAttributesObject;
+extern jclass g_cls_RCSException;
+
+extern jclass g_cls_RCSResourceObject;
+extern jclass g_cls_RCSRequest;
+
+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_Iterator_hasNext;
+extern jmethodID g_mid_Iterator_next;
+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;
+
+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 <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);
+
+
+OCEntityHandlerResult convertIntToOCEntityHandlerResult(int result);
+
+/**
+ * @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_RCSRemoteResourceObject = NULL;
+jclass g_cls_RCSRemoteResourceAttributesObject = NULL;
+jclass g_cls_RCSException = NULL;
+
+jclass g_cls_RCSResourceObject = NULL;
+jclass g_cls_RCSRequest = 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_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;
+
+
+// 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;
+
+ //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);
+
+ /* g_mid_RCSRequest_ctor = env->GetMethodID(g_cls_RCSRequest, "<init>",
+ "(J)V");
+ if (!g_mid_RCSRequest_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);
+
+ 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 1:
+ return OCEntityHandlerResult::OC_EH_OK;
+ case 2:
+ return OCEntityHandlerResult::OC_EH_ERROR;
+ case 3:
+ return OCEntityHandlerResult::OC_EH_RESOURCE_CREATED;
+ case 4:
+ return OCEntityHandlerResult::OC_EH_RESOURCE_DELETED;
+ case 5:
+ return OCEntityHandlerResult::OC_EH_SLOW;
+ case 6:
+ return OCEntityHandlerResult::OC_EH_FORBIDDEN;
+ case 7:
+ 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 1:
+ return RCSResourceObject::AutoNotifyPolicy::NEVER;
+
+ case 2:
+ return RCSResourceObject::AutoNotifyPolicy::ALWAYS;
+
+ case 3:
+ return RCSResourceObject::AutoNotifyPolicy::UPDATED;
+ }
+}
+
+RCSResourceObject::SetRequestHandlerPolicy convertJavasetRequestHandlerPolicyToNativePolicy(
+ int policy)
+{
+ switch (policy)
+ {
+ case 1:
+ return RCSResourceObject::SetRequestHandlerPolicy::NEVER;
+
+ case 2:
+ 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;
+}
--- /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_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_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_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 ( 0 == jTypeofDiscovery )
+ {
+ RCSDiscoveryManager::getInstance()->discoverResourceByType(RCSAddress::multicast(), relativeUri,
+ resourceType, discoverCallback);
+ LOGI("NativeInterface_discoverResource multicast");
+ }
+ else if ( 1 == 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)
+{
+ JniResourceStateChangeListener *onResourceStateChanged = addOnStateChangeListener(env, jListener);
+ RCSRemoteResourceObject::StateChangedCallback stateChangecb = [onResourceStateChanged](
+ OIC::Service::ResourceState state)
+ {
+ onResourceStateChanged->stateChangeCallback(state);
+ };
+ try
+ {
+ m_sharedResource->startMonitoring(stateChangecb);
+ }
+ catch (BadRequestException exception)
+ {
+ 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)
+{
+ 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->isMonitoring();
+}
+
+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)
+{
+ LOGD("RCSRemoteResourceObject_nativeGetRemoteAttributes");
+ JniRCSRemoteResourceObject *resource = JniRCSRemoteResourceObject::getJniRCSRemoteResourceObject(
+ env, interfaceClass);
+ resource->getCachedAttribute(env, jKey, interfaceClass);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ResourceEncapsulation_client_RCSRemoteResourceObject_nativeGetRemoteAttributes
+(JNIEnv *env, jobject interfaceClass, jobject jResourceAttributesListener)
+{
+ LOGD("RCSRemoteResourceObject_nativeGetRemoteAttributes");
+ 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");
+ 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_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_nativeSetValueStringN
+(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();
+ }
+ else
+ {
+ NativeRCSResourceObject = RCSResourceObject::Builder(resourceURI, resourceType,
+ resourceInterface).setDiscoverable((bool)jObservableFlag).setObservable((
+ bool)jObservableFlag).build();
+ }
+ }
+ catch (OIC::Service::PlatformException exception)
+ {
+ LOGE("nativeBuild : platform Exception");
+ throwRCSException(env, exception.what());
+ }
+
+ jobject jResource = env->NewObject(g_cls_RCSResourceObject, g_mid_RCSResourceObject_ctor);
+ JniRCSResourceObject *jniRCSResourceObject = new JniRCSResourceObject(NativeRCSResourceObject);
+ RESetHandle<JniRCSResourceObject>(env, jResource, jniRCSResourceObject);
+
+ return jResource;
+
+}
--- /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, "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();
+}
+
+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 RCSAddress.java
+ *
+ * @brief 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("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 RCSDiscoveryManager.java
+ *
+ * @brief 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
+ *
+ * {@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
+ *
+ * {@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
+ *
+ * {@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
+ *
+ * {@link RCSAddress}
+ *
+ */
+ public void discoverResourceByType(RCSAddress address, String relativeURI,
+ String resourceType) throws RCSException {
+
+ Log.i(LOG_TAG, "discoverResource called");
+ String addr = address.getAddress();
+ 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 RCSRemoteResourceObject.java
+ *
+ * @brief 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 IRemoteAttributeListener m_remoteAttributeListener;
+ 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(
+ IRemoteAttributeListener listener);
+
+ private native void nativeSetRemoteAttributes(
+ RCSResourceAttributes attributes, IRemoteAttributeListener 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];
+
+ 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) {
+
+ CacheState result = CacheState.values()[0];
+
+ if (ordinal == 1)
+ result = CacheState.values()[1];
+ else if (ordinal == 2)
+ result = CacheState.values()[2];
+ else if (ordinal == 3)
+ result = CacheState.values()[3];
+
+ return result;
+ }
+ }
+
+ /**
+ * 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
+ * and setRemoteAttributes requested actions.
+ */
+ public interface IRemoteAttributeListener {
+
+ /**
+ * This callback method is called when a asynchronous response for the
+ * getRemoteAttributes request or setRemoteAttributes 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 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
+ * SET and GET request.
+ *
+ * @param listener
+ * IRemoteAttributeListener to receive asynchronous response for
+ * resource attributes SET and GET request.
+ */
+ public void setRemoteAttributesListener(IRemoteAttributeListener listener) {
+ m_remoteAttributeListener = 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>
+ * IRemoteAttributeListener should be set to get the attributes
+ *
+ * {@link IRemoteAttributeListener}
+ */
+ public void getRemoteAttributes() throws RCSException {
+
+ Log.i(LOG_TAG, "getRemoteAttributes called");
+ this.nativeGetRemoteAttributes(m_remoteAttributeListener);
+ }
+
+ /**
+ * 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>
+ * IRemoteAttributeListener should be set to call this API
+ *
+ * {@link IRemoteAttributeListener}
+ */
+ public void setRemoteAttributes(RCSResourceAttributes attributes)
+ throws RCSException {
+
+ Log.i(LOG_TAG, "getRemoteAttributes called");
+ this.nativeSetRemoteAttributes(attributes, m_remoteAttributeListener);
+ }
+
+ /**
+ * 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;
+ }
+}
--- /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 RCSException.java
+ *
+ * @brief This file provides RCSException class for RE layer
+ *
+ */
+
+package org.iotivity.ResourceEncapsulation.common;
+
+/**
+ * This is the Exception class for the Resource Encapsulation APIs
+ */
+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 RCSResourceAttributes.java
+ *
+ * @brief 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<br/>
+ *
+ * <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.
+ *
+ */
+ 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.
+ *
+ */
+ 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.
+ *
+ */
+ 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.
+ *
+ */
+ 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 Builder.java
+ *
+ * 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("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 RCSGetResponse.java
+ *
+ * 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;
+ }
+
+ @SuppressWarnings("unused")
+ private int getTypeOfGetResponse() {
+ return m_typeOfGetResponse;
+ }
+
+ @SuppressWarnings("unused")
+ private int getResult() {
+ return m_handlerResult;
+ }
+
+ @SuppressWarnings("unused")
+ private int getErrorCode() {
+ return m_errorCode;
+ }
+
+ @SuppressWarnings("unused")
+ 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 RCSRequest.java
+ *
+ * This file provides RCSRequest class which will describes the request.
+ *
+ */
+
+package org.iotivity.ResourceEncapsulation.server;
+
+/**
+ * This class describes the request.
+ */
+public class RCSRequest {
+
+ private String m_resourceUri;
+
+ private RCSRequest(String resourceUri) {
+ m_resourceUri = resourceUri;
+ }
+
+ /**
+ * Returns the URI of the request.
+ *
+ * @return Uri of the request in string form
+ */
+ 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 RCSResourceObject.java
+ *
+ * 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.e(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.e(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.e(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.e(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.e(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.e(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.e(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.e(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.e(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.e(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.e(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.e(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.e(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.e(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.e(LOG_TAG, "setAutoNotifyPolicy called");
+ this.nativeSetAutoNotifyPolicy(policy.ordinal());
+ }
+
+ /**
+ * API for getting auto notify policy
+ *
+ * @return AntoNotify policy
+ *
+ * {@link AutoNotifyPolicy}
+ *
+ */
+ public AutoNotifyPolicy getAutoNotifyPolicy() {
+ Log.e(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.e(LOG_TAG, "setSetRequestHandlerPolicy called");
+ this.nativeSetSetRequestHandlerPolicy(policy.ordinal());
+ }
+
+ /**
+ * API for getting the SetRequestHandler Policy.
+ *
+ * @return Property of setRequesthandler
+ *
+ * {@link SetRequestHandlerPolicy}
+ *
+ */
+ public SetRequestHandlerPolicy getSetRequestHandlerPolicy() {
+ Log.e(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 RCSSetResponse.java
+ *
+ * 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;
+
+/**
+ * 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.
+ *
+ * @return RCSSetResponse
+ *
+ * {@link SetRequestHandlerPolicy}
+ */
+ 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;
+ }
+
+ @SuppressWarnings("unused")
+ private int getTypeOfGetResponse() {
+ return m_typeOfSetResponse;
+ }
+
+ @SuppressWarnings("unused")
+ private int getResult() {
+ return m_handlerResult;
+ }
+
+ @SuppressWarnings("unused")
+ private int getErrorCode() {
+ return m_errorCode;
+ }
+
+ @SuppressWarnings("unused")
+ 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 DiscoveryType.java
+ *
+ * @brief This file provides a Enum to handle unicast or multicast discovery.
+ *
+ *@link RCSAddress
+ */
+
+package org.iotivity.ResourceEncapsulation.utils;
+
+/**
+ * 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 int 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;
+ }
+}
--- /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 EntityHandlerResult.java
+ *
+ * @brief This file provides EntityHandlerResult Enum & utility function.
+ *
+ */
+
+package org.iotivity.ResourceEncapsulation.utils;
+
+/**
+ * Represents the EntityHandlerResult, that application can send for a Get or a
+ * Set request.
+ *
+ * {@link RCSResourceObject} {@link RCSGetResponse} {@link RCSSetResponse}
+ */
+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')
-
-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 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')
#define _EXPIRY_TIMER_H_
#include <functional>
-#include <list>
+#include <unordered_map>
+#include <memory>
-class ExpiryTimerImpl;
-
-class ExpiryTimer
+namespace OIC
{
-public:
- typedef unsigned int Id;
- typedef std::function<void(Id)> CB;
- typedef long long DelayInMilliSec;
+ namespace Service
+ {
+
+ class TimerTask;
+
+ class ExpiryTimer
+ {
+ public:
+ typedef unsigned int Id;
+ typedef std::function< void(Id) > Callback;
+ typedef long long DelayInMilliSec;
+
+ public:
+ ExpiryTimer();
+ ~ExpiryTimer();
+
+ ExpiryTimer(ExpiryTimer&&) = default;
+ ExpiryTimer& operator=(ExpiryTimer&&) = default;
+
+ ExpiryTimer(const ExpiryTimer&) = delete;
+ ExpiryTimer& operator=(const ExpiryTimer&) = delete;
+
+ Id post(DelayInMilliSec, Callback);
+ bool cancel(Id);
+ void cancelAll();
-public:
- ExpiryTimer();
- ~ExpiryTimer();
+ size_t getNumOfPending();
+ size_t getNumOfPending() const;
-public:
- Id postTimer(DelayInMilliSec, CB); // will change name to post()
- bool cancelTimer(Id); // will change name to cancel()
- void destroyTimer(); // This function will be removed
+ private:
+ void sweep();
-private:
- void cancelAll();
+ private:
+ size_t m_nextSweep;
-private:
- std::list<Id> m_timerIDList;
- ExpiryTimerImpl* timerPtr;
-};
+ std::unordered_map< Id, std::shared_ptr< TimerTask > > m_tasks;
+ };
+ }
+}
#endif //_EXPIRY_TIMER_H_
#include "ExpiryTimer.h"
#include "ExpiryTimerImpl.h"
-ExpiryTimer::ExpiryTimer()
+namespace OIC
{
- timerPtr = ExpiryTimerImpl::getInstance();
-}
+ namespace Service
+ {
-ExpiryTimer::~ExpiryTimer()
-{
- cancelAll();
-}
+ namespace
+ {
+ constexpr size_t DEFAULT_SWEEP_SIZE{ 50 };
+ }
-void ExpiryTimer::cancelAll()
-{
- for(auto id : m_timerIDList)
- {
- timerPtr->cancel(id);
- }
- m_timerIDList.clear();
-}
+ ExpiryTimer::ExpiryTimer() :
+ m_nextSweep { DEFAULT_SWEEP_SIZE }
+ {
+ }
-ExpiryTimer::Id ExpiryTimer::postTimer(DelayInMilliSec milliSec, CB cb)
-{
- Id retID = timerPtr->post(milliSec, std::move(cb));
- m_timerIDList.push_back(retID);
+ ExpiryTimer::~ExpiryTimer()
+ {
+ cancelAll();
+ }
- return retID;
-}
+ ExpiryTimer::Id ExpiryTimer::post(DelayInMilliSec milliSec, Callback cb)
+ {
+ auto task = ExpiryTimerImpl::getInstance()->post(milliSec, std::move(cb));
+ m_tasks[task->getId()] = task;
-bool ExpiryTimer::cancelTimer(Id id)
-{
- bool ret = timerPtr->cancel(id);
- m_timerIDList.remove(id);
+ if (m_tasks.size() == m_nextSweep) sweep();
- return ret;
-}
+ return task->getId();
+ }
-void ExpiryTimer::destroyTimer()
-{
+ bool ExpiryTimer::cancel(Id id)
+ {
+ auto it = m_tasks.find(id);
+
+ if (it == m_tasks.end()) return false;
+
+ auto task = it->second;
+ m_tasks.erase(it);
+
+ if (task->isExecuted()) return false;
+
+ return ExpiryTimerImpl::getInstance()->cancel(id);
+ }
+
+ void ExpiryTimer::cancelAll()
+ {
+ sweep();
+
+ std::unordered_set< std::shared_ptr< TimerTask > > set;
+
+ for(const auto& p : m_tasks)
+ {
+ set.insert(p.second);
+ }
+
+ ExpiryTimerImpl::getInstance()->cancelAll(set);
+ m_tasks.clear();
+ }
+
+ size_t ExpiryTimer::getNumOfPending()
+ {
+ sweep();
+ return m_tasks.size();
+ }
+
+ size_t ExpiryTimer::getNumOfPending() const
+ {
+ size_t ret{ 0 };
+
+ for (const auto& p : m_tasks)
+ {
+ ret += p.second->isExecuted() ? 0U : 1U;
+ }
+
+ return ret;
+ }
+
+ void ExpiryTimer::sweep()
+ {
+ for (auto it = m_tasks.begin(); it != m_tasks.end();)
+ {
+ if (it->second->isExecuted())
+ {
+ it = m_tasks.erase(it);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ m_nextSweep = m_tasks.size() << 1;
+ }
+
+ }
}
#include "ExpiryTimerImpl.h"
-#include <unistd.h>
-#include <cstdlib>
-#include <utility>
+#include "RCSException.h"
-ExpiryTimerImpl* ExpiryTimerImpl::s_instance = nullptr;
-std::once_flag* ExpiryTimerImpl::s_flag = new std::once_flag;
-
-ExpiryTimerImpl::ExpiryTimerImpl()
+namespace OIC
{
- m_engine = std::default_random_engine(m_device());
- m_checkerThread = std::thread(&ExpiryTimerImpl::runChecker, this);
-}
+ namespace Service
+ {
-ExpiryTimerImpl::~ExpiryTimerImpl()
-{
- m_checkerThread.join();
-}
+ namespace
+ {
+ constexpr ExpiryTimerImpl::Id INVALID_ID{ 0U };
+ }
-ExpiryTimerImpl* ExpiryTimerImpl::getInstance()
-{
- std::call_once(*s_flag, [](){ s_instance = new ExpiryTimerImpl(); });
- return s_instance;
-}
+ ExpiryTimerImpl::ExpiryTimerImpl() :
+ m_tasks{ },
+ m_thread{ std::thread(&ExpiryTimerImpl::run, this) },
+ m_mutex{ },
+ m_cond{ },
+ m_stop{ false },
+ m_mt{ std::random_device{ }() },
+ m_dist{ }
+ {
+ }
-ExpiryTimerImpl::Id ExpiryTimerImpl::post(DelayInMilliSec millisec, CB cb)
-{
- Id retID = generateId();
+ ExpiryTimerImpl::~ExpiryTimerImpl()
+ {
+ {
+ std::lock_guard< std::mutex > lock{ m_mutex };
+ m_tasks.clear();
+ m_stop = true;
+ }
+ m_cond.notify_all();
+ m_thread.join();
+ }
- MilliSeconds delay(millisec);
- insertTimerCBInfo(countExpireTime(delay), cb, retID);
+ ExpiryTimerImpl* ExpiryTimerImpl::getInstance()
+ {
+ static ExpiryTimerImpl instance;
+ return &instance;
+ }
- return retID;
-}
+ std::shared_ptr< TimerTask > ExpiryTimerImpl::post(DelayInMillis delay, Callback cb)
+ {
+ if (delay < 0LL)
+ {
+ throw InvalidParameterException{ "delay can't be negative." };
+ }
-bool ExpiryTimerImpl::cancel(Id id)
-{
- bool ret = false;
- std::lock_guard<std::mutex> lockf(m_mutex);
- for(auto it: m_timerCBList)
- {
- if(it.second.m_id == id)
+ if (!cb)
+ {
+ throw InvalidParameterException{ "callback is empty." };
+ }
+
+ return addTask(convertToTime(Milliseconds{ delay }), std::move(cb), generateId());
+ }
+
+ bool ExpiryTimerImpl::cancel(Id id)
{
- if(m_timerCBList.erase(it.first)!=0)
- ret = true;
- else
- ret = false;
+ if (id == INVALID_ID) return false;
+
+ std::lock_guard< std::mutex > lock{ m_mutex };
+
+ for(auto it = m_tasks.begin(); it != m_tasks.end(); ++it)
+ {
+ if(it->second->getId() == id)
+ {
+ m_tasks.erase(it);
+ return true;
+ }
+ }
+ return false;
}
- }
- return ret;
-}
-void ExpiryTimerImpl::insertTimerCBInfo(ExpiredTime msec, CB cb, Id id)
-{
- TimerCBInfo newInfo{id, cb};
- std::lock_guard<std::mutex> lockf(m_mutex);
- m_timerCBList.insert({msec, newInfo});
- m_cond.notify_all();
-}
+ size_t ExpiryTimerImpl::cancelAll(
+ const std::unordered_set< std::shared_ptr<TimerTask > >& tasks)
+ {
+ std::lock_guard< std::mutex > lock{ m_mutex };
+ size_t erased { 0 };
+
+ for(auto it = m_tasks.begin(); it != m_tasks.end();)
+ {
+ if(tasks.count(it->second))
+ {
+ it = m_tasks.erase(it);
+ ++erased;
+ }
+ else
+ {
+ ++it;
+ }
+ }
+ return erased;
+ }
-ExpiryTimerImpl::ExpiredTime ExpiryTimerImpl::countExpireTime(MilliSeconds msec)
-{
- auto now = std::chrono::system_clock::now();
- return std::chrono::duration_cast<MilliSeconds>(now.time_since_epoch()) + msec;
-}
+ ExpiryTimerImpl::Milliseconds ExpiryTimerImpl::convertToTime(Milliseconds delay)
+ {
+ const auto now = std::chrono::system_clock::now();
+ return std::chrono::duration_cast< Milliseconds >(now.time_since_epoch()) + delay;
+ }
-ExpiryTimerImpl::Id ExpiryTimerImpl::generateId()
-{
- Id retID = m_dist(m_device);
+ std::shared_ptr< TimerTask > ExpiryTimerImpl::addTask(
+ Milliseconds delay, Callback cb, Id id)
+ {
+ std::lock_guard< std::mutex > lock{ m_mutex };
+
+ auto newTask = std::make_shared< TimerTask >(id, std::move(cb));
+ m_tasks.insert({ delay, newTask });
+ m_cond.notify_all();
+
+ return newTask;
+ }
- for(auto it = m_timerCBList.begin(); it != m_timerCBList.end(); )
- {
- if(it->second.m_id == retID || retID == 0)
+ bool ExpiryTimerImpl::containsId(Id id) const
{
- retID = m_dist(m_device);
- it = m_timerCBList.begin();
+ for (const auto& info : m_tasks)
+ {
+ if (info.second->getId() == id) return true;
+ }
+ return false;
}
- else
- {
- ++it;
- }
- }
- return retID;
-}
+ ExpiryTimerImpl::Id ExpiryTimerImpl::generateId()
+ {
+ Id newId = m_dist(m_mt);
-void ExpiryTimerImpl::runChecker()
-{
- while(true)
- {
- std::unique_lock<std::mutex> ul(m_mutex);
+ std::lock_guard< std::mutex > lock{ m_mutex };
+
+ while (newId == INVALID_ID || containsId(newId))
+ {
+ newId = m_dist(m_mt);
+ }
+ return newId;
+ }
- if(m_timerCBList.empty())
+ void ExpiryTimerImpl::executeExpired()
{
- m_cond.wait(ul);
+ if (m_tasks.empty()) return;
+
+ auto now = std::chrono::system_clock::now().time_since_epoch();
+
+ auto it = m_tasks.begin();
+ for (; it != m_tasks.end() && it->first <= now; ++it)
+ {
+ it->second->execute();
+ }
+
+ m_tasks.erase(m_tasks.begin(), it);
}
- else
+
+ ExpiryTimerImpl::Milliseconds ExpiryTimerImpl::remainingTimeForNext() const
{
- ExpiredTime expireTime;
- expireTime = m_timerCBList.begin()->first;
+ const Milliseconds& expiredTime = m_tasks.begin()->first;
- auto now = std::chrono::system_clock::now();
- MilliSeconds waitTime = expireTime - std::chrono::duration_cast<MilliSeconds>(now.time_since_epoch());
- m_cond.wait_for(ul, waitTime);
+ return std::chrono::duration_cast< Milliseconds >(expiredTime -
+ std::chrono::system_clock::now().time_since_epoch()) + Milliseconds{ 1 };
+ }
+
+ void ExpiryTimerImpl::run()
+ {
+ auto hasTaskOrStop = [this](){ return !m_tasks.empty() || m_stop; };
+
+ std::unique_lock< std::mutex > lock{ m_mutex };
+
+ while(!m_stop)
+ {
+ m_cond.wait(lock, hasTaskOrStop);
- auto callTime = std::chrono::system_clock::now();
- runExecutor(std::chrono::duration_cast<MilliSeconds>(callTime.time_since_epoch()));
+ if (m_stop) break;
+
+ m_cond.wait_for(lock, remainingTimeForNext());
+
+ executeExpired();
+ }
}
- }
-}
-void ExpiryTimerImpl::runExecutor(ExpiredTime expireTime)
-{
- for(auto it = m_timerCBList.begin(); it != m_timerCBList.end(); ++it)
- {
- if(it->first <= expireTime)
+
+ TimerTask::TimerTask(ExpiryTimerImpl::Id id, ExpiryTimerImpl::Callback cb) :
+ m_id{ id },
+ m_callback{ std::move(cb) }
{
- ExecutorThread executor(it->second);
- m_timerCBList.erase(it);
}
- else
+
+ void TimerTask::execute()
{
- break;
+ if (isExecuted()) return;
+
+ ExpiryTimerImpl::Id id { m_id };
+ m_id = INVALID_ID;
+
+ std::thread(std::move(m_callback), id).detach();
+
+ m_callback = ExpiryTimerImpl::Callback{ };
}
- }
-}
-// ExecutorThread Class
-ExpiryTimerImpl::ExecutorThread::ExecutorThread(TimerCBInfo cbInfo)
-{
- m_executorThread = std::thread(&ExpiryTimerImpl::ExecutorThread::executorFunc, this, cbInfo);
-}
+ bool TimerTask::isExecuted() const
+ {
+ return m_id == INVALID_ID;
+ }
-ExpiryTimerImpl::ExecutorThread::~ExecutorThread()
-{
- m_executorThread.detach();
-}
+ ExpiryTimerImpl::Id TimerTask::getId() const
+ {
+ return m_id;
+ }
-void ExpiryTimerImpl::ExecutorThread::executorFunc(TimerCBInfo cbInfo)
-{
- cbInfo.m_cB(cbInfo.m_id);
+ }
}
#include <chrono>
#include <condition_variable>
#include <random>
+#include <unordered_set>
+#include <atomic>
-class ExpiryTimerImpl
+namespace OIC
{
-public:
- typedef unsigned int Id;
- typedef std::function<void(Id)> CB;
+ namespace Service
+ {
+ class TimerTask;
- typedef long long DelayInMilliSec;
- typedef std::chrono::milliseconds MilliSeconds;
- typedef std::chrono::duration<int64_t, std::milli> MilliDelayTime;
- typedef std::chrono::duration<int64_t, std::milli> ExpiredTime;
+ class ExpiryTimerImpl
+ {
+ public:
+ typedef unsigned int Id;
+ typedef std::function< void(Id) > Callback;
-private:
- struct TimerCBInfo
- {
- Id m_id;
- CB m_cB;
- };
+ typedef long long DelayInMillis;
+
+ private:
+ typedef std::chrono::milliseconds Milliseconds;
+
+ private:
+ ExpiryTimerImpl();
+ ~ExpiryTimerImpl();
+
+ ExpiryTimerImpl(const ExpiryTimerImpl&) = delete;
+ ExpiryTimerImpl& operator=(const ExpiryTimerImpl&) = delete;
+
+ public:
+ static ExpiryTimerImpl* getInstance();
+
+ std::shared_ptr< TimerTask > post(DelayInMillis, Callback);
+
+ bool cancel(Id);
+ size_t cancelAll(const std::unordered_set< std::shared_ptr<TimerTask > >&);
+
+ private:
+ static Milliseconds convertToTime(Milliseconds);
+
+ std::shared_ptr< TimerTask > addTask(Milliseconds, Callback, Id);
+
+ /**
+ * @pre The lock must be acquired with m_mutex.
+ */
+ bool containsId(Id) const;
+ Id generateId();
-private:
- ExpiryTimerImpl();
- ExpiryTimerImpl(const ExpiryTimerImpl&) = delete;
- ExpiryTimerImpl& operator=(const ExpiryTimerImpl&) = delete;
- ~ExpiryTimerImpl();
+ /**
+ * @pre The lock must be acquired with m_mutex.
+ */
+ void executeExpired();
-public:
- static ExpiryTimerImpl* getInstance();
- void destroyInstance();
+ /**
+ * @pre The lock must be acquired with m_mutex.
+ */
+ Milliseconds remainingTimeForNext() const;
- Id post(DelayInMilliSec, CB);
- bool cancel(Id);
+ void run();
-private:
- Id generateId();
+ private:
+ std::multimap< Milliseconds, std::shared_ptr< TimerTask > > m_tasks;
- void insertTimerCBInfo(ExpiredTime, CB ,Id);
- ExpiredTime countExpireTime(MilliSeconds);
+ std::thread m_thread;
+ std::mutex m_mutex;
+ std::condition_variable m_cond;
+ bool m_stop;
- void runChecker();
+ std::mt19937 m_mt;
+ std::uniform_int_distribution< Id > m_dist;
- void runExecutor(ExpiredTime);
+ };
-private:
- static ExpiryTimerImpl* s_instance;
- static std::once_flag* s_flag;
+ class TimerTask
+ {
+ public:
+ TimerTask(ExpiryTimerImpl::Id, ExpiryTimerImpl::Callback);
- std::multimap<ExpiredTime, TimerCBInfo> m_timerCBList;
+ TimerTask(const TimerTask&) = delete;
+ TimerTask(TimerTask&&) = delete;
- std::thread m_checkerThread;
- std::mutex m_mutex;
- std::condition_variable m_cond;
+ TimerTask& operator=(const TimerTask&) = delete;
+ TimerTask& operator=(TimerTask&&) = delete;
- std::random_device m_device;
- std::default_random_engine m_engine;
- std::uniform_int_distribution<Id> m_dist;
+ bool isExecuted() const;
+ ExpiryTimerImpl::Id getId() const;
-public:
- class ExecutorThread
- {
- public:
- ExecutorThread(TimerCBInfo);
- ~ExecutorThread();
+ private:
+ void execute();
- public:
- void executorFunc(TimerCBInfo);
+ private:
+ std::atomic< ExpiryTimerImpl::Id > m_id;
+ ExpiryTimerImpl::Callback m_callback;
- private:
- std::thread m_executorThread;
- };
-};
+ friend class ExpiryTimerImpl;
+ };
+ }
+}
#endif //_EXPIRY_TIMER_IMPL_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 <UnitTestHelper.h>
+
+#include <mutex>
+#include <atomic>
+
+#include "RCSException.h"
+#include "ExpiryTimer.h"
+#include "ExpiryTimerImpl.h"
+
+using namespace OIC::Service;
+
+constexpr int TOLERANCE_IN_MILLIS{ 50 };
+
+class FunctionObject
+{
+public:
+ virtual ~FunctionObject() { }
+
+ virtual void execute(ExpiryTimerImpl::Id) { }
+};
+
+class ExpiryTimerImplTest: public TestWithMock
+{
+public:
+ void Proceed()
+ {
+ cond.notify_all();
+ }
+
+ void Wait(int waitingTime = TOLERANCE_IN_MILLIS)
+ {
+ std::unique_lock< std::mutex > lock{ mutex };
+ cond.wait_for(lock, std::chrono::milliseconds{ waitingTime });
+ }
+
+private:
+ std::condition_variable cond;
+ std::mutex mutex;
+};
+
+
+TEST_F(ExpiryTimerImplTest, PostThrowsIfDelayIsNegative)
+{
+ ASSERT_THROW(ExpiryTimerImpl::getInstance()->post(-1, [](ExpiryTimerImpl::Id){}), RCSException);
+}
+
+TEST_F(ExpiryTimerImplTest, PostThrowsIfCallbackIsEmpty)
+{
+ ASSERT_THROW(ExpiryTimerImpl::getInstance()->post(1, { }), RCSException);
+}
+
+TEST_F(ExpiryTimerImplTest, CallbackBeInvokedWithinTolerance)
+{
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+
+ mocks.ExpectCall(functor, FunctionObject::execute).Do(
+ [this](ExpiryTimerImpl::Id){
+ Proceed();
+ }
+ );
+
+ ExpiryTimerImpl::getInstance()->post(10,
+ std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
+
+ Wait();
+}
+
+TEST_F(ExpiryTimerImplTest, CallbackBeInvokedWithTimerId)
+{
+ ExpiryTimerImpl::Id returnedId;
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+
+ mocks.ExpectCall(functor, FunctionObject::execute).Match(
+ [this, &returnedId](ExpiryTimerImpl::Id id){
+ return returnedId == id;
+ }
+ ).Do(
+ [this](ExpiryTimerImpl::Id){
+ Proceed();
+ }
+ );
+
+ returnedId = ExpiryTimerImpl::getInstance()->post(1,
+ std::bind(&FunctionObject::execute, functor, std::placeholders::_1))->getId();
+
+ Wait();
+}
+
+TEST_F(ExpiryTimerImplTest, CanceledTaskBeNotCalled)
+{
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+
+ mocks.NeverCall(functor, FunctionObject::execute);
+
+ ExpiryTimerImpl::Id id = ExpiryTimerImpl::getInstance()->post(10,
+ std::bind(&FunctionObject::execute, functor, std::placeholders::_1))->getId();
+ ExpiryTimerImpl::getInstance()->cancel(id);
+ Wait(100);
+}
+
+TEST_F(ExpiryTimerImplTest, CancelReturnsTrueIfCanceledCorrectly)
+{
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+
+ ExpiryTimerImpl::Id id = ExpiryTimerImpl::getInstance()->post(10,
+ std::bind(&FunctionObject::execute, functor, std::placeholders::_1))->getId();
+
+ ASSERT_TRUE(ExpiryTimerImpl::getInstance()->cancel(id));
+}
+
+TEST_F(ExpiryTimerImplTest, CancelReturnsFalseIfAlreadyExecuted)
+{
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+
+ mocks.ExpectCall(functor, FunctionObject::execute).Do(
+ [this](ExpiryTimerImpl::Id){
+ Proceed();
+ }
+ );
+
+ ExpiryTimerImpl::Id id = ExpiryTimerImpl::getInstance()->post(1,
+ std::bind(&FunctionObject::execute, functor, std::placeholders::_1))->getId();
+ Wait();
+
+ ASSERT_FALSE(ExpiryTimerImpl::getInstance()->cancel(id));
+}
+
+TEST_F(ExpiryTimerImplTest, CallbackBeInvokedWithinToleranceWithMultiplePost)
+{
+ constexpr int NUM_OF_POST{ 10000 };
+ std::atomic_int called{ 0 };
+
+ for (int i=0; i<NUM_OF_POST; ++i)
+ {
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+ mocks.OnCall(functor, FunctionObject::execute).Do(
+ [&called](ExpiryTimerImpl::Id)
+ {
+ ++called;
+ }
+ );
+
+ ExpiryTimerImpl::getInstance()->post(rand() % 20 + 5,
+ std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
+ }
+
+ Wait(TOLERANCE_IN_MILLIS + 25);
+
+ ASSERT_EQ(NUM_OF_POST, called);
+}
+
+class ExpiryTimerTest: public TestWithMock
+{
+public:
+ ExpiryTimer timer;
+
+public:
+ void Proceed()
+ {
+ cond.notify_all();
+ }
+
+ void Wait(int waitingTime = TOLERANCE_IN_MILLIS)
+ {
+ std::unique_lock< std::mutex > lock{ mutex };
+ cond.wait_for(lock, std::chrono::milliseconds{ waitingTime });
+ }
+
+private:
+ std::condition_variable cond;
+ std::mutex mutex;
+};
+
+TEST_F(ExpiryTimerTest, PostThrowsIfDelayIsNegative)
+{
+ ASSERT_THROW(timer.post(-1, [](ExpiryTimer::Id){}), RCSException);
+}
+
+TEST_F(ExpiryTimerTest, PostThrowsIfCallbackIsEmpty)
+{
+ ASSERT_THROW(timer.post(1, { }), RCSException);
+}
+
+TEST_F(ExpiryTimerTest, CallbackBeInvokedWithinTolerance)
+{
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+
+ mocks.ExpectCall(functor, FunctionObject::execute).Do(
+ [this](ExpiryTimer::Id){
+ Proceed();
+ }
+ );
+
+ timer.post(10,
+ std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
+
+ Wait();
+}
+
+TEST_F(ExpiryTimerTest, CallbackBeInvokedWithTimerId)
+{
+ ExpiryTimer::Id returnedId;
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+
+ mocks.ExpectCall(functor, FunctionObject::execute).Match(
+ [this, &returnedId](ExpiryTimer::Id id){
+ return returnedId == id;
+ }
+ ).Do(
+ [this](ExpiryTimer::Id){
+ Proceed();
+ }
+ );
+
+ returnedId = timer.post(1, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
+
+ Wait();
+}
+
+TEST_F(ExpiryTimerTest, CanceledTaskBeNotCalled)
+{
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+
+ mocks.NeverCall(functor, FunctionObject::execute);
+
+ auto id = timer.post(10, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
+ timer.cancel(id);
+ Wait(100);
+}
+
+TEST_F(ExpiryTimerTest, CancelReturnsTrueIfCanceledCorrectly)
+{
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+
+ auto id = timer.post(10, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
+
+ ASSERT_TRUE(timer.cancel(id));
+}
+
+TEST_F(ExpiryTimerTest, CancelReturnsFalseIfAlreadyExecuted)
+{
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+
+ mocks.ExpectCall(functor, FunctionObject::execute).Do(
+ [this](ExpiryTimer::Id){
+ Proceed();
+ }
+ );
+
+ auto id = timer.post(1, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
+ Wait();
+
+ ASSERT_FALSE(timer.cancel(id));
+}
+
+TEST_F(ExpiryTimerTest, NumOfPendingReturnsNumberOfNotExecuted)
+{
+ constexpr size_t numOfFutureTask{ 100 };
+ constexpr size_t numOfShortDelayTask{ 100 };
+
+ for (size_t i=0; i<numOfFutureTask; ++i)
+ {
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+ mocks.OnCall(functor, FunctionObject::execute);
+
+ timer.post(1000, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
+ }
+
+ for (size_t i=0; i<numOfShortDelayTask; ++i)
+ {
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+ mocks.OnCall(functor, FunctionObject::execute);
+
+ timer.post(i, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
+ }
+
+ Wait(numOfShortDelayTask + TOLERANCE_IN_MILLIS);
+
+ ASSERT_EQ(timer.getNumOfPending(), numOfFutureTask);
+}
+
+TEST_F(ExpiryTimerTest, CancelAllCancelsAllTasks)
+{
+ constexpr size_t numOfTask{ 100 };
+
+ for (size_t i=0; i<numOfTask; ++i)
+ {
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+ mocks.NeverCall(functor, FunctionObject::execute);
+
+ timer.post(50 + i, std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
+ }
+
+ timer.cancelAll();
+
+ Wait(200);
+}
+
+TEST_F(ExpiryTimerTest, AllTasksAreCancelledAfterTimerDestroyed)
+{
+ {
+ ExpiryTimer localTimer;
+ FunctionObject* functor = mocks.Mock< FunctionObject >();
+
+ mocks.NeverCall(functor, FunctionObject::execute);
+
+ localTimer.post(50,
+ std::bind(&FunctionObject::execute, functor, std::placeholders::_1));
+ }
+
+ Wait(200);
+}
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#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
#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
static ResourceBroker * getInstance();
- const BrokerID hostResource(PrimitiveResourcePtr pResource, BrokerCB cb);
+ BrokerID hostResource(PrimitiveResourcePtr pResource, BrokerCB cb);
void cancelHostResource(BrokerID brokerId);
BROKER_STATE getResourceState(BrokerID brokerId);
#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;
}
resourcePresenceList.clear();
OC_LOG_V(DEBUG,BROKER_TAG,"destroy Timer.");
- presenceTimer.destroyTimer();
}
void DevicePresence::initializeDevicePresence(PrimitiveResourcePtr pResource)
throw;
}
presenceTimerHandle
- = presenceTimer.postTimer(BROKER_DEVICE_PRESENCE_TIMEROUT, pTimeoutCB);
+ = 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()");
}
void DevicePresence::subscribeCB(OCStackResult ret,
- const unsigned int seq, const std::string& hostAddress)
+ const unsigned int seq, const std::string & hostAddress)
{
OC_LOG_V(DEBUG, BROKER_TAG, "subscribeCB()");
OC_LOG_V(DEBUG, BROKER_TAG, "Received presence CB from: %s",hostAddress.c_str());
std::unique_lock<std::mutex> lock(timeoutMutex);
condition.wait(lock);
}
- presenceTimer.cancelTimer(presenceTimerHandle);
+ presenceTimer.cancel(presenceTimerHandle);
switch(ret)
{
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.postTimer(BROKER_DEVICE_PRESENCE_TIMEROUT, pTimeoutCB);
+ = presenceTimer.post(BROKER_DEVICE_PRESENCE_TIMEROUT, pTimeoutCB);
break;
}
case OC_STACK_INVALID_REQUEST_HANDLE:
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;
}
}
}
- void DevicePresence::timeOutCB(TimerID id)
+ void DevicePresence::timeOutCB(TimerID /*id*/)
{
OC_LOG_V(DEBUG,BROKER_TAG,"timeOutCB()");
std::unique_lock<std::mutex> lock(timeoutMutex);
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;
return s_instance;
}
- const BrokerID ResourceBroker::hostResource(PrimitiveResourcePtr pResource, BrokerCB cb)
+ BrokerID ResourceBroker::hostResource(PrimitiveResourcePtr pResource, BrokerCB cb)
{
OC_LOG_V(DEBUG, BROKER_TAG, "hostResource().");
if(pResource == nullptr || cb == nullptr || cb == NULL)
= std::unique_ptr<std::list<BrokerRequesterInfoPtr>>
(new std::list<BrokerRequesterInfoPtr>);
- timeoutHandle = expiryTimer.postTimer(BROKER_SAFE_MILLISECOND, pTimeoutCB);
+ timeoutHandle = expiryTimer.post(BROKER_SAFE_MILLISECOND, pTimeoutCB);
OC_LOG_V(DEBUG,BROKER_TAG,"initializeResourcePresence::requestGet.\n");
primitiveResource->requestGet(pGetCB);
this->state = _state;
}
- void ResourcePresence::timeOutCB(unsigned int msg)
+ void ResourcePresence::timeOutCB(unsigned int /*msg*/)
{
OC_LOG_V(DEBUG, BROKER_TAG, "timeOutCB()");
OC_LOG_V(DEBUG, BROKER_TAG, "waiting for terminate getCB\n");
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;
pollingCB();
}
- void ResourcePresence::pollingCB(unsigned int msg)
+ void ResourcePresence::pollingCB(unsigned int /*msg*/)
{
OC_LOG_V(DEBUG, BROKER_TAG, "pollingCB().\n");
if(this->requesterList->size() != 0)
{
this->requestResourceState();
- timeoutHandle = expiryTimer.postTimer(BROKER_SAFE_MILLISECOND,pTimeoutCB);
+ timeoutHandle = expiryTimer.post(BROKER_SAFE_MILLISECOND,pTimeoutCB);
}
}
- void ResourcePresence::getCB(const HeaderOptions &hos,
- const ResponseStatement& rep, int eCode)
+ void ResourcePresence::getCB(const HeaderOptions & /*hos*/,
+ const ResponseStatement & /*rep*/, int eCode)
{
OC_LOG_V(DEBUG, BROKER_TAG, "getCB().\n");
OC_LOG_V(DEBUG, BROKER_TAG, "waiting for terminate TimeoutCB.\n");
if(isWithinTime)
{
- expiryTimer.cancelTimer(timeoutHandle);
+ expiryTimer.cancel(timeoutHandle);
isWithinTime = true;
}
if(mode == BROKER_MODE::NON_PRESENCE_MODE)
{
- expiryTimer.postTimer(BROKER_SAFE_MILLISECOND,pPollingCB);
+ expiryTimer.post(BROKER_SAFE_MILLISECOND,pPollingCB);
}
}
OC_LOG_V(DEBUG, BROKER_TAG, "changePresenceMode()\n");
if(newMode != mode)
{
- expiryTimer.cancelTimer(timeoutHandle);
+ expiryTimer.cancel(timeoutHandle);
if(newMode == BROKER_MODE::NON_PRESENCE_MODE)
{
- timeoutHandle = expiryTimer.postTimer(BROKER_SAFE_MILLISECOND,pTimeoutCB);
+ timeoutHandle = expiryTimer.post(BROKER_SAFE_MILLISECOND,pTimeoutCB);
requestResourceState();
}
mode = newMode;
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();
void MockingFunc()
{
- mocks.OnCall(pResource.get(), PrimitiveResource::requestGet).Do([](GetCallback cb){});
+ mocks.OnCall(pResource.get(), PrimitiveResource::requestGet).Do([](GetCallback){});
mocks.OnCall(pResource.get(), PrimitiveResource::getHost).Return(std::string());
mocks.OnCallFuncOverload(static_cast< subscribePresenceSig1 >(OC::OCPlatform::subscribePresence)).Return(OC_STACK_OK);
}
});
mocks.OnCall(pResource.get(), PrimitiveResource::requestGet).Do(
- [](GetCallback callback){
+ [](GetCallback){
std::cout <<"End call requestGetFunc()\n";
});
mocks.OnCall(pResource.get(), PrimitiveResource::getHost).Return("address1");
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'
broker_test_env.PrependUnique(CPPPATH = [env.get('SRC_DIR')+'/extlibs/hippomocks-master',
gtest_dir + '/include'])
broker_test_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
-broker_test_env.PrependUnique(LIBS = ['rcs_client','rcs_common', 'oc', 'octbstack', 'oc_logger', 'connectivity_abstraction', 'libcoap', gtest, gtest_main])
+broker_test_env.PrependUnique(LIBS = ['rcs_client','rcs_common', 'oc', 'octbstack', 'oc_logger', 'connectivity_abstraction', 'coap', gtest, gtest_main])
if target_os not in ['windows', 'winrt']:
broker_test_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-fmessage-length=0', '-std=c++0x'])
Alias("broker_test", broker_test)
env.AppendTarget('broker_test')
-
+if env.get('TEST') == '1':
+ target_os = env.get('TARGET_OS')
+ if target_os == 'linux':
+ from tools.scons.RunTest import *
+ run_test(broker_test_env,
+ '',
+ 'service/resource-encapsulation/src/resourceBroker/unittest/broker_test')
{
sResource->requestObserve(pObserveCB);
}
- networkTimeOutHandle = networkTimer.postTimer(CACHE_DEFAULT_EXPIRED_MILLITIME, pTimerCB);
+ networkTimeOutHandle = networkTimer.post(CACHE_DEFAULT_EXPIRED_MILLITIME, pTimerCB);
}
CacheID DataCache::addSubscriber(CacheCB func, REPORT_FREQUENCY rf, long repeatTime)
mode = CACHE_MODE::OBSERVE;
}
- networkTimer.cancelTimer(networkTimeOutHandle);
- networkTimeOutHandle = networkTimer.postTimer(CACHE_DEFAULT_EXPIRED_MILLITIME, pTimerCB);
+ networkTimer.cancel(networkTimeOutHandle);
+ networkTimeOutHandle = networkTimer.post(CACHE_DEFAULT_EXPIRED_MILLITIME, pTimerCB);
notifyObservers(_rep.getAttributes());
}
if (mode != CACHE_MODE::OBSERVE)
{
- networkTimer.cancelTimer(networkTimeOutHandle);
- networkTimeOutHandle = networkTimer.postTimer(
+ networkTimer.cancel(networkTimeOutHandle);
+ networkTimeOutHandle = networkTimer.post(
CACHE_DEFAULT_EXPIRED_MILLITIME, pTimerCB);
- pollingHandle = pollingTimer.postTimer(CACHE_DEFAULT_REPORT_MILLITIME, pPollingCB);
+ pollingHandle = pollingTimer.post(CACHE_DEFAULT_REPORT_MILLITIME, pPollingCB);
}
notifyObservers(_rep.getAttributes());
sResource->cancelObserve();
mode = CACHE_MODE::FREQUENCY;
- networkTimer.cancelTimer(networkTimeOutHandle);
- networkTimeOutHandle = networkTimer.postTimer(
+ networkTimer.cancel(networkTimeOutHandle);
+ networkTimeOutHandle = networkTimer.post(
CACHE_DEFAULT_EXPIRED_MILLITIME, pTimerCB);
- pollingHandle = pollingTimer.postTimer(CACHE_DEFAULT_REPORT_MILLITIME, pPollingCB);
+ pollingHandle = pollingTimer.post(CACHE_DEFAULT_REPORT_MILLITIME, pPollingCB);
return;
}
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'
}
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));
+ }
- if (resourceURI.empty())
- {
- OC_LOG(ERROR, TAG, "discoverResource NULL resourceURI");
- throw InvalidParameterException{ "discoverResource NULL resourceURI'" };
- }
+ 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)));
+ }
}
}
}
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 == 'linux':
+ 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
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#if defined(__linux__)
+#include <unistd.h>
+#endif
+
#include "RCSResourceContainer.h"
#include "RCSBundleInfo.h"
#include "oc_logger.hpp"
using namespace OIC::Service;
using OC::oc_log_stream;
+#define MAX_PATH 2048
+
/* Annother way to create a context: */
auto info_logger = []() -> boost::iostreams::stream<OC::oc_log_stream> &
{
return os;
};
+void getCurrentPath(std::string *pPath)
+{
+ char buffer[MAX_PATH];
+
+#if defined(__linux__)
+ char *strPath = NULL;
+ int length = readlink("/proc/self/exe", buffer, MAX_PATH - 1);
+
+ if (length != -1)
+ {
+ buffer[length] = '\0';
+ strPath = strrchr(buffer, '/');
+
+ if (strPath != NULL)
+ *strPath = '\0';
+ }
+#endif
+ pPath->append(buffer);
+}
+
int main()
{
info_logger()->set_module("ContainerTest");
info_logger() << "Starting container test." << std::flush;
+ std::string strConfigPath;
+ getCurrentPath(&strConfigPath);
+ strConfigPath.append("/examples/ResourceContainerConfig.xml");
+
RCSResourceContainer *container = RCSResourceContainer::getInstance();
- container->startContainer("examples/ResourceContainerConfig.xml");
+ container->startContainer(strConfigPath);
/*so bundle add test*/
cout << "++++++++++++++++++++++++++" << endl;
HueLight::HueLight()
{
-
+ m_connector = nullptr;
}
HueLight::HueLight(HueConnector *connector, std::string address)
HueLight::~HueLight()
{
-
+ m_connector = nullptr;
}
void HueLight::initAttributes()
HueSampleBundleActivator::HueSampleBundleActivator()
{
+ m_pResourceContainer = nullptr;
+ m_connector = nullptr;
}
HueSampleBundleActivator::~HueSampleBundleActivator()
{
+ m_pResourceContainer = nullptr;
+ m_connector = nullptr;
}
void HueSampleBundleActivator::activateBundle(ResourceContainerBundleAPI *resourceContainer,
SoftSensorBundleActivator::SoftSensorBundleActivator()
{
+ m_pResourceContainer = nullptr;
}
SoftSensorBundleActivator::~SoftSensorBundleActivator()
{
+ m_pResourceContainer = nullptr;
}
void SoftSensorBundleActivator::activateBundle(ResourceContainerBundleAPI *resourceContainer,
private:
void getConfigDocument(string pathConfigFile);
- void getCurrentPath(string *pPath);
bool m_loaded;
string m_pathConfigFile;
{
m_activator = nullptr;
m_deactivator = nullptr;
+ m_resourceCreator = nullptr;
+ m_resourceDestroyer = nullptr;
m_bundleHandle = nullptr;
m_loaded = false;
m_activated = false;
+ m_java_bundle = false;
+ m_id = 0;
}
BundleInfoInternal::~BundleInfoInternal()
{
m_activator = nullptr;
m_deactivator = nullptr;
+ m_resourceCreator = nullptr;
+ m_resourceDestroyer = nullptr;
m_bundleHandle = nullptr;
}
void BundleInfoInternal::setBundleInfo(RCSBundleInfo *bundleInfo)
{
- m_ID = bundleInfo->getID();
- m_path = bundleInfo->getPath();
- m_version = bundleInfo->getPath();
+ BundleInfoInternal *source = (BundleInfoInternal *)bundleInfo;
+ m_ID = source->getID();
+ m_path = source->getPath();
+ m_version = source->getVersion();
+ m_loaded = source->isLoaded();
+ m_activated = source->isActivated();
+ m_java_bundle = source->getJavaBundle();
+ m_activator = source->getBundleActivator();
+ m_bundleHandle = source->getBundleHandle();
}
}
}
{
BundleResource::BundleResource()
{
-
+ m_pNotiReceiver = nullptr;
}
BundleResource::~BundleResource()
{
-
+ m_pNotiReceiver = nullptr;
}
void BundleResource::registerObserver(NotificationReceiver *pNotiReceiver)
std::list< string > BundleResource::getAttributeNames()
{
std::list< string > ret;
- for (RCSResourceAttributes::iterator it = m_resourceAttributes.begin(); it != m_resourceAttributes.end(); ++it){
+ for (RCSResourceAttributes::iterator it = m_resourceAttributes.begin();
+ it != m_resourceAttributes.end(); ++it)
+ {
ret.push_back(it->key());
}
return ret;
}
- RCSResourceAttributes& BundleResource::getAttributes(){
+ RCSResourceAttributes &BundleResource::getAttributes()
+ {
return m_resourceAttributes;
}
- void BundleResource::setAttribute(std::string key, RCSResourceAttributes::Value&& value)
+ void BundleResource::setAttribute(std::string key, RCSResourceAttributes::Value &&value)
{
- cout << "Bundle resource set attribute " << value.toString() << "|" << endl;
m_resourceAttributes[key] = value;
}
- RCSResourceAttributes::Value BundleResource::getAttribute(const std::string& key){
+ RCSResourceAttributes::Value BundleResource::getAttribute(const std::string &key)
+ {
cout << "Bundle resource get attribute " << m_resourceAttributes.at(key).toString() << "|" << endl;
return m_resourceAttributes.at(key);
}
{
m_loaded = false;
- getCurrentPath(&m_pathConfigFile);
- m_pathConfigFile.append("/");
m_pathConfigFile.append(configFile);
getConfigDocument(m_pathConfigFile);
{
//cout << "Name of first node is: " << m_xmlDoc.first_node()->name() << endl;
- for (bundle = m_xmlDoc.first_node()->first_node("bundle"); bundle; bundle = bundle->next_sibling())
+ for (bundle = m_xmlDoc.first_node()->first_node("bundle"); bundle; bundle =
+ bundle->next_sibling())
{
std::map< std::string, std::string > bundleMap;
//cout << "Bundle: " << bundle->name() << endl;
- for (subItem = bundle->first_node(); subItem; subItem = subItem->next_sibling())
+ for (subItem = bundle->first_node(); subItem;
+ subItem = subItem->next_sibling())
{
strKey = subItem->name();
strValue = subItem->value();
if (strlen(subItem->value()) > 0)
{
- bundleMap.insert(std::make_pair(trim_both(strKey), trim_both(strValue)));
+ bundleMap.insert(
+ std::make_pair(trim_both(strKey), trim_both(strValue)));
//cout << strKey << " " << strValue << endl;
}
}
std::map< std::string, std::string > bundleConfigMap;
// <bundle>
- for (bundle = m_xmlDoc.first_node()->first_node("bundle"); bundle; bundle = bundle->next_sibling())
+ for (bundle = m_xmlDoc.first_node()->first_node("bundle"); bundle; bundle =
+ bundle->next_sibling())
{
// <id>
strBundleId = bundle->first_node("id")->value();
// <version>
strVersion = bundle->first_node("version")->value();
- bundleConfigMap.insert(std::make_pair("version", trim_both(strVersion)));
+ bundleConfigMap.insert(
+ std::make_pair("version", trim_both(strVersion)));
configOutput->push_back(bundleConfigMap);
try
{
// <bundle>
- for (bundle = m_xmlDoc.first_node()->first_node("bundle"); bundle; bundle = bundle->next_sibling())
+ for (bundle = m_xmlDoc.first_node()->first_node("bundle"); bundle; bundle =
+ bundle->next_sibling())
{
// <id>
strBundleId = bundle->first_node("id")->value();
if (!strBundleId.compare(bundleId))
{
// <resourceInfo>
- for (resource = bundle->first_node("resources")->first_node("resourceInfo"); resource;
- resource = resource->next_sibling())
+ for (resource = bundle->first_node("resources")->first_node(
+ "resourceInfo"); resource; resource = resource->next_sibling())
{
resourceInfo tempResourceInfo;
- for (item = resource->first_node(); item; item = item->next_sibling())
+ for (item = resource->first_node(); item; item =
+ item->next_sibling())
{
strKey = item->name();
strValue = item->value();
else
{
- for (subItem = item->first_node(); subItem; subItem = subItem->next_sibling())
+ for (subItem = item->first_node(); subItem; subItem =
+ subItem->next_sibling())
{
map< string, string > propertyMap;
strKey = subItem->name();
- for (subItem2 = subItem->first_node(); subItem2; subItem2 = subItem2->next_sibling())
+ for (subItem2 = subItem->first_node(); subItem2;
+ subItem2 = subItem2->next_sibling())
{
string newStrKey = subItem2->name();
string newStrValue = subItem2->value();
- propertyMap[trim_both(newStrKey)] = trim_both(newStrValue);
+ propertyMap[trim_both(newStrKey)] = trim_both(
+ newStrValue);
}
- tempResourceInfo.resourceProperty[trim_both(strKey)].push_back(propertyMap);
+ tempResourceInfo.resourceProperty[trim_both(strKey)].push_back(
+ propertyMap);
}
}
}
try
{
- m_xmlDoc.parse< 0 >((char *)m_strConfigData.c_str());
+ m_xmlDoc.parse< 0 >((char *) m_strConfigData.c_str());
m_loaded = true;
}
catch (rapidxml::parse_error &e)
std::cout << "Configuration File load failed !!" << std::endl;
}
}
-
- void Configuration::getCurrentPath(std::string *pPath)
- {
- char buffer[2048];
- char *strPath = NULL;
-
- int length = readlink("/proc/self/exe", buffer, 2047);
-
- buffer[length] = '\0';
-
- strPath = strrchr(buffer, '/');
-
- *strPath = '\0';
-
- pPath->append(buffer);
- }
}
}
info_logger() << "Resource container without Java support" << endl;
#endif
- if(!configFile.empty()){
+ if (!configFile.empty())
+ {
m_config = new Configuration(configFile);
if (m_config->isLoaded())
error_logger() << "Container started with invalid configfile path" << endl;
}
}
- else{
+ else
+ {
info_logger() << "No configuration file for the container provided" << endl;
}
}
m_mapBundleResources.clear();
}
- delete m_config;
+ if (m_config)
+ delete m_config;
}
void ResourceContainerImpl::activateBundle(RCSBundleInfo *bundleInfo)
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)
{
return &m_instance;
}
- RCSResourceObject::Ptr ResourceContainerImpl::buildResourceObject(const std::string & strUri,
- const std::string & strResourceType)
+ RCSResourceObject::Ptr ResourceContainerImpl::buildResourceObject(const std::string &strUri,
+ const std::string &strResourceType)
{
return RCSResourceObject::Builder(strUri, strResourceType, "DEFAULT_INTERFACE").setObservable(
true).setDiscoverable(true).build();
}
}
- void ResourceContainerImpl::addBundle(const std::string &bundleId, const std::string &bundleUri, const std::string &bundlePath,
+ void ResourceContainerImpl::addBundle(const std::string &bundleId, const std::string &bundleUri,
+ const std::string &bundlePath,
std::map< string, string > params)
{
if (m_bundles.find(bundleId) != m_bundles.end())
{
RCSBundleInfo *bundleInfo = RCSBundleInfo::build();
((BundleInfoInternal *) bundleInfo)->setBundleInfo((RCSBundleInfo *) it->second);
- ret.push_back(it->second);
+ ret.push_back(bundleInfo);
}
}
return ret;
}
- void ResourceContainerImpl::addResourceConfig(const std::string &bundleId, const std::string &resourceUri,
+ void ResourceContainerImpl::addResourceConfig(const std::string &bundleId,
+ const std::string &resourceUri,
std::map< string, string > params)
{
if (m_bundles.find(bundleId) != m_bundles.end())
}
}
- void ResourceContainerImpl::removeResourceConfig(const std::string &bundleId, const std::string &resourceUri)
+ void ResourceContainerImpl::removeResourceConfig(const std::string &bundleId,
+ const std::string &resourceUri)
{
if (m_bundles.find(bundleId) != m_bundles.end())
{
void ResourceContainerImpl::registerSoBundle(RCSBundleInfo *bundleInfo)
{
- char *error;
+ const char *error;
activator_t *bundleActivator = NULL;
deactivator_t *bundleDeactivator = NULL;
}
}
- void ResourceContainerImpl::removeSoBundleResource(const std::string &bundleId, const std::string &resourceUri)
+ void ResourceContainerImpl::removeSoBundleResource(const std::string &bundleId,
+ const std::string &resourceUri)
{
if (m_mapResources.find(resourceUri) != m_mapResources.end())
{
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#if defined(__linux__)
+#include <unistd.h>
+#endif
+
#include <string>
#include <map>
#include <vector>
using namespace testing;
using namespace OIC::Service;
+#define MAX_PATH 2048
+
string CONFIG_FILE = "ResourceContainerTestConfig.xml";
+void getCurrentPath(std::string *pPath)
+{
+ char buffer[MAX_PATH];
+
+#if defined(__linux__)
+ char *strPath = NULL;
+ int length = readlink("/proc/self/exe", buffer, MAX_PATH - 1);
+
+ if (length != -1)
+ {
+ buffer[length] = '\0';
+ strPath = strrchr(buffer, '/');
+
+ if (strPath != NULL)
+ *strPath = '\0';
+ }
+#endif
+ pPath->append(buffer);
+}
/*Fake bundle resource class for testing*/
class TestBundleResource: public BundleResource
public:
RCSResourceContainer *m_pResourceContainer;
+ std::string m_strConfigPath;
protected:
void SetUp()
{
TestWithMock::SetUp();
m_pResourceContainer = RCSResourceContainer::getInstance();
+ getCurrentPath(&m_strConfigPath);
+ m_strConfigPath.append("/");
+ m_strConfigPath.append(CONFIG_FILE);
}
};
TEST_F(ResourceContainerTest, BundleRegisteredWhenContainerStartedWithValidConfigFile)
{
- m_pResourceContainer->startContainer(CONFIG_FILE);
+ m_pResourceContainer->startContainer(m_strConfigPath);
EXPECT_GT(m_pResourceContainer->listBundles().size(), (unsigned int) 0);
EXPECT_STREQ("oic.bundle.test",
TEST_F(ResourceContainerTest, BundleLoadedWhenContainerStartedWithValidConfigFile)
{
- m_pResourceContainer->startContainer(CONFIG_FILE);
+ m_pResourceContainer->startContainer(m_strConfigPath);
EXPECT_GT(m_pResourceContainer->listBundles().size(), (unsigned int) 0);
EXPECT_TRUE(((BundleInfoInternal *)(*m_pResourceContainer->listBundles().begin()))->isLoaded());
TEST_F(ResourceContainerTest, BundleActivatedWhenContainerStartedWithValidConfigFile)
{
- m_pResourceContainer->startContainer(CONFIG_FILE);
+ m_pResourceContainer->startContainer(m_strConfigPath);
EXPECT_GT(m_pResourceContainer->listBundles().size(), (unsigned int) 0);
EXPECT_TRUE(
TEST_F(ResourceContainerTest, BundleUnregisteredWhenContainerStopped)
{
- m_pResourceContainer->startContainer(CONFIG_FILE);
+ m_pResourceContainer->startContainer(m_strConfigPath);
m_pResourceContainer->stopContainer();
EXPECT_EQ((unsigned int) 0, m_pResourceContainer->listBundles().size());
TEST_F(ResourceContainerTest, BundleStoppedWithStartBundleAPI)
{
- m_pResourceContainer->startContainer(CONFIG_FILE);
+ m_pResourceContainer->startContainer(m_strConfigPath);
m_pResourceContainer->stopBundle("oic.bundle.test");
EXPECT_FALSE(
TEST_F(ResourceContainerTest, BundleStartedWithStartBundleAPI)
{
- m_pResourceContainer->startContainer(CONFIG_FILE);
+ m_pResourceContainer->startContainer(m_strConfigPath);
m_pResourceContainer->stopBundle("oic.bundle.test");
m_pResourceContainer->startBundle("oic.bundle.test");
std::map<string, string> resourceParams;
resourceParams["resourceType"] = "oic.test";
- m_pResourceContainer->startContainer(CONFIG_FILE);
+ m_pResourceContainer->startContainer(m_strConfigPath);
resources = m_pResourceContainer->listBundleResources("oic.bundle.test");
m_pResourceContainer->addResourceConfig("oic.bundle.test", "/test_resource", resourceParams);
RCSResourceObject *m_pResourceObject;
ResourceContainerBundleAPI *m_pResourceContainer;
TestBundleResource *m_pBundleResource;
+ std::string m_strConfigPath;
protected:
void SetUp()
m_pResourceObject = mocks.Mock<RCSResourceObject>();
m_pResourceContainer = ResourceContainerBundleAPI::getInstance();
+ getCurrentPath(&m_strConfigPath);
+ m_strConfigPath.append("/");
+ m_strConfigPath.append(CONFIG_FILE);
+
m_pBundleResource = new TestBundleResource();
m_pBundleResource->m_bundleId = "oic.bundle.test";
m_pBundleResource->m_uri = "/test_resource";
configInfo bundle;
map< string, string > results;
- ((ResourceContainerImpl *)m_pResourceContainer)->startContainer(CONFIG_FILE);
+ ((ResourceContainerImpl *)m_pResourceContainer)->startContainer(m_strConfigPath);
m_pResourceContainer->getBundleConfiguration("oic.bundle.test", &bundle);
results = *bundle.begin();
vector< resourceInfo > resourceConfig;
resourceInfo result;
- ((ResourceContainerImpl *)m_pResourceContainer)->startContainer(CONFIG_FILE);
+ ((ResourceContainerImpl *)m_pResourceContainer)->startContainer(m_strConfigPath);
m_pResourceContainer->getResourceConfiguration("oic.bundle.test", &resourceConfig);
result = *resourceConfig.begin();
/* Test for Configuration */
TEST(ConfigurationTest, ConfigFileLoadedWithValidPath)
{
- Configuration *config = new Configuration(CONFIG_FILE);
+ std::string strConfigPath;
+ getCurrentPath(&strConfigPath);
+ strConfigPath.append("/");
+ strConfigPath.append(CONFIG_FILE);
+
+ Configuration *config = new Configuration(strConfigPath);
EXPECT_TRUE(config->isLoaded());
}
TEST(ConfigurationTest, BundleConfigurationListParsed)
{
- Configuration *config = new Configuration(CONFIG_FILE);
+ std::string strConfigPath;
+ getCurrentPath(&strConfigPath);
+ strConfigPath.append("/");
+ strConfigPath.append(CONFIG_FILE);
+
+ Configuration *config = new Configuration(strConfigPath);
configInfo bundles;
map< string, string > results;
TEST(ConfigurationTest, BundleConfigurationParsedWithValidBundleId)
{
- Configuration *config = new Configuration(CONFIG_FILE);
+ std::string strConfigPath;
+ getCurrentPath(&strConfigPath);
+ strConfigPath.append("/");
+ strConfigPath.append(CONFIG_FILE);
+
+ Configuration *config = new Configuration(strConfigPath);
configInfo bundle;
map< string, string > results;
TEST(ConfigurationTest, BundleConfigurationNotParsedWithInvalidBundleId)
{
- Configuration *config = new Configuration(CONFIG_FILE);
+ std::string strConfigPath;
+ getCurrentPath(&strConfigPath);
+ strConfigPath.append("/");
+ strConfigPath.append(CONFIG_FILE);
+
+ Configuration *config = new Configuration(strConfigPath);
configInfo bundles;
config->getBundleConfiguration("test", &bundles);
TEST(ConfigurationTest, BundleResourceConfigurationListParsed)
{
- Configuration *config = new Configuration(CONFIG_FILE);
+ std::string strConfigPath;
+ getCurrentPath(&strConfigPath);
+ strConfigPath.append("/");
+ strConfigPath.append(CONFIG_FILE);
+
+ Configuration *config = new Configuration(strConfigPath);
vector< resourceInfo > resourceConfig;
resourceInfo result;
TEST(ConfigurationTest, BundleResourceConfigurationNotParsedWithInvalidBundleId)
{
- Configuration *config = new Configuration(CONFIG_FILE);
+ std::string strConfigPath;
+ getCurrentPath(&strConfigPath);
+ strConfigPath.append("/");
+ strConfigPath.append(CONFIG_FILE);
+
+ Configuration *config = new Configuration(strConfigPath);
configInfo bundles;
vector< resourceInfo > resourceConfig;
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')]
Ignore("./ResourceContainerInvalidConfig.xml", "./ResourceContainerInvalidConfig.xml")
Command("./TestBundleJava/hue-0.1-jar-with-dependencies.jar","./TestBundleJava/hue-0.1-jar-with-dependencies.jar", Copy("$TARGET", "$SOURCE"))
Ignore("./TestBundleJava/hue-0.1-jar-with-dependencies.jar", "./TestBundleJava/hue-0.1-jar-with-dependencies.jar")
+
+if env.get('TEST') == '1':
+ target_os = env.get('TARGET_OS')
+ if target_os == 'linux':
+ from tools.scons.RunTest import *
+ run_test(container_gtest_env,
+ '',
+ 'service/resource-encapsulation/src/resourceContainer/unittests/container_test')
\ No newline at end of file
######################################################################
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 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
ResourceClient_gtest_src = env.Glob('./*.cpp')
ResourceClient_test = ResourceClient_gtest_env.Program('ResourceClientTest', ResourceClient_gtest_src)
-Alias("ResourceClient_Test", ResourceClient_test)
+Alias("ResourceClientTest", ResourceClient_test)
env.AppendTarget('ResourceClient_test')
+if env.get('TEST') == '1':
+ target_os = env.get('TARGET_OS')
+ if target_os == 'linux':
+ from tools.scons.RunTest import *
+ run_test(ResourceClient_gtest_env, '',
+ 'service/resource-encapsulation/unittests/ResourceClientTest')
\ No newline at end of file
== 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;
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
ISSMResource()
{
location = SENSOR_LOCATION_LOCAL;
+ connectivityType = 0;
}
ISSMResource(const std::string &n, const std::string &t) :
name(n), type(t)
{
location = SENSOR_LOCATION_LOCAL;
+ connectivityType = 0;
}
SENSOR_LOCATION location;
std::string name;
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.
-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
ehRet = OC_EH_ERROR;
}
}
-
+
}
else if (flag & OC_OBSERVE_FLAG)
{
-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
-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
-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
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
g_thingsmanager->findCandidateResources(types, &onFoundCollectionResource, 5);
std::cout << "Finding Collection resource... " << std::endl;
-
+
pthread_mutex_lock(&mutex_lock);
isWaiting = 1;
pthread_mutex_unlock(&mutex_lock);
* 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.
+ * @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.
+ * @return 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,
/**
* 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.
+ * @param resource collection resource for subscribing presence of all child resources.
+ * @param callback callback funcion for result of child's presence.
*
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return 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.
+ * @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.
*
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult bindResourceToGroup(OCResourceHandle& childHandle,
std::shared_ptr< OCResource > resource, OCResourceHandle& 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 collectionResourceTypes - resource types of a group to find and join
- * @param callback - callback. It has OCResource param.
+ * @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.
+ * @return Returns ::OC_STACK_OK if success.
+ * @note It returns 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.
*/
/**
* 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.
+ * @param collectionResourceType resource type of a group to create
*
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return 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.
+ * @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.
+ * @return Returns ::OC_STACK_OK if success.
*
- * NOTE: If you want to join the resource in the remote(other) process,
+ * @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.
* 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 resource group resource pointer to join.
* It can be the callback result of findGroup().
- * @param resourceHandle - resource handle to join a group.
+ * @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,
+ * @return Returns ::OC_STACK_OK if success.
+ * @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.
/**
* 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.
+ * @param collectionResourceType resource type of a group to leave.
+ * @param resourceHandle resource handle to leave a group.
*
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return 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.
+ * @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.
+ * @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.
+ * @return Returns ::OC_STACK_OK if success.
*
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult leaveGroup(const std::shared_ptr< OCResource > resource,
std::string collectionResourceType,
/**
* API for deleting a group.
*
- * @param collectionResourceType - resource type of a group to delete.
+ * @param collectionResourceType resource type of a group to delete.
*
* @return void
*/
/**
* API for getting a list of joined groups.
*
- * @return std::map - return value of this API.
+ * @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();
* 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.
+ * @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.
+ * @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.
+ * @return 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,
* 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.
+ * @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.
*
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return 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,
* Callback is called when a response arrives.
*
* @param void
- * @return std::string - return value of this API.
+ * @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.
+ * @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.
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult doBootstrap(
std::function<
* 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.
+ * @param resource resource pointer representing the target group
+ * @param callback callback for reboot.
*
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult reboot(std::shared_ptr< OCResource > resource,
std::function<
* 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.
+ * @param resource resource pointer representing the target group
+ * @param callback callback for factoryReset.
*
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @return Returns ::OC_STACK_OK if success.
+ * @note OCStackResult is defined in ocstack.h.
*/
OCStackResult factoryReset(std::shared_ptr< OCResource > resource,
std::function<
/**
* API for extracting an action set string from the ActionSet class instance
*
- * @param newActionSet - pointer of ActionSet class instance
+ * @param newActionSet pointer of ActionSet class instance
*
- * @return std::string - return value of this API.
+ * @return std::string return value of this API.
* It returns an action set String.
- *
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @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
+ * @param desc description of an action set string
*
- * @return ActionSet* - return value of this API.
+ * @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.
+ * @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.
+ * @return Returns ::OC_STACK_OK if success.
*
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @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.
+ * @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.
*
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @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.
+ * @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.
+ * @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 OCStackResult - return value of this API.
- * It returns OC_STACK_OK if success.
+ * @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.
*
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @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.
+ * @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.
+ * @return 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.
+ * @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.
*
- * NOTE: OCStackResult is defined in ocstack.h.
+ * @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);
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])