# Ignore output dirs
/release
-/csdk/release
-/csdk/libcoap-4.1.1/release/
-/examples/release
+resource/release
+resource/csdk/release
+resource/csdk/libcoap-4.1.1/release/
+resource/examples/release
+resource/examples/debug
/debug
-csdk/debug/
-csdk/libcoap-4.1.1/debug/
-/examples/debug
-csdk/stack/samples/linux/SimpleClientServer/debug/
+resource/debug
+resource/csdk/debug/
+resource/csdk/libcoap-4.1.1/debug/
+resource/csdk/libcoap-4.1.1/linux/
+resource/csdk/linux
+resource/csdk/stack/samples/linux/SimpleClientServer/debug/
+resource/csdk/stack/samples/linux/SimpleClientServer/release/
+resource/csdk/connectivity/build/out/
+resource/oc_logger/bin/
+resource/oc_logger/lib/
+resource/oc_logger/samples/linux/release/
+resource/oc_logger/samples/linux/debug
+
+service/things-manager/build/linux/release
+service/things-manager/build/linux/debug
+service/things-manager/sdk/build/linux/
# Ignore any object files
*.o
*.obj
*.settings/
*.cproject
*.project
+
+# Ignore dependencies folder, which should be generated
+dependencies/
+
+#ignore Klocwork stuff
+.kwlp/
+.kwps/
+
+#ignore various swap files
+*.swp
--- /dev/null
+== How to build Iotivity projects ==
+
+Iotivity includes a series of projects. You can find all these projects here:
+ https://oic-review.01.org/gerrit/#/admin/projects/
+
+You can build Iotivity project on Linux / Windows / MAC OSX for various OS(
+Linux, Tizen, Android, Arduino, Windows, MAC OSX, IOS ...).
+The output of the build is in:
+ <top directory of the project>/out/<target_os>/<target_arch>/<build version>/
+e.g.
+ oic-resource/out/android/armeabi-v7a/release/.
+
+This document takes oic-resource project as example, the way to build other
+projects is almost the same.
+
+=== Iotivity project build tool scons ===
+
+Scons is a cross-platform build tool, its usage is quite similar to GNU make.
+To build a project, you just require to run following command at the directory
+where a SConstruct file exists(SConstruct is the entrance of scons build, it's
+equivalent to Makefile of 'make') :
+ $ scons [options] [target]
+
+In additional, usually the scons build script of a project provides useful help
+information(include build options). To see the help information:
+ $ scons [options] -h
+
+Note: If no value is specified for an option, the default value will be used.
+The change of options value may impact the output.
+
+
+=== Prerequites ===
+
+* 1. Scons
+
+Please refer to the following page to install scons:
+ http://www.scons.org/doc/production/HTML/scons-user.html#chap-build-install
+(Note: on Windows, install Python 2.x before installing scons)
+
+* 2. IDE/SDK Prerequites
+To build for some OS (Android / Arduino / IOS ...), an IDE/SDK may be required,
+please go to the relative page to download and install the required IDE/SDK.
+
+Android:
+To build for Android, Andorid NDK and SDK are required.
+ Android NDK: http://developer.android.com/tools/sdk/ndk/index.html
+ Android SDK: http://developer.android.com/sdk/index.html
+(Note: as in some Iotivity projects, C++11 features are used, recommend Android
+ NDK >= r10, according to our test result r10c is the best one currently)
+
+Arduino:
+To build for Arduino, Arduino IDE is required.
+ Arduino IDE: http://arduino.cc/en/Main/Software
+ (Note: recommend install Arduino IDE >=1.5.7)
+
+Arduino builds are dependent on latest Time library. Download it from here:
+ http://www.pjrc.com/teensy/td_libs_Time.html
+and extract to <arduino_ide_root>/libraries/
+
+(Note: If you are using Arduino IDE 1.5.8 BETA on Windows, it may pop up some
+dll isn't found. please copy relative dll from the IDE directory to
+C:\Windows\SysWOW64. IDE 1.5.7 doesn't have this issue. Other version IDE isn't
+tested.)
+
+Apple:
+To build for Mac OSX or IOS, Xcode is required.
+ Xcode: https://developer.apple.com/xcode/downloads/
+
+Java:
+To build the Java code, JDK is required.
+ JDK: http://www.oracle.com/technetwork/java/javase/downloads/index.html
+(If the project doesn't include Java code or you wouldn't like build the
+Java codes, this isn't required)
+
+(Note: for convenience, suggest add the IDE/SDK path in environment variable,
+so you don't need to add it in command line each time. The build script will
+guide you to do that.)
+
+* 3. External libraries
+For Android and IOS build, most of the external libraries are provided as
+binary in oic-utilities project (https://oic-review.01.org/gerrit/oic-utilities).
+Please download it in the same directory as other Iotivity projects. If it's
+in different directory, an additional option (OIC_UITLS) will be required. The
+build command should be:
+ $ scons OIC_UITLS=<path to oic-utilities> [other options] [target]
+
+(Note: for convenience, you can also add it in environment variable. So you
+don't need to add this option in command line each time.)
+ e.g.:
+ $ export OIC_UITLS=<path to oic-utilities project>
+
+
+=== Build Iotivity project on Linux(Ubuntu) ===
+
+1. Build Iotivity project for Linux
+ $ cd <top directory of the project>
+ $ sudo apt-get install libboost-dev libboost-program-options-dev
+ $ scons
+
+2. Build Iotivity project for Android
+ $ cd <top directory of the project>
+ $ scons TARGET_OS=android TARGET_ARCH=xxx
+(xxx can be x86, armeabi, armeabi-v7a, armeabi-v7a-hard. To see all of its
+allowed value, please execute command 'scons TARGET_OS=android -Q -h'.
+
+Note: Currently as x86_64/arm64_v8a external library binaries aren't provided,
+you may meet link problem if build executable binary which depends on external
+library for x86_64/arm64_v8a.
+
+3. Build Iotivity project for Arduino
+ $ cd <top directory of the project>
+ $ scons TARGET_OS=arduino TARGET_ARCH=xxx BOARD=yyy
+(xxx can be avr, arm; yyy is the name of the board, to get its allowed value
+run: scons TARGET_OS=arduino TARGET_ARCH=xxx -h. You may see a option 'CPU' in
+the output of above command line, that's due to some boards have different
+processor, to specify the processor, add 'CPU=zzz' in the command line. If no
+'CPU' option exists, that means the board only support one kind of processor,
+it's unnecessary to specify it)
+
+
+=== Build Iotivity project on Windows ===
+
+1. Build Iotivity project for Android(It's the same as on Ubuntu)
+ $ cd <top directory of the project>
+ $ scons TARGET_OS=android TARGET_ARCH=xxx
+(xxx can be x86, armeabi, armeabi-v7a, armeabi-v7a-hard ...)
+
+2. Build Iotivity project for Arduino(It's the same as on Ubuntu)
+ $ cd <top directory of the project>
+ $ scons TARGET_OS=arduino TARGET_ARCH=xxx BOARD=yyy
+(xxx can be avr, arm; yyy is the name of the board, to get its allowed value
+run: scons TARGET_OS=arduino TARGET_ARCH=xxx -h. You may see a option 'CPU' in
+the output of above command line, that's due to some boards have different
+processor, to specify the processor, add 'CPU=zzz' in the command line. If no
+'CPU' option exists, that means the board only support one kind of processor,
+it's unnecessary to specify it)
+
+
+Note: Currently most Iotivity project doesn't support Windows, so you can't set
+TARGET_OS to 'windows' except the project support Windows.
+
+That's to say if the project doesn't support Windows, run:
+ $ scons TARGET_OS=windows ....
+or run on Windows
+ $ scons
+may always fail.
+
+
+=== Build Iotivity project on Mac OSX ===
+
+1. Build Iotivity project for Mac OSX
+ $ cd <top directory of the project>
+ $ scons SYS_VERSION=yyy
+(yyy is the OSX version, e.g. 10.9)
+
+2. Build Iotivity project for Android(It's the same as on Ubuntu)
+ $ cd <top directory of the project>
+ $ scons TARGET_OS=android TARGET_ARCH=xxx
+(xxx can be x86, armeabi, armeabi-v7a, armeabi-v7a-hard)
+
+3. Build Iotivity project for IOS
+ $ cd <top directory of the project>
+ $ scons TARGET_OS=ios TARGET_ARCH=xxx SYS_VERSION=yyy
+(xxx can be i386, x86_64, armv7, armv7s, arm64, yyy is IOS version, e.g. 7.0)
+
+Note:
+1) for convenience, a script (auto_build.sh) is provided to run possible build
+at once. Following is the usage:
+
+To build:
+ $ auto_build.sh <path-to-android-ndk> <path-to-arduino-home>
+To clean:
+ $ auto_build.sh -c
+
+2) Last sync and test with commit e9403ce6d4d7a1a0ac8d12c5acc876af7f7a8f76
+If you meet build error with newest code, it may due to the scripts are not up
+to date. Please try commit 5f16c38a5380e4b5c0d82e2cfea4af5fdc30c9ac or send mail
+to <OIC-OSD@list.01.org>.
+
+3) The build scripts for services have been provided. As the services code is
+out of date, it must the sync with newest resource code, otherwise, it can't
+pass the build, currently, the build scripts for services aren't enabled. Please
+remove the '#' at line 31 in 'SConstruct' file to enable it after the code is
+updated.
+
+4) For Arduino build, the Time library should >=1.3. The old can only be built
+with Arduino IDE 1.0.x
--- /dev/null
+##
+# The main build script
+#
+##
+
+# Load common build config
+SConscript('build_common/SConscript')
+
+# Load extra options
+SConscript('extra_options.scons')
+Import('env')
+
+target_os = env.get('TARGET_OS')
+if target_os == 'arduino':
+ SConscript('arduino.scons')
+# By default, src_dir is current dir, the build_dir is:
+# ./out/<target_os>/<target_arch>/<release or debug>/
+#
+# The build_dir is a variant directory of the source directory(You can
+# consider build_dir as a soft link to src_dir, for detail please refer to:
+# http://www.scons.org/doc/production/HTML/scons-user.html#f-VariantDir
+#
+# Any way, to make the output is in build_dir, when load scripts, the path should
+# be relevant to build_dir.
+build_dir = env.get('BUILD_DIR')
+
+# Build 'resource' sub-project
+SConscript(build_dir + 'resource/SConscript')
+
+# Build 'service' sub-project
+#SConscript(build_dir + 'service/SConscript')
+
+# Append targets information to the help information, to see help info, execute command line:
+# $ scon [options] -h
+env.PrintTargets()
+
+# Print bin upload command line (arduino only)
+if target_os == 'arduino':
+ env.UploadHelp()
--- /dev/null
+##
+# This script includes arduino specific config for oic-resource
+##
+Import('env')
+
+env.ImportLib('Time')
+if env.get('NET') == 'Ethernet':
+ env.ImportLib('Ethernet')
+else:
+ env.ImportLib('WiFi')
+env.ImportLib('SPI')
\ No newline at end of file
{
echo "*********** Clean build *************"
scons -c
- rm out -rf
+ rm -rf out
}
function build()
{
- echo "*********** Build for linux *************"
- scons
+ if [ $(uname -s) = "Linux" ]
+ then
+ echo "*********** Build for linux *************"
+ scons RELEASE=$3
+ fi
# 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 for android x86 *************"
- scons BUILD_TARGET=Android CPU_ARCH=x86 ANDROID_HOME=$1 ANDROID_NDK=$2
+ scons TARGET_OS=android TARGET_ARCH=x86 ANDROID_NDK=$1 RELEASE=$3
echo "*********** Build for android armeabi *************"
- scons BUILD_TARGET=Android CPU_ARCH=armeabi ANDROID_HOME=$1 ANDROID_NDK=$2
+ scons TARGET_OS=android TARGET_ARCH=armeabi ANDROID_NDK=$1 RELEASE=$3
echo "*********** Build for android armeabi-v7a *************"
- scons BUILD_TARGET=Android CPU_ARCH=armeabi-v7a ANDROID_HOME=$1 ANDROID_NDK=$2
+ scons TARGET_OS=android TARGET_ARCH=armeabi-v7a ANDROID_NDK=$1 RELEASE=$3
echo "*********** Build for android armeabi-v7a-hard *************"
- scons BUILD_TARGET=Android CPU_ARCH=armeabi-v7a-hard ANDROID_HOME=$1 ANDROID_NDK=$2
+ scons TARGET_OS=android TARGET_ARCH=armeabi-v7a-hard ANDROID_NDK=$1 RELEASE=$3
echo "*********** Build for arduino avr *************"
- scons BUILD_TARGET=Arduino CPU_ARCH=avr ARDUINO_HOME=$3
+ scons TARGET_OS=arduino TARGET_ARCH=avr ARDUINO_HOME=$2 RELEASE=$3
echo "*********** Build for arduino arm *************"
- scons BUILD_TARGET=Arduino CPU_ARCH=arm ARDUINO_HOME=$3
+ scons TARGET_OS=arduino TARGET_ARCH=arm ARDUINO_HOME=$2 RELEASE=$3
if [ $(uname -s) = "Darwin" ]
then
- echo "*********** Build for OSX i386 *************"
- scons BUILD_TARGET=Darwin CPU_ARCH=i386 SYS_VERSION=10.9
-
- echo "*********** Build for OSX x86_64 *************"
- scons BUILD_TARGET=Darwin CPU_ARCH=x86_64 SYS_VERSION=10.9
+ echo "*********** Build for OSX *************"
+ scons TARGET_OS=darwin SYS_VERSION=10.9 RELEASE=$3
echo "*********** Build for IOS i386 *************"
- scons BUILD_TARGET=IOS CPU_ARCH=i386 SYS_VERSION=7.0
+ scons TARGET_OS=ios TARGET_ARCH=i386 SYS_VERSION=7.0 RELEASE=$3
echo "*********** Build for IOS x86_64 *************"
- scons BUILD_TARGET=IOS CPU_ARCH=x86_64 SYS_VERSION=7.0
+ scons TARGET_OS=ios TARGET_ARCH=x86_64 SYS_VERSION=7.0 RELEASE=$3
echo "*********** Build for IOS armv7 *************"
- scons BUILD_TARGET=IOS CPU_ARCH=armv7 SYS_VERSION=7.0
+ scons TARGET_OS=ios TARGET_ARCH=armv7 SYS_VERSION=7.0 RELEASE=$3
echo "*********** Build for IOS armv7s *************"
- scons BUILD_TARGET=IOS CPU_ARCH=armv7s SYS_VERSION=7.0
+ scons TARGET_OS=ios TARGET_ARCH=armv7s SYS_VERSION=7.0 RELEASE=$3
echo "*********** Build for IOS arm64 *************"
- scons BUILD_TARGET=IOS CPU_ARCH=arm64 SYS_VERSION=7.0
+ scons TARGET_OS=ios TARGET_ARCH=arm64 SYS_VERSION=7.0 RELEASE=$3
fi
}
{
echo "Usage:"
echo " build:"
- echo " `basename $0` <path-to-android-sdk> <path-to-android-ndk> <path-to-arduino-home>"
+ echo " `basename $0` <path-to-android-ndk> <path-to-arduino-home>"
echo " clean:"
echo " `basename $0` -c"
}
help
exit -1
fi
-elif [ $# -ne 3 ]
+elif [ $# -ne 2 ]
then
help
exit -1
fi
-
-build $1 $2 $3
+# Suppress "Reading ..." message and enable parallel build
+export SCONSFLAGS="-Q -j 8"
+build $1 $2 true
+build $1 $2 false
echo "===================== done ====================="
--- /dev/null
+##
+# This script includes generic build options:
+# release/debug, target os, target arch, cross toolchain, build environment etc
+##
+import os
+import platform
+
+# Map of host os and allowed target os (host: allowed target os)
+host_target_map = {
+ 'linux': ['linux', 'android', 'arduino'],
+ 'windows': ['windows', 'winrt', 'android', 'arduino'],
+ 'darwin': ['darwin', 'ios', 'android', 'arduino'],
+ }
+
+# Map of os and allowed archs (os: allowed archs)
+os_arch_map = {
+ 'linux': ['x86', 'x86_64', 'arm', 'arm64'],
+ 'android': ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'arm64-v8a'],
+ 'windows': ['x86', 'amd64', 'arm'],
+ 'winrt': ['arm'],
+ 'darwin': ['i386', 'x86_64'],
+ 'ios': ['i386', 'x86_64', 'armv7', 'armv7s', 'arm64'],
+ 'arduino': ['avr', 'arm'],
+ }
+
+host = platform.system().lower()
+
+if not host_target_map.has_key(host):
+ print "\nError: Current system (%s) isn't supported\n" % host
+ Exit(1)
+
+######################################################################
+# Get build options (the optins from command line)
+######################################################################
+target_os = ARGUMENTS.get('TARGET_OS', host).lower() # target os
+
+if target_os not in host_target_map[host]:
+ print "\nError: Unknown target os: %s (Allow values: %s)\n" % (target_os, host_target_map[host])
+ Exit(1)
+
+default_arch = platform.machine()
+if default_arch not in os_arch_map[target_os]:
+ default_arch = os_arch_map[target_os][0].lower()
+
+target_arch = ARGUMENTS.get('TARGET_ARCH', default_arch) # target arch
+
+######################################################################
+# Common build options (release, target os, target arch)
+######################################################################
+help_vars = Variables()
+help_vars.Add(BoolVariable('RELEASE', 'Build for release?', True)) # set to 'no', 'false' or 0 for debug
+help_vars.Add(EnumVariable('TARGET_OS', 'Target platform', host, host_target_map[host]))
+help_vars.Add(EnumVariable('TARGET_ARCH', 'Target architecture', default_arch, os_arch_map[target_os]))
+
+######################################################################
+# Platform(build target) specific options: SDK/NDK & toolchain
+######################################################################
+targets_support_cc = ['linux', 'arduino']
+
+if target_os in targets_support_cc:
+ # Set cross compile toolchain
+ help_vars.Add('TC_PREFIX', "Toolchain prefix (Generally only be required for cross-compiling)", os.environ.get('TC_PREFIX'))
+ help_vars.Add(PathVariable('TC_PATH',
+ 'Toolchain path (Generally only be required for cross-compiling)',
+ os.environ.get('TC_PATH')))
+
+if target_os in ['android', 'arduino']: # Android/Arduino always uses GNU compiler regardless of the host
+ env = Environment(variables = help_vars,
+ tools = ['gnulink', 'gcc', 'g++', 'ar', 'as']
+ )
+else:
+ env = Environment(variables = help_vars, TARGET_ARCH = target_arch, TARGET_OS = target_os)
+
+Help(help_vars.GenerateHelpText(env))
+
+tc_set_msg = '''
+************************************ Warning **********************************
+* Enviornment variable TC_PREFIX/TC_PATH is set. It will change the default *
+* toolchain, if it isn't what you expect you should unset it, otherwise it may*
+* cause inexplicable errors. *
+*******************************************************************************
+'''
+
+if target_os in targets_support_cc:
+ prefix = env.get('TC_PREFIX')
+ tc_path = env.get('TC_PATH')
+ if prefix:
+ env.Replace(CC = prefix + 'gcc')
+ env.Replace(CXX = prefix + 'g++')
+ env.Replace(AR = prefix + 'ar')
+ env.Replace(AS = prefix + 'as')
+ env.Replace(LINK = prefix + 'ld')
+ env.Replace(RANLIB = prefix + 'ranlib')
+
+ if tc_path:
+ env.PrependENVPath('PATH', tc_path)
+ sys_root = os.path.abspath(tc_path + '/../')
+ env.AppendUnique(CCFLAGS = ['--sysroot=' + sys_root])
+ env.AppendUnique(LINKFLAGS = ['--sysroot=' + sys_root])
+
+ if prefix or tc_path:
+ print tc_set_msg
+
+# Ensure scons be able to change its working directory
+env.SConscriptChdir(1)
+
+# Set the source directory and build directory
+# Source directory: 'dir'
+# Build directory: 'dir'/out/<target_os>/<target_arch>/<release or debug>/
+#
+# You can get the directory as following:
+# env.get('SRC_DIR')
+# env.get('BUILD_DIR')
+
+def __set_dir(env, dir):
+ if not os.path.exists(dir + '/SConstruct'):
+ print '''
+*************************************** Error *********************************
+* The directory(%s) seems isn't a source code directory, no SConstruct file is
+* found. *
+*******************************************************************************
+''' % dir
+ Exit(1)
+
+ if env.get('RELEASE'):
+ build_dir = dir + '/out/' + target_os + '/' + target_arch + '/release/'
+ else:
+ build_dir = dir + '/out/' + target_os + '/' + target_arch + '/debug/'
+ env.VariantDir(build_dir, dir, duplicate=0)
+
+ env.Replace(BUILD_DIR = build_dir)
+ env.Replace(SRC_DIR = dir)
+
+def __src_to_obj(env, src, home = ''):
+ obj = env.get('BUILD_DIR') + src.replace(home, '')
+ if env.get('OBJSUFFIX'):
+ obj += env.get('OBJSUFFIX')
+ return env.Object(obj, src)
+
+def __install(ienv, targets, name):
+ i_n = ienv.Install(env.get('BUILD_DIR'), targets)
+ Alias(name, i_n)
+ env.AppendUnique(TS = [name])
+
+def __append_target(ienv, target):
+ env.AppendUnique(TS = [target])
+
+def __print_targets(env):
+ Help('''
+===============================================================================
+Targets:\n ''')
+ for t in env.get('TS'):
+ Help(t + ' ')
+ Help('''
+\nDefault all targets will be built. You can specify the target to build:
+
+ $ scons [options] [target]
+===============================================================================
+''')
+
+env.AddMethod(__set_dir, 'SetDir')
+env.AddMethod(__print_targets, 'PrintTargets')
+env.AddMethod(__src_to_obj, 'SrcToObj')
+env.AddMethod(__append_target, 'AppendTarget')
+env.AddMethod(__install, 'InstallTarget')
+env.SetDir(env.GetLaunchDir())
+
+Export('env')
+
+# Load config of target os
+env.SConscript(target_os + '/SConscript')
+
+# Delete the temp files of configuration
+if env.GetOption('clean'):
+ dir = env.get('SRC_DIR')
+
+ if os.path.exists(dir + '/config.log'):
+ Execute(Delete(dir + '/config.log'))
+ Execute(Delete(dir + '/.sconsign.dblite'))
+ Execute(Delete(dir + '/.sconf_temp'))
+
+Return('env')
import platform
import subprocess
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH', 'ANDROID_NDK')
+Import('env')
-if not ANDROID_NDK:
+help_vars = Variables()
+help_vars.Add(PathVariable('ANDROID_NDK', 'Android NDK root directory', os.environ.get('ANDROID_NDK')))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+android_ndk = env.get('ANDROID_NDK')
+if not android_ndk:
print '''
*************************************** Error *********************************
-* Android NDK path (ANDROID_NDK) isn't set, you can set enviornment variable*
-* ANDROID_NDK or add it in command line as: *
+* Android NDK path isn't set, you can set enviornment variable ANDROID_NDK *
+* or add it in command line as: *
* # scons ANDROID_NDK=<path to android NDK> ... *
*******************************************************************************
'''
######################################################################
# Probe Android NDK default flags
######################################################################
-ndk_build_cmd = ANDROID_NDK + '/ndk-build'
+ndk_build_cmd = android_ndk + '/ndk-build'
if env['HOST_OS'] == 'win32':
if os.path.isfile(ndk_build_cmd + '.cmd'):
ndk_build_cmd += '.cmd'
* It seems android ndk path is not set properly, please check if "%s"
* is the root directory of android ndk. *
*******************************************************************************
-''' % ANDROID_NDK
+''' % android_ndk
Exit(1)
ANDROID_HOME = os.environ.get('ANDROID_HOME')
*******************************************************************************
'''
+target_arch = env.get('TARGET_ARCH')
+
# Android ndk early version doesn't support C++11. Detect the toolchain
# and platform version to make sure the newest version is used.
# Detect toolchain version
for tc_ver in ['4.9', '4.8', '4.7', '']:
- if os.path.exists(ANDROID_NDK + '/sources/cxx-stl/gnu-libstdc++/' + tc_ver):
+ if os.path.exists(android_ndk + '/sources/cxx-stl/gnu-libstdc++/' + tc_ver):
break
# Detect platform version.
platform_ver = ''
for pf_ver in range(0, 100): # 100 should be big enough :)
- if os.path.exists(ANDROID_NDK + '/platforms/android-%d' % pf_ver):
+ if os.path.exists(android_ndk + '/platforms/android-%d' % pf_ver):
platform_ver = "%d" % pf_ver
cmd = [ndk_build_cmd]
-cmd.append('APP_ABI=' + TARGET_CPU_ARCH)
+cmd.append('APP_ABI=' + target_arch)
cmd.append('APP_STL=gnustl_static')
-if RELEASE_BUILD:
+if env.get('RELEASE'):
cmd.append('APP_OPTIM=release')
else:
cmd.append('APP_OPTIM=debug')
env.AppendUnique(CPPPATH = Split(flags[8:]))
elif cmp(flags[0:8], 'SYSROOT=') == 0:
- env.AppendUnique(LINKFLAGS = ['--sysroot=' + flags[8:].strip()])
- env.AppendUnique(LIBPATH = [flags[8:].strip() + '/usr/lib'])
+ sysroot = flags[8:].strip()
+ env.AppendUnique(LINKFLAGS = ['--sysroot=' + sysroot])
+ env.AppendUnique(LIBPATH = [sysroot + '/usr/lib'])
+ # To fix android NDK issue
+ # Some functions, e.g. rand, srand. strtof ... are static in static inline
+ # prior to android-L. so libc.so before android-L doesn't have them. If build
+ # build on android-L and the function(s) is used, should link libc.a
+ if platform_ver == '' or int(platform_ver) > 20:
+ env.AppendUnique(LIBS = File(sysroot + '/usr/lib/libc.a'))
elif cmp(flags[0:8], 'LDFLAGS=') == 0:
env.AppendUnique(LINKFLAGS = Split(flags[8:]))
elif cmp(flags[0:7], 'TC_VER=') == 0: # set gnustl library path
ver = flags[7:].strip()
- env.AppendUnique(LIBPATH = [ANDROID_NDK + '/sources/cxx-stl/gnu-libstdc++/'
- + ver + '/libs/' + TARGET_CPU_ARCH])
+ env.AppendUnique(LIBPATH = [android_ndk + '/sources/cxx-stl/gnu-libstdc++/'
+ + ver + '/libs/' + target_arch])
######################################################################
# Set release/debug flags
######################################################################
-if RELEASE_BUILD:
- env.AppendUnique(CFLAGS = ['-Os'])
- env.AppendUnique(CXXFLAGS = ['-Os'])
+if env.get('RELEASE'):
+ env.AppendUnique(CCFLAGS = ['-Os'])
env.AppendUnique(CPPDEFINES = ['NDEBUG'])
env.AppendUnique(LINKFLAGS = ['-s'])
else:
- env.AppendUnique(CFLAGS = ['-g'])
- env.AppendUnique(CXXFLAGS = ['-g'])
\ No newline at end of file
+ env.AppendUnique(CCFLAGS = ['-g'])
include $(CLEAR_VARS)
LOCAL_MODULE := flags_probe
-include $(BUILD_SHARE_LIBRARY)
+include $(BUILD_SHARED_LIBRARY)
$(info TC_PREFIX=$(TOOLCHAIN_PREFIX))
$(info CFLAGS=$(TARGET_CFLAGS))
--- /dev/null
+##
+# This script includes arduino specific config
+##
+import os
+import platform
+
+Import('env')
+
+def __parse_config(f):
+ dict = {}
+
+ if not os.path.isfile(f):
+ return dict
+
+ file = open(f, 'r')
+ strs = file.readlines()
+ for str in strs:
+ str = str.strip()
+ if len(str) > 0 and str[0] == '#':
+ continue
+
+ idx = str.find('=')
+ if idx > 0:
+ dict.setdefault(str[0:idx], str[idx + 1:])
+
+ return dict
+
+def __get_boards(dict):
+ boards = []
+ keys = dict.keys()
+ for key in keys:
+ idx = key.find('.name')
+ if idx > 0:
+ if key.endswith('.name'):
+ boards.append(key[0:idx])
+ return boards
+
+def __get_cpu(dict, board):
+ cpus = []
+ keys = dict.keys()
+ for key in keys:
+ idx = key.find(board + '.menu.cpu.')
+ start = len(board + '.menu.cpu.')
+ if idx >= 0:
+ end = key.find('.', start)
+ if end > 0:
+ cpu = key[start:end]
+ exist = False
+ for c in cpus:
+ if c == cpu:
+ exist = True
+ break
+
+ if not exist:
+ cpus.append(cpu)
+ return cpus
+
+def __get_board_info(board, key):
+ if cpu:
+ v = boards_info.get(board + '.menu.cpu.' + cpu + key)
+ if not v:
+ v = boards_info.get(board + key)
+ else:
+ v = boards_info.get(board + key)
+ return v
+
+def __search_files(path, pattern, ondisk=True, source=True, strings=False, recursive=True):
+ if not recursive:
+ return Glob(pattern, ondisk, source, strings)
+
+ matches = []
+ for root, dirnames, filenames in os.walk(path):
+ matches.extend(Glob(root + '/' + pattern, ondisk, source, strings))
+
+ return matches
+
+# To make sure the src is built in 'BUILD_DIR' (by default it will be built at
+# the same directory as the .c .cpp .S)
+def __src_to_obj(env, srcs):
+ objs = []
+ prefix = env.get('BOARD') + '_'
+ if env.get('CPU'):
+ prefix += env.get('CPU') + '_'
+
+ build_dir = env.get('BUILD_DIR') + '/arduino/'
+ for src in srcs:
+ obj = src.path.replace(arduino_home, build_dir)
+ i = obj.rfind('.')
+ obj = obj[0:i]
+ if env.get('OBJSUFFIX'):
+ obj += env.get('OBJSUFFIX')
+ objs.extend(env.Object(obj, src, OBJPREFIX=prefix))
+ return objs
+
+def __import_lib(env, lib):
+ lib_path = arduino_home + '/libraries/' + lib
+ if not os.path.exists(lib_path):
+ if target_arch == 'avr':
+ lib_path = arduino_home + '/hardware/arduino/avr/libraries/' + lib
+ else:
+ lib_path = arduino_home + '/hardware/arduino/sam/libraries/' + lib
+
+ if os.path.exists(lib_path + '/src'):
+ lib_path = lib_path + '/src'
+
+ env.AppendUnique(CPPPATH = [lib_path])
+
+ if os.path.exists(lib_path + '/utility'):
+ env.AppendUnique(CPPPATH = [lib_path + '/utility'])
+
+ lib_src = []
+ lib_src.extend(__search_files(lib_path, '*.S'))
+ lib_src.extend(__search_files(lib_path, '*.c'))
+ lib_src.extend(__search_files(lib_path, '*.cpp'))
+
+ build_dir = env.get('BUILD_DIR')
+ if build_dir:
+ lib_a = env.StaticLibrary(build_dir + lib, __src_to_obj(env, lib_src))
+ else:
+ lib_a = env.StaticLibrary(lib, __src_to_obj(env, lib_src))
+ env.AppendUnique(LIBS = [File(lib_a[0])])
+
+def __build_core(env):
+ core_src = __search_files(core_folder, '*.S')
+ core_src.extend(__search_files(core_folder, '*.c'))
+ core_src.extend(__search_files(core_folder, '*.cpp'))
+
+ core_src.extend(__search_files(variant_folder, '*.S'))
+ core_src.extend(__search_files(variant_folder, '*.c'))
+ core_src.extend(__search_files(variant_folder, '*.cpp'))
+
+ core_obj = __src_to_obj(env, core_src)
+ build_dir = env.get('BUILD_DIR')
+ if build_dir:
+ s_core = env.StaticLibrary(build_dir + 'core', core_obj)
+ else:
+ s_core = env.StaticLibrary('core', core_obj)
+ env.AppendUnique(LIBS = [File(s_core[0])])
+
+ # To avoid compiler issue. Otherewise there may be warnings:
+ # undefined reference to '_exit' '_close', '_getpid' ...
+ # Above functions are used in libc.a and implemented in syscalls_sam3.c
+ if env.get('TARGET_ARCH') == 'arm':
+ for obj in core_obj:
+ if obj.name.endswith('syscalls_sam3.o'):
+ env.AppendUnique(LIBS = [File(obj)])
+
+def __create_bin(env, source):
+ name = source
+ if env.get('TARGET_ARCH') == 'avr':
+ eep = env.Command(name + '.eep', source, 'avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $SOURCE $TARGET')
+ hex = env.Command(name + '.hex', source, 'avr-objcopy -O ihex -R .eeprom $SOURCE $TARGET')
+ else:
+ hex = env.Command(name + '.hex', source, 'arm-none-eabi-objcopy -O binary $SOURCE $TARGET')
+
+# Print the command line that to upload binary to the board
+def __upload_help(env):
+ if target_arch == 'avr':
+ protocol = __get_board_info(board, '.upload.protocol')
+ speed = __get_board_info(board, '.upload.speed')
+
+ upload_cmd = arduino_home + '/hardware/tools/avr/bin/avrdude -C' + arduino_home +'/hardware/tools/avr/etc/avrdude.conf -v -v -v -v -p' \
+ + mcu + ' -c' + protocol + ' -P<serial_port>' + ' -b' + speed + ' -D -Uflash:w:<hex_file>:i'
+ else:
+ uu = __get_board_info(board, '.upload.native_usb')
+ upload_cmd = arduino_home + '/hardware/tools/bossac -i -d --port=<serial_port> -U ' + uu + ' -e -w -v -b <bin file> -R'
+
+ Help('''
+===============================================================================
+You can upload the bin file with following command line:
+''')
+ Help('\n $ ' + upload_cmd)
+ Help('''
+\nPlease replace <xxx> according to the actual situation.
+===============================================================================
+''')
+
+# ARDUINO_HOME build option
+help_vars = Variables()
+help_vars.Add(PathVariable('ARDUINO_HOME', 'ARDUINO root directory', os.environ.get('ARDUINO_HOME')))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+target_arch = env.get('TARGET_ARCH')
+arduino_home = env.get('ARDUINO_HOME')
+if not arduino_home:
+ print '''
+************************************* Error ***********************************
+* Arduino root directory isn't set, you can set enviornment variable *
+* ARDUINO_HOME or add it in command line as: *
+* # scons ARDUINO_HOME=<path to arduino root directory> ... *
+*******************************************************************************
+'''
+ Exit(1)
+
+# Overwrite suffixes and prefixes
+if env['HOST_OS'] == 'win32':
+ env['OBJSUFFIX'] = '.o'
+ env['SHOBJSUFFIX'] = '.os'
+ env['LIBPREFIX'] = 'lib'
+ env['LIBSUFFIX'] = '.a'
+ env['SHLIBPREFIX'] = 'lib'
+ env['SHLIBSUFFIX'] = '.so'
+ env['LIBPREFIXES'] = ['lib']
+ env['LIBSUFFIXES'] = ['.a', '.so']
+ env['PROGSUFFIX'] = ''
+elif platform.system().lower() == 'darwin':
+ env['SHLIBSUFFIX'] = '.so'
+ env['LIBSUFFIXES'] = ['.a', '.so']
+ env['PROGSUFFIX'] = ''
+
+# Debug/release relative flags
+if env.get('RELEASE'):
+ env.AppendUnique(CCFLAGS = ['-Os'])
+ env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+else:
+ env.AppendUnique(CCFLAGS = ['-g'])
+
+# BOARD / CPU option
+
+# Get IDE version
+if os.path.exists(arduino_home + '/lib/version.txt'):
+ vf = open(arduino_home + '/lib/version.txt', 'r')
+ version = vf.readline().replace('.', '')
+else:
+ print '''
+************************************* Error ***********************************
+* Can't find version file (lib/version.txt), please check if (%s)
+* is arduino root directory. *
+*******************************************************************************
+''' % arduino_home
+ Exit(1)
+
+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/')
+ env.Replace(CC = 'avr-gcc')
+ env.Replace(CXX = 'avr-g++')
+ env.Replace(AR = 'avr-ar')
+ env.Replace(AS = 'avr-as')
+ env.Replace(LINK = 'avr-gcc')
+ env.Replace(RANLIB = 'avr-ranlib')
+ if target_arch != 'avr':
+ print '''
+************************************* Error ***********************************
+* Arduino 1.0.x IDE only support 'avr', to support other arch at least 1.5.x *
+* is required.
+*******************************************************************************
+'''
+ Exit(1)
+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')
+ 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')
+ else:
+ print '''
+************************************* Error ***********************************
+* CPU arch %s isn't supported currently.
+*******************************************************************************
+''' % target_arch
+
+#Board option, let user to select the board
+boards = __get_boards(boards_info)
+help_vars = Variables()
+help_vars.Add(EnumVariable('BOARD', 'arduino board', boards[0], boards))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+#CPU option
+board = env.get('BOARD')
+cpus = __get_cpu(boards_info, board)
+if len(cpus) > 0:
+ help_vars = Variables()
+ help_vars.Add(EnumVariable('CPU', 'arduino board cpu', cpus[0], cpus))
+ help_vars.Update(env)
+ Help(help_vars.GenerateHelpText(env))
+
+# Arduino commom flags
+cpu = env.get('CPU')
+board = env.get('BOARD')
+mcu = __get_board_info(board, '.build.mcu')
+f_cpu = __get_board_info(board, '.build.f_cpu')
+usb_vid = __get_board_info(board, '.build.vid')
+usb_pid = __get_board_info(board, '.build.pid')
+variant = __get_board_info(board, '.build.variant')
+
+if not usb_vid:
+ usb_vid = __get_board_info(board, '.vid.0')
+if not usb_pid:
+ usb_pid = __get_board_info(board, '.pid.0')
+
+if is_1_0_x:
+ core_base = arduino_home + '/hardware/arduino/'
+else:
+ if target_arch == 'avr':
+ core_base = arduino_home + '/hardware/arduino/avr/'
+ else:
+ core_base = arduino_home + '/hardware/arduino/sam/'
+
+variant_folder = core_base + 'variants/' + variant
+env.AppendUnique(CPPPATH = [variant_folder])
+
+core = __get_board_info(board, '.build.core')
+core_folder = core_base + 'cores/' + core + '/'
+env.AppendUnique(CPPPATH = [core_folder])
+
+if is_1_0_x:
+ comm_flags = []
+ if mcu:
+ comm_flags.extend(['-mmcu=' + mcu])
+ if f_cpu:
+ comm_flags.extend(['-DF_CPU=' + f_cpu])
+ comm_flags.extend(['-DARDUINO=' + version])
+ if usb_vid:
+ comm_flags.extend(['-DUSB_VID=' + usb_vid])
+ if usb_pid:
+ comm_flags.extend(['-DUSB_PID=' + usb_pid])
+
+ env.AppendUnique(ASFLAGS = ['-x', 'assembler-with-cpp'])
+ env.AppendUnique(ASFLAGS = comm_flags)
+
+ env.AppendUnique(CFLAGS = ['-Os', '-ffunction-sections', '-fdata-sections', '-MMD'])
+ env.AppendUnique(CFLAGS = comm_flags)
+
+ env.AppendUnique(CXXFLAGS = ['-Os', '-fno-exceptions', '-ffunction-sections', '-fdata-sections','-MMD'])
+ env.AppendUnique(CXXFLAGS = comm_flags)
+
+ env.AppendUnique(LINKFLAGS = ['-Os'])
+ if mcu == 'atmega2560':
+ env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections,--relax'])
+ else:
+ env.AppendUnique(LINKFLAGS = ['-Wl,--gc-sections'])
+ env.AppendUnique(LINKFLAGS = ['-mmcu=' + mcu])
+else:
+ if target_arch == 'avr':
+ cpu_flag = '-mmcu=' + mcu
+ else:
+ cpu_flag = '-mcpu=' + mcu
+
+ comm_flag = [cpu_flag, '-DF_CPU=' + f_cpu, '-DARDUINO=' + version, '-DARDUINO_' + __get_board_info(board, '.build.board')]
+ if target_arch == 'arm':
+ comm_flag.extend(['-DARDUINO_ARCH_SAM'])
+ else:
+ comm_flag.extend(['-DARDUINO_ARCH_AVR'])
+
+ compiler_path = platform_info.get('compiler.path')
+ compiler_path = compiler_path.replace('{runtime.ide.path}', arduino_home)
+ env.PrependENVPath('PATH', compiler_path)
+ env.Replace(CC = platform_info.get('compiler.c.cmd'))
+ 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(ASFLAGS = ['-x', 'assembler-with-cpp'])
+ env.AppendUnique(ASFLAGS = comm_flag)
+ env.AppendUnique(CFLAGS = Split(platform_info.get('compiler.c.flags')))
+ env.AppendUnique(CXXFLAGS = Split(platform_info.get('compiler.cpp.flags')))
+ env.AppendUnique(ARFLAGS = Split(platform_info.get('compiler.ar.flags')))
+ env.AppendUnique(CCFLAGS = comm_flag)
+
+ extra_flags = __get_board_info(board, '.build.extra_flags')
+ if extra_flags:
+ extra_flags = extra_flags.replace('{build.usb_flags}', '')
+ env.AppendUnique(CCFLAGS = Split(extra_flags))
+ usb_flags = ['-DUSB_VID=' + usb_vid, '-DUSB_PID=' + usb_pid, '-DUSBCON', '-DUSB_MANUFACTURER="Unknown"']
+ env.AppendUnique(CCFLAGS = usb_flags)
+
+ if target_arch == 'arm':
+ env.AppendUnique(LINKFLAGS = ['-Os', '-Wl,--gc-sections', cpu_flag,
+ '-T' + variant_folder + '/' + __get_board_info(board, '.build.ldscript'),
+ '-Wl,-Map,' + env.get('BUILD_DIR') + 'arduino_prj.map'])
+ env.AppendUnique(LINKFLAGS = Split('-lm -lgcc -mthumb -Wl,--cref -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_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')
+ else:
+ env.Replace(LINKCOM = '$LINK -o $TARGET $_LIBDIRFLAGS $LINKFLAGS $SOURCES $_LIBFLAGS -Wl,--end-group')
+ else:
+ env.AppendUnique(LINKFLAGS = Split(platform_info.get('compiler.c.elf.flags')))
+ env.AppendUnique(LINKFLAGS = [cpu_flag])
+ env.AppendUnique(LIBS = 'm')
+ env.Replace(ARCOM = '$AR ' + platform_info.get('compiler.ar.flags') + ' $TARGET $SOURCES')
+
+__build_core(env)
+
+env.AddMethod(__import_lib, "ImportLib") #import arduino library
+#env.AddMethod(__build_core, "BuildCore") #build arduino core
+env.AddMethod(__create_bin, "CreateBin") #create binary files(.eep and .hex)
+env.AddMethod(__upload_help, "UploadHelp") #print the command line that to upload binary to the boardf
--- /dev/null
+##
+# This script set darwin specific flags (GNU GCC)
+#
+##
+import os
+import platform
+
+Import('env')
+
+# SYS_VERSION build option
+help_vars = Variables()
+help_vars.Add('SYS_VERSION', 'MAC OS X version / IOS version', os.environ.get('SYS_VERSION'))
+help_vars.Update(env)
+Help(help_vars.GenerateHelpText(env))
+
+sys_version = env.get('SYS_VERSION')
+
+if sys_version is None:
+ print '''
+*********************************** Error *************************************
+* MAC OSX/IOS version isn't set, please set it in command line as : *
+* # scons SYS_VERSION=<version> ... *
+* To get the version, please see: *
+* /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ *
+* /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/ *
+*******************************************************************************
+'''
+ Exit(1)
+
+target_arch = env.get('TARGET_ARCH')
+target_os = env.get('TARGET_OS')
+# Set release/debug flags
+if env.get('RELEASE'):
+ env.AppendUnique(CCFLAGS = ['-Os'])
+ env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+else:
+ env.AppendUnique(CCFLAGS = ['-g'])
+
+if target_os == 'darwin':
+ sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX' + sys_version + '.sdk/'
+else:
+ if target_arch in ['i386', 'x86_64']:
+ sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator' + sys_version + '.sdk/'
+ else:
+ sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS' + sys_version + '.sdk/'
+
+# Set arch flags
+env.AppendUnique(CCFLAGS = ['-arch', target_arch, '-isysroot', sys_root])
+env.AppendUnique(LINKFLAGS = ['-arch', target_arch, '-isysroot', sys_root])
+
+if target_os == 'darwin':
+ flag = '-mmacosx-version-min=' + sys_version
+ env.AppendUnique(CCFLAGS = [flag])
+ env.AppendUnique(LINKFLAGS = [flag])
\ No newline at end of file
--- /dev/null
+##
+# This script set ios specific flags (GNU GCC)
+#
+##
+Import('env')
+
+# setting of IOS is almost the same as Darwin(MAC OSX)
+env.SConscript('../darwin/SConscript')
+
+sys_version = env.get('SYS_VERSION')
+if env.get('TARGET_ARCH') in ['i386', 'x86_64']: #Simulator
+ flag = '-mios-simulator-version-min=' + sys_version
+ env.AppendUnique(CCFLAGS = [flag])
+ env.AppendUnique(LINKFLAGS = [flag])
+else:
+ flag = '-miphoneos-version-min=' + sys_version
+ env.AppendUnique(CCFLAGS = [flag])
+ env.AppendUnique(LINKFLAGS = [flag])
\ No newline at end of file
--- /dev/null
+##
+# This script set linux specific flags (GNU GCC)
+#
+##
+Import('env')
+
+# Set release/debug flags
+if env.get('RELEASE'):
+ env.AppendUnique(CCFLAGS = ['-Os'])
+ env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+ env.AppendUnique(LINKFLAGS = ['-s'])
+else:
+ env.AppendUnique(CCFLAGS = ['-g'])
+
+# Set arch flags
+target_arch = env.get('TARGET_ARCH')
+if target_arch in ['x86']:
+ env.AppendUnique(CCFLAGS = ['-m32'])
+ env.AppendUnique(LINKFLAGS = ['-m32'])
+elif target_arch in ['x86_64']:
+ env.AppendUnique(CCFLAGS = ['-m64'])
+ env.AppendUnique(LINKFLAGS = ['-m64'])
+elif target_arch.find('v7a-hard') > 0:
+ env.AppendUnique(CPPFLAGS = ['-march=armv7-a'])
+ env.AppendUnique(CPPFLAGS = ['-mfloat-abi=hard'])
+ env.AppendUnique(CCFLAGS = ['-mfloat-abi=hard'])
+ env.AppendUnique(LINKFLAGS = ['-mfloat-abi=hard'])
+elif target_arch.find('v7a') > 0:
+ env.AppendUnique(CPPFLAGS = ['-march=armv7-a'])
+elif target_arch.find('arm64') > 0:
+ env.AppendUnique(CPPFLAGS = ['-march=armv8-a'])
+else:
+ env.AppendUnique(CPPFLAGS = ['-march=armv5te'])
--- /dev/null
+##
+# This script includes windows specific config (MSVS/MSVC)
+##
+Import('env')
+
+# Set common flags
+env.AppendUnique(CXXFLAGS=['/wd4244', '/wd4267','/wd4345', '/wd4355', '/wd4800', '/wd4996'])
+env.AppendUnique(CCFLAGS=['/EHsc'])
+
+# Set release/debug flags
+if env.get('RELEASE'):
+ env.AppendUnique(CCFLAGS = ['/MD', '/O2', '/GF'])
+ env.AppendUnique(CPPDEFINES = ['NDEBUG'])
+else:
+ env.AppendUnique(CCFLAGS = ['/MDd', '/Od', '/ZI', '/GZ', '/Gm'])
+ env.AppendUnique(CPPDEFINES = ['_DEBUG'])
+ env.AppendUnique(LINKFLAGS = ['/debug'])
--- /dev/null
+######################################################################
+# This script manages extra build options
+#
+######################################################################
+import os
+import platform
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+src_dir = env.get('SRC_DIR')
+
+# Add 'OIC_UTILS' build option for user to set oic-utilities project path
+if target_os not in ['linux', 'darwin', 'arduino']:
+ default_dir = os.environ.get('OIC_UTILS')
+ if not default_dir:
+ default_dir = os.path.abspath(src_dir + '/../oic-utilities')
+ else:
+ default_dir = os.path.abspath(default_dir)
+
+ if not os.path.exists(default_dir):
+ default_dir = None
+
+ help_vars = Variables()
+ help_vars.Add(PathVariable('OIC_UTILS', 'oic-utilities project path', default_dir))
+ help_vars.Update(env)
+ Help(help_vars.GenerateHelpText(env))
+
+ utils_path = env.get('OIC_UTILS', default_dir)
+ if utils_path:
+ utils_path = os.path.abspath(utils_path)
+
+ if not utils_path or not os.path.exists(utils_path):
+ print '''
+*********************************** Error: ************************************
+* oic-utilities project directory isn't set properly, please set enviornment*
+* variable OIC_UTILS or set it in command line: *
+* # scons OIC_UTILS=<path to oic-utilities> ... *
+*******************************************************************************
+'''
+ Exit(1)
+
+if target_os == 'arduino':
+ # Add 'NET' build option, let user select board network connection type
+ vars = Variables()
+ vars.Add(EnumVariable('NET', 'Network connection type', 'Ethernet', ['Ethernet', 'Wifi']))
+ vars.Update(env)
+ Help(vars.GenerateHelpText(env))
+
+# check 'cereal' library, temporarily put it here
+if not os.path.exists(src_dir + '/extlibs/cereal'):
+ print '''
+*********************************** Error: **************************************
+* 'Cereal' library doesn't exist. please download cereal to extlibs directory *
+* add apply the patch as following: *
+* $ git clone https://github.com/USCiLab/cereal.git <src_dir>/extlibs/cereal*
+* $ cd <src_dir>/extlibs/cereal *
+* $ git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245 *
+* $ git apply ../../resource/patches/cereal_gcc46.patch *
+*********************************************************************************
+'''
+ Exit(1)
+else:
+ env.AppendUnique(CPPPATH = [src_dir + '/extlibs/cereal/include'])
+++ /dev/null
-1) Build with default option
- To build with default option:
- # scons
-
- To see help information with default option(the output may be different with different options):
- # scons -Q -h
-
- To clean the project:
- # scons -c
-
-2) Build with options
- To build with options:
- # scons OPTION1=xxx OPTION2=xxx OPTION3=....
-
- To see help information:
- # scons OPTION1=xxx OPTION2=xxx OPTION3=.... -Q -h
-
- To clean the project:
- # scons OPTION1=xxx OPTION2=xxx OPTION3=.... -c
-
-3) Examples
- To build default
- # scons
- To see default help
- # scons -Q -h
- To clean
- # scons -c
-
- To build android armeabi-v7a
- # scon BUILD_TARGET=Android CPU_ARCH=armeabi-v7a
- To see help
- # scon BUILD_TARGET=Android CPU_ARCH=armeabi-v7a -Q -h
- To clean
- # scon BUILD_TARGET=Android CPU_ARCH=armeabi-v7a -c
-
-Note:
- 1. To build android binary, android NDK should be newer than r8e(recommend r10).
- 2. You may be asked to set some options. Besides set it in command line, you
-can also set it by create a environment variable. Command line has higher priority.
-If both are set, the command line value will be used.
--- /dev/null
+##
+# 'resource' sub-project main build script
+#
+##
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+
+# Build libcoap
+SConscript('csdk/libcoap/SConscript')
+
+# Build liboctbstack
+SConscript('csdk/SConscript')
+
+if target_os != 'arduino':
+ # Build liboc_logger
+ SConscript('oc_logger/SConscript')
+
+ # Build liboc
+ SConscript('src/SConscript')
+
+ # Build examples
+ SConscript('examples/SConscript')
+else:
+ SConscript('csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript')
\ No newline at end of file
+++ /dev/null
-##
-# The main build script
-#
-##
-import os
-
-SRC_TOP_DIR = os.path.abspath('.') + '/' #oic-resource project top directory
-
-# Common build options
-SConscript('build_common/SConscript')
-Import('RELEASE_BUILD', 'BUILD_TARGET', 'TARGET_CPU_ARCH')
-
-# Set build directory
-if RELEASE_BUILD:
- BUILD_DIR = SRC_TOP_DIR + '/out/' + BUILD_TARGET + '/' + TARGET_CPU_ARCH + '/release/'
-else:
- BUILD_DIR = SRC_TOP_DIR + '/out/' + BUILD_TARGET + '/' + TARGET_CPU_ARCH + '/debug/'
-VariantDir(BUILD_DIR, SRC_TOP_DIR, duplicate=0)
-Export('SRC_TOP_DIR', 'BUILD_DIR')
-
-if BUILD_TARGET == 'arduino':
- SConscript('arduino.scons')
-
-# Build libcoap
-SConscript(BUILD_DIR + 'csdk/libcoap/SConscript')
-
-# Build liboctbstack
-SConscript(BUILD_DIR + 'csdk/SConscript')
-
-if BUILD_TARGET != 'arduino':
- # Build liboc_logger
- SConscript(BUILD_DIR + 'oc_logger/SConscript')
-
- # Build liboc
- SConscript(BUILD_DIR + 'src/SConscript')
-
- # Build examples
- SConscript(BUILD_DIR + 'examples/SConscript')
-
-# Print targets
-Import('env')
-
-Help('''
-===============================================================================
-Targets:\n ''')
-for t in env.get('TS'):
- Help(t + ' ')
-Help('''
-\nDefault all targets will be built. You can specify the target to build:
-
- #scons [options] [target]
-===============================================================================
-''')
\ No newline at end of file
+++ /dev/null
-##
-# This script includes arduino specific config for oic-resource
-##
-Import('env', 'TARGET_CPU_ARCH', 'ARDUINO_HOME')
-
-# 'NET' build option
-if env.get('NET') is None:
- vars = Variables()
- vars.Add(EnumVariable('NET', 'Network connection type', 'Ethernet', ['Ethernet', 'Wifi']))
- vars.Update(env)
- Help(vars.GenerateHelpText(env))
-
-env.AppendUnique(CPPPATH = [
- ARDUINO_HOME + '/libraries/Ethernet/src',
- ARDUINO_HOME + '/libraries/Ethernet/src/utility',
- ARDUINO_HOME + '/libraries/WiFi/src',
- ARDUINO_HOME + '/libraries/WiFi/src/utility',
- ARDUINO_HOME + '/libraries/Time/',
- ])
-
-if TARGET_CPU_ARCH == 'arm':
- # Include path
- env.AppendUnique(CPPPATH = [
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino',
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/USB',
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/avr',
- 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',
- ARDUINO_HOME + '/hardware/arduino/sam/variants/arduino_due_x',
- ARDUINO_HOME + '/hardware/arduino/sam/libraries/SPI',
- ])
-
- # Compiler/Linker flags
- env.AppendUnique(CXXFLAGS = ['-ffunction-sections', '-fdata-sections', '-nostdlib',
- '--param', 'max-inline-insns-single=500', '-fno-rtti', '-fno-exceptions',
- '-mcpu=cortex-m3', '-mthumb'
- ])
- env.AppendUnique(CPPDEFINES = ['printf=iprintf', 'F_CPU=84000000L', 'ARDUINO=157',
- 'ARDUINO_SAM_DUE', 'ARDUINO_ARCH_SAM', '__SAM3X8E__', 'USB_VID=0x2341',
- 'USB_PID=0x003e', 'USBCON', 'DUSB_MANUFACTURER="Unknown"', 'WITH_ARDUINO',
- ])
-
- # Source
- ARDUINO_SRC = []
- ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/*.c'))
- ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/*.cpp'))
- ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/avr/*.c'))
- ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/USB/*.cpp'))
- ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/variants/arduino_due_x/*.cpp'))
- ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/hardware/arduino/sam/libraries/SPI/*.cpp'))
-else:
- # Include path
- env.AppendUnique(CPPPATH = [
- ARDUINO_HOME + '/hardware/arduino/avr/cores/arduino',
- ARDUINO_HOME + '/hardware/arduino/avr/libraries/SPI',
- ARDUINO_HOME + '/hardware/arduino/avr/variants/mega',
- ])
-
- # Compiler/Linker flags
- env.AppendUnique(CXXFLAGS = ['-mmcu=atmega2560', '-MMD', '-std=c++0x',
- '-Wno-write-strings', '-ffunction-sections', '-fdata-sections',
- '-fno-exceptions', '-felide-constructors'
- ])
- env.AppendUnique(CPPDEFINES = ['F_CPU=16000000L', 'ARDUINO=156', 'ARDUINO_AVR_MEGA2560',
- 'ARDUINO_ARCH_AVR', 'WITH_ARDUINO', 'ATMEGA2560'
- ])
-
- # Source
- ARDUINO_SRC = [
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/WInterrupts.c',
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/wiring.c',
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/wiring_digital.c',
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/main.cpp',
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/Stream.c',
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/WMath.c',
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/WString.c',
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/HardwareSerial.c',
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/Print.c',
- ARDUINO_HOME + '/hardware/arduino/sam/cores/arduino/IPAddress.c',
- ARDUINO_HOME + '/hardware/arduino/avr/libraries/SPI/SPI.cpp',
- ]
-
-if env.get('NET') == 'Ethernet':
- ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/libraries/Ethernet/src/*.cpp'))
- ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/libraries/Ethernet/src/utility/*.cpp'))
-else:
- ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/libraries/WiFi/src/*.cpp'))
- ARDUINO_SRC.extend(Glob(ARDUINO_HOME + '/libraries/WiFi/src/utility/*.cpp'))
-
-Export('ARDUINO_SRC')
\ No newline at end of file
linux_tb_examples_release: linux_tb_stack_release
@echo "=====BUILD TB SAMPLE APPS FOR LINUX - RELEASE - <oic-resource>/csdk/stack/samples/linux/SimpleClientServer/release/====="
$(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "PLATFORM=linux" "BUILD=release"
+ $(MAKE) -C csdk/stack/samples/linux/secure "PLATFORM=linux" "BUILD=release"
linux_tb_examples_debug: linux_tb_stack_debug
@echo "=====BUILD TB SAMPLE APPS FOR LINUX - DEBUG - <oic-resource>/csdk/stack/samples/linux/SimpleClientServer/debug/====="
$(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "PLATFORM=linux" "BUILD=debug"
+ $(MAKE) -C csdk/stack/samples/linux/secure "PLATFORM=linux" "BUILD=debug"
###############################################################################
#### UB Stack (& TB Stack as prerequisite) - Linux Only ####
-rm -rf -C csdk/linux
$(MAKE) -C csdk/stack/test/linux "clean"
$(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "clean"
+ $(MAKE) -C csdk/stack/samples/linux/secure "clean"
$(MAKE) -C . "clean"
###############################################################################
$(MAKE) -C csdk "clean" "deepclean"
$(MAKE) -C csdk/stack/test/linux "clean"
$(MAKE) -C csdk/stack/samples/linux/SimpleClientServer "clean"
+ $(MAKE) -C csdk/stack/samples/linux/secure "clean"
$(MAKE) -C csdk/stack/samples/arduino/SimpleClientServer/ocserver "clean"
$(MAKE) -C . "clean"
$(MAKE) -C unittests/ "clean"
+++ /dev/null
-##
-# This script includes generic build options:
-# release/debug, build target, CPU ARCH, toolchain, build environment etc
-##
-import os
-import platform
-
-host = platform.system()
-default_arch = platform.machine()
-
-if host not in ['Linux', 'Windows', 'Darwin']:
- host = 'Linux'
-
-# Map of host and allowed targets
-allow_target_map = {
- 'Linux': ['Linux', 'Android', 'Arduino'],
- 'Windows': ['Windows', 'WinRT', 'Android', 'Arduino'],
- 'Darwin': ['Darwin', 'IOS', 'Android', 'Arduino'],
- }
-
-# Map of platform(target) and allowed archs
-allow_arch_map = {
- 'linux': ['x86', 'x86_64', 'arm', 'arm64'],
- 'android': ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'arm64-v8a'],
- 'windows': ['x86', 'amd64', 'arm'],
- 'winrt': ['arm'],
- 'darwin': ['i386', 'x86_64'],
- 'ios': ['i386', 'x86_64', 'armv7', 'armv7s', 'arm64'],
- 'arduino': ['avr', 'arm'],
- }
-
-######################################################################
-# Get build options (the optins from command line)
-######################################################################
-BUILD_TARGET = ARGUMENTS.get('BUILD_TARGET', host).lower() # target platform
-
-if not allow_arch_map.has_key(BUILD_TARGET):
- print "\nError: Unknown target platform: %s (Allow values: %s)\n" % (BUILD_TARGET, allow_target_map[host])
- Exit(1)
-
-if default_arch not in allow_arch_map[BUILD_TARGET]:
- default_arch = allow_arch_map[BUILD_TARGET][0]
- default_arch = default_arch.lower()
-
-TARGET_CPU_ARCH = ARGUMENTS.get('CPU_ARCH', default_arch) # target CPU ARCH
-ANDROID_NDK = ARGUMENTS.get('ANDROID_NDK', os.environ.get('ANDROID_NDK')) # ANDROID NDK base directory
-SYS_VERSION = ARGUMENTS.get('SYS_VERSION', os.environ.get('SYS_VERSION')) # OSX/IOS version
-ARDUINO_HOME = ARGUMENTS.get('ARDUINO_HOME', os.environ.get('ARDUINO_HOME')) # ARDUINO root directory
-
-######################################################################
-# Common build options (release, build target, CPU)
-######################################################################
-vars = Variables()
-vars.Add(BoolVariable('RELEASE', 'Build for release?', True)) # set to 'no', 'false' or 0 for debug
-vars.Add(EnumVariable('BUILD_TARGET', 'Target platform', host, allow_target_map[host]))
-vars.Add(EnumVariable('CPU_ARCH', 'Target CPU ARCH', default_arch, allow_arch_map[BUILD_TARGET]))
-
-######################################################################
-# Platform(build target) specific options: SDK/NDK & toolchain
-######################################################################
-targets_support_cc = ['linux', 'arduino']
-
-if BUILD_TARGET == 'android':
- vars.Add(PathVariable('ANDROID_NDK', 'Android NDK root directory', os.environ.get('ANDROID_NDK')))
-
-elif BUILD_TARGET in ['darwin', 'ios']:
- vars.Add('SYS_VERSION', 'MAC OS X version / IOS version', os.environ.get('SYS_VERSION'))
-
-elif BUILD_TARGET == 'arduino':
- vars.Add(PathVariable('ARDUINO_HOME', 'ARDUINO root directory', os.environ.get('ARDUINO_HOME')))
-
-if BUILD_TARGET in targets_support_cc:
- # Set cross compile toolchain
- vars.Add('TC_PREFIX', "Toolchain prefix (Generally only be required for cross-compiling)", os.environ.get('TC_PREFIX'))
- vars.Add(PathVariable('TC_PATH',
- 'Toolchain path (Generally only be required for cross-compiling)',
- os.environ.get('TC_PATH')))
-
-if BUILD_TARGET == 'android': # Android always uses GNU compiler regardless of the host
- env = Environment(variables = vars,
- tools = ['gnulink', 'gcc', 'g++', 'ar', 'as']
- )
-else:
- env = Environment(variables = vars, TARGET_ARCH = TARGET_CPU_ARCH, TARGET_OS = BUILD_TARGET)
-
-Help(vars.GenerateHelpText(env))
-
-RELEASE_BUILD = env.get('RELEASE') # Whethere is release build, True: release, False: debug
-
-tc_set_msg = '''
-************************************ Warning **********************************
-* Enviornment variable TC_PREFIX/TC_PATH is set. It will change the default *
-* toolchain, if it isn't what you expect you should unset it, otherwise it may*
-* cause inexplicable errors. *
-*******************************************************************************
-'''
-
-if BUILD_TARGET in targets_support_cc:
- prefix = ARGUMENTS.get('TC_PREFIX', os.environ.get('TC_PREFIX'))
- tc_path = ARGUMENTS.get('TC_PATH', os.environ.get('TC_PATH'))
- if prefix:
- env.Replace(CC = prefix + 'gcc')
- env.Replace(CXX = prefix + 'g++')
- env.Replace(AR = prefix + 'ar')
- env.Replace(AS = prefix + 'as')
- env.Replace(LINK = prefix + 'ld')
- env.Replace(RANLIB = prefix + 'ranlib')
-
- if tc_path:
- env.PrependENVPath('PATH', tc_path)
- sys_root = os.path.abspath(tc_path + '/../')
- env.AppendUnique(CFLAGS = ['--sysroot=' + sys_root])
- env.AppendUnique(CXXFLAGS = ['--sysroot=' + sys_root])
- env.AppendUnique(LINKFLAGS = ['--sysroot=' + sys_root])
-
- if prefix or tc_path:
- print tc_set_msg
-
-# Ensure scons be able to change its working directory
-env.SConscriptChdir(1)
-
-Export('env', 'RELEASE_BUILD', 'BUILD_TARGET', 'TARGET_CPU_ARCH',
- 'ANDROID_NDK', 'SYS_VERSION', 'ARDUINO_HOME')
-
-# Load config of specific platform(build target)
-env.SConscript(BUILD_TARGET + '/SConscript')
-
-Return('env')
\ No newline at end of file
+++ /dev/null
-##
-# This script includes arduino specific config
-##
-import os
-import platform
-
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH', 'ARDUINO_HOME')
-
-if not ARDUINO_HOME:
- print '''
-************************************* Error ***********************************
-* Arduino root directory (ARDUINO_HOME) isn't set, you can set enviornment *
-* variable ARDUINO_HOME or add it in command line as: *
-* # scons ARDUINO_HOME=<path to arduino root directory> ... *
-*******************************************************************************
-'''
- Exit(1)
-
-# Overwrite suffixes and prefixes
-if env['HOST_OS'] == 'win32':
- env['OBJSUFFIX'] = '.o'
- env['SHOBJSUFFIX'] = '.os'
- env['LIBPREFIX'] = 'lib'
- env['LIBSUFFIX'] = '.a'
- env['SHLIBPREFIX'] = 'lib'
- env['SHLIBSUFFIX'] = '.so'
- env['LIBPREFIXES'] = ['lib']
- env['LIBSUFFIXES'] = ['.a', '.so']
- env['PROGSUFFIX'] = ''
-elif platform.system().lower() == 'darwin':
- env['SHLIBSUFFIX'] = '.so'
- env['LIBSUFFIXES'] = ['.a', '.so']
- env['PROGSUFFIX'] = ''
-
-# Set toolchain
-def find_toolchain(dir, tc):
- for root, dirs, files in os.walk(dir, True, None, False):
- for f in files:
- lf = f.lower()
- if lf == tc:
- return root
- return None
-
-if TARGET_CPU_ARCH == 'arm':
- prefix = 'arm-none-eabi-'
-else:
- prefix = 'avr-'
-
-tc_path = find_toolchain(ARDUINO_HOME + '/hardware/tools/', prefix + 'g++')
-if not tc_path:
- print '''
-************************************* Error ***********************************
-* Arduino toolchain isn't detected. Please specify the toolchain prefix and *
-* path, you can do it by setting enviornment variable TC_PREFIX and TC_PATH or*
-* add it in command line as: *
-* # scons TC_PREFIX=<prefix> TC_PATH=<path to toolchain> ... *
-* e.g. scons TC_PREFIX=avr- TC_PATH=/opt/arduino-1.5.7/hardware/tools/avr/bin * *
-* Note: TC_PREFIX shouldn't include path *
-*******************************************************************************
-'''
- Exit(1)
-
-env.PrependENVPath('PATH', tc_path)
-env.Replace(CC = prefix + 'gcc')
-env.Replace(CXX = prefix + 'g++')
-env.Replace(AR = prefix + 'ar')
-env.Replace(AS = prefix + 'as')
-env.Replace(LINK = prefix + 'ld')
-env.Replace(RANLIB = prefix + 'ranlib')
-
-sys_root = os.path.abspath(os.path.join(tc_path, '..'))
-env.AppendUnique(CFLAGS = ['--sysroot=' + sys_root])
-env.AppendUnique(CXXFLAGS = ['--sysroot=' + sys_root])
-env.AppendUnique(LINKFLAGS = ['--sysroot=' + sys_root])
-
-# Debug/release relative flags
-if RELEASE_BUILD:
- env.AppendUnique(CFLAGS = ['-Os'])
- env.AppendUnique(CXXFLAGS = ['-Os'])
- env.AppendUnique(CPPDEFINES = ['NDEBUG'])
- env.AppendUnique(LINKFLAGS = ['-s'])
-else:
- env.AppendUnique(CFLAGS = ['-g'])
- env.AppendUnique(CXXFLAGS = ['-g'])
\ No newline at end of file
+++ /dev/null
-##
-# This script set darwin specific flags (GNU GCC)
-#
-##
-import platform
-
-Import('env', 'RELEASE_BUILD', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'SYS_VERSION')
-
-if SYS_VERSION is None:
- print '''
-*********************************** Error *************************************
-* MAC OSX/IOS version isn't set, please set it in command line as : *
-* # scons SYS_VERSION=<version> ... *
-* To get the version, please see: *
-* /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ *
-* /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/ *
-*******************************************************************************
-'''
- Exit(1)
-
-# Set release/debug flags
-if RELEASE_BUILD:
- env.AppendUnique(CFLAGS = ['-Os'])
- env.AppendUnique(CXXFLAGS = ['-Os'])
- env.AppendUnique(CPPDEFINES = ['NDEBUG'])
-else:
- env.AppendUnique(CFLAGS = ['-g'])
- env.AppendUnique(CXXFLAGS = ['-g'])
-
-if BUILD_TARGET == 'darwin':
- SYS_ROOT = '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX' + SYS_VERSION + '.sdk/'
-else:
- if TARGET_CPU_ARCH in ['i386', 'x86_64']:
- SYS_ROOT = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator' + SYS_VERSION + '.sdk/'
- else:
- SYS_ROOT = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS' + SYS_VERSION + '.sdk/'
-
-# Set arch flags
-env.AppendUnique(CXXFLAGS = ['-arch', TARGET_CPU_ARCH, '-isysroot', SYS_ROOT])
-env.AppendUnique(CCFLAGS = ['-arch', TARGET_CPU_ARCH, '-isysroot', SYS_ROOT])
-env.AppendUnique(LINKFLAGS = ['-arch', TARGET_CPU_ARCH, '-isysroot', SYS_ROOT])
-
-if BUILD_TARGET == 'darwin':
- flag = '-mmacosx-version-min=' + SYS_VERSION
- env.AppendUnique(CXXFLAGS = [flag])
- env.AppendUnique(CCFLAGS = [flag])
- env.AppendUnique(LINKFLAGS = [flag])
\ No newline at end of file
+++ /dev/null
-##
-# This script set ios specific flags (GNU GCC)
-#
-##
-Import('env', 'TARGET_CPU_ARCH', 'SYS_VERSION')
-
-# setting of IOS is almost the same as Darwin(MAC OSX)
-env.SConscript('../darwin/SConscript')
-
-if TARGET_CPU_ARCH in ['i386', 'x86_64']: #Simulator
- flag = '-mios-simulator-version-min=' + SYS_VERSION
- env.AppendUnique(CXXFLAGS = [flag])
- env.AppendUnique(CCFLAGS = [flag])
- env.AppendUnique(LINKFLAGS = [flag])
-else:
- flag = '-miphoneos-version-min=' + SYS_VERSION
- env.AppendUnique(CXXFLAGS = [flag])
- env.AppendUnique(CCFLAGS = [flag])
- env.AppendUnique(LINKFLAGS = [flag])
\ No newline at end of file
+++ /dev/null
-##
-# This script set linux specific flags (GNU GCC)
-#
-##
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH')
-
-# Set release/debug flags
-if RELEASE_BUILD:
- env.AppendUnique(CFLAGS = ['-Os'])
- env.AppendUnique(CXXFLAGS = ['-Os'])
- env.AppendUnique(CPPDEFINES = ['NDEBUG'])
- env.AppendUnique(LINKFLAGS = ['-s'])
-else:
- env.AppendUnique(CFLAGS = ['-g'])
- env.AppendUnique(CXXFLAGS = ['-g'])
-
-# Set arch flags
-if TARGET_CPU_ARCH in ['x86']:
- env.AppendUnique(CFLAGS = ['-m32'])
- env.AppendUnique(CXXFLAGS = ['-m32'])
- env.AppendUnique(LINKFLAGS = ['-m32'])
-elif TARGET_CPU_ARCH in ['x86_64']:
- env.AppendUnique(CXXFLAGS = ['-m64'])
- env.AppendUnique(CFLAGS = ['-m64'])
- env.AppendUnique(LINKFLAGS = ['-m64'])
-elif TARGET_CPU_ARCH.find('v7a-hard') > 0:
- env.AppendUnique(CPPFLAGS = ['-march=armv7-a'])
- env.AppendUnique(CPPFLAGS = ['-mfloat-abi=hard'])
- env.AppendUnique(CFLAGS = ['-mfloat-abi=hard'])
- env.AppendUnique(CXXFLAGS = ['-mfloat-abi=hard'])
- env.AppendUnique(LINKFLAGS = ['-mfloat-abi=hard'])
-elif TARGET_CPU_ARCH.find('v7a') > 0:
- env.AppendUnique(CPPFLAGS = ['-march=armv7-a'])
-elif TARGET_CPU_ARCH.find('arm64') > 0:
- env.AppendUnique(CPPFLAGS = ['-march=armv8-a'])
-else:
- env.AppendUnique(CPPFLAGS = ['-march=armv5te'])
\ No newline at end of file
+++ /dev/null
-##
-# This script includes windows specific config (MSVS/MSVC)
-##
-Import('env', 'RELEASE_BUILD', 'TARGET_CPU_ARCH')
-
-# Set common flags
-env.AppendUnique(CXXFLAGS=['/wd4244', '/wd4267','/wd4345', '/wd4355', '/wd4800', '/wd4996'])
-env.AppendUnique(CFLAGS=['/EHsc'])
-env.AppendUnique(CXXFLAGS=['/EHsc'])
-
-# Set release/debug flags
-if RELEASE_BUILD:
- env.AppendUnique(CFLAGS = ['/MD', '/O2', '/GF'])
- env.AppendUnique(CXXFLAGS = ['/MD', '/O2', '/GF'])
- env.AppendUnique(CPPDEFINES = ['NDEBUG'])
-else:
- env.AppendUnique(CFLAGS = ['/MDd', '/Od', '/ZI', '/GZ', '/Gm'])
- env.AppendUnique(CXXFLAGS = ['/MDd', '/Od', '/ZI', '/GZ', '/Gm'])
- env.AppendUnique(CPPDEFINES = ['_DEBUG'])
- env.AppendUnique(LINKFLAGS = ['/debug'])
\ No newline at end of file
##
-# liboctbstack (static library) build script
+# liboctbstack (share library) build script
##
-Import('env', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'RELEASE_BUILD', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
-liboctbstack_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
-# Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-Import('OIC_UTILS')
+liboctbstack_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
# As in the source code, it includes arduino Time library (C++)
# It requires compile the .c with g++
-if BUILD_TARGET == 'arduino':
+if target_os == 'arduino':
liboctbstack_env.Replace(CC = env.get('CXX'))
liboctbstack_env.Replace(CFLAGS = env.get('CXXFLAGS'))
# Build flags
######################################################################
liboctbstack_env.PrependUnique(CPPPATH = [
- OIC_UTILS + '/tb/cJSON/',
+ '../../extlibs/cjson/',
'ocsocket/include',
'logger/include',
'ocrandom/include',
'../oc_logger/include'
])
-if BUILD_TARGET not in ['arduino', 'windows', 'winrt']:
+if target_os not in ['arduino', 'windows', 'winrt']:
liboctbstack_env.AppendUnique(CPPDEFINES = ['WITH_POSIX'])
liboctbstack_env.AppendUnique(CFLAGS = ['-std=c99'])
-if BUILD_TARGET not in ['windows', 'winrt']:
+if target_os not in ['windows', 'winrt']:
liboctbstack_env.AppendUnique(CFLAGS = ['-Wall'])
-if not RELEASE_BUILD:
+if target_os == 'android':
+ liboctbstack_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+ liboctbstack_env.AppendUnique(LIBS = ['coap', 'm'])
+
+if target_os == 'arduino':
+ liboctbstack_env.AppendUnique(CPPDEFINES = ['NDEBUG', 'WITH_ARDUINO'])
+else:
+ liboctbstack_env.AppendUnique(CFLAGS = ['-fPIC'])
+
+if target_os in ['darwin', 'ios']:
+ liboctbstack_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+ liboctbstack_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+ liboctbstack_env.AppendUnique(LIBS = ['coap'])
+
+if not env.get('RELEASE'):
liboctbstack_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
######################################################################
######################################################################
OCTBSTACK_SRC = 'stack/src/'
liboctbstack_src = [
+ '../../extlibs/cjson/cJSON.c',
'occoap/src/occoap.c',
'occoap/src/occoaphelper.c',
OCTBSTACK_SRC + 'ocstack.c',
OCTBSTACK_SRC + 'occlientcb.c',
OCTBSTACK_SRC + 'ocresource.c',
OCTBSTACK_SRC + 'ocobserve.c',
+ OCTBSTACK_SRC + 'ocserverrequest.c',
OCTBSTACK_SRC + 'occollection.c',
+ OCTBSTACK_SRC + 'ocsecurity.c'
]
-
-if RELEASE_BUILD:
- prefix = TARGET_CPU_ARCH + '-'
+if target_os == 'arduino':
+ liboctbstack = liboctbstack_env.StaticLibrary('octbstack', liboctbstack_src)
else:
- prefix = TARGET_CPU_ARCH + 'd-'
-cjson_obj = liboctbstack_env.Object(OIC_UTILS + '/tb/cJSON/cJSON.c', OBJPREFIX=prefix)
-liboctbstack_src.append(cjson_obj)
+ liboctbstack = liboctbstack_env.SharedLibrary('octbstack', liboctbstack_src)
-liboctbstack = liboctbstack_env.StaticLibrary('octbstack', liboctbstack_src)
-i_lctbs = liboctbstack_env.Install(BUILD_DIR, liboctbstack)
-Alias('liboctbstack', i_lctbs)
-env.AppendUnique(TS = ['liboctbstack'])
+liboctbstack_env.InstallTarget(liboctbstack, 'liboctbstack')
##
-# libcoap (static library) build script
+# libcoap (share library) build script
##
-Import('env', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'RELEASE_BUILD', 'BUILD_DIR', 'ARDUINO_HOME')
+Import('env')
libcoap_env = env.Clone()
-# As in the source code, it includes arduino Time library (C++)
+target_os = env.get('TARGET_OS')
+# As in the source code(C) includes arduino Time library head file(C++)
# It requires compile the .c with g++
-if BUILD_TARGET == 'arduino':
+if target_os == 'arduino':
libcoap_env.Replace(CC = env.get('CXX'))
libcoap_env.Replace(CFLAGS = env.get('CXXFLAGS'))
'../../oc_logger/include'
])
-if BUILD_TARGET not in ['arduino', 'windows', 'winrt']:
+if target_os not in ['arduino', 'windows', 'winrt']:
libcoap_env.AppendUnique(CPPDEFINES = ['WITH_POSIX'])
- libcoap_env.AppendUnique(CFLAGS = ['-std=gnu99'])
+ libcoap_env.AppendUnique(CFLAGS = ['-std=gnu99', '-fPIC'])
-if BUILD_TARGET not in ['windows', 'winrt']:
+if target_os not in ['windows', 'winrt']:
libcoap_env.AppendUnique(CFLAGS = ['-Wall', '-ffunction-sections',
'-fdata-sections', '-fno-exceptions'])
-if not RELEASE_BUILD:
+if target_os == 'android':
+ libcoap_env.AppendUnique(LIBS = ['log'])
+
+if target_os == 'arduino':
+ libcoap_env.AppendUnique(CPPDEFINES = ['NDEBUG', 'WITH_ARDUINO'])
+
+if target_os in ['darwin', 'ios']:
+ libcoap_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+
+if not env.get('RELEASE'):
libcoap_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
######################################################################
'encode.c',
'uri.c',
'coap_list.c',
- 'resource.c',
+# 'resource.c',
'hashkey.c',
'str.c',
'option.c',
'../../oc_logger/c/oc_console_logger.c'
]
-if BUILD_TARGET == 'arduino':
+if target_os == 'arduino':
if env.get('NET') == 'Wifi':
libcoap_src.append(['../ocsocket/src/ocsocket_arduino_wifi.cpp'])
else:
libcoap_src.append(['../ocsocket/src/ocsocket_arduino.cpp'])
-
- if RELEASE_BUILD:
- prefix = TARGET_CPU_ARCH + '-'
- else:
- prefix = TARGET_CPU_ARCH + 'd-'
- time_obj = libcoap_env.Object(ARDUINO_HOME + '/libraries/Time/Time.cpp', OBJPREFIX=prefix)
- libcoap_src.append(time_obj)
else:
libcoap_src.append(['../ocsocket/src/ocsocket.c'])
-libcoap = libcoap_env.StaticLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap')
-i_lc = libcoap_env.Install(BUILD_DIR, libcoap)
-Alias('libcoap', i_lc)
-env.AppendUnique(TS = ['libcoap'])
\ No newline at end of file
+if target_os == 'arduino':
+ libcoap = libcoap_env.StaticLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap_')
+else:
+ libcoap = libcoap_env.SharedLibrary('libcoap', libcoap_src, OBJPREFIX='libcoap_')
+
+libcoap_env.InstallTarget(libcoap, 'libcoap')
* Copyright (C) 2010--2012,2014 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
- * README for terms of use.
+ * README for terms of use.
*/
#ifndef _COAP_BLOCK_H_
#define _COAP_BLOCK_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "option.h"
#include "encode.h"
#include "pdu.h"
#endif
/**
- * Structure of Block options.
+ * Structure of Block options.
*/
typedef struct {
- unsigned int num:20; /**< block number */
- unsigned int m:1; /**< 1 if more blocks follow, 0 otherwise */
- unsigned int szx:3; /**< block size */
+ unsigned int num:20; /**< block number */
+ unsigned int m:1; /**< 1 if more blocks follow, 0 otherwise */
+ unsigned int szx:3; /**< block size */
} coap_block_t;
/**
- * Returns the value of the least significant byte of a Block option @p opt.
+ * Returns the value of the least significant byte of a Block option @p opt.
* For zero-length options (i.e. num == m == szx == 0), COAP_OPT_BLOCK_LAST
* returns @c NULL.
*/
* value @c 1. Otherwise, @c 0 is returned.
*
* @param pdu The pdu to search for option @p type.
- * @param type The option to search for (must be COAP_OPTION_BLOCK1 or
+ * @param type The option to search for (must be COAP_OPTION_BLOCK1 or
* COAP_OPTION_BLOCK2)
* @param block The block structure to initilize.
* @return @c 1 on success, @c 0 otherwise.
* space is required. The actual length of the resource is specified
* in @p data_length.
*
- * This function may change *block to reflect the values written to
+ * This function may change *block to reflect the values written to
* @p pdu. As the function takes into consideration the remaining space
- * @p pdu, no more options should be added after coap_write_block_opt()
+ * @p pdu, no more options should be added after coap_write_block_opt()
* has returned.
*
* @param block The block structure to use. On return, this object
* @return @c 1 on success, or a negative value on error.
*/
int coap_write_block_opt(coap_block_t *block, unsigned short type,
- coap_pdu_t *pdu, size_t data_length);
+ coap_pdu_t *pdu, size_t data_length);
-/**
+/**
* Adds the @p block_num block of size 1 << (@p block_szx + 4) from
* source @p data to @p pdu.
*
* @return @c 1 on success, @c 0 otherwise.
*/
int coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data,
- unsigned int block_num, unsigned char block_szx);
+ unsigned int block_num, unsigned char block_szx);
/**@}*/
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _COAP_BLOCK_H_ */
RANDOM_DIR = $(ROOT_DIR)/ocrandom
STACK_DIR = $(ROOT_DIR)/stack
OCMALLOC_DIR = $(ROOT_DIR)/ocmalloc
+EXTLIBS_DIR = $(ROOT_DIR)/../../extlibs
+TINYDTLS_DIR = $(EXTLIBS_DIR)/tinydtls
INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include -I$(RANDOM_DIR)/include \
- -I$(OCMALLOC_DIR)/include -I$(OC_LOG_DIR)/include
+ -I$(OCMALLOC_DIR)/include -I$(OC_LOG_DIR)/include -I$(STACK_DIR)/include
# Note for Arduino: The CC flag is set to the C++ compiler since Arduino build
# includes Time.h header file which has C++ style definitions.
:$(OC_LOG_DIR)/c
ifeq ($(PLATFORM),linux)
-ifneq ($(wildcard $(ROOT_DIR)/tinydtls/libtinydtls.a),)
+ifneq ($(wildcard $(TINYDTLS_DIR)/libtinydtls.a),)
$(info "Building libcoap with DTLS support")
SOURCES += netdtls.c
VPATH += sec
- TINYDTLS_DIR = $(ROOT_DIR)/tinydtls
NETDTLS_DIR = sec
INC_DIRS += -I$(TINYDTLS_DIR) -I$(NETDTLS_DIR) -I.
CC_FLAGS.debug += -DWITH_DTLS
else
{
node->timeout = MAX_MULTICAST_DELAY_SEC * ((COAP_TICKS_PER_SECOND * (r & 0xFF)) >> 8);
- node->delayedResponse = 1;
+ node->delayedResNeeded = 1;
}
if (flag & SEND_SECURE_PORT) {
coap_address_t src, dst;
coap_queue_t *node;
- unsigned char delayRes = 0;
+ unsigned char delayedResNeeded = 0;
#ifdef WITH_CONTIKI
pbuf = uip_appdata;
// Set the delayed response flag for responding to multicast requests
if (sockfd == ctx->sockfd_wellknown && bytes_read > 0) {
- delayRes = 1;
+ delayedResNeeded = 1;
}
#if defined(WITH_DTLS)
// Perform the DTLS decryption if packet is coming on secure port
}
//set the delayed response flag
- node->delayedResponse = delayRes;
+ node->delayedResNeeded = delayedResNeeded;
//set the secure flag on the received packet
#if defined(WITH_DTLS)
if (ctx->timer_configured)
{
- printf("clearing\n");
sys_untimeout(coap_retransmittimer_execute, (void*)ctx);
ctx->timer_configured = 0;
}
* */
delay = 0;
}
-
- printf("scheduling for %d ticks\n", delay);
sys_timeout(delay, coap_retransmittimer_execute, (void*)ctx);
ctx->timer_configured = 1;
}
#include "coap_time.h"
typedef enum {
- SEND_NOW = (1 << 0), /*Flag used when sending non-confirmable, ACK and RESET coap pdus*/
- SEND_NOW_CON = (1 << 1), /*Flag used when sending confirmable coap pdu*/
- SEND_DELAYED = (1 << 2), /*Flag used to delay the transmission of coap pdu*/
- SEND_RETX = (1 << 3), /*Flag used to retransmit a confirmable pdu*/
- SEND_SECURE_PORT = (1 << 4) /*Flag used to indicate that PDU needs to
- be transmitted on secure port */
+ SEND_NOW = (1 << 0), // Flag used when sending non-confirmable,
+ // ACK and RESET coap pdus, Automatically set in SendCoAPPdu
+ // Do not use in upper stack APIs
+ SEND_NOW_CON = (1 << 1), // Flag used when sending confirmable coap pdu,
+ // Automatically set in SendCoAPPdu,
+ // Do not use in upper stack APIs
+ SEND_DELAYED = (1 << 2), // Flag used to delay the transmission of coap pdu
+ SEND_RETX = (1 << 3), // Flag used to retransmit a confirmable pdu
+ SEND_SECURE_PORT = (1 << 4) // Flag used to indicate that PDU needs to
+ // be transmitted on secure port
} coap_send_flags_t;
struct coap_queue_t;
coap_pdu_t *pdu; /**< the CoAP PDU to send */
- unsigned char delayedResponse; /**< delayed response flag */
+ unsigned char delayedResNeeded; /**< delayed response flag */
unsigned char secure; /**< rx/tx will use secure channel (DTLS) */
} coap_queue_t;
#define COAP_OPTION_LOCATION_QUERY 20 /* E, String, 0-255 B, (none) */
#define COAP_OPTION_PROXY_URI 35 /* C, String, 1-1034 B, (none) */
#define COAP_OPTION_PROXY_SCHEME 39 /* C, String, 1-255 B, (none) */
+#define COAP_OPTION_SIZE2 28 /* E, uint, 0-4 B, (none) */
#define COAP_OPTION_SIZE1 60 /* E, uint, 0-4 B, (none) */
/* option types from draft-ietf-coap-observe-09 */
* This function returns the number of bytes written or @c 0 on error.
*/
size_t coap_add_option(coap_pdu_t *pdu, unsigned short type,
- unsigned int len, const unsigned char *data);
+ unsigned int len, const unsigned char *data);
/**
* Adds option of given type to pdu that is passed as first
* written before the PDU can be sent, or @c NULL on error.
*/
unsigned char *coap_add_option_later(coap_pdu_t *pdu, unsigned short type,
- unsigned int len);
+ unsigned int len);
/**
* Adds given data to the pdu that is passed as first parameter. Note
#include "debug.h"
#include "logger.h"
#include "mem.h"
+#include "ocsecurityconfig.h"
#define MOD_NAME ("netdtls.c")
#define get_dtls_ctx(coap_ctx) (coap_ctx->coap_dtls_ctx->dtls_ctx)
+extern void OCGetDtlsPskCredentials(OCDtlsPskCredsBlob **credInfo);
/**
* An internal method to invoke tinyDTLS library 'dtls_write' method.
if (existing_node) {
node->timeout = existing_node->timeout;
- node->delayedResponse = existing_node->delayedResponse;
+ node->delayedResNeeded = existing_node->delayedResNeeded;
}
// Add the node in cachedqueue list
node->t = (now - ctx->sendqueue_basetime) + node->timeout;
}
- node->delayedResponse = 0;
+ node->delayedResNeeded = 0;
node->next = NULL;
coap_insert_node(&ctx->sendqueue, node);
}
if (!ctx)
return ;
- for (;node=get_cached_pdu(ctx, dst);) {
+ for (;(node=get_cached_pdu(ctx, dst));) {
OC_LOG(DEBUG, MOD_NAME, PCF("Sending cached PDU"));
OC_LOG_BUFFER(DEBUG, MOD_NAME, (uint8_t*)node->pdu->hdr, node->pdu->length);
// Send this PDU to DTLS library for encryption
static int get_psk_credentials(dtls_context_t *ctx,
const session_t *session,
dtls_credentials_type_t type,
- const unsigned char *desc, size_t descLen,
- unsigned char *result, size_t resultLen)
+ const unsigned char *desc, size_t desc_len,
+ unsigned char *result, size_t result_len)
{
+ int ret = -1;
+ OCDtlsPskCredsBlob *creds_blob = NULL;
-#define RS_IDENTITY ("1111111111111111")
-#define CLIENT_IDENTITY ("2222222222222222")
-#define RS_CLIENT_PSK ("AAAAAAAAAAAAAAAA")
+ //Retrieve the credentials blob from security module
+ OCGetDtlsPskCredentials(&creds_blob);
- if (type == DTLS_PSK_HINT)
- {
- if (sizeof(RS_IDENTITY) < resultLen)
- {
- memcpy(result, RS_IDENTITY, sizeof(RS_IDENTITY));
- return sizeof(RS_IDENTITY);
- }
- }
- else if (type == DTLS_PSK_IDENTITY)
- {
- if (sizeof(CLIENT_IDENTITY) < resultLen)
- {
- memcpy(result, CLIENT_IDENTITY, sizeof(CLIENT_IDENTITY));
- return sizeof(CLIENT_IDENTITY);
+ if (!creds_blob)
+ return ret;
+
+ if ((type == DTLS_PSK_HINT) || (type == DTLS_PSK_IDENTITY)) {
+ if (DTLS_PSK_ID_LEN <= result_len){
+ memcpy(result, creds_blob->identity, DTLS_PSK_ID_LEN);
+ ret = DTLS_PSK_ID_LEN;
}
}
- else if (type == DTLS_PSK_KEY && (desc))
- {
- if (descLen == sizeof(RS_IDENTITY) &&
- !memcmp(desc, RS_IDENTITY, descLen))
- {
- memcpy(result, RS_CLIENT_PSK, sizeof(RS_CLIENT_PSK));
- return sizeof(RS_CLIENT_PSK);
- }
- if (descLen == sizeof(CLIENT_IDENTITY) &&
- !memcmp(desc, CLIENT_IDENTITY, descLen))
- {
- memcpy(result, RS_CLIENT_PSK, sizeof(RS_CLIENT_PSK));
- return sizeof(RS_CLIENT_PSK);
+
+ if ((type == DTLS_PSK_KEY) && (desc) && (desc_len == DTLS_PSK_PSK_LEN)) {
+ //Check if we have the credentials for the device with which we
+ //are trying to perform a handshake
+ for (int i =0; i < creds_blob->num; i++) {
+ if (memcmp(desc, creds_blob->creds[i].id, DTLS_PSK_ID_LEN) == 0)
+ {
+ memcpy(result, creds_blob->creds[i].psk, DTLS_PSK_PSK_LEN);
+ ret = DTLS_PSK_PSK_LEN;
+ }
}
}
- return -1;
+ return ret;
}
OCMALLOC_DIR = ocmalloc
EXTLIBS_DIR = ../../extlibs
CJSON_DIR = $(EXTLIBS_DIR)/cjson
-TINYDTLS_DIR = tinydtls
+TINYDTLS_DIR = $(EXTLIBS_DIR)/tinydtls
OCCOAP_SRC = $(OCCOAP_DIR)/src
OCTBSTACK_SRC = $(OCTBSTACK_DIR)/src
OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/occlientcb.c
OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/ocresource.c
OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/ocobserve.c
+OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/ocserverrequest.c
OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/occollection.c
+OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/ocsecurity.c
SOURCES := $(CJSON_SOURCES)
SOURCES += $(OCCOAP_SOURCES)
buildScript_all: objdirs obj_build liboctbstack.a
-make_lcoap:
+make_lcoap:
$(MAKE) -C $(LCOAP_DIR) "BUILD=$(BUILD)" "PLATFORM=$(PLATFORM)" "ARDUINOWIFI=$(ARDUINOWIFI)"
-objdirs:
+objdirs:
mkdir -p $(PLATFORM)
mkdir -p $(PLATFORM)/$(ARDUINO_SHIELD_TYPE)
mkdir -p $(OUT_DIR)
$(foreach source,$(SOURCES), $(CC) $(CFLAGS) $(source) -o $(patsubst %.c, %.o, $(patsubst %, $(OBJ_DIR)/%, $(notdir $(source))));)
liboctbstack.a: obj_build
- @echo "Building $@"
+ @echo "Building $@"
# Unpackage libcoap.a to $(OBJ_DIR)/$(BUILD). The output objects from OCStack and OCCoap are already at this location
@cd $(OBJ_DIR) && $(AR) -x $(PLATFORM_SPECIFIC_BACKOUT)$(LCOAP_DIR)/$(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD)/libcoap.a
# Repackage all the objects at this location into a single archive. This is OCStack, OCCoap, and LibCoap (LibCoap contains OCRandom, OCLogger, and OCSocket.).
$(AR) -r $(OUT_DIR)/$@ $(OBJ_DIR)/*.o
-
+
ifeq ($(PLATFORM),linux)
ifneq ($(wildcard $(TINYDTLS_DIR)/libtinydtls.a),)
$(info "Building liboctbstack with DTLS support")
- mkdir -p $(OBJ_DIR)/$(TINYDTLS_DIR)
- @cd $(OBJ_DIR)/$(TINYDTLS_DIR) && $(AR) -x ../$(PLATFORM_SPECIFIC_BACKOUT)$(TINYDTLS_DIR)/libtinydtls.a
- $(AR) -q $(OUT_DIR)/$@ $(OBJ_DIR)/$(TINYDTLS_DIR)/*.o
+ mkdir -p $(OBJ_DIR)/tinydtls
+ @cd $(OBJ_DIR)/tinydtls && $(AR) -x ../$(PLATFORM_SPECIFIC_BACKOUT)$(TINYDTLS_DIR)/libtinydtls.a
+ $(AR) -q $(OUT_DIR)/$@ $(OBJ_DIR)/tinydtls/*.o
endif
endif
OCStackResult OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCCoAPToken * token,
const char *Uri, const char *payload, OCHeaderOption * options, uint8_t numOptions);
+/**
+ * Send a response to a request.
+ *
+ * @param response - pointer to OCServerProtocolResponse that contains all request and
+ * response info necessary to send the response to the client
+ * @return
+ * OC_STACK_OK - No errors; Success
+ * OC_STACK_ERROR - Error sending response
+ */
+OCStackResult OCDoCoAPResponse(OCServerProtocolResponse *response);
/**
* Stop the CoAP client or server processing
void OCGenerateCoAPToken(OCCoAPToken * token);
/**
- * Initiate sending of CoAP messages. Example: server uses it to send observe messages
- *
- * @return 0 - success, else - TBD error
- */
-OCStackResult OCSendCoAPNotification (unsigned char * uri, OCDevAddr *dstAddr,
- OCQualityOfService qos, OCCoAPToken * token,
- unsigned char *payload, OCResource *resPtr, uint32_t maxAge);
-
-/**
* Retrieve the end-point info where resource is being hosted.
* Currently, this method only provides the IP port with which the socket
* is bound. This internal method may be extended in future to retrieve
CreateNewOptionNode(unsigned short key, unsigned int length,
unsigned char *data);
-// Internal function to create OCRequest struct at the server from a received coap pdu
-OCStackResult FormOCRequest(OCRequest * * requestLoc, OCQualityOfService qos,
- unsigned char * uriBuf, OCObserveReq * observeReq,
- OCEntityHandlerRequest * entityHandlerRequest,
- uint8_t secure);
-
-// Internal function to create OCEntityHandlerRequest at the server from a received coap pdu
-OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequestLoc,
- OCMethod method, unsigned char * resBuf, unsigned char * bufReqPayload,
- unsigned char * queryBuf, unsigned char *newResUriBuf);
-
// Internal function to retrieve Uri and Query from received coap pdu
OCStackResult ParseCoAPPdu(coap_pdu_t * pdu, unsigned char * uriBuf,
- unsigned char * queryBuf, uint8_t * * observeOptionLoc,
- uint8_t * * maxAgeOptionLoc, unsigned char * * payloadLoc,
- OCHeaderOption * rcvVendorSpecificHeaderOptions,
- uint8_t * numRcvVendorSpecificHeaderOptions);
+ unsigned char * queryBuf, uint32_t * observeOption,
+ uint32_t * maxAgeOption,
+ uint8_t * numVendorSpecificHeaderOptions,
+ OCHeaderOption * vendorSpecificHeaderOptions,
+ coap_block_t * block1, coap_block_t * block2,
+ uint16_t * size1, uint16_t * size2,
+ unsigned char * payload);
// Internal function to retrieve a Token from received coap pdu
void RetrieveOCCoAPToken(const coap_pdu_t * pdu, OCCoAPToken * rcvdToken);
-// Internal function to create OCObserveReq at the server
-OCStackResult FormOCObserveReq(OCObserveReq ** observeReqLoc, uint32_t obsOption,
- OCDevAddr * remote, OCCoAPToken * rcvdToken);
-
// Internal function to create OCResponse struct at the client from a received coap pdu
OCStackResult FormOCResponse(OCResponse * * responseLoc, ClientCB * cbNode,
uint8_t TTL, OCClientResponse * clientResponse);
// Internal function to form the standard response option list
OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType,
- uint32_t * addMaxAge, uint8_t observeOptionLength, uint32_t * observeOptionPtr,
+ uint32_t * addMaxAge, uint32_t * observeOptionPtr,
uint16_t * addPortNumber, uint8_t uriLength, unsigned char * uri,
uint8_t queryLength, unsigned char * query, OCHeaderOption * vendorSpecificHeaderOptions,
uint8_t numVendorSpecificHeaderOptions);
#include <limits.h>
#include <ctype.h>
-//-----------------------------------------------------------------------------
+//=============================================================================
// Macros
-//-----------------------------------------------------------------------------
+//=============================================================================
#define TAG PCF("OCCoAP")
#define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
{OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg); goto exit;} }
//=============================================================================
+// Defines
+//=============================================================================
+#define COAP_BLOCK_FILL_VALUE (0xFF)
+
+//=============================================================================
// Private Variables
//=============================================================================
// silence warnings
(void) ctx;
-
- OCStackResult result = OC_STACK_OK;
- OCCoAPToken sentToken;
- uint8_t * observeOption = NULL;
coap_pdu_t * sentPdu = sentQueue->pdu;
+ OCStackResult result = OC_STACK_ERROR;
+ uint32_t observationOption = OC_OBSERVE_NO_OPTION;
+ // {{0}} to eliminate warning for known compiler bug 53119
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
+ OCCoAPToken sentToken = {{0}};
- // fill the buffers of Uri and Query
- result = ParseCoAPPdu(sentPdu, NULL, NULL, &observeOption, NULL, NULL, NULL, NULL);
+ result = ParseCoAPPdu(sentPdu, NULL, NULL, &observationOption, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
VERIFY_SUCCESS(result, OC_STACK_OK);
// fill OCCoAPToken structure
RetrieveOCCoAPToken(sentPdu, &sentToken);
- if(msgType == COAP_MESSAGE_RST){
- // now the observer should be deleted
+ if(msgType == COAP_MESSAGE_RST)
+ {
if(myStackMode != OC_CLIENT)
{
- result = OCObserverStatus(&sentToken, OC_OBSERVER_NOT_INTERESTED);
- if(result == OC_STACK_OK){
+ result = OCStackFeedBack(&sentToken, OC_OBSERVER_NOT_INTERESTED);
+ if(result == OC_STACK_OK)
+ {
OC_LOG_V(DEBUG, TAG,
"Received RST, removing all queues associated with Token %d bytes",
sentToken.tokenLength);
sentToken.tokenLength);
}
}
- }else if(observeOption && msgType == COAP_MESSAGE_ACK){
+ }
+ else if(observationOption != OC_OBSERVE_NO_OPTION && msgType == COAP_MESSAGE_ACK)
+ {
OC_LOG_V(DEBUG, TAG, "Received ACK, for Token %d bytes",sentToken.tokenLength);
OC_LOG_BUFFER(INFO, TAG, sentToken.token, sentToken.tokenLength);
// now the observer is still interested
if(myStackMode != OC_CLIENT)
{
- OCObserverStatus(&sentToken, OC_OBSERVER_STILL_INTERESTED);
+ OCStackFeedBack(&sentToken, OC_OBSERVER_STILL_INTERESTED);
}
}
-
- exit:
- OCFree(observeOption);
+exit:
+ return;
}
//This function is called back by libcoap when a request is received
{
// silence warnings
(void) ctx;
+ OCServerProtocolRequest protocolRequest = {(OCMethod)0};
+ coap_block_t rcvdBlock1;
+ coap_block_t rcvdBlock2;
+ memset(&rcvdBlock1, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t));
+ memset(&rcvdBlock2, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t));
+ uint16_t rcvdSize1 = 0;
+ coap_pdu_t * rcvdPdu = rcvdRequest->pdu;
+ coap_pdu_t * sendPdu = NULL;
+ coap_send_flags_t sendFlag;
+ OCStackResult result = OC_STACK_ERROR;
+ OCStackResult requestResult = OC_STACK_ERROR;
if(myStackMode == OC_CLIENT)
{
return;
}
- OCStackResult result = OC_STACK_ERROR;
- OCStackResult responseResult = OC_STACK_ERROR;
- OCRequest * request = NULL;
- OCEntityHandlerRequest entityHandlerRequest;
- OCCoAPToken rcvdToken;
- OCObserveReq * rcvdObsReq = NULL;
- coap_pdu_t * sendPdu = NULL;
- coap_list_t *optList = NULL;
- uint8_t mediaType = COAP_MEDIATYPE_APPLICATION_JSON;
- uint32_t maxAge = 0x2ffff;
- OCMethod ocMethod;
-
- unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
- unsigned char rcvdQuery[MAX_QUERY_LENGTH] = { 0 };
- unsigned char bufRes[MAX_RESPONSE_LENGTH] = { 0 };
- unsigned char newResourceUri[MAX_RESPONSE_LENGTH] = { 0 };
- uint8_t * rcvObserveOption = NULL;
- unsigned char * bufReqPayload = NULL;
- uint32_t observeOption = OC_RESOURCE_NO_OBSERVE;
- coap_send_flags_t sendFlag;
- memset(&entityHandlerRequest, 0, sizeof(OCEntityHandlerRequest));
-
- coap_pdu_t * recvPdu = rcvdRequest->pdu;
-
- // fill the buffers of Uri and Query
- result = ParseCoAPPdu(recvPdu, rcvdUri, rcvdQuery, &rcvObserveOption, NULL, &bufReqPayload,
- entityHandlerRequest.rcvdVendorSpecificHeaderOptions,
- &(entityHandlerRequest.numRcvdVendorSpecificHeaderOptions));
- VERIFY_SUCCESS(result, OC_STACK_OK);
- if(rcvObserveOption){
- observeOption = (uint32_t)(*rcvObserveOption);
- }
+ protocolRequest.observationOption = OC_OBSERVE_NO_OPTION;
+ protocolRequest.qos = (rcvdPdu->hdr->type == COAP_MESSAGE_CON) ?
+ OC_HIGH_QOS : OC_LOW_QOS;
+ protocolRequest.coapID = rcvdPdu->hdr->id;
+ protocolRequest.delayedResNeeded = rcvdRequest->delayedResNeeded;
+ protocolRequest.secured = rcvdRequest->secure;
// fill OCCoAPToken structure
- RetrieveOCCoAPToken(recvPdu, &rcvdToken);
+ RetrieveOCCoAPToken(rcvdPdu, &protocolRequest.requestToken);
+ OC_LOG_V(INFO, TAG, " Token received %d bytes",
+ protocolRequest.requestToken.tokenLength);
+ OC_LOG_BUFFER(INFO, TAG, protocolRequest.requestToken.token,
+ protocolRequest.requestToken.tokenLength);
+
+ // fill OCDevAddr
+ memcpy(&protocolRequest.requesterAddr, (OCDevAddr *) &rcvdRequest->remote,
+ sizeof(OCDevAddr));
+
+ // Retrieve Uri and Query from received coap pdu
+ result = ParseCoAPPdu(rcvdPdu, protocolRequest.resourceUrl,
+ protocolRequest.query,
+ &(protocolRequest.observationOption), NULL,
+ &(protocolRequest.numRcvdVendorSpecificHeaderOptions),
+ protocolRequest.rcvdVendorSpecificHeaderOptions,
+ &rcvdBlock1, &rcvdBlock2, &rcvdSize1, NULL,
+ protocolRequest.reqJSONPayload);
+ VERIFY_SUCCESS(result, OC_STACK_OK);
- switch (recvPdu->hdr->code)
+ switch (rcvdPdu->hdr->code)
{
case COAP_REQUEST_GET:
- {
- ocMethod = OC_REST_GET;
- break;
- }
+ {
+ protocolRequest.method = OC_REST_GET;
+ break;
+ }
case COAP_REQUEST_POST:
- {
- ocMethod = OC_REST_POST;
- break;
- }
+ {
+ protocolRequest.method = OC_REST_POST;
+ break;
+ }
case COAP_REQUEST_DELETE:
- {
- ocMethod = OC_REST_DELETE;
- break;
- }
+ {
+ protocolRequest.method = OC_REST_DELETE;
+ break;
+ }
case COAP_REQUEST_PUT:
- {
- ocMethod = OC_REST_PUT;
- break;
- }
+ {
+ protocolRequest.method = OC_REST_PUT;
+ break;
+ }
default:
- {
- OC_LOG_V(ERROR, TAG, "Received CoAP method %d not supported",
- recvPdu->hdr->code);
- goto exit;
- }
+ {
+ OC_LOG_V(ERROR, TAG, "Received CoAP method %d not supported",
+ rcvdPdu->hdr->code);
+ goto exit;
+ }
}
- // fill OCEntityHandlerRequest structure
- result = FormOCEntityHandlerRequest(&entityHandlerRequest, ocMethod,
- bufRes, bufReqPayload, rcvdQuery, newResourceUri);
- VERIFY_SUCCESS(result, OC_STACK_OK);
-
- // fill OCObserveReq
- result = FormOCObserveReq(&rcvdObsReq, observeOption,
- (OCDevAddr *)&(rcvdRequest->remote), &rcvdToken);
- VERIFY_SUCCESS(result, OC_STACK_OK);
-
- // fill OCRequest structure
- result = FormOCRequest(&request, (recvPdu->hdr->type == COAP_MESSAGE_CON) ?
- OC_HIGH_QOS : OC_LOW_QOS, rcvdUri, rcvdObsReq, &entityHandlerRequest,
- rcvdRequest->secure);
- VERIFY_SUCCESS(result, OC_STACK_OK);
-
- OC_LOG_V(INFO, TAG, " Receveid uri: %s", request->resourceUrl);
- OC_LOG_V(INFO, TAG, " Receveid query: %s", entityHandlerRequest.query);
- OC_LOG_V(INFO, TAG, " Receveid payload: %s",
- request->entityHandlerRequest->reqJSONPayload);
- OC_LOG_V(INFO, TAG, " Token received %d bytes",
- rcvdToken.tokenLength);
- OC_LOG_BUFFER(INFO, TAG, rcvdToken.token, rcvdToken.tokenLength);
-
- // process the request
- responseResult = HandleStackRequests(request);
- #ifdef WITH_PRESENCE
- if(responseResult == OC_STACK_PRESENCE_DO_NOT_HANDLE)
+ if(rcvdBlock1.szx != 7)
{
- goto exit;
+ protocolRequest.reqPacketSize = 1 << (rcvdBlock1.szx + 4);
+ protocolRequest.reqMorePacket = rcvdBlock1.m;
+ protocolRequest.reqPacketNum = rcvdBlock1.num;
+ }
+ else
+ {
+ // No block1 received
+ rcvdSize1 = strlen((const char *)protocolRequest.reqJSONPayload)+1;
+ protocolRequest.reqTotalSize = rcvdSize1;
}
- #endif
- // do not process further if received an error
- // ex : when receive a non-secure request to a secure resource
- if(responseResult == OC_STACK_ERROR)
+ if(rcvdBlock2.szx != 7)
{
- goto exit;
+ protocolRequest.resPacketSize = 1 << (rcvdBlock2.szx + 4);
+ protocolRequest.resPacketNum = rcvdBlock2.num;
}
- OC_LOG_V(INFO, TAG, "Response from ocstack: %s",
- request->entityHandlerRequest->resJSONPayload);
+ requestResult = HandleStackRequests(&protocolRequest);
- if(rcvdObsReq)
+ if(requestResult == OC_STACK_VIRTUAL_DO_NOT_HANDLE ||
+ requestResult == OC_STACK_OK ||
+ requestResult == OC_STACK_RESOURCE_CREATED ||
+ requestResult == OC_STACK_RESOURCE_DELETED)
{
- switch(rcvdObsReq->result)
- {
- case OC_STACK_OK:
- observeOption = rcvdObsReq->option;
- result = FormOptionList(&optList, &mediaType, &maxAge,
- sizeof(observeOption), &observeOption,
- NULL, 0, NULL, 0, NULL,
- request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
- request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
- break;
- case OC_STACK_OBSERVER_NOT_ADDED:
- case OC_STACK_OBSERVER_NOT_REMOVED:
- case OC_STACK_INVALID_OBSERVE_PARAM:
- default:
- result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
- 0, NULL, 0, NULL,
- request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
- request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
- break;
+ goto exit;
+ }
+ else if(requestResult == OC_STACK_NO_MEMORY ||
+ requestResult == OC_STACK_ERROR ||
+ requestResult == OC_STACK_NOTIMPL ||
+ requestResult == OC_STACK_NO_RESOURCE ||
+ requestResult == OC_STACK_RESOURCE_ERROR)
+ {
+ // TODO: should we send an error also when we receive a non-secured request to a secure resource?
+ // TODO: should we consider some sort of error response
+ OC_LOG(DEBUG, TAG, PCF("We should send some sort of error message"));
+ // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
+ sendPdu = GenerateCoAPPdu((rcvdPdu->hdr->type == COAP_MESSAGE_CON)? COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
+ OCToCoAPResponseCode(requestResult), rcvdPdu->hdr->id,
+ &protocolRequest.requestToken, NULL, NULL);
+ VERIFY_NON_NULL(sendPdu);
+ coap_show_pdu(sendPdu);
+ sendFlag = (coap_send_flags_t)(rcvdRequest->secure ? SEND_SECURE_PORT : 0);
+ if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
+ sendFlag)
+ != OC_STACK_OK){
+ OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
}
+ goto exit;
}
- else
+ else if(requestResult == OC_STACK_SLOW_RESOURCE)
{
- if (responseResult == OC_STACK_RESOURCE_CREATED)
+ if(rcvdPdu->hdr->type == COAP_MESSAGE_CON)
{
- result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
- strlen((char *)newResourceUri), newResourceUri, 0, NULL,
- request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
- request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
+ // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
+ sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0, rcvdPdu->hdr->id,
+ NULL, NULL, NULL);
+ VERIFY_NON_NULL(sendPdu);
+ coap_show_pdu(sendPdu);
+
+ sendFlag = (coap_send_flags_t)(rcvdRequest->secure ? SEND_SECURE_PORT : 0);
+ if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
+ sendFlag)
+ != OC_STACK_OK){
+ OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
+ }
}
else
{
- result = FormOptionList(&optList, &mediaType, &maxAge, 0, NULL, NULL,
- 0, NULL, 0, NULL,
- request->entityHandlerRequest->sendVendorSpecificHeaderOptions,
- request->entityHandlerRequest->numSendVendorSpecificHeaderOptions);
+ goto exit;
}
}
-
- VERIFY_SUCCESS(result, OC_STACK_OK);
-
- // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
- sendPdu = GenerateCoAPPdu(
- (rcvdRequest->pdu->hdr->type == COAP_MESSAGE_CON) ?
- COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
- OCToCoAPResponseCode(responseResult), rcvdRequest->pdu->hdr->id,
- &rcvdToken,
- request->entityHandlerRequest->resJSONPayload, optList);
- VERIFY_NON_NULL(sendPdu);
- coap_show_pdu(sendPdu);
-
- sendFlag = (coap_send_flags_t)(rcvdRequest->delayedResponse ? SEND_DELAYED : 0);
- sendFlag = (coap_send_flags_t)( sendFlag | (rcvdRequest->secure ? SEND_SECURE_PORT : 0));
-
- if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) &(rcvdRequest->remote), sendPdu,
- sendFlag)
- != OC_STACK_OK){
- OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
- }
-
exit:
- OCFree(rcvObserveOption);
- OCFree(rcvdObsReq);
- OCFree(request);
+ return;
}
uint32_t GetTime(float afterSeconds)
const coap_queue_t * rcvdResponse) {
OCResponse * response = NULL;
OCCoAPToken rcvdToken;
- OCClientResponse clientResponse;
+ OCClientResponse clientResponse = {0};
ClientCB * cbNode = NULL;
- unsigned char * bufRes = NULL;
- uint8_t * rcvObserveOption = NULL;
- uint8_t * rcvMaxAgeOption = NULL;
- uint32_t sequenceNumber = OC_RESOURCE_NO_OBSERVE;
+ unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
+ uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION;
uint32_t maxAge = 0;
- char * resourceTypeName = NULL;
OCStackResult result = OC_STACK_ERROR;
- coap_pdu_t *sendPdu = NULL;
+ coap_pdu_t * sendPdu = NULL;
coap_pdu_t * recvPdu = NULL;
- uint8_t remoteIpAddr[4];
- uint16_t remotePortNu;
- unsigned char fullUri[MAX_URI_LENGTH] = { 0 };
unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
uint8_t isObserveNotification = 0;
#ifdef WITH_PRESENCE
+ char * resourceTypeName = NULL;
+ uint8_t remoteIpAddr[4];
+ uint16_t remotePortNu;
+ unsigned char fullUri[MAX_URI_LENGTH] = { 0 };
uint8_t isPresenceNotification = 0;
uint8_t isMulticastPresence = 0;
uint32_t lowerBound;
uint32_t higherBound;
char * tok = NULL;
#endif
- memset(&clientResponse, 0, sizeof(OCClientResponse));
+ coap_block_t rcvdBlock1 = {COAP_BLOCK_FILL_VALUE};
+ coap_block_t rcvdBlock2 = {COAP_BLOCK_FILL_VALUE};
+ uint16_t rcvdSize2 = 0;
VERIFY_NON_NULL(ctx);
VERIFY_NON_NULL(rcvdResponse);
recvPdu = rcvdResponse->pdu;
- result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &rcvObserveOption, &rcvMaxAgeOption, &bufRes,
+ result = ParseCoAPPdu(recvPdu, rcvdUri, NULL, &sequenceNumber, &maxAge,
+ &clientResponse.numRcvdVendorSpecificHeaderOptions,
clientResponse.rcvdVendorSpecificHeaderOptions,
- &(clientResponse.numRcvdVendorSpecificHeaderOptions));
- VERIFY_SUCCESS(result, OC_STACK_OK);
-
- if(rcvObserveOption){
- sequenceNumber = *((uint32_t *) rcvObserveOption);
- }
+ &rcvdBlock1, &rcvdBlock2, NULL, &rcvdSize2, bufRes);
- if(rcvMaxAgeOption){
- maxAge = *((uint32_t *) rcvMaxAgeOption);
- }
+ VERIFY_SUCCESS(result, OC_STACK_OK);
OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u", sequenceNumber);
OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", maxAge);
if(!strcmp((char *)rcvdUri, (char *)OC_PRESENCE_URI)){
isPresenceNotification = 1;
OC_LOG(INFO, TAG, PCF("Received a presence notification"));
- tok = strtok((char *)bufRes, ":");
- sequenceNumber = (uint32_t )atoi(tok);
+ tok = strtok((char *)bufRes, "[:]}");
+ bufRes[strlen((char *)bufRes)] = ':';
+ tok = strtok(NULL, "[:]}");
+ bufRes[strlen((char *)bufRes)] = ':';
+ VERIFY_NON_NULL(tok);
+ sequenceNumber = (uint32_t )atol(tok);
OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", sequenceNumber);
- tok = strtok(NULL, ":");
- maxAge = (uint32_t )atoi(tok);
+ tok = strtok(NULL, "[:]}");
+ VERIFY_NON_NULL(tok);
+ maxAge = (uint32_t )atol(tok);
OC_LOG_V(DEBUG, TAG, "The received TTL is %u", maxAge);
- tok = strtok(NULL, ":");
- bufRes[strlen((char *)bufRes)] = ':';
+ tok = strtok(NULL, "[:]}");
if(tok) {
+ bufRes[strlen((char *)bufRes)] = ':';
resourceTypeName = (char *)OCMalloc(strlen(tok));
if(!resourceTypeName)
{
goto exit;
}
strcpy(resourceTypeName, tok);
- bufRes[strlen((char *)bufRes)] = ':';
OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
resourceTypeName);
}
+ bufRes[strlen((char *)bufRes)] = ']';
}
#endif
cbNode = GetClientCB(&rcvdToken, NULL, NULL);
#ifdef WITH_PRESENCE
- // Check if the application subcribed for presence
+ // Check if the application subscribed for presence
if(!cbNode)
{
// get the address of the remote
sprintf((char *)fullUri, "%s%s", OC_MULTICAST_IP, rcvdUri);
cbNode = GetClientCB(NULL, NULL, fullUri);
isMulticastPresence = 1;
+ isPresenceNotification = 0;
}
#endif
if(cbNode)
{
+ if(!isObserveNotification)
+ {
+ #ifdef WITH_PRESENCE
+ if(!isPresenceNotification)
+ {
+ #endif
+ OC_LOG(INFO, TAG, PCF("Received a regular response"));
+ if(recvPdu->hdr->type == COAP_MESSAGE_CON)
+ {
+ sendPdu = GenerateCoAPPdu(COAP_MESSAGE_ACK, 0,
+ recvPdu->hdr->id, NULL, NULL, NULL);
+ VERIFY_NON_NULL(sendPdu);
+ result = SendCoAPPdu(gCoAPCtx, (coap_address_t*) &rcvdResponse->remote,
+ sendPdu,
+ (coap_send_flags_t)(rcvdResponse->secure ? SEND_SECURE_PORT : 0));
+ }
+ #ifdef WITH_PRESENCE
+ }
+ #endif
+ }
if(isObserveNotification)
{
OC_LOG(INFO, TAG, PCF("Received an observe notification"));
if(cbNode->method == OC_REST_OBSERVE &&
(clientResponse.sequenceNumber <= cbNode->sequenceNumber ||
(clientResponse.sequenceNumber > cbNode->sequenceNumber &&
- clientResponse.sequenceNumber == MAX_SEQUENCE_NUMBER)))
+ clientResponse.sequenceNumber == (MAX_SEQUENCE_NUMBER))))
{
OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
Ignoring Incoming:%d Against Current:%d.",
{
OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
+ if(cbNode->presence)
+ {
+ OCFree(cbNode->presence->timeOut);
+ OCFree(cbNode->presence);
+ cbNode->presence = NULL;
+ }
}
else
{
cbNode->sequenceNumber = clientResponse.sequenceNumber;;
}
+ // Ensure that a filter is actually applied.
if(resourceTypeName && response->cbNode->filterResourceType)
{
- if(strcmp(resourceTypeName,
- (const char *)response->cbNode->filterResourceType)!=0)
+ if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
{
- //Ignore presence callback if resource type does not match filter.
goto exit;
}
}
remotePortNu);
mcNode = GetMCPresenceNode(senderUri);
- if(mcNode != NULL)
+ if(maxAge == 0)
+ {
+ OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
+ response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
+ if(cbNode->presence)
+ {
+ OCFree(cbNode->presence->timeOut);
+ OCFree(cbNode->presence);
+ cbNode->presence = NULL;
+ }
+ }
+ else if(mcNode != NULL)
{
if(mcNode->nonce == clientResponse.sequenceNumber)
{
}
}
+ // Ensure that a filter is actually applied.
if(resourceTypeName && response->cbNode->filterResourceType)
{
- if(strcmp(resourceTypeName,
- (const char *)response->cbNode->filterResourceType)!=0)
+ if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
{
- //Ignore presence callback if resource type does not match filter.
goto exit;
}
}
-
}
#endif
}
-
HandleStackResponses(response);
}
else if(!cbNode && isObserveNotification)
VERIFY_SUCCESS(result, OC_STACK_OK);
}
exit:
- OCFree(rcvObserveOption);
- OCFree(rcvMaxAgeOption);
+ OCFree(resourceTypeName);
OCFree(response);
}
goto exit;
}
- VERIFY_SUCCESS(FormOptionList(&optList, NULL, NULL, 0, NULL,
+ VERIFY_SUCCESS(FormOptionList(&optList, NULL, NULL, NULL,
(uint16_t*)&uri.port, uri.path.length, uri.path.s, uri.query.length,
uri.query.s, options, numOptions), OC_STACK_OK);
case OC_REST_CANCEL_OBSERVE:
coapMethod = COAP_REQUEST_GET;
observeOption = (method == OC_REST_CANCEL_OBSERVE)?
- OC_RESOURCE_OBSERVE_DEREGISTER:OC_RESOURCE_OBSERVE_REGISTER;
+ OC_OBSERVE_DEREGISTER:OC_OBSERVE_REGISTER;
coap_insert(&optList, CreateNewOptionNode(COAP_OPTION_OBSERVE,
sizeof(observeOption), (uint8_t *)&observeOption), OrderOptions);
break;
return ret;
}
-OCStackResult OCSendCoAPNotification (unsigned char * uri, OCDevAddr *dstAddr,
- OCQualityOfService qos, OCCoAPToken * token,
- unsigned char *payload, OCResource *resPtr, uint32_t maxAge)
+OCStackResult OCDoCoAPResponse(OCServerProtocolResponse *response)
{
OCStackResult result = OC_STACK_ERROR;
+ coap_pdu_t * sendPdu = NULL;
coap_list_t *optList = NULL;
- uint8_t coapMsgType = COAP_MESSAGE_NON;
+ uint8_t msgType = COAP_MESSAGE_NON;
uint8_t mediaType = COAP_MEDIATYPE_APPLICATION_JSON;
- coap_pdu_t *sendPdu;
+ uint32_t maxAge = 0x2ffff;
+ coap_send_flags_t sendFlag = (coap_send_flags_t)0;
- OC_LOG(INFO, TAG, PCF("Entering OCSendCoAPNotification"));
+ //uint32_t observeOption = OC_OBSERVE_NO_OPTION;
+ //OCStackResult responseResult;
- coapMsgType = OCToCoAPQoS(qos);
+ OC_LOG(INFO, TAG, PCF("Entering OCDoCoAPResponse"));
- #ifdef WITH_PRESENCE
- if(!strcmp((const char *)uri, OC_PRESENCE_URI))
+ if(response->notificationFlag && response->qos == OC_HIGH_QOS)
{
- result = FormOptionList(&optList, &mediaType, NULL, 0, NULL,
- NULL, strlen((char *)uri), uri, 0, NULL, NULL, 0);
+ msgType = COAP_MESSAGE_CON;
}
- else
+ else if(response->notificationFlag && response->qos != OC_HIGH_QOS)
{
- #endif
- result = FormOptionList(&optList, &mediaType, &maxAge, sizeof(resPtr->sequenceNum),
- &resPtr->sequenceNum, NULL, strlen((char *)uri), uri, 0, NULL, NULL, 0);
- #ifdef WITH_PRESENCE
+ msgType = COAP_MESSAGE_NON;
+ }
+ else if(!response->notificationFlag && !response->slowFlag && response->qos == OC_HIGH_QOS)
+ {
+ msgType = COAP_MESSAGE_ACK;
+ }
+ else if(!response->notificationFlag && response->slowFlag && response->qos == OC_HIGH_QOS)
+ {
+ msgType = COAP_MESSAGE_CON;
+ }
+ else if(!response->notificationFlag)
+ {
+ msgType = COAP_MESSAGE_NON;
+ }
+
+ if(response->coapID == 0)
+ {
+ response->coapID = coap_new_message_id(gCoAPCtx);
}
- #endif
- VERIFY_SUCCESS(result, OC_STACK_OK);
- if(resPtr->resourceProperties == 0)
+ if (response->observationOption != OC_OBSERVE_NO_OPTION)
{
- result = OC_STACK_RESOURCE_DELETED;
+ result = FormOptionList(&optList, &mediaType, &maxAge,
+ &response->observationOption, NULL,
+ strlen((char *)response->resourceUri), response->resourceUri,
+ 0, NULL,
+ response->sendVendorSpecificHeaderOptions,
+ response->numSendVendorSpecificHeaderOptions);
}
+ else
+ {
+ result = FormOptionList(&optList, &mediaType, &maxAge,
+ NULL, NULL,
+ strlen((char *)response->resourceUri), response->resourceUri,
+ 0, NULL,
+ response->sendVendorSpecificHeaderOptions,
+ response->numSendVendorSpecificHeaderOptions);
+ }
+ VERIFY_SUCCESS(result, OC_STACK_OK);
+
+ sendPdu = GenerateCoAPPdu(msgType, OCToCoAPResponseCode(response->result),
+ response->coapID, response->requestToken, (unsigned char *)response->payload,
+ optList);
- sendPdu = GenerateCoAPPdu(
- coapMsgType == COAP_MESSAGE_CON ? COAP_MESSAGE_CON : COAP_MESSAGE_NON,
- OCToCoAPResponseCode(result), coap_new_message_id(gCoAPCtx),
- token, payload, optList);
VERIFY_NON_NULL(sendPdu);
coap_show_pdu(sendPdu);
- // TODO : resourceProperties will determine if the packet will be send using secure port
- if(SendCoAPPdu(gCoAPCtx, (coap_address_t*) dstAddr, sendPdu ,
- (coap_send_flags_t)((resPtr->resourceProperties & OC_SECURE) ? SEND_SECURE_PORT : 0) )
+ sendFlag = (coap_send_flags_t)(response->delayedResNeeded ? SEND_DELAYED : 0);
+ sendFlag = (coap_send_flags_t)( sendFlag | (response->secured ? SEND_SECURE_PORT : 0));
+
+ if (SendCoAPPdu(gCoAPCtx, (coap_address_t *) (response->requesterAddr), sendPdu, sendFlag)
!= OC_STACK_OK)
{
- OC_LOG(DEBUG, TAG, PCF("A problem occurred in sending a pdu"));
+ OC_LOG(ERROR, TAG, PCF("A problem occurred in sending a pdu"));
+ return OC_STACK_ERROR;
}
+
return OC_STACK_OK;
+
exit:
+ OC_LOG(ERROR, TAG, PCF("Error formatting server response"));
return OC_STACK_ERROR;
}
+
/**
* Stop the CoAP client or server processing
*
#include "occoaphelper.h"
#include "ocstackconfig.h"
#include "logger.h"
-#include "ocobserve.h"
#include "coap_time.h"
#include "ocmalloc.h"
ret = COAP_RESPONSE_405;
break;
+ case OC_STACK_NOTIMPL :
+ ret = COAP_RESPONSE_501;
+ break;
+
default:
ret = COAP_RESPONSE_500;
}
ret = OC_STACK_INVALID_METHOD;
break;
+ case COAP_RESPONSE_501 :
+ ret = OC_STACK_NOTIMPL;
+ break;
+
default:
decimal = ((coapCode >> 5) * 100) + (coapCode & 31);
if (decimal >= 200 && decimal <= 231)
// Retrieve Uri and Query from received coap pdu
OCStackResult ParseCoAPPdu(coap_pdu_t * pdu, unsigned char * uriBuf,
- unsigned char * queryBuf, uint8_t * * observeOptionLoc,
- uint8_t * * maxAgeOptionLoc, unsigned char * * payloadLoc,
- OCHeaderOption * rcvVendorSpecificHeaderOptions,
- uint8_t * numRcvVendorSpecificHeaderOptions)
+ unsigned char * queryBuf, uint32_t * observeOption,
+ uint32_t * maxAgeOption,
+ uint8_t * numVendorSpecificHeaderOptions,
+ OCHeaderOption * vendorSpecificHeaderOptions,
+ coap_block_t * block1, coap_block_t * block2,
+ uint16_t * size1, uint16_t * size2,
+ unsigned char * payload)
{
coap_opt_filter_t filter;
coap_opt_iterator_t opt_iter;
coap_opt_t *option = NULL;
- size_t bufLen = 0;
size_t optLen = 0;
- uint8_t * observeOption = NULL;
- uint8_t * maxAgeOption = NULL;
- uint8_t optionFound = 0;
+ unsigned char * optVal = NULL;
+ size_t uriBufLen = 0;
+ size_t queryBufLen = 0;
+ unsigned char * payloadLoc = NULL;
+ size_t payloadLength = 0;
+ coap_option_filter_clear(filter);
if(uriBuf)
{
- // parse the Uri
- coap_option_filter_clear(filter);
coap_option_setb(filter, COAP_OPTION_URI_PATH);
- coap_option_iterator_init(pdu, &opt_iter, filter);
- while ((option = coap_option_next(&opt_iter)))
+ }
+ if(queryBuf)
+ {
+ coap_option_setb(filter, COAP_OPTION_URI_QUERY);
+ }
+ if(observeOption)
+ {
+ coap_option_setb(filter, COAP_OPTION_OBSERVE);
+ }
+ if(maxAgeOption)
+ {
+ coap_option_setb(filter, COAP_OPTION_MAXAGE);
+ }
+ if(block1)
+ {
+ coap_option_setb(filter, COAP_OPTION_BLOCK1);
+ }
+ if(block2)
+ {
+ coap_option_setb(filter, COAP_OPTION_BLOCK2);
+ }
+ if(size1)
+ {
+ coap_option_setb(filter, COAP_OPTION_SIZE1);
+ }
+ if(size2)
+ {
+ coap_option_setb(filter, COAP_OPTION_SIZE2);
+ }
+ if(vendorSpecificHeaderOptions)
+ {
+ coap_option_setbVendor(filter);
+ }
+ if(payload)
+ {
+ coap_get_data(pdu, &payloadLength, &payloadLoc);
+ memcpy(payload, payloadLoc, payloadLength);
+ }
+ coap_option_iterator_init(pdu, &opt_iter, filter);
+
+ while ((option = coap_option_next(&opt_iter)))
+ {
+ optLen = COAP_OPT_LENGTH(option);
+ optVal = COAP_OPT_VALUE(option);
+ switch(opt_iter.type)
{
- optLen = COAP_OPT_LENGTH(option);
- if (bufLen + 1 + optLen < MAX_URI_LENGTH)
+ case COAP_OPTION_URI_PATH:
+ if (uriBufLen + 1 + optLen < MAX_URI_LENGTH)
{
//we still have room in the buffer
- uriBuf[bufLen++] = '/';
- memcpy(uriBuf + bufLen, COAP_OPT_VALUE(option), optLen);
- bufLen += optLen;
+ uriBuf[uriBufLen++] = '/';
+ memcpy(uriBuf + uriBufLen, optVal, optLen);
+ uriBufLen += optLen;
}
else
{
- // TODO: we should check that resources do not have long uri at the resource creation
return OC_STACK_NO_MEMORY;
}
- }
- uriBuf[bufLen] = '\0';
- }
-
- if(queryBuf)
- {
- // parse the Query
- bufLen = 0;
- coap_option_filter_clear(filter);
- coap_option_setb(filter, COAP_OPTION_URI_QUERY);
- coap_option_iterator_init(pdu, &opt_iter, filter);
- while ((option = coap_option_next(&opt_iter)))
- {
- optLen = COAP_OPT_LENGTH(option);
- if (bufLen + 1 + optLen < MAX_QUERY_LENGTH)
+ break;
+ case COAP_OPTION_URI_QUERY:
+ if (queryBufLen + 1 + optLen < MAX_QUERY_LENGTH)
{
//we still have room in the buffer
- memcpy(queryBuf + bufLen, COAP_OPT_VALUE(option), optLen);
- bufLen += optLen;
- queryBuf[bufLen++] = '&';
+ memcpy(queryBuf + queryBufLen, optVal, optLen);
+ queryBufLen += optLen;
+ queryBuf[queryBufLen++] = '&';
}
else
{
- // TODO: should it be OC_STACK_NO_MEMORY
+ // TODO: we should check that resources do not have long uri
+ // at the resource creation
return OC_STACK_NO_MEMORY;
}
- }
- // delete last '&'
- queryBuf[bufLen ? (bufLen - 1) : (bufLen)] = '\0';
- }
-
- if(observeOptionLoc)
- {
- optionFound = 0;
- // parse the observe option
- coap_option_filter_clear(filter);
- coap_option_setb(filter, COAP_OPTION_OBSERVE);
- coap_option_iterator_init(pdu, &opt_iter, filter);
- while ((option = coap_option_next(&opt_iter)))
- {
- observeOption = (uint8_t *) OCMalloc(COAP_OPT_LENGTH(option));
- if(!observeOption)
+ break;
+ case COAP_OPTION_OBSERVE:
+ memcpy(observeOption, optVal, optLen);
+ OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing the observe option %u",
+ *observeOption);
+ break;
+ case COAP_OPTION_MAXAGE:
+ memcpy(maxAgeOption, optVal, optLen);
+ OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing the max age option %u",
+ *maxAgeOption);
+ break;
+ case COAP_OPTION_BLOCK1:
+ block1->szx = COAP_OPT_BLOCK_SZX(option);
+ block1->num = coap_opt_block_num(option);
+ block1->m = 0;
+ if(COAP_OPT_BLOCK_MORE(option))
{
- return OC_STACK_NO_MEMORY;
+ block1->m = 1;
}
- memcpy(observeOption, COAP_OPT_VALUE(option),COAP_OPT_LENGTH(option));
- optionFound = 1;
+ OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing block1 %u:%u:%u",
+ block1->num, block1->m, block1->szx);
break;
- }
- if(optionFound)
- {
- *observeOptionLoc = observeOption;
- }
- else
- {
- OCFree(observeOption);
- *observeOptionLoc = NULL;
- }
- }
-
-
- if(maxAgeOptionLoc)
- {
- optionFound = 0;
- // parse the observe option
- coap_option_filter_clear(filter);
- coap_option_setb(filter, COAP_OPTION_MAXAGE);
- coap_option_iterator_init(pdu, &opt_iter, filter);
- while ((option = coap_option_next(&opt_iter)))
- {
- maxAgeOption = (uint8_t *) OCMalloc(COAP_OPT_LENGTH(option));
- if(!maxAgeOption)
+ case COAP_OPTION_BLOCK2:
+ block2->szx = COAP_OPT_BLOCK_SZX(option);
+ block2->num = coap_opt_block_num(option);
+ block2->m = 0;
+ if(COAP_OPT_BLOCK_MORE(option))
{
- return OC_STACK_NO_MEMORY;
+ block2->m = 1;
}
- memcpy(maxAgeOption, COAP_OPT_VALUE(option),COAP_OPT_LENGTH(option));
- optionFound = 1;
+ OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing block2 %u:%u:%u",
+ block1->num, block1->m, block1->szx);
break;
- }
- if(optionFound)
- {
- *maxAgeOptionLoc = maxAgeOption;
- }
- else
- {
- OCFree(maxAgeOption);
- *maxAgeOptionLoc = NULL;
- }
- }
-
- if(rcvVendorSpecificHeaderOptions)
- {
- coap_option_filter_clear(filter);
- coap_option_setbVendor(filter);
- coap_option_iterator_init(pdu, &opt_iter, filter);
- uint8_t i = 0;
- while((option = coap_option_next(&opt_iter)))
- {
- if(i >= MAX_HEADER_OPTIONS ||
- COAP_OPT_LENGTH(option) > MAX_HEADER_OPTION_DATA_LENGTH)
+ case COAP_OPTION_SIZE1:
+ break;
+ case COAP_OPTION_SIZE2:
+ break;
+ default:
+ if(*numVendorSpecificHeaderOptions >= MAX_HEADER_OPTIONS ||
+ optLen > MAX_HEADER_OPTION_DATA_LENGTH)
{
return OC_STACK_NO_MEMORY;
}
- rcvVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
- rcvVendorSpecificHeaderOptions[i].optionID = opt_iter.type;
- rcvVendorSpecificHeaderOptions[i].optionLength = COAP_OPT_LENGTH(option);
- memcpy(rcvVendorSpecificHeaderOptions[i].optionData, COAP_OPT_VALUE(option),
- rcvVendorSpecificHeaderOptions[i].optionLength);
- OC_LOG_V(INFO, TAG, " Parsing option %d with", rcvVendorSpecificHeaderOptions[i].optionID);
- OC_LOG_BUFFER(INFO, TAG, rcvVendorSpecificHeaderOptions[i].optionData,
- rcvVendorSpecificHeaderOptions[i].optionLength);
- i++;
+ vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].protocolID = OC_COAP_ID;
+ vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionID = opt_iter.type;
+ vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionLength = optLen;
+ memcpy(vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionData, optVal, optLen);
+ OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^Parsing vendor specific option %u",
+ vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionID);
+ OC_LOG_BUFFER(DEBUG, TAG, vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionData,
+ vendorSpecificHeaderOptions[*numVendorSpecificHeaderOptions].optionLength);
+ (*numVendorSpecificHeaderOptions)++;
}
-
- *numRcvVendorSpecificHeaderOptions = i;
- }
-
- // get the payload
- if(payloadLoc)
- {
- coap_get_data(pdu, &bufLen, payloadLoc);
- }
-
- return OC_STACK_OK;
-}
-
-// Form the OCRequest struct
-OCStackResult FormOCRequest(OCRequest * * requestLoc, OCQualityOfService qos,
- unsigned char * uriBuf, OCObserveReq * observeReq,
- OCEntityHandlerRequest * entityHandlerRequest,
- uint8_t secure)
-{
- OCRequest * request = NULL;
-
- // allocate it
- request = (OCRequest *) OCMalloc(sizeof(OCRequest));
- if (!request)
- {
- return OC_STACK_NO_MEMORY;
}
- // fill in qos
- request->qos = qos;
-
- // fill in uri
- request->resourceUrl = uriBuf;
-
- request->secure = secure;
-
- // fill in observe
- request->observe = observeReq;
-
- // add entityHandlerRequest
- request->entityHandlerRequest = entityHandlerRequest;
-
- //TODO: this needs to be filled in the future
- request->sequenceNum = 0;
-
- *requestLoc = request;
- return OC_STACK_OK;
-}
-
-// Form the OCObserveReq struct
-OCStackResult FormOCObserveReq(OCObserveReq ** observeReqLoc, uint32_t observeOption,
- OCDevAddr * remote, OCCoAPToken * rcvdToken)
-{
- OCObserveReq * observeReq;
-
- if(observeOption == OC_RESOURCE_NO_OBSERVE)
+ if(uriBuf)
{
- return OC_STACK_OK;
+ uriBuf[uriBufLen] = '\0';
}
-
- observeReq = (OCObserveReq *)OCMalloc(sizeof(OCObserveReq));
- if(!observeReq)
+ // delete last '&' in the query
+ if(queryBuf)
{
- *observeReqLoc = NULL;
- return OC_STACK_NO_MEMORY;
+ queryBuf[queryBufLen?queryBufLen-1:queryBufLen] = '\0';
}
- observeReq->option = observeOption;
- observeReq->subAddr = remote;
- observeReq->token = rcvdToken;
- observeReq->result = OC_STACK_OK;
-
- *observeReqLoc = observeReq;
+ OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^The final parsed uri is %s", uriBuf);
+ OC_LOG_V(DEBUG, TAG, "^^^^^^^^^^^^The final parsed query is %s", queryBuf);
return OC_STACK_OK;
}
-// Form the OCEntityHandlerRequest struct
-OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequestLoc,
- OCMethod method, unsigned char * resBuf, unsigned char * bufReqPayload,
- unsigned char * queryBuf, unsigned char *newResUriBuf)
-{
- if (entityHandlerRequestLoc)
- {
- //set it to NULL for now, it will be modified in ocstack
- entityHandlerRequestLoc->resource = NULL;
-
- entityHandlerRequestLoc->method = method;
-
- // fill in query
- entityHandlerRequestLoc->query = queryBuf;
-
- // fill payload
- entityHandlerRequestLoc->reqJSONPayload = bufReqPayload;
-
- entityHandlerRequestLoc->resJSONPayload = resBuf;
- entityHandlerRequestLoc->resJSONPayloadLen = MAX_RESPONSE_LENGTH;
-
- entityHandlerRequestLoc->obsInfo = NULL;
- entityHandlerRequestLoc->newResourceUri = newResUriBuf;
-
- entityHandlerRequestLoc->numSendVendorSpecificHeaderOptions = 0;
- return OC_STACK_OK;
- }
-
- return OC_STACK_INVALID_PARAM;
-}
-
// Retrieve the token from the PDU
void RetrieveOCCoAPToken(const coap_pdu_t * pdu, OCCoAPToken * rcvdToken)
{
}
OCStackResult FormOptionList(coap_list_t * * optListLoc, uint8_t * addMediaType,
- uint32_t * addMaxAge, uint8_t observeOptionLength, uint32_t * observeOptionPtr,
+ uint32_t * addMaxAge, uint32_t * observeOptionPtr,
uint16_t * addPortNumber, uint8_t uriLength, unsigned char * uri,
uint8_t queryLength, unsigned char * query,
OCHeaderOption * vendorSpecificHeaderOptions,
coap_insert(optListLoc, optNode, OrderOptions);
}
- if(observeOptionLength && observeOptionPtr)
+ if(observeOptionPtr)
{
optNode = CreateNewOptionNode(COAP_OPTION_OBSERVE,
- observeOptionLength, (uint8_t *)observeOptionPtr);
+ sizeof(*observeOptionPtr), (uint8_t *)observeOptionPtr);
VERIFY_NON_NULL(optNode);
coap_insert(optListLoc, optNode, OrderOptions);
OCStackResult HandleFailedCommunication(coap_context_t * ctx, coap_queue_t * queue)
{
+ //TODO: this function should change to only use OCStackFeedBack
OCResponse * response = NULL;
ClientCB * cbNode = NULL;
- ResourceObserver * observer = NULL;
OCClientResponse clientResponse;
OCCoAPToken token;
OCStackResult result = OC_STACK_OK;
HandleStackResponses(response);
observation:
- observer = GetObserverUsingToken (&token);
- if(!observer)
- {
- goto exit;
- }
-
- result = OCObserverStatus(&token, OC_OBSERVER_FAILED_COMM);
+ result = OCStackFeedBack(&token, OC_OBSERVER_FAILED_COMM);
if(result == OC_STACK_OK)
{
coap_cancel_all_messages(ctx, &queue->remote, token.token, token.tokenLength);
}
-
- exit:
-
- OCFree(response);
+ OCFree(response);
return result;
}
while (nextQueue && nextQueue->t <= now - ctx->sendqueue_basetime)
{
nextQueue = coap_pop_next( ctx );
- if((uint8_t)nextQueue->delayedResponse)
+ if((uint8_t)nextQueue->delayedResNeeded)
{
OC_LOG_V(DEBUG, TAG, "Sending Delayed response TID %d",
nextQueue->id);
* Allocates a block of size bytes, returning a pointer to the beginning of
* the allocated block.
*
- * NOTE: This function is intended to be used internally by the TB Stack.
- * It is not intended to be used by applications.
- *
* @param size - Size of the memory block in bytes, where size > 0
*
* @return
void *OCMalloc(size_t size);
/**
- * Deallocate a block of memory previously allocated by a call to OCMalloc
+ * Allocates a block of memory for an array of num elements, each of them
+ * size bytes long and initializes all its bits to zero.
+ *
+ * @param num - The number of elements
+ * @param size - Size of the element type in bytes, where size > 0
*
- * NOTE: This function is intended to be used internally by the TB Stack.
- * It is not intended to be used by applications.
+ * @return
+ * on success, a pointer to the allocated memory block
+ * on failure, a null pointer is returned
+ */
+void *OCCalloc(size_t num, size_t size);
+
+/**
+ * Deallocate a block of memory previously allocated by a call to OCMalloc
*
* @param ptr - Pointer to block of memory previously allocated by OCMalloc.
* If ptr is a null pointer, the function does nothing.
void *OCMalloc(size_t size)
{
-#ifdef ENABLE_MALLOC_DEBUG
- void *ptr = 0;
-
if (0 == size)
{
return NULL;
}
+#ifdef ENABLE_MALLOC_DEBUG
+ void *ptr = 0;
+
ptr = malloc(size);
OC_LOG_V(INFO, TAG, "malloc: ptr=%p, size=%u", ptr, size);
return ptr;
#else
- if (0 == size)
+ return malloc(size);
+#endif
+}
+
+void *OCCalloc(size_t num, size_t size)
+{
+ if(0 == size || 0 == num)
{
return NULL;
}
- return malloc(size);
+
+#ifdef ENABLE_MALLOC_DEBUG
+ void *ptr = 0;
+
+ ptr = calloc(num, size);
+ OC_LOG_V(INFO, TAG, "calloc: ptr=%p, num=%u, size=%u", ptr, num, size);
+ return ptr;
+#else
+ return calloc(num, size);
#endif
}
INC_DIRS += -I$(GTEST_DIR)/include
CC_FLAGS.debug := -g -O0 -g3 -Wall -ffunction-sections -fdata-sections -fno-exceptions \
- -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) -DTB_LOG
+ -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG
CC_FLAGS.release := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-exceptions \
- -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD)
-
-LDLIBS += -loctbstack -lgtest -lgtest_main -lpthread
-CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(LDLIBS) -L$(GTEST_DIR)/lib/.libs
+ -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD)
+
+LDLIBS += -loctbstack -lpthread
+CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(LDLIBS) $(GTEST_DIR)/lib/.libs/libgtest.a \
+ $(GTEST_DIR)/lib/.libs/libgtest_main.a
SOURCES := unittest.cpp
PROGRAMS := unittest
-all: prep_dirs $(OBJECTS) $(PROGRAMS)
+all: prep_dirs $(OBJECTS) $(PROGRAMS)
prep_dirs:
-mkdir -p $(OUT_DIR)
$(OBJ_DIR)/%.o: %.cpp
$(CC) -c $(CPPFLAGS) $< -o $@
-unittest: $(OBJ_DIR)/unittest.o
+unittest: $(OBJ_DIR)/unittest.o
$(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
.PHONY: clean
EXPECT_TRUE(NULL == pBuffer);
OCFree(pBuffer);
}
+
+TEST(OCCalloc, CallocPass1)
+{
+ // Try to allocate a small buffer
+ pBuffer = (uint8_t *)OCCalloc(1, 1);
+ EXPECT_TRUE(pBuffer);
+ OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocPass2)
+{
+ // Try to allocate a small buffer
+ pBuffer = (uint8_t *)OCCalloc(1, 128);
+ EXPECT_TRUE(pBuffer);
+ OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocPass3)
+{
+ // Try to allocate a buffer for an array
+ pBuffer = (uint8_t *)OCCalloc(5, 128);
+ EXPECT_TRUE(pBuffer);
+ OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail1)
+{
+ // Try to allocate a buffer of size 0
+ pBuffer = (uint8_t *)OCCalloc(1, 0);
+ EXPECT_TRUE(NULL == pBuffer);
+ OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail2)
+{
+ // Try to allocate a buffer with num of 0
+ pBuffer = (uint8_t *)OCCalloc(0, 5);
+ EXPECT_TRUE(NULL == pBuffer);
+ OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail3)
+{
+ // Try to allocate a buffer with size and num 0
+ pBuffer = (uint8_t *)OCCalloc(0, 0);
+ EXPECT_TRUE(NULL == pBuffer);
+ OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail4)
+{
+ // Try to allocate a ridiculous amount of RAM
+ pBuffer = (uint8_t *)OCCalloc(1, (size_t)0x7FFFFFFFFFFFFFFF);
+ EXPECT_TRUE(NULL == pBuffer);
+ OCFree(pBuffer);
+}
uint8_t *addrv4, uint32_t addrLen);
+//-- OCDevAddrToString ----------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to convert the OCDevAddr to string format
+ *
+ * @param[in] addr
+ * OCDevAddr address.
+ * @param[out] stringAddress the target string where the address
+ * is to be stored. Memory for this parameter is
+ * allocated by the caller.
+ *
+ * Note: The length of stringAddress may not exceed DEV_ADDR_SIZE_MAX
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+int32_t OCDevAddrToString(OCDevAddr *addr, char *stringAddress);
+
+
//-- OCDevAddrToIPv4Addr -------------------------------------------------
/** @ingroup ocsocket
*
}
// bind to multicast port
- struct sockaddr_in sa;
+ struct sockaddr_in sa = {0};
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)(ipmcastaddr->addr);
- memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = sin->sin_addr.s_addr;
sa.sin_port = sin->sin_port;
}
// add membership to receiving socket
- struct ip_mreq mreq;
- memset(&mreq, 0, sizeof(struct ip_mreq));
+ struct ip_mreq mreq = {0};
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
if ((ret = setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
return (close(sockfd));
}
+//convert OCDevAddr to String
+int32_t OCDevAddrToString(OCDevAddr* addr, char* stringAddress)
+{
+ uint8_t a;
+ uint8_t b;
+ uint8_t c;
+ uint8_t d;
+
+ if(OCDevAddrToIPv4Addr(addr, &a, &b, &c, &d) == 0)
+ {
+ if (!stringAddress)
+ {
+ return ERR_INVALID_INPUT;
+ }
+
+ sprintf(stringAddress, "%u.%u.%u.%u",
+ a, b, c, d);
+ return ERR_SUCCESS;
+ }
+ else
+ {
+ return ERR_INVALID_INPUT;
+ }
+}
/// Retrieve the IPv4 address embedded inside OCDev address data structure
int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b,
int32_t sfd;
char loopch=0;
int set_option_on = 1;
- struct sockaddr_in mcastsock, peer;
+ struct sockaddr_in mcastsock = {0}, peer;
uint8_t recvbuf[MAX_BUF];
uint32_t len, bufLen, fromlen;
}
//Initialize the group sockaddr structure with a
- memset((char *) &mcastsock, 0, sizeof(mcastsock));
mcastsock.sin_family = AF_INET;
mcastsock.sin_addr.s_addr = inet_addr(argv[2]);
mcastsock.sin_port = htons(atoi(argv[3]));
return -1;
}
- struct ip_mreq mreq;
- memset(&mreq, 0, sizeof(struct ip_mreq));
+ struct ip_mreq mreq = {0};
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
mreq.imr_multiaddr.s_addr = mcastsock.sin_addr.s_addr;
if ((setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
#include <ocstack.h>
#include <occoaptoken.h>
+#include <ocresource.h>
typedef struct OCPresence {
// This is the TTL associated with presence
// Struct to hold TTL info for presence
#ifdef WITH_PRESENCE
OCPresence * presence;
- unsigned char * filterResourceType;
+ OCResourceType * filterResourceType;
#endif
// next node in this list
struct ClientCB *next;
* @param[in] requestUri
* the resource uri of the request.
* @param[in] resourceType
- * the resourceType associated with this request.
+ * the resourceType associated with a presence request.
*
* @brief If the handle you're looking for does not exist, the stack will reply with a RST message.
*
*/
//------------------------------------------------------------------------
OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData,
- OCCoAPToken * token, OCDoHandle handle, OCMethod method,
+ OCCoAPToken * token, OCDoHandle *handle, OCMethod method,
unsigned char * requestUri, unsigned char * resourceType);
//-- DeleteClientCB -----------------------------------------------------------
//------------------------------------------------------------------------
ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * requestUri);
+
+/**
+ * Inserts a new resource type filter into this clientCB node.
+ *
+ * @param cbNode - the node to add the new resourceType filter to
+ * @param resourceTypeName - the value to create the new resourceType filter from
+ *
+ * @return
+ * OC_STACK_OK on success
+ * OC_STACK_ERROR with invalid parameters
+ * OC_STACK_NO_MEMORY when out of memory
+ */
+OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName);
+
//-- DeleteClientCBList --------------------------------------------------
/** @ingroup ocstack
*
#define OC_COLLECTION_H
#include "ocstack.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
+
+uint8_t GetNumOfResourcesInCollection (OCResource *resource);
OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
OCEntityHandlerRequest *entityHandlerRequest);
/* In CoAP sequence number is a 24 bit field */
#define MAX_SEQUENCE_NUMBER (0xFFFFFF)
-#define OC_RESOURCE_OBSERVE_REGISTER (0)
-#define OC_RESOURCE_OBSERVE_DEREGISTER (1)
-#define OC_RESOURCE_NO_OBSERVE (2)
#define MAX_OBSERVER_FAILED_COMM (2)
#define MAX_OBSERVER_NON_COUNT (3)
-#define OC_OBSERVER_NOT_INTERESTED (0)
-#define OC_OBSERVER_STILL_INTERESTED (1)
-#define OC_OBSERVER_FAILED_COMM (2)
-
/* This information is stored for each registerd observer */
typedef struct ResourceObserver {
// Observation Identifier for request
struct ResourceObserver *next;
} ResourceObserver;
-OCStackResult OCObserverStatus(OCCoAPToken * token, uint8_t status);
-
-OCStackResult ProcessObserveRequest (OCResource *resource, OCRequest *request);
-
-OCStackResult SendObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
- OCResourceType *resourceType, OCQualityOfService qos);
+#ifdef WITH_PRESENCE
+OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
+ OCResourceType *resourceType, OCQualityOfService qos);
+#else
+OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
+ OCQualityOfService qos);
+#endif
+OCStackResult SendListObserverNotification (OCResource * resource,
+ OCObservationId *obsIdList, uint8_t numberOfIds,
+ unsigned char *notificationJSONPayload, uint32_t maxAge,
+ OCQualityOfService qos);
void DeleteObserverList();
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#ifndef OC_RESOURCE_H
-#define OC_RESOURCE_H
-
-#include "ocstack.h"
-#include "ocstackinternal.h"
-
-#define OC_RSRVD_OC "oc"
-#define OC_RSRVD_PAYLOAD "payload"
-#define OC_RSRVD_HREF "href"
-#define OC_RSRVD_RESOURCE_TYPE "rt"
-#define OC_RSRVD_INTERFACE "if"
-#define OC_RSRVD_INTERFACE_DEFAULT "oc.mi.def"
-#define OC_RSRVD_INTERFACE_LL "oc.mi.ll"
-#define OC_RSRVD_INTERFACE_BATCH "oc.mi.b"
-#define OC_RSRVD_OBSERVABLE "obs"
-#define OC_RSRVD_SECURE "sec"
-#define OC_RSRVD_HOSTING_PORT "port"
-
-#define OC_JSON_PREFIX "{\"oc\":["
-#define OC_JSON_PREFIX_LEN (sizeof(OC_JSON_PREFIX) - 1)
-#define OC_JSON_SUFFIX "]}"
-#define OC_JSON_SUFFIX_LEN (sizeof(OC_JSON_SUFFIX) - 1)
-#define OC_JSON_SEPARATOR ','
-
-#define OC_RESOURCE_OBSERVABLE 1
-#define OC_RESOURCE_SECURE 1
+#ifndef OCRESOURCE_H_
+#define OCRESOURCE_H_
-typedef enum {
- STACK_RES_DISCOVERY_NOFILTER = 0,
- STACK_RES_DISCOVERY_IF_FILTER,
- STACK_RES_DISCOVERY_RT_FILTER
-} StackQueryTypes;
+#define OC_OBSERVER_NOT_INTERESTED (0)
+#define OC_OBSERVER_STILL_INTERESTED (1)
+#define OC_OBSERVER_FAILED_COMM (2)
+
+//-----------------------------------------------------------------------------
+// Virtual Resource Presence Attributes
+//-----------------------------------------------------------------------------
+#ifdef WITH_PRESENCE
+typedef struct PRESENCERESOURCE{
+ OCResourceHandle handle;
+ uint32_t presenceTTL;
+} PresenceResource;
+#endif
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+struct rsrc_t;
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+// IF here stands for Interface
typedef enum {
- OC_RESOURCE_VIRTUAL = 0,
- OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER,
- OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER,
- OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER,
- OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER,
- OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER,
- OC_RESOURCE_NOT_SPECIFIED
-} ResourceHandling;
+ STACK_IF_DEFAULT = 0,
+ STACK_IF_LL,
+ STACK_IF_BATCH,
+ STACK_IF_INVALID
+} OCStackIfTypes;
+
+typedef struct resourcetype_t {
+ struct resourcetype_t *next; // linked list; for multiple types on resource
+
+ // Name of the type; this string is ‘.’ (dot) separate list of segments where each segment is a
+ // namespace and the final segment is the type; type and sub-types can be separate with
+ // ‘-‘ (dash) usually only two segments would be defined. Either way this string is meant to be
+ // human friendly and is used opaquely and not parsed by code. This name is used in the “rt=”
+ // parameter of a resource description when resources are introspected and is also use in the
+ // <base URI>/types list of available types.
+ char *resourcetypename;
+} OCResourceType;
+
+typedef struct attr_t {
+ struct attr_t *next; // Points to next resource in list
-OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * request);
+ // The name of the attribute; used to look up the attribute in list;
+ // for a given attribute SHOULD not be changed once assigned
+ const char *attrName;
+ char *attrValue; // value of the attribute as string
+} OCAttribute;
-const char * GetVirtualResourceUri( OCVirtualResources resource);
-OCResource *FindResourceByUri(const char* resourceUri);
-uint8_t IsVirtualResource(const char* resourceUri);
+typedef struct resourceinterface_t {
+ struct resourceinterface_t *next; // linked list; for multiple interfaces on resource
-OCStackResult DetermineResourceHandling (OCRequest *request,
- ResourceHandling *handling,
- OCResource **resource);
+ // Name of the interface; this is ‘.’ (dot) separate list of segments where each segment is a
+ // namespace and the final segment is the interface; usually only two segments would be
+ // defined. Either way this string is opaque and not parsed by segment
+ char *name ;
-OCStackResult
-BuildJSONResponse(ResourceHandling resHandling, OCResource *resource, OCRequest *request);
+ // Supported content types to serialize request and response on this interface
+ // (REMOVE for V1 – only jSON for all but core.ll that uses Link Format)
+#if 0
+ char *inputContentType ;
+ char *outputContentType ;
+#endif
+ /*** Future placeholder for access control and policy ***/
+} OCResourceInterface;
-OCEntityHandlerResult
-BuildObsJSONResponse(OCResource *resource, OCEntityHandlerRequest *ehRequest);
+typedef struct rsrc_t {
+ struct rsrc_t *next; // Points to next resource in list
+ // Relative path on the device; will be combined with base url to create fully qualified path
+ char *host;
+ char *uri;
+ OCResourceType *rsrcType; // Resource type(s); linked list
+ OCResourceInterface *rsrcInterface; // Resource interface(s); linked list
+ OCAttribute *rsrcAttributes; // Resource interface(s); linked list
+ // Array of pointers to resources; can be used to represent a container of resources
+ // (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection)
+ struct rsrc_t *rsrcResources[MAX_CONTAINED_RESOURCES];
+ //struct rsrc_t *rsrcResources;
+ // Pointer to function that handles the entity bound to the resource.
+ // This handler has to be explicitly defined by the programmer
+ OCEntityHandler entityHandler;
+ // Properties on the resource – defines meta information on the resource
+ OCResourceProperty resourceProperties ; /* ACTIVE, DISCOVERABLE etc */
+ // Pointer to an opaque object where app/user specific data can be placed with the resource;
+ // this could be information for the entity handler between invocations
+ void *context;
+ // NOTE: Methods supported by this resource should be based on the interface targeted
+ // i.e. look into the interface structure based on the query request Can be removed here;
+ // place holder for the note above
+ /* method_t methods; */
+ // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value.
+ uint32_t sequenceNum;
+} OCResource;
-OCStackResult
-BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
- char *filterValue, char * out, uint16_t *remaining);
-OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult);
-#endif //OC_RESOURCE_H
+#endif /* OCRESOURCE_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 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 OC_RESOURCEHANDLER_H
+#define OC_RESOURCEHANDLER_H
+
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include "ocserverrequest.h"
+
+#define OC_RSRVD_OC "oc"
+#define OC_RSRVD_PAYLOAD "payload"
+#define OC_RSRVD_HREF "href"
+#define OC_RSRVD_RESOURCE_TYPE "rt"
+#define OC_RSRVD_RESOURCE_TYPE_PRESENCE "core.presence"
+#define OC_RSRVD_INTERFACE "if"
+#define OC_RSRVD_INTERFACE_DEFAULT "oc.mi.def"
+#define OC_RSRVD_INTERFACE_LL "oc.mi.ll"
+#define OC_RSRVD_INTERFACE_BATCH "oc.mi.b"
+#define OC_RSRVD_OBSERVABLE "obs"
+#define OC_RSRVD_SECURE "sec"
+#define OC_RSRVD_HOSTING_PORT "port"
+
+#define OC_JSON_PREFIX "{\"oc\":["
+#define OC_JSON_PREFIX_LEN (sizeof(OC_JSON_PREFIX) - 1)
+#define OC_JSON_SUFFIX "]}"
+#define OC_JSON_SUFFIX_LEN (sizeof(OC_JSON_SUFFIX) - 1)
+#define OC_JSON_SEPARATOR ','
+
+#define OC_RESOURCE_OBSERVABLE 1
+#define OC_RESOURCE_SECURE 1
+
+typedef enum {
+ STACK_RES_DISCOVERY_NOFILTER = 0,
+ STACK_RES_DISCOVERY_IF_FILTER,
+ STACK_RES_DISCOVERY_RT_FILTER
+} StackQueryTypes;
+
+typedef enum {
+ OC_RESOURCE_VIRTUAL = 0,
+ OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER,
+ OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER,
+ OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER,
+ OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER,
+ OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER,
+ OC_RESOURCE_NOT_SPECIFIED
+} ResourceHandling;
+
+OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest * request);
+
+const char * GetVirtualResourceUri( OCVirtualResources resource);
+OCResource *FindResourceByUri(const char* resourceUri);
+uint8_t IsVirtualResource(const char* resourceUri);
+
+OCStackResult DetermineResourceHandling (OCServerRequest *request,
+ ResourceHandling *handling,
+ OCResource **resource);
+
+OCStackResult
+ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request);
+
+OCStackResult
+BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
+ char *filterValue, char * out, uint16_t *remaining);
+
+OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult);
+
+#endif //OC_RESOURCEHANDLER_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 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 OC_SERVER_REQUEST_H
+#define OC_SERVER_REQUEST_H
+
+#include "occoap.h"
+
+/**
+ * The signature of the internal call back functions to handle responses from entity handler
+ */
+typedef OCStackResult (* OCEHResponseHandler)(OCEntityHandlerResponse * ehResponse);
+OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse);
+OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse);
+
+// following structure will be created in occoap and passed up the stack on the server side
+typedef struct OCServerRequest {
+ // the REST method retrieved from received request PDU
+ OCMethod method;
+ // resourceUrl will be filled in occoap using the path options in received request PDU
+ unsigned char resourceUrl[MAX_URI_LENGTH];
+ // resource query send by client
+ unsigned char query[MAX_QUERY_LENGTH];
+
+ // qos is indicating if the request is CON or NON
+ OCQualityOfService qos;
+ // Observe option field
+ uint32_t observationOption;
+ OCStackResult observeResult;
+ uint8_t numResponses;
+ OCEHResponseHandler ehResponseHandler;
+ //////////////////////////////////////////////////////////
+ // IP address & port of client registered for observe //These
+ OCDevAddr requesterAddr; //Members
+ // CoAP token for the observe request //Might
+ OCCoAPToken requestToken; //Be
+ // The ID of CoAP pdu //Kept in
+ uint16_t coapID; //CoAP
+ uint8_t delayedResNeeded;
+ uint8_t secured;
+ //////////////////////////////////////////////////////////
+ // An array of the received vendor specific header options
+ uint8_t numRcvdVendorSpecificHeaderOptions;
+ OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
+ uint8_t requestComplete;
+ struct OCServerRequest * next;
+ // Flag indicating slow response
+ uint8_t slowFlag;
+ uint8_t notificationFlag;
+ // reqJSON is retrieved from the payload of the received request PDU
+ unsigned char reqJSONPayload[1];
+} OCServerRequest;
+
+// following structure will be created in ocstack to aggregate responses (in future: for block transfer)
+typedef struct OCServerResponse {
+ struct OCServerResponse * next;
+ // this is the pointer to server payload data to be transferred
+ unsigned char *payload;
+ uint16_t remainingPayloadSize;
+ OCRequestHandle requestHandle;
+} OCServerResponse;
+
+OCServerRequest * GetServerRequestUsingToken (const OCCoAPToken token);
+
+OCServerRequest * GetServerRequestUsingHandle (const OCServerRequest * handle);
+
+OCServerResponse * GetServerResponseUsingHandle (const OCServerRequest * handle);
+
+OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
+ uint8_t delayedResNeeded, uint8_t secured, uint8_t notificationFlag, OCMethod method,
+ uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption,
+ OCQualityOfService qos, unsigned char * query,
+ OCHeaderOption * rcvdVendorSpecificHeaderOptions,
+ unsigned char * reqJSONPayload, OCCoAPToken * requestToken,
+ OCDevAddr * requesterAddr, unsigned char * resourceUrl, uint32_t reqTotalSize);
+
+OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle);
+
+// Internal function to create OCEntityHandlerRequest at the server from a received coap pdu
+OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest, OCRequestHandle request,
+ OCMethod method, OCResourceHandle resource, unsigned char * queryBuf, unsigned char * bufReqPayload,
+ uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction,
+ OCObservationId observeID);
+
+void FindAndDeleteServerRequest(OCServerRequest * serverRequest);
+
+void DeleteServerRequest(OCServerRequest * serverRequest);
+
+void FindAndDeleteServerResponse(OCServerResponse * serverResponse);
+
+void DeleteServerResponse(OCServerResponse * serverResponse);
+
+#endif //OC_SERVER_REQUEST_H
#define OC_COAP_SCHEME "coap://"
#define OC_OFFSET_SEQUENCE_NUMBER (4) // the first outgoing sequence number will be 5
-//-----------------------------------------------------------------------------
-// Virtual Resource Presence Attributes
-//-----------------------------------------------------------------------------
-#ifdef WITH_PRESENCE
-typedef struct PRESENCERESOURCE{
- OCResourceHandle handle;
- uint32_t presenceTTL;
-} PresenceResource;
-#endif
-
-//-----------------------------------------------------------------------------
-// Forward declarations
-//-----------------------------------------------------------------------------
-struct rsrc_t;
-
-//-----------------------------------------------------------------------------
-// Typedefs
-//-----------------------------------------------------------------------------
-
-// IF here stands for Interface
-typedef enum {
- STACK_IF_DEFAULT = 0,
- STACK_IF_LL,
- STACK_IF_BATCH
-} OCStackIfTypes;
-
-typedef struct resourcetype_t {
- struct resourcetype_t *next; // linked list; for multiple types on resource
-
- // Name of the type; this string is ‘.’ (dot) separate list of segments where each segment is a
- // namespace and the final segment is the type; type and sub-types can be separate with ‘-‘ (dash)
- // usually only two segments would be defined. Either way this string is meant to be human friendly
- // and is used opaquely and not parsed by code
- // This name is used in the “rt=” parameter of a resource description when resources are introspected
- // and is also use in the <base URI>/types list of available types
- char *resourcetypename;
-} OCResourceType;
-
-typedef struct attr_t {
- struct attr_t *next; // Points to next resource in list
-
- // The name of the attribute; used to look up the attribute in list;
- // for a given attribute SHOULD not be changed once assigned
- const char *attrName;
- char *attrValue; // value of the attribute as string
-} OCAttribute;
-
-typedef struct resourceinterface_t {
- struct resourceinterface_t *next; // linked list; for multiple interfaces on resource
-
- // Name of the interface; this is ‘.’ (dot) separate list of segments where each segment is
- // a namespace and the final segment is the interface; usually only two segments would be defined.
- // Either way this string is opaque and not parsed by segment
- char *name ;
-
- // Supported content types to serialize request and response on this interface
- // (REMOVE for V1 – only jSON for all but core.ll that uses Link Format)
-#if 0
- char *inputContentType ;
- char *outputContentType ;
-#endif
- /*** Future placeholder for access control and policy ***/
-} OCResourceInterface;
-
-typedef struct rsrc_t {
- struct rsrc_t *next; // Points to next resource in list
- // Relative path on the device; will be combined with base url to create fully qualified path
- char *host;
- char *uri;
- OCResourceType *rsrcType; // Resource type(s); linked list
- OCResourceInterface *rsrcInterface; // Resource interface(s); linked list
- OCAttribute *rsrcAttributes; // Resource interface(s); linked list
- // Array of pointers to resources; can be used to represent a container of resources
- // (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection)
- struct rsrc_t *rsrcResources[MAX_CONTAINED_RESOURCES];
- //struct rsrc_t *rsrcResources;
- // Pointer to function that handles the entity bound to the resource.
- // This handler has to be explicitly defined by the programmer
- OCEntityHandler entityHandler;
- // Properties on the resource – defines meta information on the resource
- OCResourceProperty resourceProperties ; /* ACTIVE, DISCOVERABLE etc */
- // Pointer to an opaque object where app/user specific data can be placed with the resource;
- // this could be information for the entity handler between invocations
- void *context;
- // NOTE: Methods supported by this resource should be based on the interface targeted
- // i.e. look into the interface structure based on the query request Can be removed here; place holder for the note above
- /* method_t methods; */
- // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value.
- uint32_t sequenceNum;
-} OCResource;
-
typedef struct {
// Observe option field
uint32_t option;
// following structure will be created in occoap and passed up the stack on the server side
typedef struct {
+ // Observe option field
+ uint32_t observationOption;
+ // the REST method retrieved from received request PDU
+ OCMethod method;
// resourceUrl will be filled in occoap using the path options in received request PDU
- unsigned char * resourceUrl;
+ unsigned char resourceUrl[MAX_URI_LENGTH];
+ // resource query send by client
+ unsigned char query[MAX_QUERY_LENGTH];
+ // reqJSON is retrieved from the payload of the received request PDU
+ unsigned char reqJSONPayload[MAX_REQUEST_LENGTH];
+ // qos is indicating if the request is CON or NON
+ OCQualityOfService qos;
+ // An array of the received vendor specific header options
+ uint8_t numRcvdVendorSpecificHeaderOptions;
+ OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
+ //////////////////////////////////////////////////////////
+ // TODO: Consider moving these member to CoAP
+ // IP address & port of client registered for observe
+ OCDevAddr requesterAddr;
+ // CoAP token for the observe request
+ OCCoAPToken requestToken;
+ // The ID of CoAP pdu
+ uint16_t coapID;
+ uint8_t delayedResNeeded;
+ uint8_t secured;
+ //////////////////////////////////////////////////////////
+ uint8_t reqMorePacket;
+ uint32_t reqPacketNum;
+ uint16_t reqPacketSize;
+ uint32_t resPacketNum;
+ uint16_t resPacketSize;
+ uint32_t reqTotalSize;
+} OCServerProtocolRequest;
+
+typedef struct
+{
+ // Observe option field
+ uint32_t observationOption;
// qos is indicating if the request is CON or NON
OCQualityOfService qos;
- // this structure points to the information for processing observe option
- OCObserveReq *observe;
- // If a subscription update, this is count of observe notifications from server perspective.
- uint32_t sequenceNum;
- // this structure will be passed to entity handler
- OCEntityHandlerRequest * entityHandlerRequest;
- // Indicate whether the request arrives on a secure port
- uint8_t secure;
-} OCRequest;
+ // Allow the entity handler to pass a result with the response
+ OCStackResult result;
+ // IP address & port of client registered for observe
+ OCDevAddr *requesterAddr;
+ // CoAP token for the observe request
+ OCCoAPToken *requestToken;
+ // The ID of CoAP pdu
+ uint16_t coapID;
+ // Flag indicating that response is to be delayed before sending
+ uint8_t delayedResNeeded;
+ uint8_t secured;
+ uint8_t slowFlag;
+ uint8_t notificationFlag;
+ // this is the pointer to server payload data to be transferred
+ unsigned char *payload;
+ // size of server payload data. Don't rely on null terminated data for size
+ uint16_t payloadSize;
+ // An array of the vendor specific header options the entity handler wishes to use in response
+ uint8_t numSendVendorSpecificHeaderOptions;
+ OCHeaderOption *sendVendorSpecificHeaderOptions;
+ // URI of new resource that entity handler might create
+ unsigned char * resourceUri;
+} OCServerProtocolResponse;
// following structure will be created in occoap and passed up the stack on the client side
typedef struct {
//-----------------------------------------------------------------------------
// Internal function prototypes
//-----------------------------------------------------------------------------
-
-OCStackResult HandleStackRequests(OCRequest * request);
-OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCQualityOfService qos);
+OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status);
+OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest);
void HandleStackResponses(OCResponse * response);
int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port);
+#ifdef WITH_PRESENCE
+OCStackResult SendPresenceNotification(OCResourceType *resourceType);
+#endif
OCStackResult BindResourceInterfaceToResource(OCResource* resource,
const char *resourceInterfaceName);
OCStackResult BindResourceTypeToResource(OCResource* resource,
const char *resourceTypeName);
+OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName);
#ifdef WITH_PRESENCE
//TODO: should the following function be public?
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_SECURITY_H
+#define OC_SECURITY_H
+
+#include "ocstack.h"
+#include "ocsecurityconfig.h"
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * Provides the DTLS PSK credetials blob to OC stack.
+ *
+ * @param credInfo
+ * binary blob containing credentials
+ * @param len
+ * length of binary blob
+ *
+ * @retval OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult OCSetDtlsPskCredentials(const OCDtlsPskCredsBlob *credInfo,
+ size_t len);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif //OC_SECURITY_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_SECURITY_CONFIG_H
+#define OC_SECURITY_CONFIG_H
+
+#include <stdint.h>
+
+#define DTLS_PSK_ID_LEN 16
+#define DTLS_PSK_PSK_LEN 16
+
+#define DtlsPskCredsBlobVer_1 1 /**< Credentials stored in plaintext */
+#define DtlsPskCredsBlobVer_CurrentVersion DtlsPskCredsBlobVer_1
+
+/**
+ * Credentials for a device. Includes identity and the associated PSK.
+ */
+typedef struct
+{
+ unsigned char id[DTLS_PSK_ID_LEN];
+ unsigned char psk[DTLS_PSK_PSK_LEN];
+} OCDtlsPskCreds;
+
+
+/**
+ * Binary blob containing device identity and the credentials for all devices
+ * trusted by this device.
+ */
+typedef struct
+{
+ uint16_t blobVer; /**< version of the blob */
+ uint16_t reserved; /**< reserved for future use */
+ unsigned char identity[DTLS_PSK_ID_LEN]; /**< identity of self */
+ uint32_t num; /**< number of credentials in this blob */
+ OCDtlsPskCreds creds[1]; /**< list of credentials. Size of this
+ array is determined by 'num' variable. */
+} OCDtlsPskCredsBlob;
+
+
+#endif //OC_SECURITY_CONFIG_H
+
+
OC_STACK_OK = 0,
OC_STACK_RESOURCE_CREATED,
OC_STACK_RESOURCE_DELETED,
+ OC_STACK_CONTINUE,
/* Success status code - END HERE */
/* Error status code - START HERE */
OC_STACK_INVALID_URI,
OC_STACK_SLOW_RESOURCE,
OC_STACK_NO_OBSERVERS, /* resource has no registered observers */
OC_STACK_OBSERVER_NOT_FOUND,
- OC_STACK_OBSERVER_NOT_ADDED,
- OC_STACK_OBSERVER_NOT_REMOVED,
#ifdef WITH_PRESENCE
OC_STACK_PRESENCE_STOPPED,
OC_STACK_PRESENCE_TIMEOUT,
OC_STACK_PRESENCE_DO_NOT_HANDLE,
#endif
+ OC_STACK_VIRTUAL_DO_NOT_HANDLE,
OC_STACK_INVALID_OPTION,
OC_STACK_MALFORMED_RESPONSE, /* the remote reply contained malformed data */
+ OC_STACK_PERSISTENT_BUFFER_REQUIRED,
+ OC_STACK_INVALID_REQUEST_HANDLE,
OC_STACK_ERROR
/* Error status code - END HERE */
} OCStackResult;
*/
typedef void * OCResourceHandle;
+typedef void * OCRequestHandle;
+typedef void * OCResponseHandle;
+
/**
* Unique identifier for each observation request. Used when observations are
* registered or deregistering. Used by entity handler to signal specific
OCObservationId obsId;
} OCObservationInfo;
+/**
+ * Possible returned values from entity handler
+ */
+typedef enum {
+ OC_EH_OK = 0,
+ OC_EH_ERROR,
+ OC_EH_RESOURCE_CREATED,
+ OC_EH_RESOURCE_DELETED,
+ OC_EH_SLOW,
+ OC_EH_FORBIDDEN
+} OCEntityHandlerResult;
+
// following structure will be used to define the vendor specific header options to be included
// in communication packets
typedef struct {
// Associated resource
OCResourceHandle resource;
- // resource query send by client
- unsigned char * query;
+ OCRequestHandle requestHandle;
// the REST method retrieved from received request PDU
OCMethod method;
- // reqJSON is retrieved from the payload of the received request PDU
- unsigned const char * reqJSONPayload;
- // resJSON is allocated in the stack and will be used by entity handler to fill in its response
- unsigned char * resJSONPayload;
- // Length of maximum allowed response
- uint16_t resJSONPayloadLen;
+ // resource query send by client
+ unsigned char * query;
// Information associated with observation - valid only when OCEntityHandler
// flag includes OC_OBSERVE_FLAG
- OCObservationInfo *obsInfo;
+ OCObservationInfo obsInfo;
// An array of the received vendor specific header options
uint8_t numRcvdVendorSpecificHeaderOptions;
- OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
- // An array of the vendor specific header options the entity handler wishes to use in response
- uint8_t numSendVendorSpecificHeaderOptions;
- OCHeaderOption sendVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
- // URI of new resource that entity handler might create
- unsigned char *newResourceUri;
-
+ OCHeaderOption * rcvdVendorSpecificHeaderOptions;
+ // reqJSON is retrieved from the payload of the received request PDU
+ unsigned char * reqJSONPayload;
}OCEntityHandlerRequest;
/**
* Response from queries to remote servers. Queries are made by calling the @ref OCDoResource API.
*/
typedef struct {
- // the is the result of our stack, OCStackResult should contain coap/other error codes;
- OCStackResult result;
// Address of remote server
OCDevAddr * addr;
+ // the is the result of our stack, OCStackResult should contain coap/other error codes;
+ OCStackResult result;
// If associated with observe, this will represent the sequence of notifications from server.
uint32_t sequenceNumber;
// resJSONPayload is retrieved from the payload of the received request PDU
OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
}OCClientResponse;
+typedef struct
+{
+ // Request handle is passed to server via the entity handler for each incoming request.
+ // Stack assigns when request is received, server sets to indicate what request response is for
+ OCRequestHandle requestHandle;
+ // New handle for tracking block (or slow) response. Stack assigns, server uses for subsequent calls
+ OCResponseHandle *responseHandle;
+ // Resource handle
+ OCResourceHandle resourceHandle;
+ // Allow the entity handler to pass a result with the response
+ OCEntityHandlerResult ehResult;
+ // this is the pointer to server payload data to be transferred
+ unsigned char *payload;
+ // size of server payload data. I don't think we should rely on null terminated data for size
+ uint16_t payloadSize;
+ // An array of the vendor specific header options the entity handler wishes to use in response
+ uint8_t numSendVendorSpecificHeaderOptions;
+ OCHeaderOption sendVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
+ // URI of new resource that entity handler might create
+ unsigned char resourceUri[MAX_URI_LENGTH];
+ // Server sets to true for persistent response buffer, false for non-persistent response buffer
+ uint8_t persistentBufferFlag;
+} OCEntityHandlerResponse;
+
typedef enum {
OC_INIT_FLAG = (1 << 0),
OC_REQUEST_FLAG = (1 << 1),
} OCCallbackData;
/**
- * Possible returned values from entity handler
- */
-typedef enum {
- OC_EH_OK = 0,
- OC_EH_ERROR,
- OC_EH_RESOURCE_CREATED,
- OC_EH_RESOURCE_DELETED,
- OC_EH_FORBIDDEN
-} OCEntityHandlerResult;
-
-/**
* Application server implementations must implement this callback to consume requests OTA.
* Entity handler callback needs to fill the resPayload of the entityHandlerRequest.
*/
OCStackResult OCProcess();
/**
- * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
+ * Discover or Perform requests on a specified resource (specified by that Resource's respective
+ * URI).
*
- * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
+ * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of
+ * calling this API.
* @param method - @ref OCMethod to perform on the resource
* @param requiredUri - URI of the resource to interact with
* @param referenceUri - URI of the reference resource
* header options to be sent with the request
* @param numOptions - Number of header options to be included
*
+ * Note: Presence subscription amendments (ie. adding additional resource type filters by calling
+ * this API again) require the use of the same base URI as the original request to successfully
+ * amend the presence filters.
+ *
* @return
* OC_STACK_OK - no errors
* OC_STACK_INVALID_CALLBACK - invalid callback function pointer
* @param obsIdList - list of observation ids that need to be notified
* @param numberOfIds - number of observation ids included in obsIdList
* @param notificationJSONPayload - JSON encoded payload to send in notification
+ * @param qos - desired quality of service of the observation notifications
* NOTE: The memory for obsIdList and notificationJSONPayload is managed by the
* entity invoking the API. The maximum size of the notification is 1015 bytes
* for non-Arduino platforms. For Arduino the maximum size is 247 bytes.
*/
OCStackResult
OCNotifyListOfObservers (OCResourceHandle handle,
- OCObservationId *obsIdList,
- uint8_t numberOfIds,
- unsigned char *notificationJSONPayload,
- OCQualityOfService qos);
+ OCObservationId *obsIdList,
+ uint8_t numberOfIds,
+ unsigned char *notificationJSONPayload,
+ OCQualityOfService qos);
+
+
+/**
+ * Send a response to a request.
+ * The response can be a normal, slow, or block (i.e. a response that
+ * is too large to be sent in a single PDU and must span multiple transmissions)
+ *
+ * @param response - pointer to structure that contains response parameters
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ */
+OCStackResult OCDoResponse(OCEntityHandlerResponse *response);
+
+/**
+ * Cancel a response. Applies to a block response
+ *
+ * @param responseHandle - response handle set by stack in OCServerResponse after
+ * OCDoResponse is called
+ *
+ * @return
+ * OC_STACK_OK - No errors; Success
+ * OC_STACK_INVALID_PARAM - The handle provided is invalid.
+ */
+OCStackResult OCCancelResponse(OCResponseHandle responseHandle);
+
#ifdef __cplusplus
}
--- /dev/null
+Import('env')
+
+arduino_simplecs_env = env.Clone()
+######################################################################
+# Build flags
+######################################################################
+arduino_simplecs_env.PrependUnique(CPPPATH = [
+ '../../../../../ocsocket/include',
+ '../../../../../logger/include',
+ '../../../../../stack/include',
+ '../../../../../../oc_logger/include'
+ ])
+
+arduino_simplecs_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+arduino_simplecs_env.PrependUnique(LIBS = ['octbstack', 'coap'])
+
+arduino_simplecs = arduino_simplecs_env.Program('SimpleClientServer', 'ocserver.cpp')
+env.CreateBin('SimpleClientServer')
+
+i_arduino_simplecs = arduino_simplecs_env.Install(env.get('BUILD_DIR'), arduino_simplecs)
+
+Alias('arduino_simplecs', i_arduino_simplecs)
+env.AppendTarget('arduino_simplecs')
\ No newline at end of file
PROGMEM const char TAG[] = "ArduinoServer";
-int gLEDUnderObservation = 0;
-void createLEDResource();
-typedef struct LEDRESOURCE{
+int gLightUnderObservation = 0;
+void createLightResource();
+
+/* Structure to represent a Light resource */
+typedef struct LIGHTRESOURCE{
OCResourceHandle handle;
bool state;
int power;
-} LEDResource;
+} LightResource;
-static LEDResource LED;
+static LightResource Light;
-static char responsePayloadGet[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"on\",\"power\":10}}";
-static char responsePayloadPut[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"off\",\"power\":0}}";
+static char responsePayloadGet[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"on\",\"power\":10}}";
+static char responsePayloadPut[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"off\",\"power\":0}}";
/// This is the port which Arduino Server will use for all unicast communication with it's peers
static uint16_t OC_WELL_KNOWN_PORT = 5683;
// http://www.atmel.com/webdoc/AVRLibcReferenceManual/malloc_1malloc_intro.html
void PrintArduinoMemoryStats()
{
-#ifdef ARDUINO_AVR_MEGA2560
+ #ifdef ARDUINO_AVR_MEGA2560
//This var is declared in avr-libc/stdlib/malloc.c
//It keeps the largest address not allocated for heap
extern char *__brkval;
int tmp;
OC_LOG_V(INFO, TAG, "Stack: %u Heap: %u", (unsigned int)&tmp, (unsigned int)__brkval);
OC_LOG_V(INFO, TAG, "Unallocated Memory between heap and stack: %u",
- ((unsigned int)&tmp - (unsigned int)__brkval));
-#endif
+ ((unsigned int)&tmp - (unsigned int)__brkval));
+ #endif
}
// This is the entity handler for the registered resource.
OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest )
{
OCEntityHandlerResult ehRet = OC_EH_OK;
+ OCEntityHandlerResponse response = {0};
+ char payload[MAX_RESPONSE_LENGTH] = {0};
if(entityHandlerRequest && (flag & OC_REQUEST_FLAG))
{
OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+
if(OC_REST_GET == entityHandlerRequest->method)
{
- if (strlen(responsePayloadGet) < entityHandlerRequest->resJSONPayloadLen)
+ size_t responsePayloadGetLength = strlen(responsePayloadGet);
+ if (responsePayloadGetLength < (sizeof(payload) - 1))
{
- strncpy((char *)entityHandlerRequest->resJSONPayload, responsePayloadGet, entityHandlerRequest->resJSONPayloadLen);
+ strncpy(payload, responsePayloadGet, responsePayloadGetLength);
}
else
{
ehRet = OC_EH_ERROR;
}
}
- if(OC_REST_PUT == entityHandlerRequest->method)
+ else if(OC_REST_PUT == entityHandlerRequest->method)
{
//Do something with the 'put' payload
- if (strlen(responsePayloadPut) < entityHandlerRequest->resJSONPayloadLen)
+ size_t responsePayloadPutLength = strlen(responsePayloadPut);
+ if (responsePayloadPutLength < (sizeof(payload) - 1))
{
- strncpy((char *)entityHandlerRequest->resJSONPayload, responsePayloadPut, entityHandlerRequest->resJSONPayloadLen);
+ strncpy((char *)payload, responsePayloadPut, responsePayloadPutLength);
}
else
{
ehRet = OC_EH_ERROR;
}
- }
+ }
+
+ if (ehRet == OC_EH_OK)
+ {
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = entityHandlerRequest->requestHandle;
+ response.resourceHandle = entityHandlerRequest->resource;
+ response.ehResult = ehRet;
+ response.payload = (unsigned char *)payload;
+ response.payloadSize = strlen(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");
+ ehRet = OC_EH_ERROR;
+ }
+ }
}
if (entityHandlerRequest && (flag & OC_OBSERVE_FLAG))
{
- if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
+ if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
{
OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
- gLEDUnderObservation = 1;
+ gLightUnderObservation = 1;
}
- else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
+ else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
{
OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
}
return ehRet;
}
-
// This method is used to display 'Observe' functionality of OC Stack.
static uint8_t modCounter = 0;
-void *ChangeLEDRepresentation (void *param)
+void *ChangeLightRepresentation (void *param)
{
(void)param;
OCStackResult result = OC_STACK_ERROR;
modCounter += 1;
if(modCounter % 10 == 0) // Matching the timing that the Linux Sample Server App uses for the same functionality.
{
- LED.power += 5;
- if (gLEDUnderObservation)
+ Light.power += 5;
+ if (gLightUnderObservation)
{
- OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", LED.power);
- result = OCNotifyAllObservers (LED.handle, OC_NA_QOS);
+ OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
+ result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
if (OC_STACK_NO_OBSERVERS == result)
{
- gLEDUnderObservation = 0;
+ gLightUnderObservation = 0;
}
}
}
return NULL;
}
-
-
//The setup function is called once at startup of the sketch
void setup()
{
// Add your initialization code here
-
// Note : This will initialize Serial port on Arduino at 115200 bauds
OC_LOG_INIT();
-
OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
uint16_t port = OC_WELL_KNOWN_PORT;
return;
}
- // Declare and create the example resource: LED
- createLEDResource();
-
+ // Declare and create the example resource: Light
+ createLightResource();
}
// The loop function is called in an endless loop
OC_LOG(ERROR, TAG, PCF("OCStack process error"));
return;
}
- ChangeLEDRepresentation(NULL);
+ ChangeLightRepresentation(NULL);
}
-void createLEDResource()
+void createLightResource()
{
- LED.state = false;
- OCStackResult res = OCCreateResource(&LED.handle,
- "core.led",
+ Light.state = false;
+ OCStackResult res = OCCreateResource(&Light.handle,
+ "core.light",
"oc.mi.def",
- "/a/led",
+ "/a/light",
OCEntityHandlerCb,
OC_DISCOVERABLE|OC_OBSERVABLE);
- OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+ OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
}
const char *getResult(OCStackResult result) {
case OC_STACK_NO_OBSERVERS:
return "OC_STACK_NO_OBSERVERS";
#ifdef WITH_PRESENCE
- case OC_STACK_PRESENCE_DO_NOT_HANDLE:
- return "OC_STACK_PRESENCE_DO_NOT_HANDLE";
+ case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+ return "OC_STACK_VIRTUAL_DO_NOT_HANDLE";
case OC_STACK_PRESENCE_STOPPED:
return "OC_STACK_PRESENCE_STOPPED";
case OC_STACK_PRESENCE_TIMEOUT:
OCSOCKET_DIR = $(ROOT_DIR)/ocsocket
LCOAP_DIR = $(ROOT_DIR)/libcoap-4.1.1
OCCOAP_DIR = $(ROOT_DIR)/occoap
+OCMALLOC_DIR = $(ROOT_DIR)/ocmalloc
OCTBSTACK_DIR = $(ROOT_DIR)/stack
EXTLIBS_DIR = $(ROOT_DIR)/../../extlibs
CJSON_DIR = $(EXTLIBS_DIR)/cjson
OCSOCKET_INC = $(OCSOCKET_DIR)/include
LCOAP_INC = $(LCOAP_DIR)
OCCOAP_INC = $(OCCOAP_DIR)/include
+OCMALLOC_INC = $(OCMALLOC_DIR)/include
OCTBSTACK_INC = $(OCTBSTACK_DIR)/include
CJSON_INC = $(CJSON_DIR)
INC_DIRS += -I$(OCSOCKET_INC)
INC_DIRS += -I$(LCOAP_INC)
INC_DIRS += -I$(OCCOAP_INC)
+INC_DIRS += -I$(OCMALLOC_INC)
INC_DIRS += -I$(OCTBSTACK_INC)
INC_DIRS += -I$(CJSON_INC)
CJSON_SOURCES := $(CJSON_SRC)/cJSON.c
-SOURCES := $(CJSON_SOURCES)
-SOURCES += occlient.cpp ocserver.cpp occlientcoll.cpp ocservercoll.cpp common.cpp ocserverbasicops.cpp occlientbasicops.cpp
+SOURCES := $(CJSON_SOURCES)
+SOURCES += occlient.cpp ocserver.cpp occlientcoll.cpp ocservercoll.cpp common.cpp ocserverbasicops.cpp occlientbasicops.cpp ocserverslow.cpp occlientslow.cpp
OBJECTS:= $(patsubst %.cpp, $(OBJ_DIR)/%.o, $(SOURCES))
PROGRAMS += ocserver
PROGRAMS += occlient
PROGRAMS += ocserverbasicops
+PROGRAMS += ocserverslow
PROGRAMS += ocservercoll
PROGRAMS += occlientcoll
PROGRAMS += occlientbasicops
+PROGRAMS += occlientslow
all: c_sdk prep_dirs $(OBJECTS) $(PROGRAMS)
ocserver: $(OBJ_DIR)/ocserver.o $(OBJ_DIR)/common.o
$(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
+ocserverslow: $(OBJ_DIR)/ocserverslow.o $(OBJ_DIR)/common.o
+ $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
+
ocserverbasicops: $(OBJ_DIR)/ocserverbasicops.o $(OBJ_DIR)/common.o
$(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
occlientbasicops: $(OBJ_DIR)/occlientbasicops.o $(OBJ_DIR)/common.o
$(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
+occlientslow: $(OBJ_DIR)/occlientslow.o $(OBJ_DIR)/common.o
+ $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
+
occlientcoll: $(OBJ_DIR)/occlientcoll.o $(OBJ_DIR)/common.o
$(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
OCDoHandle handle;
cbData.cb = cb;
- cbData.context = (void*)CTX_VAL;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
ret = OCDoResource(&handle, method, query.str().c_str(), 0,
}
OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
- if(ctx == (void*)CTX_VAL)
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
}
OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
{
- if(ctx == (void*)CTX_VAL)
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully");
}
OCStackApplicationResult deleteReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
{
- if(ctx == (void*)CTX_VAL)
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for DELETE recvd successfully");
}
return OC_STACK_DELETE_TRANSACTION;
}
-OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
- if(ctx == (void*)CTX_VAL)
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+{
+ if(clientResponse == NULL)
{
- OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
+ OC_LOG(INFO, TAG, "The clientResponse is NULL");
+ return OC_STACK_DELETE_TRANSACTION;
}
-
- if(clientResponse)
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
- OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
- OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
- OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response", clientResponse->resJSONPayload);
+ OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
}
+
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+ OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response", clientResponse->resJSONPayload);
+
if(clientResponse->rcvdVendorSpecificHeaderOptions &&
clientResponse->numRcvdVendorSpecificHeaderOptions)
{
}
OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
- if(ctx == (void*)CTX_VAL)
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for OBS query recvd successfully");
}
OC_LOG_V(INFO, TAG, "Callback Context for OBSERVE notification recvd successfully %d", gNumObserveNotifies);
OC_LOG_V(INFO, TAG, "JSON = %s =============> Obs Response", clientResponse->resJSONPayload);
gNumObserveNotifies++;
- if (gNumObserveNotifies == 50) //large number to test observing in DELETE case.
+ if (gNumObserveNotifies == 3) //large number to test observing in DELETE case.
{
if(TEST_CASE == TEST_OBS_REQ_NON || TEST_CASE == TEST_OBS_REQ_CON){
- printf ("RESET\n");
if (OCCancel (gObserveDoHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK){
OC_LOG(ERROR, TAG, "Observe cancel error");
}
}
#ifdef WITH_PRESENCE
OCStackApplicationResult presenceCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
- if(ctx == (void*)CTX_VAL)
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for Presence recvd successfully");
}
uint8_t remoteIpAddr[4];
uint16_t remotePortNu;
- if (ctx == (void*) CTX_VAL)
+ if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
}
strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
}
cbData.cb = discoveryReqCB;
- cbData.context = (void*)CTX_VAL;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0);
if (ret != OC_STACK_OK)
// Defines
//-----------------------------------------------------------------------------
#define TAG "occlient"
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
#ifndef MAX_LENGTH_IPv4_ADDR
#define MAX_LENGTH_IPv4_ADDR 16
#endif
OCDoHandle handle;
cbData.cb = cb;
- cbData.context = (void*)CTX_VAL;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
ret = OCDoResource(&handle, method, query.str().c_str(), 0,
OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
{
- if(ctx == (void*)CTX_VAL)
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
}
OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
{
- if(ctx == (void*)CTX_VAL)
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully");
}
OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
{
- if(ctx == (void*)CTX_VAL)
+ if(clientResponse == NULL)
{
- OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
+ OC_LOG(INFO, TAG, "The clientResponse is NULL");
+ return OC_STACK_DELETE_TRANSACTION;
}
-
- if(clientResponse)
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
{
- OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
- OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
- OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
- clientResponse->resJSONPayload);
+ OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
}
+
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+ OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
+ clientResponse->resJSONPayload);
+
if(clientResponse->rcvdVendorSpecificHeaderOptions &&
clientResponse->numRcvdVendorSpecificHeaderOptions)
{
uint8_t remoteIpAddr[4];
uint16_t remotePortNu;
- if (ctx == (void*) CTX_VAL)
+ if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
{
OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
}
strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
}
cbData.cb = discoveryReqCB;
- cbData.context = (void*)CTX_VAL;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0);
if (ret != OC_STACK_OK)
// Defines
//-----------------------------------------------------------------------------
#define TAG "occlientbasicops"
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
#ifndef MAX_LENGTH_IPv4_ADDR
#define MAX_LENGTH_IPv4_ADDR 16
#endif
std::string getQueryStrForGetPut(unsigned const char * responsePayload);
#define TAG PCF("occlient")
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
#ifndef MAX_LENGTH_IPv4_ADDR
#define MAX_LENGTH_IPv4_ADDR 16
#endif
void PrintUsage()
{
- OC_LOG(INFO, TAG, "Usage : occlient -t <Test Case>");
+ OC_LOG(INFO, TAG, "Usage : occlientcoll -t <Test Case>");
OC_LOG(INFO, TAG, "Test Case 1 : Discover Resources && Initiate GET Request on an"\
"available resource using default interface.");
OC_LOG(INFO, TAG, "Test Case 2 : Discover Resources && Initiate GET Request on an"\
}
OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
- if(clientResponse) {}
- if(ctx == (void*)CTX_VAL) {
+ if(clientResponse == NULL)
+ {
+ OC_LOG(INFO, TAG, "The clientResponse is NULL");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE) {
OC_LOG_V(INFO, TAG, "Callback Context for PUT query recvd successfully");
OC_LOG_V(INFO, TAG, "JSON = %s =============> Discovered", clientResponse->resJSONPayload);
}
OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
OC_LOG_V(INFO, TAG, "StackResult: %s",
getResult(clientResponse->result));
- if(ctx == (void*)CTX_VAL) {
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE) {
OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
if(clientResponse->sequenceNumber == 0) {
OC_LOG_V(INFO, TAG, "Callback Context for GET query recvd successfully");
OC_LOG_V(INFO, TAG, "Fnd' Rsrc': %s", clientResponse->resJSONPayload);
}
else {
- OC_LOG_V(INFO, TAG, "Callback Context for OBSERVE notification recvd successfully %d", gNumObserveNotifies);
+ OC_LOG_V(INFO, TAG, "Callback Context for Get recvd successfully %d", gNumObserveNotifies);
OC_LOG_V(INFO, TAG, "Fnd' Rsrc': %s", clientResponse->resJSONPayload);
gNumObserveNotifies++;
if (gNumObserveNotifies == 3)
OC_LOG_V(INFO, TAG, "StackResult: %s",
getResult(clientResponse->result));
- if (ctx == (void*) CTX_VAL) {
+ if (ctx == (void*) DEFAULT_CONTEXT_VALUE) {
OC_LOG_V(INFO, TAG, "Callback Context recvd successfully");
}
OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
-#if 0
+
OC_LOG_V(INFO, TAG,
"Device =============> Discovered %s @ %d.%d.%d.%d:%d",
clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1],
remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
-#endif
if(TEST == TEST_UNKNOWN_RESOURCE_GET_DEFAULT || TEST == TEST_UNKNOWN_RESOURCE_GET_BATCH ||\
TEST == TEST_UNKNOWN_RESOURCE_GET_LINK_LIST)
std::ostringstream getQuery;
getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << "/SomeUnknownResource";
cbData.cb = getReqCB;
- cbData.context = (void*)CTX_VAL;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_LOW_QOS,
std::ostringstream obsReg;
obsReg << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << getQueryStrForGetPut(clientResponse->resJSONPayload);
cbData.cb = getReqCB;
- cbData.context = (void*)CTX_VAL;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
OC_LOG_V(INFO, TAG, "OBSERVE payload from client = %s ", putPayload.c_str());
getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) <<
"/a/room" << queryInterface[TEST].text;
cbData.cb = putReqCB;
- cbData.context = (void*)CTX_VAL;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str());
std::cout << "Get Query: " << getQuery.str() << std::endl;
cbData.cb = getReqCB;
- cbData.context = (void*)CTX_VAL;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_LOW_QOS,
&cbData, NULL, 0);
strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
cbData.cb = discoveryReqCB;
- cbData.context = (void*)CTX_VAL;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS,
&cbData, NULL, 0);
}
int main(int argc, char* argv[]) {
- if(argc >= 2 && strcmp(argv[1], "-t") == 0)
+ uint8_t addr[20] = {0};
+ uint8_t* paddr = NULL;
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+ int opt;
+
+ while ((opt = getopt(argc, argv, "t:")) != -1)
{
- TEST = atoi(argv[2]);
- if(TEST >= MAX_TESTS || TEST < 1)
+ switch(opt)
{
+ case 't':
+ TEST = atoi(optarg);
+ break;
+ default:
PrintUsage();
- return 0;
+ return -1;
}
}
- else
- {
+ if(TEST <= TEST_INVALID || TEST >= MAX_TESTS){
PrintUsage();
- return 0;
+ return -1;
}
- uint8_t addr[20] = {0};
- uint8_t* paddr = NULL;
- uint16_t port = USE_RANDOM_PORT;
- uint8_t ifname[] = "eth0";
/*Get Ip address on defined interface and initialize coap on it with random port number
* this port number will be used as a source port in all coap communications*/
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <iostream>
+#include <sstream>
+#include "ocstack.h"
+#include "logger.h"
+#include "occlientslow.h"
+
+static int UNICAST_DISCOVERY = 0;
+static int TEST_CASE = 0;
+static const char * TEST_APP_UNICAST_DISCOVERY_QUERY = "coap://0.0.0.0:5683/oc/core";
+static std::string putPayload = "{\"state\":\"off\",\"power\":10}";
+static std::string coapServerIP = "255.255.255.255";
+static std::string coapServerPort = "5683";
+static std::string coapServerResource = "/a/led";
+
+int gQuitFlag = 0;
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+ if (signum == SIGINT)
+ {
+ gQuitFlag = 1;
+ }
+}
+
+static void PrintUsage()
+{
+ OC_LOG(INFO, TAG, "Usage : occlient -u <0|1> -t <1|2|3>");
+ OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources");
+ OC_LOG(INFO, TAG, "-t 1 : Discover Resources");
+ OC_LOG(INFO, TAG, "-t 2 : Discover Resources and Initiate Nonconfirmable Get Request");
+ OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Confirmable Get Request");
+}
+
+OCStackResult InvokeOCDoResource(std::ostringstream &query,
+ OCMethod method, OCQualityOfService qos,
+ OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions)
+{
+ OCStackResult ret;
+ OCCallbackData cbData;
+ OCDoHandle handle;
+
+ cbData.cb = cb;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
+ cbData.cd = NULL;
+
+ ret = OCDoResource(&handle, method, query.str().c_str(), 0,
+ NULL,
+ qos, &cbData, options, numOptions);
+
+ if (ret != OC_STACK_OK)
+ {
+ OC_LOG_V(ERROR, TAG, "OCDoResource returns error %d with method %d", ret, method);
+ }
+
+ return ret;
+}
+
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+{
+ if(clientResponse == NULL)
+ {
+ OC_LOG(INFO, TAG, "The clientResponse is NULL");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
+ {
+ OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
+ }
+
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+ OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
+ clientResponse->resJSONPayload);
+
+ if(clientResponse->rcvdVendorSpecificHeaderOptions &&
+ clientResponse->numRcvdVendorSpecificHeaderOptions)
+ {
+ 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)
+ {
+ OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
+ ((OCHeaderOption)rcvdOptions[i]).optionID );
+ OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
+ ((OCHeaderOption)rcvdOptions[i]).optionLength);
+ }
+ }
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+// This is a function called back when a device is discovered
+OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
+ OCClientResponse * clientResponse)
+{
+ uint8_t remoteIpAddr[4];
+ uint16_t remotePortNu;
+
+ if (ctx == (void*) DEFAULT_CONTEXT_VALUE)
+ {
+ OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
+ }
+
+ if (clientResponse)
+ {
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+
+ OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
+ remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
+ OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
+
+ OC_LOG_V(INFO, TAG,
+ "Device =============> Discovered %s @ %d.%d.%d.%d:%d",
+ clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1],
+ remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
+
+ parseClientResponse(clientResponse);
+
+ switch(TEST_CASE)
+ {
+ case TEST_NON_CON_OP:
+ InitGetRequest(OC_LOW_QOS);
+ break;
+ case TEST_CON_OP:
+ InitGetRequest(OC_HIGH_QOS);
+ break;
+ default:
+ PrintUsage();
+ break;
+ }
+ }
+
+ return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
+
+}
+
+int InitGetRequest(OCQualityOfService qos)
+{
+ OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
+ std::ostringstream query;
+ query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
+
+ return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)?
+ OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0));
+}
+
+int InitDiscovery()
+{
+ OCStackResult ret;
+ OCCallbackData cbData;
+ OCDoHandle handle;
+ /* Start a discovery query*/
+ char szQueryUri[64] = { 0 };
+ if (UNICAST_DISCOVERY)
+ {
+ strcpy(szQueryUri, TEST_APP_UNICAST_DISCOVERY_QUERY);
+ }
+ else
+ {
+ strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
+ }
+ cbData.cb = discoveryReqCB;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
+ cbData.cd = NULL;
+ ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0);
+ if (ret != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ }
+ return ret;
+}
+
+int main(int argc, char* argv[])
+{
+ uint8_t addr[20] = {0};
+ uint8_t* paddr = NULL;
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+ int opt;
+
+ while ((opt = getopt(argc, argv, "u:t:")) != -1)
+ {
+ switch(opt)
+ {
+ case 'u':
+ UNICAST_DISCOVERY = atoi(optarg);
+ break;
+ case 't':
+ TEST_CASE = atoi(optarg);
+ break;
+ default:
+ PrintUsage();
+ return -1;
+ }
+ }
+
+ if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) ||
+ (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) )
+ {
+ PrintUsage();
+ return -1;
+ }
+
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
+ sizeof(addr)) == ERR_SUCCESS)
+ {
+ OC_LOG_V(INFO, TAG, "Starting occlient on address %s",addr);
+ paddr = addr;
+ }
+
+ /* Initialize OCStack*/
+ if (OCInit((char *) paddr, port, OC_CLIENT) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack init error");
+ return 0;
+ }
+
+ InitDiscovery();
+
+ // Break from loop with Ctrl+C
+ OC_LOG(INFO, TAG, "Entering occlient main loop...");
+ signal(SIGINT, handleSigInt);
+ while (!gQuitFlag)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+
+ sleep(2);
+ }
+ OC_LOG(INFO, TAG, "Exiting occlient main loop...");
+
+ if (OCStop() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack stop error");
+ }
+
+ return 0;
+}
+
+std::string getIPAddrTBServer(OCClientResponse * clientResponse)
+{
+ if(!clientResponse) return "";
+ if(!clientResponse->addr) return "";
+ uint8_t a, b, c, d = 0;
+ if(0 != OCDevAddrToIPv4Addr(clientResponse->addr, &a, &b, &c, &d) ) return "";
+
+ char ipaddr[16] = {'\0'};
+ // ostringstream not working correctly here, hence snprintf
+ snprintf(ipaddr, sizeof(ipaddr), "%d.%d.%d.%d", a,b,c,d);
+ return std::string (ipaddr);
+}
+
+
+std::string getPortTBServer(OCClientResponse * clientResponse)
+{
+ if(!clientResponse) return "";
+ if(!clientResponse->addr) return "";
+ uint16_t p = 0;
+ if(0 != OCDevAddrToPort(clientResponse->addr, &p) ) return "";
+ std::ostringstream ss;
+ ss << p;
+ return ss.str();
+}
+
+std::string getQueryStrForGetPut(OCClientResponse * clientResponse)
+{
+ return "/a/led";
+}
+
+void parseClientResponse(OCClientResponse * clientResponse)
+{
+ coapServerIP = getIPAddrTBServer(clientResponse);
+ coapServerPort = getPortTBServer(clientResponse);
+ coapServerResource = getQueryStrForGetPut(clientResponse);
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 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 OCCLIENT_BASICOPS_H_
+#define OCCLIENT_BASICOPS_H_
+
+#include "ocstack.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define TAG "occlientslow"
+#define DEFAULT_CONTEXT_VALUE 0x99
+#ifndef MAX_LENGTH_IPv4_ADDR
+#define MAX_LENGTH_IPv4_ADDR 16
+#endif
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+
+/**
+ * List of methods that can be inititated from the client
+ */
+typedef enum {
+ TEST_DISCOVER_REQ = 1,
+ TEST_NON_CON_OP,
+ TEST_CON_OP,
+ MAX_TESTS
+} CLIENT_TEST;
+
+//-----------------------------------------------------------------------------
+// Function prototype
+//-----------------------------------------------------------------------------
+
+/* call getResult in common.cpp to get the result in string format. */
+const char *getResult(OCStackResult result);
+
+/* Get the IP address of the server */
+std::string getIPAddrTBServer(OCClientResponse * clientResponse);
+
+/* Get the port number the server is listening on */
+std::string getPortTBServer(OCClientResponse * clientResponse);
+
+/* Returns the query string for GET and PUT operations */
+std::string getQueryStrForGetPut(OCClientResponse * clientResponse);
+
+/* Following are initialization functions for GET, PUT
+ * POST & Discovery operations
+ */
+int InitGetRequest(OCQualityOfService qos);
+int InitDiscovery();
+
+/* Function to retrieve ip address, port no. of the server
+ * and query for the operations to be performed.
+ */
+void parseClientResponse(OCClientResponse * clientResponse);
+
+/* This function calls OCDoResource() which in turn makes calls
+ * to the lower layers
+ */
+OCStackResult InvokeOCDoResource(std::ostringstream &query,
+ OCMethod method, OCQualityOfService qos,
+ OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions);
+
+//-----------------------------------------------------------------------------
+// Callback functions
+//-----------------------------------------------------------------------------
+
+/* Following are callback functions for the GET and Discovery operations
+ */
+
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse);
+
+OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
+ OCClientResponse * clientResponse);
+
+#endif
#include "cJSON.h"
#include "ocserver.h"
+//string length of "/a/light/" + std::numeric_limits<int>::digits10 + '\0'"
+// 9 + 9 + 1 = 19
+const int URI_MAXSIZE = 19;
static int gObserveNotifyType = 3;
return jsonResponse;
}
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
{
+ OCEntityHandlerResult ehResult;
char *getResp = constructJsonResponse(ehRequest);
- if (ehRequest->resJSONPayloadLen > strlen ((char *)getResp))
+ if (maxPayloadSize > strlen ((char *)getResp))
{
- strncpy((char *)ehRequest->resJSONPayload, getResp,
- strlen((char *)getResp));
+ strncpy(payload, getResp, strlen((char *)getResp));
+ ehResult = OC_EH_OK;
}
else
{
OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
- ehRequest->resJSONPayloadLen);
+ maxPayloadSize);
+ ehResult = OC_EH_ERROR;
}
free(getResp);
+
+ return ehResult;
}
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
{
+ OCEntityHandlerResult ehResult;
char *putResp = constructJsonResponse(ehRequest);
- if (ehRequest->resJSONPayloadLen > strlen ((char *)putResp))
+ if (maxPayloadSize > strlen ((char *)putResp))
{
- strncpy((char *)ehRequest->resJSONPayload, putResp,
- strlen((char *)putResp));
+ strncpy(payload, putResp, strlen((char *)putResp));
+ ehResult = OC_EH_OK;
}
else
{
OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
- ehRequest->resJSONPayloadLen);
+ maxPayloadSize);
+ ehResult = OC_EH_ERROR;
}
free(putResp);
+
+ return ehResult;
}
-OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, OCEntityHandlerResponse *response, char *payload, uint16_t maxPayloadSize)
{
OCEntityHandlerResult ehResult = OC_EH_OK;
char *respPLPost_light = NULL;
if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
{
// Create new Light instance
- char newLightUri[15] = "/a/light/";
- sprintf (newLightUri + strlen(newLightUri), "%d", gCurrLightInstance);
+ char newLightUri[URI_MAXSIZE];
+ snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
+
json = cJSON_CreateObject();
cJSON_AddStringToObject(json,"href",gResourceUri);
cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
gLightInstance[gCurrLightInstance].power = 0;
gCurrLightInstance++;
respPLPost_light = cJSON_Print(json);
- strncpy ((char *)ehRequest->newResourceUri, newLightUri, MAX_URI_LENGTH);
+ strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
ehResult = OC_EH_RESOURCE_CREATED;
}
}
}
- if (respPLPost_light != NULL && ehRequest->resJSONPayloadLen > \
- strlen((char *)respPLPost_light))
+ if ((respPLPost_light != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_light)))
{
- strncpy((char *)ehRequest->resJSONPayload, respPLPost_light,
- strlen((char *)respPLPost_light));
+ strncpy(payload, respPLPost_light, strlen((char *)respPLPost_light));
}
else
{
OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
- ehRequest->resJSONPayloadLen);
+ maxPayloadSize);
+ ehResult = OC_EH_ERROR;
}
free(respPLPost_light);
return ehResult;
}
-OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
{
+ if(ehRequest == NULL)
+ {
+ OC_LOG(INFO, TAG, "The ehRequest is NULL");
+ return OC_EH_ERROR;
+ }
OCEntityHandlerResult ehResult = OC_EH_OK;
OC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %d ", __func__, ehRequest->resource);
* 1a. pass the delete request to the c stack
* 1b. internally, the c stack figures out what needs to be done and does it accordingly
* (e.g. send observers notification, remove observers...)
- * 1c. the c stack returns with the result whether the request is fullfilLight.
+ * 1c. the c stack returns with the result whether the request is fullfilled.
* 2. optionally, app removes observers out of its array 'interestedObservers'
*/
ehResult = OC_EH_FORBIDDEN;
}
- if (ehRequest->resJSONPayloadLen > strlen ((char *)deleteResponse))
+ if (maxPayloadSize > strlen ((char *)deleteResponse))
{
- strncpy((char *)ehRequest->resJSONPayload, deleteResponse, strlen((char *)deleteResponse));
+ strncpy(payload, deleteResponse, strlen((char *)deleteResponse));
}
else
{
OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
- ehRequest->resJSONPayloadLen);
+ maxPayloadSize);
+ ehResult = OC_EH_ERROR;
}
return ehResult;
}
-OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
{
OC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
response = responsePayloadResourceDoesNotExist;
if ( (ehRequest != NULL) &&
- (ehRequest->resJSONPayloadLen > strlen ((char *)response)) )
+ (maxPayloadSize > strlen ((char *)response)) )
{
- strncpy((char *)ehRequest->resJSONPayload, response, strlen((char *)response));
+ strncpy((char *)payload, response, strlen((char *)response));
}
else
{
OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
- ehRequest->resJSONPayloadLen);
+ maxPayloadSize);
}
return OC_EH_RESOURCE_DELETED;
void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
{
OC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d",
- ehRequest->obsInfo->obsId);
+ ehRequest->obsInfo.obsId);
for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
{
if (interestedObservers[i].valid == false)
{
- interestedObservers[i].observationId = ehRequest->obsInfo->obsId;
+ interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
interestedObservers[i].valid = true;
gLightUnderObservation = 1;
break;
bool clientStillObserving = false;
OC_LOG_V (INFO, TAG, "Received observation deregistration request for observation Id %d",
- ehRequest->obsInfo->obsId);
+ ehRequest->obsInfo.obsId);
for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
{
- if (interestedObservers[i].observationId == ehRequest->obsInfo->obsId)
+ if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
{
interestedObservers[i].valid = false;
}
OC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
OCEntityHandlerResult ehResult = OC_EH_OK;
+ OCEntityHandlerResponse response;
+ char payload[MAX_RESPONSE_LENGTH] = {0};
+
+ // Validate pointer
+ if (!entityHandlerRequest)
+ {
+ OC_LOG (ERROR, TAG, "Invalid request pointer");
+ return OC_EH_ERROR;
+ }
+
+ // Initialize certain response fields
+ response.numSendVendorSpecificHeaderOptions = 0;
+ memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+ memset(response.resourceUri, 0, sizeof response.resourceUri);
if (flag & OC_INIT_FLAG)
{
if (flag & OC_REQUEST_FLAG)
{
OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
- if (entityHandlerRequest)
+ if (entityHandlerRequest->resource == NULL) {
+ OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
+ ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest, payload, sizeof(payload) - 1);
+ }
+ else if (OC_REST_GET == entityHandlerRequest->method)
{
- if (entityHandlerRequest->resource == NULL) {
- OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
- ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest);
- }
- else if (OC_REST_GET == entityHandlerRequest->method)
- {
- OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
- ProcessGetRequest (entityHandlerRequest);
- }
- else if (OC_REST_PUT == entityHandlerRequest->method)
- {
- OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
- ProcessPutRequest (entityHandlerRequest);
- }
- else if (OC_REST_DELETE == entityHandlerRequest->method)
- {
- OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
- ehResult = ProcessDeleteRequest (entityHandlerRequest);
- }
- else
+ OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+ ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+ }
+ else if (OC_REST_PUT == entityHandlerRequest->method)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+ ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+ }
+ else if (OC_REST_DELETE == entityHandlerRequest->method)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
+ ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+ }
+ else
+ {
+ OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+ entityHandlerRequest->method);
+ ehResult = OC_EH_ERROR;
+ }
+
+ // If the result isn't an error or forbidden, send response
+ if (!((ehResult == OC_EH_ERROR) || (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 = (unsigned char *)payload;
+ response.payloadSize = strlen(payload);
+ // Indicate that response is NOT in a persistent buffer
+ response.persistentBufferFlag = 0;
+
+ // Send the response
+ if (OCDoResponse(&response) != OC_STACK_OK)
{
- OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
- entityHandlerRequest->method);
+ OC_LOG(ERROR, TAG, "Error sending response");
+ ehResult = OC_EH_ERROR;
}
}
}
if (flag & OC_OBSERVE_FLAG)
{
OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
- if (entityHandlerRequest)
+ if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
{
- if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
- {
- OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
- }
- else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
- {
- OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
- }
+ OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
+ }
+ else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
+ {
+ OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
}
}
OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
OCEntityHandlerResult ehResult = OC_EH_OK;
+ OCEntityHandlerResponse response;
+ char payload[MAX_RESPONSE_LENGTH] = {0};
+
+ // Validate pointer
+ if (!entityHandlerRequest)
+ {
+ OC_LOG (ERROR, TAG, "Invalid request pointer");
+ return OC_EH_ERROR;
+ }
+
+ // Initialize certain response fields
+ response.numSendVendorSpecificHeaderOptions = 0;
+ memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+ memset(response.resourceUri, 0, sizeof response.resourceUri);
if (flag & OC_INIT_FLAG)
{
if (flag & OC_REQUEST_FLAG)
{
OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
- if (entityHandlerRequest)
+ if (OC_REST_GET == entityHandlerRequest->method)
{
- if (OC_REST_GET == entityHandlerRequest->method)
- {
- OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
- ProcessGetRequest (entityHandlerRequest);
- }
- else if (OC_REST_PUT == entityHandlerRequest->method)
- {
- OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
- ProcessPutRequest (entityHandlerRequest);
- }
- else if (OC_REST_POST == entityHandlerRequest->method)
- {
- OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
- ehResult = ProcessPostRequest (entityHandlerRequest);
- }
- else if (OC_REST_DELETE == entityHandlerRequest->method)
+ OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+ ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+ }
+ else if (OC_REST_PUT == entityHandlerRequest->method)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+ ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+ }
+ else if (OC_REST_POST == entityHandlerRequest->method)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
+ ehResult = ProcessPostRequest (entityHandlerRequest, &response, payload, sizeof(payload) - 1);
+ }
+ else if (OC_REST_DELETE == entityHandlerRequest->method)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
+ ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
+ }
+ else
+ {
+ OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+ entityHandlerRequest->method);
+ }
+
+ // If the result isn't an error or forbidden, send response
+ if (!((ehResult == OC_EH_ERROR) || (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 = (unsigned char *)payload;
+ response.payloadSize = strlen(payload);
+ // Indicate that response is NOT in a persistent buffer
+ response.persistentBufferFlag = 0;
+
+ // Handle vendor specific options
+ if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
+ entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
{
- OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
- ehResult = ProcessDeleteRequest (entityHandlerRequest);
+ OC_LOG (INFO, TAG, "Received vendor specific options");
+ uint8_t i = 0;
+ OCHeaderOption * rcvdOptions = entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
+ for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
+ {
+ 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 );
+ OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
+ ((OCHeaderOption)rcvdOptions[i]).optionLength);
+ }
+ }
+ OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions;
+ uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
+ uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
+ sendOptions[0].protocolID = OC_COAP_ID;
+ sendOptions[0].optionID = 2248;
+ memcpy(sendOptions[0].optionData, option2, sizeof(option2));
+ sendOptions[0].optionLength = 10;
+ sendOptions[1].protocolID = OC_COAP_ID;
+ sendOptions[1].optionID = 2600;
+ memcpy(sendOptions[1].optionData, option3, sizeof(option3));
+ sendOptions[1].optionLength = 10;
+ response.numSendVendorSpecificHeaderOptions = 2;
}
- else
+
+ // Send the response
+ if (OCDoResponse(&response) != OC_STACK_OK)
{
- OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
- entityHandlerRequest->method);
+ OC_LOG(ERROR, TAG, "Error sending response");
+ ehResult = OC_EH_ERROR;
}
}
}
if (flag & OC_OBSERVE_FLAG)
{
OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
- if (entityHandlerRequest)
+
+ if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
{
- if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
- {
- OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
- ProcessObserveRegister (entityHandlerRequest);
- }
- else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
- {
- OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
- ProcessObserveDeregister (entityHandlerRequest);
- }
+ OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
+ ProcessObserveRegister (entityHandlerRequest);
}
- }
- if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
- entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
- {
- OC_LOG (INFO, TAG, "Received vendor specific options");
- uint8_t i = 0;
- OCHeaderOption * rcvdOptions = entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
- for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
+ else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
{
- 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 );
- OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
- ((OCHeaderOption)rcvdOptions[i]).optionLength);
- }
+ OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
+ ProcessObserveDeregister (entityHandlerRequest);
}
- OCHeaderOption * sendOptions = entityHandlerRequest->sendVendorSpecificHeaderOptions;
- uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
- uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
- sendOptions[0].protocolID = OC_COAP_ID;
- sendOptions[0].optionID = 2248;
- memcpy(sendOptions[0].optionData, option2, sizeof(option2));
- sendOptions[0].optionLength = 10;
- sendOptions[1].protocolID = OC_COAP_ID;
- sendOptions[1].optionID = 2600;
- memcpy(sendOptions[1].optionData, option3, sizeof(option3));
- sendOptions[1].optionLength = 10;
- entityHandlerRequest->numSendVendorSpecificHeaderOptions = 2;
}
return ehResult;
uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2;
OCObservationId obsNotify[numNotifies];
- while (1)
+ while (!gQuitFlag)
{
sleep(10);
Light.power += 5;
/* Following methods process the PUT, GET, POST, Delete,
* & Observe requests */
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest);
-OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest);
-OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest);
-OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest);
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload,
+ uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload,
+ uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+ OCEntityHandlerResponse *response,
+ char *payload,
+ uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload,
+ uint16_t maxPayloadSize);
+
+OCEntityHandlerResult ProcessNonExistingResourceRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload,
+ uint16_t maxPayloadSize);
+
void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest);
void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest);
#include "cJSON.h"
#include "ocserverbasicops.h"
-int gQuitFlag = 0;
+//string length of "/a/led/" + std::numeric_limits<int>::digits10 + '\0'"
+// 7 + 9 + 1 = 17
+const int URI_MAXSIZE = 17;
+
+volatile sig_atomic_t gQuitFlag = 0;
static LEDResource LED;
// This variable determines instance number of the LED resource.
return jsonResponse;
}
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
{
+ OCEntityHandlerResult ehResult;
char *getResp = constructJsonResponse(ehRequest);
- if (ehRequest->resJSONPayloadLen > strlen ((char *)getResp))
+ if (maxPayloadSize > strlen ((char *)getResp))
{
- strncpy((char *)ehRequest->resJSONPayload, getResp,
- strlen((char *)getResp));
+ strncpy(payload, getResp, strlen((char *)getResp));
+ ehResult = OC_EH_OK;
}
else
{
OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
- ehRequest->resJSONPayloadLen);
+ maxPayloadSize);
+ ehResult = OC_EH_ERROR;
}
free(getResp);
+
+ return ehResult;
}
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
{
+ OCEntityHandlerResult ehResult;
char *putResp = constructJsonResponse(ehRequest);
- if (ehRequest->resJSONPayloadLen > strlen ((char *)putResp))
+ if (maxPayloadSize > strlen ((char *)putResp))
{
- strncpy((char *)ehRequest->resJSONPayload, putResp,
- strlen((char *)putResp));
+ strncpy(payload, putResp, strlen((char *)putResp));
+ ehResult = OC_EH_OK;
}
else
{
OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
- ehRequest->resJSONPayloadLen);
+ maxPayloadSize);
+ ehResult = OC_EH_ERROR;
}
free(putResp);
+
+ return ehResult;
}
-void ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
{
char *respPLPost_led = NULL;
cJSON *json;
cJSON *format;
+ OCEntityHandlerResult ehResult;
/*
* The entity handler determines how to process a POST request.
if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
{
// Create new LED instance
- char newLedUri[15] = "/a/led/";
- sprintf (newLedUri + strlen(newLedUri), "%d", gCurrLedInstance);
+ char newLedUri[URI_MAXSIZE ];
+ snprintf(newLedUri, URI_MAXSIZE, "/a/led/%d", gCurrLedInstance);
json = cJSON_CreateObject();
}
}
- if (respPLPost_led != NULL && ehRequest->resJSONPayloadLen > strlen ((char *)respPLPost_led))
+ if ((respPLPost_led != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_led)))
{
- strncpy((char *)ehRequest->resJSONPayload, respPLPost_led,
- strlen((char *)respPLPost_led));
+ strncpy(payload, respPLPost_led, strlen((char *)respPLPost_led));
+ ehResult = OC_EH_OK;
}
else
{
OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
- ehRequest->resJSONPayloadLen);
+ maxPayloadSize);
+ ehResult = OC_EH_ERROR;
}
free(respPLPost_led);
+
+ return ehResult;
}
OCEntityHandlerResult
OCEntityHandlerRequest *entityHandlerRequest)
{
OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+ OCEntityHandlerResponse response;
+ char payload[MAX_RESPONSE_LENGTH] = {0};
+
if (flag & OC_INIT_FLAG)
{
OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
+ ehResult = OC_EH_OK;
}
if (flag & OC_REQUEST_FLAG)
{
if (OC_REST_GET == entityHandlerRequest->method)
{
OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
- ProcessGetRequest (entityHandlerRequest);
+ ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
}
else if (OC_REST_PUT == entityHandlerRequest->method)
{
OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
- ProcessPutRequest (entityHandlerRequest);
+ ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
}
else if (OC_REST_POST == entityHandlerRequest->method)
{
OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
- ProcessPostRequest (entityHandlerRequest);
+ ehResult = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
}
else
{
OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
entityHandlerRequest->method);
}
+
+ if (ehResult == OC_EH_OK)
+ {
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = entityHandlerRequest->requestHandle;
+ response.resourceHandle = entityHandlerRequest->resource;
+ response.ehResult = ehResult;
+ response.payload = (unsigned char *)payload;
+ response.payloadSize = strlen(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;
+ }
+ }
}
}
- return OC_EH_OK;
+ return ehResult;
}
/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
uint8_t* paddr = NULL;
uint16_t port = OC_WELL_KNOWN_PORT;
uint8_t ifname[] = "eth0";
- int opt;
-
OC_LOG(DEBUG, TAG, "OCServer is starting...");
/*Get Ip address on defined interface and initialize coap on it with random port number
/* Following methods process the PUT, GET, POST
* requests
*/
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPostRequest (OCEntityHandlerRequest *ehRequest);
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload,
+ uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload,
+ uint16_t maxPayloadSize);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload,
+ uint16_t maxPayloadSize);
/* call getResult in common.cpp to get the result in string format. */
const char *getResult(OCStackResult result);
#define TAG PCF("ocservercontainer")
-int gQuitFlag = 0;
+volatile sig_atomic_t gQuitFlag = 0;
int gLightUnderObservation = 0;
void createResources();
typedef struct LIGHTRESOURCE{
const char rspPutFanCollection[] = "{\"href\":\"/a/fan\"}";
const char rspFailureFan[] = "{\"href\":\"/a/fan\",\"rep\":{\"error\":\"FAN_OP_FAIL\"}}";
+typedef enum {
+ TEST_INVALID = 0,
+ TEST_DEFAULT_COLL_EH,
+ TEST_APP_COLL_EH,
+ MAX_TESTS
+} SERVER_TEST;
+
+void PrintUsage()
+{
+ OC_LOG(INFO, TAG, "Usage : ocservercoll -t <Test Case>");
+ OC_LOG(INFO, TAG, "Test Case 1 : Create room resource with default collection entity handler.");
+ OC_LOG(INFO, TAG, "Test Case 2 : Create room resource with application collection entity handler.");
+}
+
+unsigned static int TEST = TEST_INVALID;
+
static OCEntityHandlerResult
-HandleCallback(OCEntityHandlerRequest * ehRequest, const char* opStr, const char* errStr)
+HandleCallback(OCEntityHandlerRequest * ehRequest,
+ const char* opStr,
+ const char* errStr,
+ char *payload,
+ uint16_t maxPayloadSize)
{
OCEntityHandlerResult ret = OC_EH_OK;
- if (strlen(opStr) < ehRequest->resJSONPayloadLen)
+ // Append opStr or errStr, after making sure there is
+ // enough room in the payload
+ if (strlen(opStr) < (maxPayloadSize - strlen(payload)))
{
- strncat((char*)ehRequest->resJSONPayload, opStr, ehRequest->resJSONPayloadLen);
+ strncat((char*)payload, opStr, strlen(opStr));
}
- else if (strlen(errStr) < ehRequest->resJSONPayloadLen)
+ else if (strlen(errStr) < (maxPayloadSize - strlen(payload)))
{
- strncat((char*)ehRequest->resJSONPayload, errStr, ehRequest->resJSONPayloadLen);
+ strncat((char*)payload, errStr, strlen(errStr));
ret = OC_EH_ERROR;
}
else
}
static void
-PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest )
+PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest)
{
const char* typeOfMessage;
(ehRequest->method == OC_REST_GET) ? "OC_REST_GET" : "OC_REST_PUT" );
}
-OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,\
- OCEntityHandlerRequest * ehRequest )
+OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest * ehRequest)
{
OCEntityHandlerResult ret = OC_EH_OK;
+ OCEntityHandlerResponse response;
+ char payload[MAX_RESPONSE_LENGTH] = {0};
OC_LOG_V(INFO, TAG, "Callback for Room");
PrintReceivedMsgInfo(flag, ehRequest );
{
if(query.find("oc.mi.def") != std::string::npos)
{
- ret = HandleCallback(ehRequest, rspGetRoomDefault, rspFailureRoom);
+ ret = HandleCallback(ehRequest, rspGetRoomDefault, rspFailureRoom, payload, sizeof(payload));
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, ",", ",");
- ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight);
+ ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+ ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight, payload, sizeof(payload));
}
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, ",", ",");
- ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan);
+ ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+ ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan, payload, sizeof(payload));
}
}
else if(query.find("oc.mi.ll") != std::string::npos)
{
- ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom);
+ ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom, payload, sizeof(payload));
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, ",", ",");
- ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight);
+ ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+ ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight, payload, sizeof(payload));
}
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, ",", ",");
- ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan);
+ ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+ ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan, payload, sizeof(payload));
}
}
else if(query.find("oc.mi.b") != std::string::npos)
{
- ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom);
+ ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom, payload, sizeof(payload));
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, ",", ",");
- ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight);
+ ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+ ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight, payload, sizeof(payload));
}
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, ",", ",");
- ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan);
+ ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+ ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan, payload, sizeof(payload));
+ }
+ }
+ if (ret == OC_EH_OK)
+ {
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = ehRequest->requestHandle;
+ response.resourceHandle = ehRequest->resource;
+ response.ehResult = ret;
+ response.payload = (unsigned char *)payload;
+ response.payloadSize = strlen(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");
+ ret = OC_EH_ERROR;
}
}
}
- if(OC_REST_PUT == ehRequest->method)
+ else if(OC_REST_PUT == ehRequest->method)
{
if(query.find("oc.mi.def") != std::string::npos)
{
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, rspPutRoomDefault, rspFailureRoom);
+ ret = HandleCallback(ehRequest, rspPutRoomDefault, rspFailureRoom, payload, sizeof(payload));
}
}
if(query.find("oc.mi.ll") != std::string::npos)
{
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom);
+ ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom, payload, sizeof(payload));
}
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, ",", ",");
- ret = HandleCallback(ehRequest, rspPutLightCollection, rspFailureLight);
+ ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+ ret = HandleCallback(ehRequest, rspPutLightCollection, rspFailureLight, payload, sizeof(payload));
}
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, ",", ",");
- ret = HandleCallback(ehRequest, rspPutFanCollection, rspFailureFan);
+ ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+ ret = HandleCallback(ehRequest, rspPutFanCollection, rspFailureFan, payload, sizeof(payload));
}
}
if(query.find("oc.mi.b") != std::string::npos)
{
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom);
+ ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom, payload, sizeof(payload));
}
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, ",", ",");
- ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight);
+ ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+ ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight, payload, sizeof(payload));
}
if(ret != OC_EH_ERROR)
{
- ret = HandleCallback(ehRequest, ",", ",");
- ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan);
+ ret = HandleCallback(ehRequest, ",", ",", payload, sizeof(payload));
+ ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan, payload, sizeof(payload));
}
}
+ if (ret == OC_EH_OK)
+ {
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = ehRequest->requestHandle;
+ response.resourceHandle = ehRequest->resource;
+ response.ehResult = ret;
+ response.payload = (unsigned char *)payload;
+ response.payloadSize = strlen(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");
+ ret = OC_EH_ERROR;
+ }
+ }
+ }
+ else
+ {
+ OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+ ehRequest->method);
+ ret = OC_EH_ERROR;
}
}
else if (ehRequest && flag == OC_OBSERVE_FLAG)
return ret;
}
-OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest ) {
+OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest)
+{
OCEntityHandlerResult ret = OC_EH_OK;
+ OCEntityHandlerResponse response;
+ char payload[MAX_RESPONSE_LENGTH] = {0};
OC_LOG_V(INFO, TAG, "Callback for Light");
PrintReceivedMsgInfo(flag, ehRequest );
{
if(OC_REST_GET == ehRequest->method)
{
- ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight);
+ ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight, payload, sizeof(payload));
+ }
+ else if(OC_REST_PUT == ehRequest->method)
+ {
+ ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight, payload, sizeof(payload));
}
- if(OC_REST_PUT == ehRequest->method)
+ else
{
- ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight);
+ OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+ ehRequest->method);
+ ret = OC_EH_ERROR;
+ }
+
+ if (ret == OC_EH_OK)
+ {
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = ehRequest->requestHandle;
+ response.resourceHandle = ehRequest->resource;
+ response.ehResult = ret;
+ response.payload = (unsigned char *)payload;
+ response.payloadSize = strlen(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");
+ ret = OC_EH_ERROR;
+ }
}
}
else if (ehRequest && flag == OC_OBSERVE_FLAG)
return ret;
}
-OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest ) {
+OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest)
+{
OCEntityHandlerResult ret = OC_EH_OK;
+ OCEntityHandlerResponse response;
+ char payload[MAX_RESPONSE_LENGTH] = {0};
OC_LOG_V(INFO, TAG, "Callback for Fan");
PrintReceivedMsgInfo(flag, ehRequest );
{
if(OC_REST_GET == ehRequest->method)
{
- ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan);
+ ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan, payload, sizeof(payload));
+ }
+ else if(OC_REST_PUT == ehRequest->method)
+ {
+ ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan, payload, sizeof(payload));
}
- if(OC_REST_PUT == ehRequest->method)
+ else
+ {
+ OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+ ehRequest->method);
+ ret = OC_EH_ERROR;
+ }
+
+ if (ret == OC_EH_OK)
{
- ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan);
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = ehRequest->requestHandle;
+ response.resourceHandle = ehRequest->resource;
+ response.ehResult = ret;
+ response.payload = (unsigned char *)payload;
+ response.payloadSize = strlen(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");
+ ret = OC_EH_ERROR;
+ }
}
+
}
else if (ehRequest && flag == OC_OBSERVE_FLAG)
{
}
/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
-void handleSigInt(int signum) {
- if (signum == SIGINT) {
+void handleSigInt(int signum)
+{
+ if (signum == SIGINT)
+ {
gQuitFlag = 1;
}
}
(void)param;
OCStackResult result = OC_STACK_ERROR;
- while (1)
+ while (!gQuitFlag)
{
sleep(10);
light.power += 5;
if (gLightUnderObservation)
{
- OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", light.power);
+ OC_LOG_V(INFO, TAG,
+ " =====> Notifying stack of new power level %d\n", light.power);
result = OCNotifyAllObservers (light.handle, OC_NA_QOS);
if (OC_STACK_NO_OBSERVERS == result)
{
return NULL;
}
-int main() {
- printf("hello world from main\n");
- OC_LOG(DEBUG, TAG, "OCServer is starting...");
+int main(int argc, char* argv[])
+{
uint8_t addr[20] = {0};
uint8_t* paddr = NULL;
uint16_t port = 0;
uint8_t ifname[] = "eth0";
pthread_t threadId;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "t:")) != -1)
+ {
+ switch(opt)
+ {
+ case 't':
+ TEST = atoi(optarg);
+ break;
+ default:
+ PrintUsage();
+ return -1;
+ }
+ }
+ if(TEST <= TEST_INVALID || TEST >= MAX_TESTS){
+ PrintUsage();
+ return -1;
+ }
+ OC_LOG(DEBUG, TAG, "OCServer is starting...");
/*Get Ip address on defined interface and initialize coap on it with random port number
* this port number will be used as a source port in all coap communications*/
- if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
+ if (OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
sizeof(addr)) == ERR_SUCCESS)
{
OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
// Break from loop with Ctrl-C
OC_LOG(INFO, TAG, "Entering ocserver main loop...");
signal(SIGINT, handleSigInt);
- while (!gQuitFlag) {
- if (OCProcess() != OC_STACK_OK) {
+ while (!gQuitFlag)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
OC_LOG(ERROR, TAG, "OCStack process error");
return 0;
}
OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
- if (OCStop() != OC_STACK_OK) {
+ if (OCStop() != OC_STACK_OK)
+ {
OC_LOG(ERROR, TAG, "OCStack process error");
}
return 0;
}
-void createResources() {
+void createResources()
+{
light.state = false;
OCResourceHandle fan;
OC_LOG_V(INFO, TAG, "Created light resource with result: %s", getResult(res));
OCResourceHandle room;
- res = OCCreateResource(&room,
- "core.room",
- "oc.mi.b",
- "/a/room",
- OCEntityHandlerRoomCb,
- OC_DISCOVERABLE);
+
+ if(TEST == TEST_APP_COLL_EH)
+ {
+ res = OCCreateResource(&room,
+ "core.room",
+ "oc.mi.b",
+ "/a/room",
+ OCEntityHandlerRoomCb,
+ OC_DISCOVERABLE);
+ }
+ else
+ {
+ res = OCCreateResource(&room,
+ "core.room",
+ "oc.mi.b",
+ "/a/room",
+ NULL,
+ OC_DISCOVERABLE);
+ }
+
OC_LOG_V(INFO, TAG, "Created room resource with result: %s", getResult(res));
OCBindResourceInterfaceToResource(room, "oc.mi.ll");
OCBindResourceInterfaceToResource(room, "oc.mi.def");
res = OCBindResource(room, fan);
OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
}
-
-
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <list>
+#include "ocstack.h"
+#include "ocmalloc.h"
+#include "logger.h"
+#include "cJSON.h"
+#include "ocserverslow.h"
+
+volatile sig_atomic_t gQuitFlag = 0;
+
+static std::list<OCEntityHandlerRequest *> gRequestList;
+static constexpr unsigned int SLOW_RESPONSE_DELAY_SEC = 5;
+
+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 unsigned int gCurrLedInstance = 0;
+static constexpr unsigned int SAMPLE_MAX_NUM_POST_INSTANCE = 2;
+static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
+
+//char *gResourceUri= const_cast<char *>("/a/led");
+char *gResourceUri= (char *)"/a/led";
+
+static constexpr uint16_t OC_WELL_KNOWN_PORT = 5683;
+
+//This function takes the request as an input and returns the response
+//in JSON format.
+char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
+{
+ cJSON *json = cJSON_CreateObject();
+ cJSON *format;
+ char *jsonResponse;
+ LEDResource *currLEDResource = &LED;
+
+ OC_LOG(INFO, TAG, "Entering constructJsonResponse");
+
+ if (ehRequest->resource == gLedInstance[0].handle)
+ {
+ OC_LOG(INFO, TAG, "handle 0");
+ currLEDResource = &gLedInstance[0];
+ gResourceUri = const_cast<char *>("a/led/0");
+ }
+ else if (ehRequest->resource == gLedInstance[1].handle)
+ {
+ OC_LOG(INFO, TAG, "handle 1");
+ currLEDResource = &gLedInstance[1];
+ gResourceUri = const_cast<char *>("a/led/1");
+ }
+
+ if(OC_REST_PUT == ehRequest->method)
+ {
+ cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload);
+ currLEDResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring ,
+ "on") ? true:false);
+ currLEDResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble;
+ cJSON_Delete(putJson);
+ }
+
+ cJSON_AddStringToObject(json,"href",gResourceUri);
+ cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
+ cJSON_AddStringToObject(format, "state", (char *) (currLEDResource->state ? "on":"off"));
+ cJSON_AddNumberToObject(format, "power", currLEDResource->power);
+
+ OC_LOG(INFO, TAG, "Before constructJsonResponse print");
+ jsonResponse = cJSON_Print(json);
+ OC_LOG(INFO, TAG, "Before constructJsonResponse delete");
+ cJSON_Delete(json);
+
+ OC_LOG(INFO, TAG, "Before constructJsonResponse return");
+ return jsonResponse;
+}
+
+void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+{
+ OC_LOG(INFO, TAG, "Entering ProcessGetRequest");
+ char *getResp = constructJsonResponse(ehRequest);
+ OC_LOG(INFO, TAG, "After constructJsonResponse");
+ OCEntityHandlerResponse response;
+
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = ehRequest->requestHandle;
+ response.resourceHandle = ehRequest->resource;
+ response.ehResult = OC_EH_OK;
+ response.payload = (unsigned char *)getResp;
+ response.payloadSize = strlen(getResp) + 1;
+ 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");
+ }
+
+ free(getResp);
+}
+
+OCEntityHandlerRequest *CopyRequest(OCEntityHandlerRequest *entityHandlerRequest)
+{
+ OC_LOG(INFO, TAG, "Copying received request for slow response");
+ OCEntityHandlerRequest *request = (OCEntityHandlerRequest *)OCMalloc(sizeof(OCEntityHandlerRequest));
+ if (request)
+ {
+ // Do shallow copy
+ memcpy(request, entityHandlerRequest, sizeof(OCEntityHandlerRequest));
+ // Do deep copy of query
+ request->query = (unsigned char * )OCMalloc(strlen((const char *)entityHandlerRequest->query) + 1);
+ if (request->query)
+ {
+ strcpy((char *)request->query, (const char *)entityHandlerRequest->query);
+
+ // Copy the request payload
+ request->reqJSONPayload = (unsigned char * )OCMalloc(strlen((const char *)entityHandlerRequest->reqJSONPayload) + 1);
+ if (request->reqJSONPayload)
+ {
+ strcpy((char *)request->reqJSONPayload, (const char *)entityHandlerRequest->reqJSONPayload);
+
+ // Ignore vendor specific header options for example
+ request->numRcvdVendorSpecificHeaderOptions = 0;
+ request->rcvdVendorSpecificHeaderOptions = NULL;
+ }
+ else
+ {
+ OCFree(request->query);
+ OCFree(request);
+ request = NULL;
+ }
+ }
+ else
+ {
+ OCFree(request);
+ request = NULL;
+ }
+ }
+
+ if (request)
+ {
+ OC_LOG(INFO, TAG, "Copied client request");
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Error copying client request");
+ }
+ return request;
+}
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest *entityHandlerRequest)
+{
+ OCEntityHandlerResult result = OC_EH_ERROR;
+ OCEntityHandlerRequest *request = NULL;
+
+ OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+ if (flag & OC_INIT_FLAG)
+ {
+ OC_LOG(INFO, TAG, "Flag includes OC_INIT_FLAG");
+ result = OC_EH_OK;
+ }
+ if (flag & OC_REQUEST_FLAG)
+ {
+ OC_LOG(INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+ if (entityHandlerRequest)
+ {
+ OC_LOG_V (INFO, TAG, "request query %s from client",
+ entityHandlerRequest->query);
+ OC_LOG_V (INFO, TAG, "request payload %s from client",
+ entityHandlerRequest->reqJSONPayload);
+ // Make deep copy of received request and queue it for slow processing
+ request = CopyRequest(entityHandlerRequest);
+ if (request)
+ {
+
+ OC_LOG(INFO, TAG, "Scheduling slow response for received request");
+ gRequestList.push_back(request);
+ // Indicate to the stack that this is a slow response
+ result = OC_EH_SLOW;
+ // Start the slow response alarm
+ alarm(SLOW_RESPONSE_DELAY_SEC);
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Error queuing request for slow response");
+ // Indicate to the stack that this is a slow response
+ result = OC_EH_ERROR;
+ }
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Invalid request");
+ result = OC_EH_ERROR;
+ }
+ }
+ return result;
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+ if (signum == SIGINT)
+ {
+ gQuitFlag = 1;
+ }
+}
+
+// SIGINT alarm handler: alarm set by entity handler. Does
+// slow response when fired
+void AlarmHandler(int sig)
+{
+ if (sig == SIGALRM)
+ {
+ OC_LOG (INFO, TAG, "Server starting slow response");
+ if (gRequestList.empty())
+ {
+ OC_LOG (INFO, TAG, "No requests to service");
+ return;
+ }
+
+ // Get the request from the list
+ OCEntityHandlerRequest *entityHandlerRequest = gRequestList.front();
+ gRequestList.pop_front();
+ if (entityHandlerRequest->method == OC_REST_GET)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+ ProcessGetRequest (entityHandlerRequest);
+ }
+ else
+ {
+ OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+ entityHandlerRequest->method);
+ }
+ // Free the request
+ OCFree(entityHandlerRequest->query);
+ OCFree(entityHandlerRequest->reqJSONPayload);
+ OCFree(entityHandlerRequest);
+
+ // If there are more requests in list, re-arm the alarm signal
+ if (gRequestList.empty())
+ {
+ alarm(SLOW_RESPONSE_DELAY_SEC);
+ }
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ uint8_t addr[20] = {0};
+ uint8_t* paddr = NULL;
+ uint16_t port = OC_WELL_KNOWN_PORT;
+ uint8_t ifname[] = "eth0";
+
+
+ OC_LOG(DEBUG, TAG, "OCServer is starting...");
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
+ sizeof(addr)) == ERR_SUCCESS)
+ {
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ paddr = addr;
+ }
+
+ if (OCInit((char *) paddr, port, 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);
+
+ // Initialize slow response alarm
+ signal(SIGALRM, AlarmHandler);
+
+ // 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;
+ }
+
+ sleep(2);
+ }
+
+ OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+ // Free requests
+ if (!gRequestList.empty())
+ {
+ for (auto iter = gRequestList.begin(); iter != gRequestList.end(); ++iter)
+ {
+ OCFree((*iter)->query);
+ OCFree((*iter)->reqJSONPayload);
+ OCFree(*iter);
+ }
+ gRequestList.clear();
+ }
+
+ 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.mi.def",
+ uri,
+ OCEntityHandlerCb,
+ OC_DISCOVERABLE|OC_OBSERVABLE);
+ OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+
+ return 0;
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 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 OCSERVER_SLOW_H_
+#define OCSERVER_SLOW_H_
+
+#include "ocstack.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define TAG "ocserverslow"
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+
+/* Structure to represent a LED resource */
+typedef struct LEDRESOURCE{
+ OCResourceHandle handle;
+ bool state;
+ int power;
+} LEDResource;
+
+//-----------------------------------------------------------------------------
+// Function prototypes
+//-----------------------------------------------------------------------------
+
+/* 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 */
+char* constructJsonResponse (OCEntityHandlerRequest *ehRequest);
+
+/* Following method process the GET request
+ */
+void ProcessGetRequest (OCEntityHandlerRequest *ehRequest);
+
+/* call getResult in common.cpp to get the result in string format. */
+const char *getResult(OCStackResult result);
+
+//-----------------------------------------------------------------------------
+// Callback functions
+//-----------------------------------------------------------------------------
+
+/* Entity Handler callback functions */
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest *entityHandlerRequest);
+
+#endif
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#include <ocstack.h>
+#include <ocsecurity.h>
+#include <logger.h>
#include <stdio.h>
#include <stdlib.h>
-#include <ocstack.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define TAG "sample-common"
+
+OCStackResult SetCredentials(const char* filename) {
+
+ FILE *fp = NULL;
+ uint8_t *data = NULL;
+ struct stat st;
+ OCStackResult ret = OC_STACK_ERROR;
+
+ fp = fopen(filename, "rb");
+ if (fp)
+ {
+ if (stat(filename, &st) == 0)
+ {
+ data = (uint8_t*)malloc(st.st_size);
+ if (data)
+ {
+ if (fread(data, 1, st.st_size, fp) == (size_t)st.st_size)
+ {
+ // Provide credentials to OC Stack
+ ret = OCSetDtlsPskCredentials((OCDtlsPskCredsBlob *)data,
+ st.st_size);
+ }
+ else
+ {
+ OC_LOG_V(FATAL, TAG, "Error in reading file %s", filename);
+ }
+ }
+ }
+ fclose(fp);
+ }
+ else
+ {
+ OC_LOG_V(FATAL, TAG, "Unable to open %s file", filename);
+ }
+
+ free(data);
+
+ return ret;
+}
const char *getResult(OCStackResult result) {
switch (result) {
case OC_STACK_NO_OBSERVERS:
return "OC_STACK_NO_OBSERVERS";
#ifdef WITH_PRESENCE
- case OC_STACK_PRESENCE_DO_NOT_HANDLE:
- return "OC_STACK_PRESENCE_DO_NOT_HANDLE";
+ case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+ return "OC_STACK_VIRTUAL_DO_NOT_HANDLE";
case OC_STACK_PRESENCE_STOPPED:
return "OC_STACK_PRESENCE_STOPPED";
#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 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 OCSAMPLE_COMMON_H_
+#define OCSAMPLE_COMMON_H_
+
+/* Get the result in string format. */
+const char *getResult(OCStackResult result);
+
+/* Read the credentials from persistent storage and provide to OC stack. */
+OCStackResult SetCredentials(const char* filename);
+
+#endif //OCSAMPLE_COMMON_H_
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 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 "ocsecurityconfig.h"
+#include "logger.h"
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define TAG "gen_sec_bin"
+
+void printStruct(const char * device, OCDtlsPskCredsBlob* s)
+{
+ OC_LOG(INFO, TAG, device);
+ OC_LOG_V(INFO, TAG, "Version - %d", s->blobVer);
+ OC_LOG(INFO, TAG, "My Identity :");
+ OC_LOG_BUFFER(INFO, TAG, s->identity, DTLS_PSK_ID_LEN);
+
+ OC_LOG_V(INFO, TAG, "Number of trusted Peers - %d", s->num);
+ OC_LOG(INFO, TAG, "Peer Identity :");
+ OC_LOG_BUFFER(INFO, TAG, s->creds[0].id, DTLS_PSK_ID_LEN);
+ OC_LOG(INFO, TAG, "Peer Psk :");
+ OC_LOG_BUFFER(INFO, TAG, s->creds[0].psk, DTLS_PSK_PSK_LEN);
+}
+
+
+int main()
+{
+ OCDtlsPskCredsBlob * s = NULL;
+ OCDtlsPskCredsBlob * c = NULL;
+ FILE* fps, *fpc;
+
+ int i;
+
+ srand(time(NULL));
+
+ s = (OCDtlsPskCredsBlob*) malloc(sizeof(OCDtlsPskCredsBlob));
+ c = (OCDtlsPskCredsBlob*) malloc(sizeof(OCDtlsPskCredsBlob));
+
+ memset(s, 0, sizeof(OCDtlsPskCredsBlob));
+ memset(c, 0, sizeof(OCDtlsPskCredsBlob));
+
+ s->blobVer = DtlsPskCredsBlobVer_CurrentVersion;
+ c->blobVer = DtlsPskCredsBlobVer_CurrentVersion;
+
+ s->num = c->num = 1;
+
+ for(i = 0; i < DTLS_PSK_ID_LEN; i++)
+ {
+ c->creds[0].id[i] = s->identity[i] = rand() % (2^8);
+
+ s->creds[0].id[i] = c->identity[i] = rand() % (2^8);
+
+ c->creds[0].psk[i] = s->creds[0].psk[i] = rand() % (2^8);
+ }
+
+ // Print Credentials
+ printStruct("Server", s);
+ printStruct("Client", c);
+
+ // Write to files
+ if ((fps = (FILE*) fopen("server_cred.bin", "wb")) != NULL)
+ {
+ fwrite(s, sizeof(OCDtlsPskCredsBlob), 1, fps);
+ fclose(fps);
+ }
+
+
+ if ((fpc = (FILE*) fopen("client_cred.bin", "wb")) != NULL)
+ {
+ fwrite(c, sizeof(OCDtlsPskCredsBlob), 1, fpc);
+ fclose(fpc);
+ }
+
+ memset(s, 0, sizeof(OCDtlsPskCredsBlob));
+ memset(c, 0, sizeof(OCDtlsPskCredsBlob));
+ // Read from files; print and verify manually
+ if ((fps = (FILE*) fopen("server_cred.bin", "rb")) != NULL)
+ {
+ if (sizeof(OCDtlsPskCredsBlob) != fread(s, 1, sizeof(OCDtlsPskCredsBlob), fps))
+ {
+ OC_LOG(INFO, TAG, PCF("Reading from the file failed."));
+ }
+ fclose(fps);
+ }
+
+
+ if ((fpc = (FILE*) fopen("client_cred.bin", "rb")) != NULL)
+ {
+ if (sizeof(OCDtlsPskCredsBlob) != fread(c, 1, sizeof(OCDtlsPskCredsBlob), fpc))
+ {
+ OC_LOG(INFO, TAG, PCF("Reading from the file failed."));
+ }
+ fclose(fpc);
+ }
+
+ printf("\n\n");
+ OC_LOG(INFO, TAG, PCF("Reading from file and printing again to verify manually"));
+ printStruct("Server", s);
+ printStruct("Client", c);
+
+ free(s);
+ free(c);
+}
+
CJSON_SOURCES := $(CJSON_SRC)/cJSON.c
SOURCES := $(CJSON_SOURCES)
-SOURCES += common.cpp ocserverbasicops.cpp occlientbasicops.cpp
+SOURCES += common.cpp ocserverbasicops.cpp occlientbasicops.cpp gen_sec_bin.cpp
OBJECTS:= $(patsubst %.cpp, $(OBJ_DIR)/%.o, $(SOURCES))
PROGRAMS += ocserverbasicops
PROGRAMS += occlientbasicops
+PROGRAMS += gen_sec_bin
all: c_sdk prep_dirs $(OBJECTS) $(PROGRAMS)
occlientbasicops: $(OBJ_DIR)/occlientbasicops.o $(OBJ_DIR)/common.o
$(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
+gen_sec_bin: $(OBJ_DIR)/gen_sec_bin.o
+ $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
+
.PHONY: clean
clean: legacy_clean
#include "logger.h"
#include "occlientbasicops.h"
#include "cJSON.h"
+#include "common.h"
#define TAG "occlientbasicops"
static int UNICAST_DISCOVERY = 0;
static std::string coapServerResource;
static int coapSecureResource;
+//File containing Client's Identity and the PSK credentials
+//of other devices which the client trusts
+//This can be generated using 'gen_sec_bin' application
+static char CRED_FILE[] = "client_cred.bin";
+
+
int gQuitFlag = 0;
/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
return 0;
}
+ /*
+ * Read DTLS PSK credentials from persistent storage and
+ * set in the OC stack.
+ */
+ if (SetCredentials(CRED_FILE) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "SetCredentials failed");
+ return 0;
+ }
+
InitDiscovery();
timeout.tv_sec = 0;
// Function prototype
//-----------------------------------------------------------------------------
-/* call getResult in common.cpp to get the result in string format. */
-const char *getResult(OCStackResult result);
-
/* Get the IP address of the server */
std::string getIPAddrTBServer(OCClientResponse * clientResponse);
#include "logger.h"
#include "cJSON.h"
#include "ocserverbasicops.h"
+#include "common.h"
int gQuitFlag = 0;
static uint16_t OC_WELL_KNOWN_PORT = 5683;
+//File containing Server's Identity and the PSK credentials
+//of other devices which the server trusts
+//This can be generated using 'gen_sec_bin' application
+static char CRED_FILE[] = "server_cred.bin";
+
//This function takes the request as an input and returns the response
//in JSON format.
char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
return jsonResponse;
}
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload, size_t maxPayloadSize)
{
- char *getResp = constructJsonResponse(ehRequest);
+ OCEntityHandlerResult ehResult;
- if (ehRequest->resJSONPayloadLen > strlen ((char *)getResp))
+ char *getResp = constructJsonResponse(ehRequest);
+ if (maxPayloadSize > strlen (getResp))
{
- strncpy((char *)ehRequest->resJSONPayload, getResp,
- strlen((char *)getResp));
+ strcpy(payload, getResp);
+ ehResult = OC_EH_OK;
}
else
{
OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
- ehRequest->resJSONPayloadLen);
+ maxPayloadSize);
+ ehResult = OC_EH_ERROR;
}
free(getResp);
+
+ return ehResult;
}
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload, size_t maxPayloadSize)
{
- char *putResp = constructJsonResponse(ehRequest);
+ OCEntityHandlerResult ehResult;
- if (ehRequest->resJSONPayloadLen > strlen ((char *)putResp))
+ char *putResp = constructJsonResponse(ehRequest);
+ if (maxPayloadSize > strlen (putResp))
{
- strncpy((char *)ehRequest->resJSONPayload, putResp,
- strlen((char *)putResp));
+ strcpy(payload, putResp);
+ ehResult = OC_EH_OK;
}
else
{
OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
- ehRequest->resJSONPayloadLen);
+ maxPayloadSize);
+ ehResult = OC_EH_ERROR;
}
free(putResp);
+
+ return ehResult;
}
-void ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload, size_t maxPayloadSize)
{
char *respPLPost_led = NULL;
cJSON *json;
cJSON *format;
+ OCEntityHandlerResult ehResult;
/*
* The entity handler determines how to process a POST request.
}
}
- if (respPLPost_led != NULL && ehRequest->resJSONPayloadLen > strlen ((char *)respPLPost_led))
+ if ((respPLPost_led != NULL) && (maxPayloadSize > strlen (respPLPost_led)))
{
- strncpy((char *)ehRequest->resJSONPayload, respPLPost_led,
- strlen((char *)respPLPost_led));
+ strcpy(payload, respPLPost_led);
+ ehResult = OC_EH_OK;
}
else
{
OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
- ehRequest->resJSONPayloadLen);
+ maxPayloadSize);
+ ehResult = OC_EH_ERROR;
}
free(respPLPost_led);
+
+ return ehResult;
}
OCEntityHandlerResult
OCEntityHandlerRequest *entityHandlerRequest)
{
OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+ OCEntityHandlerResponse response;
+ char payload[MAX_RESPONSE_LENGTH];
+
if (flag & OC_INIT_FLAG)
{
OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
+ ehResult = OC_EH_OK;
}
if (flag & OC_REQUEST_FLAG)
{
if (OC_REST_GET == entityHandlerRequest->method)
{
OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
- ProcessGetRequest (entityHandlerRequest);
+ ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload));
}
else if (OC_REST_PUT == entityHandlerRequest->method)
{
OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
- ProcessPutRequest (entityHandlerRequest);
+ ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload));
}
else if (OC_REST_POST == entityHandlerRequest->method)
{
OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
- ProcessPostRequest (entityHandlerRequest);
+ ehResult = ProcessPostRequest (entityHandlerRequest, payload, sizeof(payload));
}
else
{
OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
entityHandlerRequest->method);
}
+
+ if (ehResult == OC_EH_OK)
+ {
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = entityHandlerRequest->requestHandle;
+ response.resourceHandle = entityHandlerRequest->resource;
+ response.ehResult = ehResult;
+ response.payload = (unsigned char *)payload;
+ response.payloadSize = strlen(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;
+ }
+ }
}
}
- return OC_EH_OK;
+ return ehResult;
}
/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
}
/*
+ * Read DTLS PSK credentials from persistent storage and
+ * set in the OC stack.
+ */
+ if (SetCredentials(CRED_FILE) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "SetCredentials failed");
+ return 0;
+ }
+ /*
* Declare and create the example resource: LED
*/
createLEDResource(gResourceUri, &LED, false, 0);
return 0;
}
nanosleep(&timeout, NULL);
- //sleep(2);
}
OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
/* Following methods process the PUT, GET, POST
* requests
*/
-void ProcessGetRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPutRequest (OCEntityHandlerRequest *ehRequest);
-void ProcessPostRequest (OCEntityHandlerRequest *ehRequest);
-
-/* call getResult in common.cpp to get the result in string format. */
-const char *getResult(OCStackResult result);
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload,
+ size_t maxPayloadSize);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload,
+ size_t maxPayloadSize);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+ char *payload,
+ size_t maxPayloadSize);
//-----------------------------------------------------------------------------
// Callback functions
OCMulticastNode * mcPresenceNodes = NULL;
OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData,
- OCCoAPToken * token, OCDoHandle handle, OCMethod method,
- unsigned char * requestUri, unsigned char * resourceType) {
- ClientCB *cbNode;
- cbNode = (ClientCB*) OCMalloc(sizeof(ClientCB));
- if (cbNode) {
- cbNode->callBack = cbData->cb;
- cbNode->context = cbData->context;
- cbNode->deleteCallback = cbData->cd;
- memcpy(&(cbNode->token), token, sizeof(OCCoAPToken));
- cbNode->handle = handle;
- cbNode->method = method;
- cbNode->sequenceNumber = 0;
- #ifdef WITH_PRESENCE
- cbNode->presence = NULL;
- cbNode->filterResourceType = resourceType;
- #endif
- cbNode->requestUri = requestUri;
- LL_APPEND(cbList, cbNode);
+ OCCoAPToken * token, OCDoHandle *handle, OCMethod method,
+ unsigned char * requestUri, unsigned char * resourceTypeName) {
+
+ ClientCB *cbNode = NULL;
+
+ #ifdef WITH_PRESENCE
+ if(method == OC_REST_PRESENCE)
+ { // Retrieve the presence callback structure for this specific requestUri.
+ cbNode = GetClientCB(NULL, NULL, requestUri);
+ }
+ #endif // WITH_PRESENCE
+
+ if(!cbNode)// If it does not already exist, create new node.
+ {
+ cbNode = (ClientCB*) OCMalloc(sizeof(ClientCB));
+ if(!cbNode)
+ {
+ *clientCB = NULL;
+ goto exit;
+ }
+ else
+ {
+ cbNode->callBack = cbData->cb;
+ cbNode->context = cbData->context;
+ cbNode->deleteCallback = cbData->cd;
+ memcpy(&(cbNode->token), token, sizeof(OCCoAPToken));
+ cbNode->handle = *handle;
+ cbNode->method = method;
+ cbNode->sequenceNumber = 0;
+ #ifdef WITH_PRESENCE
+ cbNode->presence = NULL;
+ cbNode->filterResourceType = NULL;
+ #endif // WITH_PRESENCE
+ cbNode->requestUri = requestUri;
+ LL_APPEND(cbList, cbNode);
+ *clientCB = cbNode;
+ }
+ }
+ else
+ {
+ // Ensure that the handle the SDK hands back up to the application layer for the
+ // OCDoResource call matches the found ClientCB Node.
*clientCB = cbNode;
- return OC_STACK_OK;
+ OCFree(requestUri);
+ OCFree(*handle);
+ *handle = cbNode->handle;
}
- *clientCB = NULL;
- return OC_STACK_NO_MEMORY;
+
+ #ifdef WITH_PRESENCE
+ if(method == OC_REST_PRESENCE && resourceTypeName)
+ { // Amend the found or created node by adding a new resourceType to it.
+ return InsertResourceTypeFilter(cbNode, (const char *)resourceTypeName);
+ }
+ #endif
+
+ return OC_STACK_OK;
+
+ exit:
+ return OC_STACK_NO_MEMORY;
}
void DeleteClientCB(ClientCB * cbNode) {
if(cbNode->presence) {
OCFree(cbNode->presence->timeOut);
OCFree(cbNode->presence);
- OCFree(cbNode->filterResourceType);
}
- #endif
+ if(cbNode->method == OC_REST_PRESENCE)
+ {
+ OCResourceType * pointer = cbNode->filterResourceType;
+ OCResourceType * next = NULL;
+ while(pointer)
+ {
+ next = pointer->next;
+ OCFree(pointer->resourcetypename);
+ OCFree(pointer);
+ pointer = next;
+ }
+ }
+ #endif // WITH_PRESENCE
OCFree(cbNode);
cbNode = NULL;
}
return NULL;
}
+OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName)
+{
+ OCResourceType * newResourceType = NULL;
+ if(cbNode && resourceTypeName)
+ {
+ // Form a new resourceType member.
+ newResourceType = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
+ if(!newResourceType)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+
+ newResourceType->next = NULL;
+ newResourceType->resourcetypename = (char *) resourceTypeName;
+
+ LL_APPEND(cbNode->filterResourceType, newResourceType);
+ return OC_STACK_OK;
+ }
+ return OC_STACK_ERROR;
+}
void DeleteClientCBList() {
ClientCB* out;
#include <string.h>
#include "ocstack.h"
#include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "logger.h"
#include "debug.h"
#include "cJSON.h"
char *endToken;
char *innerToken = strtok_r (token, "=", &endToken);
numParam = 0;
+
// Internal loop parses the field to extract values (parameters) assigned to each field
while (innerToken != NULL)
{
-
numParam++;
if (strcmp (innerToken, OC_RSRVD_INTERFACE) == 0)
{
return OC_STACK_INVALID_QUERY;
}
- if (!ifPtr)
- {
- // IF not specified in query, use default IF
- *ifParam = STACK_IF_DEFAULT;
- }
- else
+ if (ifPtr)
{
if(CheckIFParamSupport((OCResource *)resource, ifPtr) != OC_STACK_OK)
+ {
return OC_STACK_INVALID_QUERY;
-
+ }
if (strcmp (ifPtr, OC_RSRVD_INTERFACE_DEFAULT) == 0)
+ {
*ifParam = STACK_IF_DEFAULT;
+ }
else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_LL) == 0)
+ {
*ifParam = STACK_IF_LL;
+ }
else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_BATCH) == 0)
+ {
*ifParam = STACK_IF_BATCH;
+ }
else
{
return OC_STACK_ERROR;
}
}
-
- if (!rtPtr)
+ else
{
- // RT not specified in query. Use the first resource type for the resource as default.
- *rtParam = (char *) OCGetResourceTypeName (resource, 0);
+ // IF not specified in query, use default IF
+ *ifParam = STACK_IF_DEFAULT;
}
- else
+
+ if (rtPtr)
{
if (CheckRTParamSupport((OCResource *)resource, rtPtr) == OC_STACK_OK)
+ {
*rtParam = rtPtr;
+ }
else
+ {
return OC_STACK_INVALID_QUERY;
+ }
+ }
+ else
+ {
+ // RT not specified in query. Use the first resource type for the resource as default.
+ *rtParam = (char *) OCGetResourceTypeName (resource, 0);
}
OC_LOG_V(INFO, TAG, "Query params: IF = %d, RT = %s", *ifParam, *rtParam);
return OC_STACK_OK;
}
-static OCStackResult BuildRootResourceJSON(OCResource *resource, OCEntityHandlerRequest *ehRequest)
+
+
+static OCStackResult BuildRootResourceJSON(OCResource *resource,
+ unsigned char * bufferPtr, uint16_t *remaining)
{
OCStackResult ret = OC_STACK_ERROR;
cJSON *resObj;
OC_LOG(INFO, TAG, PCF("Entering BuildRootResourceJSON"));
resObj = cJSON_CreateObject();
+
if (resource)
{
cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resource->uri));
}
jsonStr = cJSON_PrintUnformatted (resObj);
jsonLen = strlen(jsonStr);
- if (jsonLen < ehRequest->resJSONPayloadLen)
+ if (jsonLen < *remaining)
{
- strcpy((char*)ehRequest->resJSONPayload, jsonStr);
- ehRequest->resJSONPayloadLen -= jsonLen;
- ehRequest->resJSONPayload += jsonLen;
- ret = OC_STACK_OK;
- }
-
- if (ehRequest->resJSONPayloadLen >= (sizeof(OC_JSON_SEPARATOR) + 1))
- {
- *ehRequest->resJSONPayload = OC_JSON_SEPARATOR;
- ehRequest->resJSONPayload++;
- ehRequest->resJSONPayloadLen--;
+ strcpy((char*) bufferPtr, jsonStr);
+ *remaining -= jsonLen;
+ bufferPtr += jsonLen;
ret = OC_STACK_OK;
}
static OCStackResult
-BuildCollectionJSONResponse(OCResource *resource, OCEntityHandlerRequest *ehRequest,
+HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest,
uint8_t filterOn, char *filterValue)
{
OCStackResult ret = OC_STACK_ERROR;
- ret = BuildRootResourceJSON(resource, ehRequest);
+ unsigned char jsonbuffer[MAX_RESPONSE_LENGTH] = {0};
+ size_t jsonbufferLength = 0;
+ uint16_t remaining = 0;
+ unsigned char * ptr = NULL;
+ OCResource * collResource = (OCResource *) ehRequest->resource;
+
+ ptr = jsonbuffer;
+ remaining = MAX_RESPONSE_LENGTH;
+
+ ret = BuildRootResourceJSON(collResource, ptr, &remaining);
+ ptr += strlen((char*)ptr);
+
+ if (ret == OC_STACK_OK && remaining >= (sizeof(OC_JSON_SEPARATOR) + 1))
+ {
+ *ptr = OC_JSON_SEPARATOR;
+ ptr++;
+ remaining--;
+ }
+ else
+ {
+ ret = OC_STACK_ERROR;
+ }
+ *(ptr + 1) = '\0';
- unsigned char* buffer = ehRequest->resJSONPayload;
- uint16_t remaining = ehRequest->resJSONPayloadLen;
if (ret == OC_STACK_OK)
{
for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
{
- OCResource* temp = resource->rsrcResources[i];
+ OCResource* temp = collResource->rsrcResources[i];
if (temp)
{
- ret = BuildVirtualResourceResponse(temp, filterOn, filterValue, (char*)buffer, &remaining);
+ ret = BuildVirtualResourceResponse(temp, filterOn, filterValue, (char*)ptr, &remaining);
if (ret != OC_STACK_OK)
{
break;
}
-
- buffer += strlen((char*)buffer);
- if (resource->rsrcResources[i+1] && remaining > sizeof(OC_JSON_SEPARATOR))
+ ptr += strlen((char*)ptr);
+ if (collResource->rsrcResources[i+1] && remaining > sizeof(OC_JSON_SEPARATOR))
{
- *buffer = OC_JSON_SEPARATOR;
- buffer++;
+ *ptr = OC_JSON_SEPARATOR;
+ ptr++;
remaining--;
}
+ *(ptr + 1) = '\0';
}
else
{
break;
}
}
- ehRequest->resJSONPayload = buffer;
- ehRequest->resJSONPayloadLen = remaining;
}
+ jsonbufferLength = strlen((const char *)jsonbuffer);
+ if(ret == OC_STACK_OK && jsonbufferLength)
+ {
+ OCEntityHandlerResponse response = {0};
+ response.ehResult = OC_EH_OK;
+ response.payload = jsonbuffer;
+ response.payloadSize = jsonbufferLength + 1;
+ response.persistentBufferFlag = 0;
+ response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+ response.resourceHandle = (OCResourceHandle) collResource;
+ ret = OCDoResponse(&response);
+ }
return ret;
}
-
static OCStackResult
-BuildCollectionBatchJSONResponse(OCEntityHandlerFlag flag,
- OCResource *resource, OCEntityHandlerRequest *ehRequest)
+HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
{
OCStackResult stackRet = OC_STACK_ERROR;
- OCEntityHandlerResult ehRet = OC_EH_ERROR;
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+ unsigned char jsonbuffer[MAX_RESPONSE_LENGTH] = {0};
+ size_t jsonbufferLength = 0;
+ uint16_t remaining = 0;
+ unsigned char * ptr = NULL;
+ OCResource * collResource = (OCResource *) ehRequest->resource;
+
+ ptr = jsonbuffer;
+ remaining = MAX_RESPONSE_LENGTH;
+
+ stackRet = BuildRootResourceJSON(collResource, ptr, &remaining);
+ ptr += strlen((char*)ptr);
+ *(ptr + 1) = '\0';
+
+ jsonbufferLength = strlen((const char *)jsonbuffer);
+ if(jsonbufferLength)
+ {
+ OCEntityHandlerResponse response = {0};
+ response.ehResult = OC_EH_OK;
+ response.payload = jsonbuffer;
+ response.payloadSize = jsonbufferLength + 1;
+ response.persistentBufferFlag = 0;
+ response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+ response.resourceHandle = (OCResourceHandle) collResource;
+ stackRet = OCDoResponse(&response);
+ }
- stackRet = BuildRootResourceJSON(resource, ehRequest);
if (stackRet == OC_STACK_OK)
{
- OCResourceHandle origResourceHandle = ehRequest->resource;
-
for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
{
- OCResource* temp = resource->rsrcResources[i];
+ OCResource* temp = collResource->rsrcResources[i];
if (temp)
{
+ // Note that all entity handlers called through a collection
+ // will get the same pointer to ehRequest, the only difference
+ // is ehRequest->resource
ehRequest->resource = (OCResourceHandle) temp;
- ehRet = temp->entityHandler(OC_REQUEST_FLAG, ehRequest);
- stackRet = EntityHandlerCodeToOCStackCode(ehRet);
+ ehResult = temp->entityHandler(OC_REQUEST_FLAG, ehRequest);
- if(ehRet == OC_EH_OK)
+ // The default collection handler is returning as OK
+ if(stackRet != OC_STACK_SLOW_RESOURCE)
{
- unsigned char* buffer = ehRequest->resJSONPayload;
- ehRequest->resJSONPayloadLen =
- ehRequest->resJSONPayloadLen - strlen((char*)buffer);
-
- buffer += strlen((char*)buffer);
- ehRequest->resJSONPayload = buffer;
- if ( resource->rsrcResources[i+1] &&
- ehRequest->resJSONPayloadLen > sizeof(OC_JSON_SEPARATOR) )
- {
- * buffer = OC_JSON_SEPARATOR;
- buffer++;
- ehRequest->resJSONPayload = buffer;
- ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen - 1;
- }
+ stackRet = OC_STACK_OK;
}
- else
+ // if a single resource is slow, then entire response will be treated
+ // as slow response
+ if(ehResult == OC_EH_SLOW)
{
- break;
+ OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+ ((OCServerRequest *)ehRequest->requestHandle)->slowFlag = 1;
+ stackRet = EntityHandlerCodeToOCStackCode(ehResult);
}
}
else
{
- break;
+ break;
}
}
-
- ehRequest->resource = origResourceHandle;
+ ehRequest->resource = (OCResourceHandle) collResource;
}
return stackRet;
}
+uint8_t GetNumOfResourcesInCollection (OCResource *resource)
+{
+ uint8_t num = 0;
+ for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+ {
+ if (resource->rsrcResources[i])
+ {
+ num++;
+ }
+ }
+ return num;
+}
+
OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
OCEntityHandlerRequest *ehRequest)
{
- OCStackResult result;
- OCStackIfTypes ifQueryParam;
- char *rtQueryParam;
+ OCStackResult result = OC_STACK_ERROR;
+ OCStackIfTypes ifQueryParam = STACK_IF_INVALID;
+ char *rtQueryParam = NULL;
- OC_LOG(INFO, TAG, PCF("DefaultCollectionEntityHandler"));
+ OC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query);
if (flag != OC_REQUEST_FLAG)
return OC_STACK_ERROR;
// Get attributes of collection resource and properties of contined resource
// M1 release does not support attributes for collection resource, so the GET
// operation is same as the GET on LL interface.
-
OC_LOG(INFO, TAG, PCF("STACK_IF_DEFAULT"));
- return BuildCollectionJSONResponse( (OCResource *)ehRequest->resource,
- ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
+ return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
case STACK_IF_LL:
OC_LOG(INFO, TAG, PCF("STACK_IF_LL"));
- return BuildCollectionJSONResponse( (OCResource *)ehRequest->resource,
- ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
+ return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
case STACK_IF_BATCH:
OC_LOG(INFO, TAG, PCF("STACK_IF_BATCH"));
- return BuildCollectionBatchJSONResponse(flag, (OCResource *)ehRequest->resource, ehRequest);
+ ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse;
+ ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
+ GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
+ return HandleBatchInterface(ehRequest);
default:
return OC_STACK_ERROR;
return OC_STACK_ERROR;
case STACK_IF_BATCH:
- return BuildCollectionBatchJSONResponse(flag, (OCResource *)ehRequest->resource, ehRequest);
+ ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse;
+ ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
+ GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
+ return HandleBatchInterface(ehRequest);
default:
return OC_STACK_ERROR;
#include "ocstackconfig.h"
#include "ocstackinternal.h"
#include "ocobserve.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "occoap.h"
#include "utlist.h"
#include "debug.h"
#include "ocrandom.h"
#include "ocmalloc.h"
+#include "ocserverrequest.h"
// Module Name
#define MOD_NAME PCF("ocobserve")
#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
static struct ResourceObserver * serverObsList = NULL;
-extern uint32_t SERVER_DISCOVERABLE;
-OCStackResult OCObserverStatus(OCCoAPToken * token, uint8_t status)
+// send notifications based on the qos of the request
+// The qos passed as a parameter overrides what the client requested
+// If we want the client preference taking high priority make:
+// qos = resourceObserver->qos;
+OCQualityOfService DetermineObserverQoS(OCMethod method, ResourceObserver * resourceObserver,
+ OCQualityOfService appQoS)
{
- OCStackResult result = OC_STACK_ERROR;
- ResourceObserver * observer = NULL;
- OCEntityHandlerRequest ehRequest;
- OCObservationInfo observationInfo;
- unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
-
- switch(status)
+ OCQualityOfService decidedQoS = appQoS;
+ if(appQoS == OC_NA_QOS)
{
- case OC_OBSERVER_NOT_INTERESTED:
- OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
- observer = GetObserverUsingToken (token);
- if(observer)
- {
- FormOCEntityHandlerRequest(&ehRequest, OC_REST_CANCEL_OBSERVE, bufRes,
- NULL, NULL, NULL);
- ehRequest.obsInfo = &observationInfo;
- ehRequest.obsInfo->action = OC_OBSERVE_DEREGISTER;
- ehRequest.obsInfo->obsId = observer->observeId;
- observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
- }
- //observer is dead, or it is not observing anymore
- result = DeleteObserverUsingToken (token);
- if(result != OC_STACK_OK)
- {
- result = OC_STACK_OBSERVER_NOT_REMOVED;
- }
- else
- {
- OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
- }
- break;
- case OC_OBSERVER_STILL_INTERESTED:
- //observer is still interested
- OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
- notifications, reset the failedCount"));
- observer = GetObserverUsingToken(token);
- if(observer)
- {
- observer->forceHighQos = 0;
- observer->failedCommCount = 0;
- result = OC_STACK_OK;
- }
- else
- {
- result = OC_STACK_OBSERVER_NOT_FOUND;
- }
- break;
- case OC_OBSERVER_FAILED_COMM:
- //observer is not reachable
- OC_LOG(DEBUG, TAG, PCF("observer is not reachable"));
- observer = GetObserverUsingToken(token);
- if(observer)
- {
- if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
- {
- FormOCEntityHandlerRequest(&ehRequest, OC_REST_CANCEL_OBSERVE, bufRes,
- NULL, NULL, NULL);
- ehRequest.obsInfo = &observationInfo;
- ehRequest.obsInfo->action = OC_OBSERVE_DEREGISTER;
- ehRequest.obsInfo->obsId = observer->observeId;
- observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
-
- result = DeleteObserverUsingToken (token);
- if(result != OC_STACK_OK)
- {
- result = OC_STACK_OBSERVER_NOT_REMOVED;
- }
- else
- {
- OC_LOG(DEBUG, TAG, PCF("removing an observer"));
- }
- }
- else
- {
- observer->failedCommCount++;
- result = OC_STACK_OBSERVER_NOT_REMOVED;
- }
- observer->forceHighQos = 1;
- OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
- }
- break;
- default:
- break;
+ decidedQoS = resourceObserver->qos;
}
- return result;
-}
-
-OCStackResult ProcessObserveRequest (OCResource *resource, OCRequest *request)
-{
- OCStackResult stackRet = OC_STACK_ERROR;
- OCEntityHandlerResult ehRet = OC_EH_ERROR;
- OCEntityHandlerRequest *ehReq = request->entityHandlerRequest;
- OCObserveReq *obs = request->observe;
- OCObservationInfo observationInfo;
- OCObservationId obsId;
- ResourceObserver *resObs = NULL;
-
- OC_LOG(INFO, TAG, PCF("Entering ProcessObserveRequest"));
-
- request->entityHandlerRequest->resource = (OCResourceHandle)resource;
- request->entityHandlerRequest->obsInfo = &observationInfo;
-
- if (obs->option == OC_RESOURCE_OBSERVE_REGISTER)
+ if(appQoS != OC_HIGH_QOS)
{
- // Request to register new observation
- observationInfo.action = OC_OBSERVE_REGISTER;
- // Generate observation Id for the request
- while (1)
- {
- if (OC_STACK_OK != GenerateObserverId (&obsId))
- return OC_STACK_ERROR;
-
- // Check if observation Id already exists
- resObs = GetObserverUsingId (obsId);
- if (NULL == resObs)
- {
- OC_LOG_V(INFO, TAG, "Observation ID is %d", obsId);
- break;
- }
- }
-
- observationInfo.obsId = obsId;
- // Register the observation request with entity handler
- ehRet = resource->entityHandler ((OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG),
- request->entityHandlerRequest);
- if (ehRet == OC_EH_OK)
- {
- // Add subscriber to the server observation list
- stackRet = AddObserver ((const char*)(request->resourceUrl),
- (const char *)(ehReq->query),
- obsId, obs->token, obs->subAddr,
- resource, request->qos);
- if(stackRet != OC_STACK_OK)
- {
- obs->result = OC_STACK_OBSERVER_NOT_ADDED;
- stackRet = OC_STACK_OBSERVER_NOT_ADDED;
- // If the observation was not added in the stack notify the entity handler
- observationInfo.action = OC_OBSERVE_DEREGISTER;
- // If the entity handler is unable to deregister, stack cannot do anything,
- // hence the return value from entity handler is not being checked
- resource->entityHandler (OC_OBSERVE_FLAG, request->entityHandlerRequest);
- }
- else
+ OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
+ resourceObserver->lowQosCount);
+ #ifdef WITH_PRESENCE
+ if((resourceObserver->forceHighQos \
+ || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT) \
+ && method != OC_REST_PRESENCE)
+ #else
+ if(resourceObserver->forceHighQos \
+ || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT)
+ #endif
{
- OC_LOG(DEBUG, TAG, PCF("Added observer successfully"));
+ resourceObserver->lowQosCount = 0;
+ // at some point we have to to send CON to check on the
+ // availability of observer
+ OC_LOG(INFO, TAG, PCF("This time we are sending the notification as High qos"));
+ decidedQoS = OC_HIGH_QOS;
}
- }
- else
- {
- stackRet = OC_STACK_OBSERVER_NOT_ADDED;
- }
- }
- else if (obs->option == OC_RESOURCE_OBSERVE_DEREGISTER)
- {
- // Request to deregister observation
- observationInfo.action = OC_OBSERVE_DEREGISTER;
-
- // Get observation Id using token
- resObs = GetObserverUsingToken (obs->token);
- if (NULL == resObs)
- {
- // Stack does not contain this observation request
- // Either token is incorrect or observation list is corrupted
- return OC_STACK_ERROR;
- }
- observationInfo.action = OC_OBSERVE_DEREGISTER;
- observationInfo.obsId = resObs->observeId;
- // Deregister the observation with entity handler. Ignoring return value
- // from entity handler and deleting the observation from stack
- resource->entityHandler ((OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG),
- request->entityHandlerRequest);
- stackRet = DeleteObserverUsingToken (obs->token);
- if(stackRet != OC_STACK_OK)
- {
- obs->result = OC_STACK_OBSERVER_NOT_REMOVED;
- stackRet = OC_STACK_OBSERVER_NOT_REMOVED;
- }
else
{
- OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+ (resourceObserver->lowQosCount)++;
}
}
- else
- {
- // Invalid observe option
- OC_LOG(ERROR, TAG, PCF("Invalid CoAP observe option"));
- obs->result = OC_STACK_INVALID_OBSERVE_PARAM;
- }
- return stackRet;
+ return decidedQoS;
}
-OCStackResult SendObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
- OCResourceType *resourceType, OCQualityOfService qos)
+#ifdef WITH_PRESENCE
+OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
+ OCResourceType *resourceType, OCQualityOfService qos)
+#else
+OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
+ OCQualityOfService qos)
+#endif
{
+ OC_LOG(INFO, TAG, PCF("Entering SendObserverNotification"));
+ OCStackResult result = OC_STACK_ERROR;
+ ResourceObserver * resourceObserver = serverObsList;
uint8_t numObs = 0;
- OCStackResult stackRet = OC_STACK_ERROR;
- OCEntityHandlerResult ehRet = OC_EH_ERROR;
- ResourceObserver *resourceObserver = serverObsList;
- OCEntityHandlerRequest entityHandlerReq;
- unsigned char* jsonPayload = NULL;
- unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
+ OCServerRequest * request = NULL;
+ OCEntityHandlerRequest ehRequest = {0};
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
// Find clients that are observing this resource
while (resourceObserver)
if(method != OC_REST_PRESENCE)
{
#endif
- // Invoke the entity handler for the client to process
- // the query according to the new representation
- FormOCEntityHandlerRequest(&entityHandlerReq, OC_REST_GET, bufRes,
- NULL, resourceObserver->query, NULL);
- entityHandlerReq.resource = (OCResourceHandle)resPtr;
-
- // Even if entity handler for a resource is not successful
- // we continue calling entity handler for other resources
- ehRet = BuildObsJSONResponse((OCResource *) resPtr, &entityHandlerReq);
- jsonPayload = (unsigned char *)(entityHandlerReq.resJSONPayload);
+ qos = DetermineObserverQoS(method, resourceObserver, qos);
+ result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET,
+ 0, resPtr->sequenceNum, qos, resourceObserver->query,
+ NULL, NULL,
+ &resourceObserver->token, resourceObserver->addr,
+ resourceObserver->resUri, 0);
+ request->observeResult = OC_STACK_OK;
+ if(request && result == OC_STACK_OK)
+ {
+ result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
+ request->method, (OCResourceHandle) resPtr, request->query,
+ request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+ request->rcvdVendorSpecificHeaderOptions, OC_OBSERVE_NO_OPTION, 0);
+ if(result == OC_STACK_OK)
+ {
+ ehResult = resPtr->entityHandler(OC_REQUEST_FLAG, &ehRequest);
+ if(ehResult == OC_EH_ERROR)
+ {
+ FindAndDeleteServerRequest(request);
+ }
+ }
+ }
#ifdef WITH_PRESENCE
}
else
{
- //we know it is the default entity handler
+ OCEntityHandlerResponse ehResponse = {0};
+ unsigned char presenceResBuf[MAX_RESPONSE_LENGTH] = {0};
+ //This is effectively the implementation for the presence entity handler.
OC_LOG(DEBUG, TAG, PCF("This notification is for Presence"));
-
- // we create the payload here
- if(resourceType)
+ result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET,
+ 0, OC_OBSERVE_NO_OPTION, OC_LOW_QOS,
+ NULL, NULL, NULL, &resourceObserver->token,
+ resourceObserver->addr, resourceObserver->resUri, 0);
+ if(result == OC_STACK_OK)
{
- sprintf((char *)bufRes, "%u:%u:%s",
- resPtr->sequenceNum, maxAge, resourceType->resourcetypename);
- }
- else
- {
- sprintf((char *)bufRes, "%u:%u", resPtr->sequenceNum, maxAge);
+ // we create the payload here
+ if(resourceType && resourceType->resourcetypename)
+ {
+ sprintf((char *)presenceResBuf, "%u:%u:%s",
+ resPtr->sequenceNum, maxAge, resourceType->resourcetypename);
+ }
+ else
+ {
+ sprintf((char *)presenceResBuf, "%u:%u", resPtr->sequenceNum, maxAge);
+ }
+ ehResponse.ehResult = OC_EH_OK;
+ ehResponse.payload = presenceResBuf;
+ ehResponse.payloadSize = strlen((const char *)presenceResBuf) + 1;
+ ehResponse.persistentBufferFlag = 0;
+ ehResponse.requestHandle = (OCRequestHandle) request;
+ ehResponse.resourceHandle = (OCResourceHandle) resPtr;
+ strcpy((char *)ehResponse.resourceUri, (const char *)resourceObserver->resUri);
+ result = OCDoResponse(&ehResponse);
}
-
- jsonPayload = bufRes;
- ehRet = OC_EH_OK;
}
-
#endif
- if (OC_EH_OK == ehRet)
+ }
+ resourceObserver = resourceObserver->next;
+ }
+ if (numObs == 0)
+ {
+ OC_LOG(INFO, TAG, PCF("Resource has no observers"));
+ result = OC_STACK_NO_OBSERVERS;
+ }
+ return result;
+}
+
+OCStackResult SendListObserverNotification (OCResource * resource,
+ OCObservationId *obsIdList, uint8_t numberOfIds,
+ unsigned char *notificationJSONPayload, uint32_t maxAge,
+ OCQualityOfService qos)
+{
+ uint8_t numIds = numberOfIds;
+ ResourceObserver *observation = NULL;
+ uint8_t numSentNotification = 0;
+ OCServerRequest * request = NULL;
+ OCStackResult result = OC_STACK_ERROR;
+ OCEntityHandlerResponse ehResponse = {0};
+
+ OC_LOG(INFO, TAG, PCF("Entering SendListObserverNotification"));
+ while(numIds)
+ {
+ OC_LOG_V(INFO, TAG, "Need to notify observation id %d", *obsIdList);
+ observation = NULL;
+ observation = GetObserverUsingId (*obsIdList);
+ if(observation)
+ {
+ // Found observation - verify if it matches the resource handle
+ if (observation->resource == resource)
{
- stackRet = OC_STACK_OK;
- OC_LOG_V(INFO, TAG, "OCStack payload: %s",
- jsonPayload);
-
- // send notifications based on the qos of the request
- // The qos passed as a parameter overrides what the client requested
- // If we want the client preference taking high priority add:
- // qos = resourceObserver->qos;
- if(qos == OC_NA_QOS){
- qos = resourceObserver->qos;
- }
- if(qos != OC_HIGH_QOS)
+ qos = DetermineObserverQoS(OC_REST_GET, observation, qos);
+
+ result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET,
+ 0, resource->sequenceNum, qos, observation->query,
+ NULL, NULL, &observation->token,
+ observation->addr, observation->resUri, 0);
+ request->observeResult = OC_STACK_OK;
+ if(request && result == OC_STACK_OK)
{
- OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
- resourceObserver->lowQosCount);
- #ifdef WITH_PRESENCE
- if((resourceObserver->forceHighQos \
- || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT) \
- && method != OC_REST_PRESENCE)
- #else
- if(resourceObserver->forceCON \
- || resourceObserver->NONCount >= MAX_OBSERVER_NON_COUNT)
- #endif
+ memset(&ehResponse, 0, sizeof(OCEntityHandlerResponse));
+ ehResponse.ehResult = OC_EH_OK;
+ ehResponse.payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
+ if(!ehResponse.payload)
{
- resourceObserver->lowQosCount = 0;
- // at some point we have to to send CON to check on the
- // availability of observer
- OC_LOG(INFO, TAG, PCF("This time we are sending the \
- notification as High qos"));
- qos = OC_HIGH_QOS;
+ FindAndDeleteServerRequest(request);
+ continue;
}
- else
+ strcpy((char *)ehResponse.payload, (const char *)notificationJSONPayload);
+ ehResponse.payloadSize = strlen((const char *)ehResponse.payload) + 1;
+ ehResponse.persistentBufferFlag = 0;
+ ehResponse.requestHandle = (OCRequestHandle) request;
+ ehResponse.resourceHandle = (OCResourceHandle) resource;
+ result = OCDoResponse(&ehResponse);
+ if(result == OC_STACK_OK)
{
- resourceObserver->lowQosCount++;
+ OCFree(ehResponse.payload);
+ FindAndDeleteServerRequest(request);
}
}
- stackRet = OCSendCoAPNotification(resourceObserver->resUri, resourceObserver->addr,
- qos, &(resourceObserver->token), jsonPayload, resPtr, maxAge);
- }
- else
- {
- stackRet = OC_STACK_ERROR;
+ else
+ {
+ FindAndDeleteServerRequest(request);
+ }
+
+ numSentNotification++;
}
}
- resourceObserver = resourceObserver->next;
+ obsIdList++;
+ numIds--;
}
- if (numObs == 0)
+ if(numSentNotification == numberOfIds)
{
- OC_LOG(INFO, TAG, PCF("Resource has no observers"));
- stackRet = OC_STACK_NO_OBSERVERS;
+ return OC_STACK_OK;
+ }
+ else if(numSentNotification == 0)
+ {
+ return OC_STACK_NO_OBSERVERS;
+ }
+ else
+ {
+ //TODO: we need to signal that not every one in the
+ // list got an update, should we also indicate who did not receive on?
+ return OC_STACK_OK;
}
- return stackRet;
}
OCStackResult GenerateObserverId (OCObservationId *observationId)
{
- OC_LOG(INFO, TAG, PCF("Entering GenerateObserverId"));
+ ResourceObserver *resObs = NULL;
+ OC_LOG(INFO, TAG, PCF("Entering GenerateObserverId"));
VERIFY_NON_NULL (observationId);
- *observationId = OCGetRandomByte();
- return OC_STACK_OK;
+ do
+ {
+ *observationId = OCGetRandomByte();
+ // Check if observation Id already exists
+ resObs = GetObserverUsingId (*observationId);
+ } while (NULL != resObs);
+
+ OC_LOG_V(INFO, TAG, "Observation ID is %u", *observationId);
+
+ return OC_STACK_OK;
exit:
return OC_STACK_ERROR;
}
{
ResourceObserver *obsNode = NULL;
- obsNode = (ResourceObserver *) OCMalloc(sizeof(ResourceObserver));
+ obsNode = (ResourceObserver *) OCCalloc(1, sizeof(ResourceObserver));
if (obsNode)
{
- memset(obsNode, 0, sizeof(ResourceObserver));
obsNode->observeId = obsId;
obsNode->resUri = (unsigned char *)OCMalloc(strlen(resUri)+1);
}
obsNode->token.tokenLength = token->tokenLength;
- memcpy (&(obsNode->token.token), token->token, token->tokenLength);
+ memcpy (obsNode->token.token, token->token, token->tokenLength);
obsNode->addr = (OCDevAddr *)OCMalloc(sizeof(OCDevAddr));
VERIFY_NON_NULL (obsNode->addr);
#include "ocstack.h"
#include "ocstackconfig.h"
#include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "ocobserve.h"
#include "occollection.h"
#include "occoap.h"
/// Module Name
#define TAG PCF("ocresource")
+#define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
+ {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
+
#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
TAG, PCF(#arg " is NULL")); return (retVal); } }
}
}
jsonStr = cJSON_PrintUnformatted (resObj);
+
jsonLen = strlen(jsonStr);
if (jsonLen < *remaining)
{
cJSON_Delete (resObj);
free (jsonStr);
-
OC_LOG(INFO, TAG, PCF("Exiting BuildVirtualResourceResponse"));
return ret;
}
-OCEntityHandlerResult
-BuildObsJSONResponse(OCResource *resource, OCEntityHandlerRequest *ehRequest)
-{
- OCEntityHandlerResult ret = OC_EH_ERROR;
- unsigned char* saveJSONPayLoadPtr = ehRequest->resJSONPayload;
-
- if (ehRequest->resJSONPayloadLen > OC_JSON_PREFIX_LEN)
- {
- strcpy((char*)ehRequest->resJSONPayload, OC_JSON_PREFIX);
- ehRequest->resJSONPayloadLen -= OC_JSON_PREFIX_LEN;
- ehRequest->resJSONPayload += OC_JSON_PREFIX_LEN;
- }
-
- ret = resource->entityHandler(OC_REQUEST_FLAG, ehRequest);
-
- ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen -
- strlen((char*)ehRequest->resJSONPayload);
- ehRequest->resJSONPayload += strlen((char*)ehRequest->resJSONPayload);
-
- if (ehRequest->resJSONPayloadLen > OC_JSON_SUFFIX_LEN)
- {
- strcpy((char*)ehRequest->resJSONPayload, OC_JSON_SUFFIX);
- }
- ehRequest->resJSONPayload = saveJSONPayLoadPtr;
- return ret;
-}
-
-
TODO ("Does it make sense to make this method as inline")
const char * GetVirtualResourceUri( OCVirtualResources resource)
{
}
-OCStackResult DetermineResourceHandling (OCRequest *request,
+OCStackResult DetermineResourceHandling (OCServerRequest *request,
ResourceHandling *handling,
OCResource **resource)
{
// Resource does not exist
// and default device handler does not exist
+ *handling = OC_RESOURCE_NOT_SPECIFIED;
return OC_STACK_NO_RESOURCE;
}
// secure resource will entertain only authorized requests
- if ((resourcePtr->resourceProperties & OC_SECURE) && (request->secure == 0))
+ if ((resourcePtr->resourceProperties & OC_SECURE) && (request->secured == 0))
{
OC_LOG(INFO, TAG, PCF("Un-authorized request. Ignore it!"));
return OC_STACK_RESOURCE_ERROR;
case OC_EH_OK:
result = OC_STACK_OK;
break;
+ case OC_EH_SLOW:
+ result = OC_STACK_SLOW_RESOURCE;
+ break;
case OC_EH_ERROR:
result = OC_STACK_ERROR;
break;
result = OC_STACK_RESOURCE_CREATED;
break;
case OC_EH_RESOURCE_DELETED:
- result = OC_STACK_NO_RESOURCE;
+ result = OC_STACK_RESOURCE_DELETED;
break;
default:
result = OC_STACK_ERROR;
}
static OCStackResult
-HandleVirtualResource (OCRequest *request, OCResource* resource)
+HandleVirtualResource (OCServerRequest *request, OCResource* resource)
{
OCStackResult result = OC_STACK_ERROR;
char *filterValue = NULL;
uint8_t filterOn = 0;
uint16_t remaining = 0;
- unsigned char *buffer = NULL;
+ unsigned char * ptr = NULL;
+ uint8_t firstLoopDone = 0;
+ unsigned char discoveryResBuf[MAX_RESPONSE_LENGTH] = {0};
OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource"));
result = ValidateUrlQuery (request->resourceUrl,
- request->entityHandlerRequest->query, &filterOn,
+ request->query, &filterOn,
&filterValue);
if (result == OC_STACK_OK)
{
if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0)
{
- remaining = request->entityHandlerRequest->resJSONPayloadLen;
- buffer = request->entityHandlerRequest->resJSONPayload;
+ ptr = discoveryResBuf;
+ remaining = MAX_RESPONSE_LENGTH;
+
while(resource)
{
if((resource->resourceProperties & OC_ACTIVE)
{
// if there is data on the buffer, we have already added a response,
// so we need to add a comma before we do anything
- if(buffer != request->entityHandlerRequest->resJSONPayload
- && remaining >= (sizeof(OC_JSON_SEPARATOR)+1))
+ if(firstLoopDone
+ && remaining >= (sizeof(OC_JSON_SEPARATOR)+1))
{
- *buffer = OC_JSON_SEPARATOR;
- buffer++;
+ *ptr = OC_JSON_SEPARATOR;
+ ptr++;
remaining--;
}
-
+ firstLoopDone = 1;
result = BuildVirtualResourceResponse(resource, filterOn, filterValue,
- (char*)buffer, &remaining);
+ (char*)ptr, &remaining);
+
if (result != OC_STACK_OK)
{
// if this failed, we need to remove the comma added above.
- if(buffer != request->entityHandlerRequest->resJSONPayload)
+ if(!firstLoopDone)
{
- buffer--;
- *buffer = '\0';
+ ptr--;
+ *ptr = '\0';
remaining++;
}
-
break;
}
- buffer += strlen((char*)buffer);
+ ptr += strlen((char *)ptr);
+ *(ptr + 1) = '\0';
}
resource = resource->next;
}
+
+ if(strlen((const char *)discoveryResBuf) > 0)
+ {
+ OCEntityHandlerResponse response = {0};
+
+ response.ehResult = OC_EH_OK;
+ response.payload = discoveryResBuf;
+ response.payloadSize = strlen((const char *)discoveryResBuf) + 1;
+ response.persistentBufferFlag = 0;
+ response.requestHandle = (OCRequestHandle) request;
+ response.resourceHandle = (OCResourceHandle) resource;
+
+ result = OCDoResponse(&response);
+ }
}
#ifdef WITH_PRESENCE
else
{
if(resource->resourceProperties & OC_ACTIVE){
- SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(NULL);
}
- result = OC_STACK_PRESENCE_DO_NOT_HANDLE;
}
#endif
}
-
- if (result == OC_STACK_OK)
- {
- request->entityHandlerRequest->resJSONPayloadLen = remaining;
- request->entityHandlerRequest->resJSONPayload = buffer;
- }
-
+ result = OC_STACK_VIRTUAL_DO_NOT_HANDLE;
return result;
}
static OCStackResult
-HandleDefaultDeviceEntityHandler (OCRequest *request)
+HandleDefaultDeviceEntityHandler (OCServerRequest *request)
{
OCStackResult result = OC_STACK_OK;
- OCEntityHandlerResult ehResult;
- OCEntityHandlerRequest *ehRequest = request->entityHandlerRequest;
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+ OCEntityHandlerRequest ehRequest = {0};
+
+ OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
+ result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
+ request->method, (OCResourceHandle) NULL, request->query,
+ request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+ request->rcvdVendorSpecificHeaderOptions, (OCObserveAction)request->observationOption, (OCObservationId)0);
+ VERIFY_SUCCESS(result, OC_STACK_OK);
// At this point we know for sure that defaultDeviceHandler exists
- ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, ehRequest,
+ ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
(char*) request->resourceUrl);
-
+ if(ehResult == OC_EH_SLOW)
+ {
+ OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+ request->slowFlag = 1;
+ }
+ else if(ehResult == OC_EH_ERROR)
+ {
+ FindAndDeleteServerRequest(request);
+ }
result = EntityHandlerCodeToOCStackCode(ehResult);
-
- ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen -
- strlen((char*)ehRequest->resJSONPayload);
- ehRequest->resJSONPayload += strlen((char*)ehRequest->resJSONPayload);
-
+exit:
return result;
}
static OCStackResult
-HandleResourceWithEntityHandler (OCRequest *request,
+HandleResourceWithEntityHandler (OCServerRequest *request,
OCResource *resource,
uint8_t collectionResource)
{
- OCStackResult result = OC_STACK_OK;
- OCEntityHandlerResult ehResult = OC_EH_OK;
+ OCStackResult result = OC_STACK_ERROR;
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+ OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
+ ResourceObserver *resObs = NULL;
- OCEntityHandlerRequest *ehRequest = request->entityHandlerRequest;
+ OCEntityHandlerRequest ehRequest = {0};
OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler"));
-
- ehRequest->resource = (OCResourceHandle)resource;
-
- // status code from entity handler is ignored unless observe call
- if (request->observe == NULL)
+ result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
+ request->method, (OCResourceHandle) resource, request->query,
+ request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+ request->rcvdVendorSpecificHeaderOptions,
+ (OCObserveAction)request->observationOption, 0);
+ VERIFY_SUCCESS(result, OC_STACK_OK);
+
+ if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
{
- ehResult = resource->entityHandler(OC_REQUEST_FLAG, ehRequest);
- result = EntityHandlerCodeToOCStackCode(ehResult);
+ OC_LOG(INFO, TAG, PCF("No observation requested"));
+ ehFlag = OC_REQUEST_FLAG;
}
- else
+ else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER &&
+ !collectionResource)
{
- // If an observation register/deregister is included handle separately
- if (!collectionResource)
+ OC_LOG(INFO, TAG, PCF("Registering observation requested"));
+ result = GenerateObserverId(&ehRequest.obsInfo.obsId);
+ VERIFY_SUCCESS(result, OC_STACK_OK);
+
+ result = AddObserver ((const char*)(request->resourceUrl),
+ (const char *)(request->query),
+ ehRequest.obsInfo.obsId, &request->requestToken,
+ &request->requesterAddr, resource, request->qos);
+ if(result == OC_STACK_OK)
{
- result = ProcessObserveRequest (resource, request);
+ OC_LOG(DEBUG, TAG, PCF("Added observer successfully"));
+ request->observeResult = OC_STACK_OK;
+ ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
}
else
{
- // Observation on collection resources not currently supported
- result = OC_STACK_ERROR;
+ result = OC_STACK_OK;
+ request->observeResult = OC_STACK_ERROR;
+ OC_LOG(DEBUG, TAG, PCF("Observer Addition failed"));
+ ehFlag = OC_REQUEST_FLAG;
}
+
}
+ else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
+ !collectionResource)
+ {
+ OC_LOG(INFO, TAG, PCF("Deregistering observation requested"));
+ resObs = GetObserverUsingToken (&request->requestToken);
+ if (NULL == resObs)
+ {
+ // Stack does not contain this observation request
+ // Either token is incorrect or observation list is corrupted
+ result = OC_STACK_ERROR;
+ goto exit;
+ }
+ ehRequest.obsInfo.obsId = resObs->observeId;
+ ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
- if (result == OC_STACK_OK || OC_STACK_RESOURCE_CREATED)
+ result = DeleteObserverUsingToken (&request->requestToken);
+ if(result == OC_STACK_OK)
+ {
+ OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+ request->observeResult = OC_STACK_OK;
+ }
+ else
+ {
+ result = OC_STACK_OK;
+ request->observeResult = OC_STACK_ERROR;
+ OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
+ }
+ }
+ else
{
- ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen -
- strlen((char*)ehRequest->resJSONPayload);
- ehRequest->resJSONPayload += strlen((char*)ehRequest->resJSONPayload);
+ result = OC_STACK_ERROR;
+ goto exit;
}
+ ehResult = resource->entityHandler(ehFlag, &ehRequest);
+ if(ehResult == OC_EH_SLOW)
+ {
+ OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+ request->slowFlag = 1;
+ }
+ else if(ehResult == OC_EH_ERROR)
+ {
+ FindAndDeleteServerRequest(request);
+ }
+ result = EntityHandlerCodeToOCStackCode(ehResult);
+exit:
return result;
}
-
static OCStackResult
-HandleCollectionResourceDefaultEntityHandler (OCRequest *request,
+HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
OCResource *resource)
{
- request->entityHandlerRequest->resource = (OCResourceHandle)resource;
- return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, request->entityHandlerRequest));
-}
+ OCStackResult result = OC_STACK_ERROR;
+ OCEntityHandlerRequest ehRequest = {0};
+
+ result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
+ request->method, (OCResourceHandle) resource, request->query,
+ request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
+ request->rcvdVendorSpecificHeaderOptions,
+ (OCObserveAction)request->observationOption, (OCObservationId) 0);
+ if(result != OC_STACK_OK)
+ {
+ return result;
+ }
+ return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest));
+}
OCStackResult
-BuildJSONResponse(ResourceHandling resHandling, OCResource *resource, OCRequest *request)
+ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
{
OCStackResult ret = OC_STACK_OK;
- // save the response payload pointer, this pointer will be moved as
- // different entity handlers will be called
- unsigned char* saveJSONPayLoadPtr = request->entityHandlerRequest->resJSONPayload;
- unsigned char* buffer = saveJSONPayLoadPtr;
- uint16_t remaining = request->entityHandlerRequest->resJSONPayloadLen;
-
- // add suffix in payload
- if (remaining > OC_JSON_PREFIX_LEN)
- {
- strcpy((char*)buffer, OC_JSON_PREFIX);
- remaining -= OC_JSON_PREFIX_LEN;
- buffer += OC_JSON_PREFIX_LEN;
- }
-
- // move the entity handler payload pointer and update
- // remaining valid bytes to fill data
- request->entityHandlerRequest->resJSONPayload = buffer;
- request->entityHandlerRequest->resJSONPayloadLen = remaining;
-
switch (resHandling)
{
case OC_RESOURCE_VIRTUAL:
- {
- ret = HandleVirtualResource (request, resource);
- break;
- }
-
+ {
+ ret = HandleVirtualResource (request, resource);
+ break;
+ }
case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
- {
- ret = HandleDefaultDeviceEntityHandler(request);
- break;
- }
+ {
+ ret = HandleDefaultDeviceEntityHandler(request);
+ break;
+ }
case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
- {
- OC_LOG(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER"));
- return OC_STACK_ERROR;
- }
-
+ {
+ OC_LOG(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER"));
+ return OC_STACK_ERROR;
+ }
case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
- {
- ret = HandleResourceWithEntityHandler (request, resource, 0);
- break;
- }
+ {
+ ret = HandleResourceWithEntityHandler (request, resource, 0);
+ break;
+ }
case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
- {
- ret = HandleResourceWithEntityHandler (request, resource, 1);
- break;
- }
-
+ {
+ ret = HandleResourceWithEntityHandler (request, resource, 1);
+ break;
+ }
case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
- {
- ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
- break;
- }
-
+ {
+ ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
+ break;
+ }
+ case OC_RESOURCE_NOT_SPECIFIED:
+ {
+ ret = OC_STACK_NO_RESOURCE;
+ break;
+ }
default:
- {
- OC_LOG(INFO, TAG, PCF("Invalid Resource Determination"));
- return OC_STACK_ERROR;
- }
- }
-
- remaining = request->entityHandlerRequest->resJSONPayloadLen;
-
- if (remaining > OC_JSON_SUFFIX_LEN)
- {
- strcpy((char*)request->entityHandlerRequest->resJSONPayload, OC_JSON_SUFFIX);
+ {
+ OC_LOG(INFO, TAG, PCF("Invalid Resource Determination"));
+ return OC_STACK_ERROR;
+ }
}
-
- // update payload pointer with it's original location and original length
- request->entityHandlerRequest->resJSONPayload = saveJSONPayLoadPtr;
- request->entityHandlerRequest->resJSONPayloadLen = MAX_RESPONSE_LENGTH;
-
return ret;
}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 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 "ocmalloc.h"
+#include "ocsecurity.h"
+#include "ocsecurityconfig.h"
+#include <string.h>
+
+static OCDtlsPskCredsBlob* pskCredsBlob;
+static int pskCredsBlobLen;
+
+// Internal API. Invoked by OC stack to cleanup memory
+void DeinitOCSecurityInfo()
+{
+ if (pskCredsBlob)
+ {
+ // Initialize sensitive data to zeroes before freeing.
+ memset(pskCredsBlob, 0, pskCredsBlobLen);
+
+ OCFree(pskCredsBlob);
+ pskCredsBlob = NULL;
+ }
+}
+
+// Internal API. Invoked by OC stack to retrieve credentials from this module
+void OCGetDtlsPskCredentials(OCDtlsPskCredsBlob **credInfo)
+{
+ *credInfo = pskCredsBlob;
+}
+
+/**
+ * Provides the DTLS PSK credetials blob to OC stack.
+ *
+ * @param credInfo
+ * binary blob containing credentials
+ * @param len
+ * length of binary blob
+ *
+ * @retval OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult OCSetDtlsPskCredentials(const OCDtlsPskCredsBlob *credInfo,
+ size_t len)
+{
+ if(credInfo && len > 0)
+ {
+ if (credInfo->blobVer != DtlsPskCredsBlobVer_CurrentVersion)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // Remove existing blob
+ DeinitOCSecurityInfo();
+ // Allocate storage for new blob
+ pskCredsBlob = (OCDtlsPskCredsBlob*)OCMalloc(len);
+ if (pskCredsBlob)
+ {
+ memcpy(pskCredsBlob, credInfo, len);
+ pskCredsBlobLen = len;
+ return OC_STACK_OK;
+ }
+
+ return OC_STACK_NO_MEMORY;
+ }
+
+ return OC_STACK_INVALID_PARAM;
+}
+
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 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 "ocserverrequest.h"
+#include "ocresourcehandler.h"
+
+// Module Name
+#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
+
+#define TAG PCF("ocserverrequest")
+
+static struct OCServerRequest * serverRequestList = NULL;
+static struct OCServerResponse * serverResponseList = NULL;
+
+OCServerRequest * GetServerRequestUsingToken (const OCCoAPToken token)
+{
+ OCServerRequest * out = NULL;
+ LL_FOREACH (serverRequestList, out)
+ {
+ OC_LOG(INFO, TAG,PCF("comparing tokens"));
+ OC_LOG_BUFFER(INFO, TAG, token.token, token.tokenLength);
+ OC_LOG_BUFFER(INFO, TAG, out->requestToken.token, out->requestToken.tokenLength);
+ if((out->requestToken.tokenLength == token.tokenLength) &&
+ (memcmp(out->requestToken.token, token.token, token.tokenLength) == 0))
+ {
+ return out;
+ }
+ }
+ OC_LOG(INFO, TAG, PCF("Server Request not found!!"));
+ return NULL;
+}
+
+OCServerRequest * GetServerRequestUsingHandle (const OCServerRequest * handle)
+{
+ OCServerRequest * out = NULL;
+ LL_FOREACH (serverRequestList, out)
+ {
+ if(out == handle)
+ {
+ return out;
+ }
+ }
+ OC_LOG(INFO, TAG, PCF("Server Request not found!!"));
+ return NULL;
+}
+
+OCServerResponse * GetServerResponseUsingHandle (const OCServerRequest * handle)
+{
+ OCServerResponse * out = NULL;
+ LL_FOREACH (serverResponseList, out)
+ {
+ if(out->requestHandle == handle)
+ {
+ return out;
+ }
+ }
+ OC_LOG(INFO, TAG, PCF("Server Response not found!!"));
+ return NULL;
+}
+
+OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
+ uint8_t delayedResNeeded, uint8_t secured, uint8_t notificationFlag, OCMethod method,
+ uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption,
+ OCQualityOfService qos, unsigned char * query,
+ OCHeaderOption * rcvdVendorSpecificHeaderOptions,
+ unsigned char * reqJSONPayload, OCCoAPToken * requestToken,
+ OCDevAddr * requesterAddr, unsigned char * resourceUrl, uint32_t reqTotalSize)
+{
+ OCServerRequest * serverRequest = NULL;
+
+ serverRequest = (OCServerRequest *) OCCalloc(1, sizeof(OCServerRequest) + reqTotalSize - 1);
+ VERIFY_NON_NULL(serverRequest);
+
+ serverRequest->coapID = coapID;
+ serverRequest->delayedResNeeded = delayedResNeeded;
+ serverRequest->secured = secured;
+ serverRequest->notificationFlag = notificationFlag;
+
+ serverRequest->method = method;
+ serverRequest->numRcvdVendorSpecificHeaderOptions = numRcvdVendorSpecificHeaderOptions;
+ serverRequest->observationOption = observationOption;
+ serverRequest->observeResult = OC_STACK_ERROR;
+ serverRequest->qos = qos;
+ serverRequest->ehResponseHandler = HandleSingleResponse;
+ serverRequest->numResponses = 1;
+ if(query)
+ {
+ memcpy(serverRequest->query, query, strlen((const char *)query) + 1);
+ }
+ if(rcvdVendorSpecificHeaderOptions)
+ {
+ memcpy(serverRequest->rcvdVendorSpecificHeaderOptions, rcvdVendorSpecificHeaderOptions,
+ MAX_HEADER_OPTIONS * sizeof(OCHeaderOption));
+ }
+ if(reqJSONPayload)
+ {
+ memcpy((void *)serverRequest->reqJSONPayload, (void *)reqJSONPayload,
+ strlen((const char *)reqJSONPayload) + 1);
+ }
+ serverRequest->requestComplete = 0;
+ if(requestToken)
+ {
+ memcpy(&serverRequest->requestToken, requestToken, sizeof(OCCoAPToken));
+ }
+ if(requesterAddr)
+ {
+ memcpy(&serverRequest->requesterAddr, requesterAddr, sizeof(OCDevAddr));
+ }
+ if(resourceUrl)
+ {
+ memcpy(serverRequest->resourceUrl, resourceUrl, strlen((const char *)resourceUrl) + 1);
+ }
+ *request = serverRequest;
+ OC_LOG(INFO, TAG, PCF("Server Request Added!!"));
+ LL_APPEND (serverRequestList, serverRequest);
+ return OC_STACK_OK;
+
+exit:
+ if (serverRequest)
+ {
+ OCFree(serverRequest);
+ serverRequest = NULL;
+ }
+ *request = NULL;
+ return OC_STACK_NO_MEMORY;
+}
+
+OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle)
+{
+ OCServerResponse * serverResponse = NULL;
+
+ serverResponse = (OCServerResponse *) OCCalloc(1, sizeof(OCServerResponse));
+ VERIFY_NON_NULL(serverResponse);
+
+ serverResponse->payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
+ VERIFY_NON_NULL(serverResponse->payload);
+ memset(serverResponse->payload, 0, sizeof(MAX_RESPONSE_LENGTH));
+
+ serverResponse->remainingPayloadSize = MAX_RESPONSE_LENGTH;
+ serverResponse->requestHandle = requestHandle;
+
+ *response = serverResponse;
+ OC_LOG(INFO, TAG, PCF("Server Response Added!!"));
+ LL_APPEND (serverResponseList, serverResponse);
+ return OC_STACK_OK;
+
+exit:
+ if (serverResponse)
+ {
+ OCFree(serverResponse);
+ serverResponse = NULL;
+ }
+ *response = NULL;
+ return OC_STACK_NO_MEMORY;
+}
+
+// Form the OCEntityHandlerRequest struct
+OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest, OCRequestHandle request,
+ OCMethod method, OCResourceHandle resource, unsigned char * queryBuf, unsigned char * bufReqPayload,
+ uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction,
+ OCObservationId observeID)
+{
+ if (entityHandlerRequest)
+ {
+ memset(entityHandlerRequest, 0, sizeof(OCEntityHandlerRequest));
+ entityHandlerRequest->requestHandle = request;
+ entityHandlerRequest->method = method;
+ entityHandlerRequest->resource = (OCResourceHandle) resource;
+ entityHandlerRequest->query = queryBuf;
+ entityHandlerRequest->reqJSONPayload = bufReqPayload;
+ entityHandlerRequest->numRcvdVendorSpecificHeaderOptions = numVendorOptions;
+ entityHandlerRequest->rcvdVendorSpecificHeaderOptions = vendorOptions;
+
+ entityHandlerRequest->obsInfo.action = observeAction;
+ entityHandlerRequest->obsInfo.obsId = observeID;
+ return OC_STACK_OK;
+ }
+
+ return OC_STACK_INVALID_PARAM;
+}
+
+void FindAndDeleteServerResponse(OCServerResponse * serverResponse)
+{
+ OCServerResponse* tmp;
+ if(serverResponse)
+ {
+ LL_FOREACH(serverResponseList, tmp)
+ {
+ if (serverResponse == tmp)
+ {
+ DeleteServerResponse(tmp);
+ return;
+ }
+ }
+ }
+}
+
+void DeleteServerResponse(OCServerResponse * serverResponse)
+{
+ if(serverResponse) {
+ LL_DELETE(serverResponseList, serverResponse);
+ OCFree(serverResponse->payload);
+ OCFree(serverResponse);
+ OC_LOG(INFO, TAG, PCF("Server Response Removed!!"));
+ }
+}
+
+void FindAndDeleteServerRequest(OCServerRequest * serverRequest)
+{
+ OCServerRequest* tmp;
+ if(serverRequest)
+ {
+ LL_FOREACH(serverRequestList, tmp)
+ {
+ if (serverRequest == tmp)
+ {
+ DeleteServerRequest(tmp);
+ return;
+ }
+ }
+ }
+}
+
+void DeleteServerRequest(OCServerRequest * serverRequest)
+{
+ if(serverRequest) {
+ LL_DELETE(serverRequestList, serverRequest);
+ OCFree(serverRequest);
+ serverRequest = NULL;
+ OC_LOG(INFO, TAG, PCF("Server Request Removed!!"));
+ }
+}
+
+OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
+{
+ OCStackResult result = OC_STACK_ERROR;
+ OCServerProtocolResponse protocolResponse = {0};
+
+ OC_LOG_V(INFO, TAG, "Inside HandleSingleResponse: %s", ehResponse->payload);
+
+ OCServerRequest *serverRequest = (OCServerRequest *)ehResponse->requestHandle;
+ // Format protocol response structure with data needed for
+ // sending the response
+ protocolResponse.qos = serverRequest->qos;
+
+ if((OCResource *)ehResponse->resourceHandle &&
+ ((OCResource *)ehResponse->resourceHandle)->resourceProperties == (OCResourceProperty) 0)
+ {
+ ehResponse->ehResult = OC_EH_RESOURCE_DELETED;
+ }
+ protocolResponse.result = EntityHandlerCodeToOCStackCode(ehResponse->ehResult);
+ protocolResponse.requesterAddr = &serverRequest->requesterAddr;
+ protocolResponse.requestToken = &serverRequest->requestToken;
+ protocolResponse.numSendVendorSpecificHeaderOptions = ehResponse->numSendVendorSpecificHeaderOptions;
+ protocolResponse.sendVendorSpecificHeaderOptions = ehResponse->sendVendorSpecificHeaderOptions;
+ protocolResponse.resourceUri = ehResponse->resourceUri;
+ protocolResponse.delayedResNeeded = serverRequest->delayedResNeeded;
+ protocolResponse.secured = serverRequest->secured;
+ protocolResponse.slowFlag = serverRequest->slowFlag;
+ protocolResponse.notificationFlag = serverRequest->notificationFlag;
+
+ //should we put the prefix and suffix here?
+ protocolResponse.payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
+ if(!protocolResponse.payload)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+ strcpy((char *)protocolResponse.payload, (const char *)OC_JSON_PREFIX);
+ strcat((char *)protocolResponse.payload, (const char *)ehResponse->payload);
+ strcat((char *)protocolResponse.payload, (const char *)OC_JSON_SUFFIX);
+ protocolResponse.payloadSize = strlen((const char *)protocolResponse.payload) + 1;
+ protocolResponse.resourceUri = ehResponse->resourceUri;
+
+ //revise the following
+ protocolResponse.coapID = serverRequest->coapID;
+ if(serverRequest->observeResult == OC_STACK_OK)
+ {
+ protocolResponse.observationOption = serverRequest->observationOption;
+ }
+ else
+ {
+ protocolResponse.observationOption = OC_OBSERVE_NO_OPTION;
+ }
+ // Make call to OCCoAP layer
+ result = OCDoCoAPResponse(&protocolResponse);
+
+ OCFree(protocolResponse.payload);
+ //Delete the request
+ FindAndDeleteServerRequest(serverRequest);
+ return result;
+}
+
+OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
+{
+ OCStackResult stackRet = OC_STACK_ERROR;
+ OCServerRequest * serverRequest = NULL;
+ OCServerResponse * serverResponse = NULL;
+
+ OC_LOG_V(INFO, TAG, "Inside HandleAggregateResponse: %s", ehResponse->payload);
+
+ serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+ serverResponse = GetServerResponseUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+
+ if(serverRequest)
+ {
+ if(!serverResponse)
+ {
+ OC_LOG(INFO, TAG, PCF("This is the first response fragment"));
+ stackRet = AddServerResponse(&serverResponse, ehResponse->requestHandle);
+ if (OC_STACK_OK != stackRet)
+ {
+ OC_LOG(ERROR, TAG, PCF("Error adding server response"));
+ return stackRet;
+ }
+ VERIFY_NON_NULL(serverResponse);
+ VERIFY_NON_NULL(serverResponse->payload);
+ }
+
+ if((serverResponse->remainingPayloadSize >= ehResponse->payloadSize + 1 &&
+ serverRequest->numResponses == 1) ||
+ (serverResponse->remainingPayloadSize >= ehResponse->payloadSize + 2 &&
+ serverRequest->numResponses > 1))
+ {
+ OC_LOG(INFO, TAG, PCF("There is room in response buffer"));
+ // append
+ sprintf((char *)serverResponse->payload, "%s%s", (char *)serverResponse->payload, (char *)ehResponse->payload);
+ OC_LOG_V(INFO, TAG, "Current aggregated response ...%s", serverResponse->payload);
+ serverResponse->remainingPayloadSize -= ehResponse->payloadSize;
+ (serverRequest->numResponses)--;
+ if(serverRequest->numResponses == 0)
+ {
+ OC_LOG(INFO, TAG, PCF("This is the last response fragment"));
+ ehResponse->payload = serverResponse->payload;
+ ehResponse->payloadSize = strlen((char *) serverResponse->payload) + 1;
+ stackRet = HandleSingleResponse(ehResponse);
+ //Delete the request and response
+ FindAndDeleteServerRequest(serverRequest);
+ FindAndDeleteServerResponse(serverResponse);
+ }
+ else
+ {
+ OC_LOG(INFO, TAG, PCF("More response fragment to come"));
+ // TODO: we should consider using strcat rather than setting a char by char here!
+ sprintf((char *)serverResponse->payload, "%s%c", (char *)serverResponse->payload,OC_JSON_SEPARATOR);
+ OC_LOG_V(INFO, TAG, "Current aggregated response ...%s", serverResponse->payload);
+ (serverResponse->remainingPayloadSize)--;
+ stackRet = OC_STACK_OK;
+ }
+ }
+ else
+ {
+ OC_LOG(INFO, TAG, PCF("No room in response buffer"));
+ //Delete the request and response
+ FindAndDeleteServerRequest(serverRequest);
+ FindAndDeleteServerResponse(serverResponse);
+ stackRet = OC_STACK_NO_MEMORY;
+ }
+ }
+exit:
+ return stackRet;
+}
//-----------------------------------------------------------------------------
#include "ocstack.h"
#include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "occlientcb.h"
#include "ocobserve.h"
#include "ocrandom.h"
#include "debug.h"
#include "occoap.h"
#include "ocmalloc.h"
+#include "ocserverrequest.h"
//-----------------------------------------------------------------------------
// Typedefs
//-----------------------------------------------------------------------------
typedef enum {
- OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED
+ OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED, OC_STACK_UNINIT_IN_PROGRESS
} OCStackState;
#ifdef WITH_PRESENCE
#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
TAG, PCF(#arg " is NULL")); return (retVal); } }
+//TODO: we should allow the server to define this
+#define MAX_OBSERVE_AGE (0x2FFFFUL)
+//-----------------------------------------------------------------------------
+// Externs
+//-----------------------------------------------------------------------------
+extern void DeinitOCSecurityInfo();
+
//-----------------------------------------------------------------------------
// Internal API function
//-----------------------------------------------------------------------------
+// This internal function is called to update the stack with the status of
+// observers and communication failures
+OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
+{
+ OCStackResult result = OC_STACK_ERROR;
+ ResourceObserver * observer = NULL;
+ OCEntityHandlerRequest ehRequest = {0};
+
+ switch(status)
+ {
+ case OC_OBSERVER_NOT_INTERESTED:
+ OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
+ observer = GetObserverUsingToken (token);
+ if(observer)
+ {
+ result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
+ OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
+ NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
+ if(result != OC_STACK_OK)
+ {
+ return result;
+ }
+ observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
+ }
+ //observer is not observing anymore
+ result = DeleteObserverUsingToken (token);
+ if(result == OC_STACK_OK)
+ {
+ OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+ }
+ else
+ {
+ result = OC_STACK_OK;
+ OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
+ }
+ break;
+ case OC_OBSERVER_STILL_INTERESTED:
+ //observer is still interested
+ OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
+ notifications, reset the failedCount"));
+ observer = GetObserverUsingToken(token);
+ if(observer)
+ {
+ observer->forceHighQos = 0;
+ observer->failedCommCount = 0;
+ result = OC_STACK_OK;
+ }
+ else
+ {
+ result = OC_STACK_OBSERVER_NOT_FOUND;
+ }
+ break;
+ case OC_OBSERVER_FAILED_COMM:
+ //observer is not reachable
+ OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
+ observer = GetObserverUsingToken(token);
+ if(observer)
+ {
+ if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
+ {
+ result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
+ OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
+ NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
+ if(result != OC_STACK_OK)
+ {
+ return OC_STACK_ERROR;
+ }
+ observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
+ //observer is unreachable
+ result = DeleteObserverUsingToken (token);
+ if(result == OC_STACK_OK)
+ {
+ OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+ }
+ else
+ {
+ result = OC_STACK_OK;
+ OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
+ }
+ }
+ else
+ {
+ observer->failedCommCount++;
+ result = OC_STACK_CONTINUE;
+ }
+ observer->forceHighQos = 1;
+ OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
+ }
+ break;
+ default:
+ OC_LOG(ERROR, TAG, PCF("Unknown status"));
+ result = OC_STACK_ERROR;
+ break;
+ }
+ return result;
+}
+
//This function will be called back by occoap layer when a request is received
-OCStackResult HandleStackRequests(OCRequest * request)
+OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
{
OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
ResourceHandling resHandling;
OCResource *resource;
- VERIFY_NON_NULL(request, ERROR, OC_STACK_ERROR);
- VERIFY_NON_NULL(request->entityHandlerRequest, ERROR, OC_STACK_ERROR);
-
- result = DetermineResourceHandling (request, &resHandling, &resource);
+ OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
+ if(!request)
+ {
+ OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
+ result = AddServerRequest(&request, protocolRequest->coapID,
+ protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
+ protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
+ protocolRequest->observationOption, protocolRequest->qos,
+ protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
+ protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
+ &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
+ protocolRequest->reqTotalSize);
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG(ERROR, TAG, PCF("Error adding server request"));
+ return result;
+ }
+ VERIFY_NON_NULL(request, ERROR, OC_STACK_NO_MEMORY);
- if (result == OC_STACK_OK)
+ if(!protocolRequest->reqMorePacket)
+ {
+ request->requestComplete = 1;
+ }
+ }
+ else
{
- result = BuildJSONResponse(resHandling, resource, request);
+ OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request"));
}
+ if(request->requestComplete)
+ {
+ OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
+ result = DetermineResourceHandling (request, &resHandling, &resource);
+ if (result == OC_STACK_OK)
+ {
+ result = ProcessRequest(resHandling, resource, request);
+ }
+ else
+ {
+ result = OC_STACK_ERROR;
+ }
+ }
+ else
+ {
+ OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
+ result = OC_STACK_CONTINUE;
+ }
return result;
}
static void incrementSequenceNumber(OCResource * resPtr);
static OCStackResult verifyUriQueryLength(const char * inputUri,
uint16_t uriLen);
+static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI);
-
//-----------------------------------------------------------------------------
// Public APIs
//-----------------------------------------------------------------------------
OC_LOG(INFO, TAG, PCF("Entering OCStop"));
- if (stackState != OC_STACK_INITIALIZED)
+ if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
+ {
+ OC_LOG(DEBUG, TAG, PCF("Stack already stopping, exiting"));
+ return OC_STACK_OK;
+ }
+ else if (stackState != OC_STACK_INITIALIZED)
{
OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
return OC_STACK_ERROR;
}
+ stackState = OC_STACK_UNINIT_IN_PROGRESS;
+
+ #ifdef WITH_PRESENCE
+ // Ensure that the TTL associated with ANY and ALL presence notifications originating from
+ // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
+ presenceResource.presenceTTL = 0;
+ #endif // WITH_PRESENCE
+
// Free memory dynamically allocated for resources
deleteAllResources();
stackState = OC_STACK_UNINITIALIZED;
result = OC_STACK_OK;
} else {
+ stackState = OC_STACK_INITIALIZED;
result = OC_STACK_ERROR;
}
+ // Deinit security blob
+ DeinitOCSecurityInfo();
+
if (result != OC_STACK_OK) {
OC_LOG(ERROR, TAG, PCF("Stack stop error"));
}
ClientCB *clientCB = NULL;
unsigned char * requestUri = NULL;
unsigned char * resourceType = NULL;
- char * newURI = (char *)requiredUri;
+ char * newUri = (char *)requiredUri;
(void) referenceUri;
OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
#ifdef WITH_PRESENCE
if(method == OC_REST_PRESENCE)
{
- result = getResourceType(requiredUri, &resourceType, &newURI);
+ result = getResourceType(requiredUri, &resourceType, &newUri);
+ if(resourceType) {
+ OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
+ }
+ else
+ {
+ OC_LOG(DEBUG, TAG, "Got Resource Type is NULL.");
+ }
if(result != OC_STACK_OK)
{
goto exit;
requestUri = (unsigned char *) OCMalloc(uriLen + 1);
if(requestUri)
{
- memcpy(requestUri, newURI, (uriLen + 1));
+ memcpy(requestUri, newUri, (uriLen + 1));
}
else
{
// with the request
OCGenerateCoAPToken(&token);
- if((result = AddClientCB(&clientCB, cbData, &token, *handle, method, requestUri, resourceType))
+ if((result = AddClientCB(&clientCB, cbData, &token, handle, method, requestUri, resourceType))
!= OC_STACK_OK)
{
result = OC_STACK_NO_MEMORY;
}
// Make call to OCCoAP layer
- result = OCDoCoAPResource(method, qos, &token, newURI, request, options, numOptions);
+ result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
exit:
- if(newURI != requiredUri)
+ if(newUri != requiredUri)
{
- OCFree(newURI);
+ OCFree(newUri);
}
if (result != OC_STACK_OK)
{
// a different random 32-bit integer number is used
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- return SendPresenceNotification(NULL, OC_LOW_QOS);
+ return SendPresenceNotification(NULL);
}
/**
result = OCChangeResourceProperty(
&(((OCResource *) presenceResource.handle)->resourceProperties),
OC_ACTIVE, 0);
- result = SendPresenceNotification(NULL, OC_LOW_QOS);
+ result = SendPresenceNotification(NULL);
return result;
}
}
}
// Create the pointer and insert it into the resource list
- pointer = (OCResource *) OCMalloc(sizeof(OCResource));
+ pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
if (!pointer) {
goto exit;
}
- memset(pointer, 0, sizeof(OCResource));
pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
insertResource(pointer);
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(pointer->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(pointer->rsrcType);
}
#endif
exit:
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
}
#endif
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
}
#endif
TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
// Create the resourcetype and insert it into the resource list
- pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
+ pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
if (!pointer) {
goto exit;
}
- memset(pointer, 0, sizeof(OCResourceType));
// Set the resourceTypeName
size = strlen(resourceTypeName) + 1;
TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
// Create the resourceinterface and insert it into the resource list
- pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
+ pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
if (!pointer) {
goto exit;
}
- memset(pointer, 0, sizeof(OCResourceInterface));
// Set the resourceinterface name
size = strlen(resourceInterfaceName) + 1;
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(resource->rsrcType);
}
#endif
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(resource->rsrcType);
}
#endif
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+ SendPresenceNotification(resource->rsrcType);
}
#endif
return;
}
+#ifdef WITH_PRESENCE
/**
* Notify Presence subscribers that a resource has been modified
*
* @param qos - Quality Of Service
*
*/
-OCStackResult SendPresenceNotification(OCResourceType *resourceType, OCQualityOfService qos)
+OCStackResult SendPresenceNotification(OCResourceType *resourceType)
{
OCResource *resPtr = NULL;
OCStackResult result;
maxAge = 0;
}
- result = SendObserverNotification(method, resPtr, maxAge, resourceType, qos);
-
+ result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
return result;
}
+#endif
/**
* Notify observers that an observed value has changed.
* OC_STACK_NO_OBSERVERS - no more observers intrested in resource
*/
OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
+
+ OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
+
OCResource *resPtr = NULL;
OCStackResult result;
OCMethod method = OC_REST_NOMETHOD;
uint32_t maxAge = 0;
OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
-
+ #ifdef WITH_PRESENCE
+ if(handle == presenceResource.handle)
+ {
+ return OC_STACK_OK;
+ }
+ #endif // WITH_PRESENCE
VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
// Verify that the resource exists
//only increment in the case of regular observing (not presence)
incrementSequenceNumber(resPtr);
method = OC_REST_OBSERVE;
- maxAge = 0x2FFFF;
- result = SendObserverNotification (method, resPtr, maxAge, NULL, qos);
+ maxAge = MAX_OBSERVE_AGE;
+ #ifdef WITH_PRESENCE
+ result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos);
+ #else
+ result = SendAllObserverNotification (method, resPtr, maxAge, qos);
+ #endif
return result;
}
}
{
OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
+ OCResource *resPtr = NULL;
+ //TODO: we should allow the server to define this
+ uint32_t maxAge = MAX_OBSERVE_AGE;
+
VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
- uint8_t numIds = numberOfIds;
- ResourceObserver *observation;
- OCResource *resPtr = NULL;
- uint32_t maxAge = 0;
- unsigned char bufNotify[MAX_RESPONSE_LENGTH] = {0};
- unsigned char *currPtr;
- uint8_t numSentNotification = 0;
-
- // Verify the notification payload length does not exceed the maximim
- // the stack can handle
- if ((strlen((char *)notificationJSONPayload) +
- OC_JSON_PREFIX_LEN + OC_JSON_SUFFIX_LEN) > MAX_RESPONSE_LENGTH)
- {
- OC_LOG(INFO, TAG, PCF("Observe notification message length too long"));
- return OC_STACK_ERROR;
- }
-
// Verify that the resource exists
resPtr = findResource ((OCResource *) handle);
if (NULL == resPtr || myStackMode == OC_CLIENT)
else
{
incrementSequenceNumber(resPtr);
- //TODO: we should allow the serve to define thisl
- maxAge = 0x2FFFF;
}
+ return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
+ notificationJSONPayload, maxAge, qos));
+}
- while (numIds)
+/**
+ * Send a response to a request.
+ * The response can be a regular, slow, or block (i.e. a response that
+ * is too large to be sent in a single PDU and must span multiple transmissions)
+ *
+ * @param response - pointer to structure that contains response parameters
+ *
+ * @return
+ * OC_STACK_OK - No errors; Success
+ * OC_STACK_INVALID_PARAM - Invalid pointer to OCServerResponse
+ * OC_STACK_INVALID_REQUEST_HANDLE - Request handle not found
+ * OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a
+ * persistent response buffer is necessary
+ */
+OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
+{
+ OCStackResult result = OC_STACK_ERROR;
+ OCServerRequest *serverRequest = NULL;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
+
+ // Validate input parameters
+ VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
+
+ // TODO: Placeholder for creating a response entry when implementing
+ // block transfer feature
+
+ // If a response payload is present, check if block transfer is required
+ if (ehResponse->payload && OCIsPacketTransferRequired(NULL,
+ (const char *)ehResponse->payload, ehResponse->payloadSize))
{
- OC_LOG_V(INFO, TAG, "Need to notify observation id %d", *obsIdList);
- observation = NULL;
- observation = GetObserverUsingId (*obsIdList);
- if (observation)
+ OC_LOG(INFO, TAG, PCF("Block transfer required"));
+
+ // Persistent response buffer is needed for block transfer
+ if (!ehResponse->persistentBufferFlag)
{
- // Found observation - verify if it matches the resource handle
- if (observation->resource == resPtr)
- {
- strcpy((char*)bufNotify, OC_JSON_PREFIX);
- currPtr = bufNotify + OC_JSON_PREFIX_LEN;
- memcpy (currPtr, notificationJSONPayload, strlen((char *)notificationJSONPayload));
- currPtr += strlen((char *)notificationJSONPayload);
- strcpy((char*)currPtr, OC_JSON_SUFFIX);
-
- // send notifications based on the qos of the request
- // The qos passed as a parameter overrides what the client requested
- // If we want the client preference taking high priority add:
- // QoS = resourceObserver->qos;
- if(qos == OC_NA_QOS){
- qos = observation->qos;
- }
- if(qos != OC_HIGH_QOS)
- {
- OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
- observation->lowQosCount);
- if(observation->forceHighQos \
- || observation->lowQosCount >= MAX_OBSERVER_NON_COUNT)
- {
- observation->lowQosCount = 0;
- // at some point we have to to send CON to check on the
- // availability of observer
- OC_LOG(INFO, TAG, PCF("This time we are sending the \
- notification as High qos"));
- qos = OC_HIGH_QOS;
- }
- else
- {
- observation->lowQosCount++;
- }
- }
- OCSendCoAPNotification (observation->resUri, observation->addr,
- qos, &(observation->token),
- bufNotify, resPtr, maxAge);
- numSentNotification++;
- }
+ OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
+ return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
}
- obsIdList++;
- numIds--;
- }
- if(numSentNotification == numberOfIds)
- {
- return OC_STACK_OK;
- }
- else if(numSentNotification == 0)
- {
- return OC_STACK_NO_OBSERVERS;
+ // TODO: Placeholder for block transfer handling
+ // TODO: Placeholder for setting the the response handle in the OCServerResponse struct
+ // when implementing the block transfer feature
}
else
{
- //TODO: we need to signal that not every one in the
- // list got an update, should we also indicate who did not receive on?
- return OC_STACK_OK;
+ // Normal response
+
+ // Get pointer to request info
+ serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+ if(serverRequest)
+ {
+ result = serverRequest->ehResponseHandler(ehResponse);
+ }
}
+ return result;
+}
+
+/**
+ * Cancel a response. Applies to a block response
+ *
+ * @param responseHandle - response handle set by stack in OCServerResponse after
+ * OCDoResponse is called
+ *
+ * @return
+ * OC_STACK_OK - No errors; Success
+ * OC_STACK_INVALID_PARAM - The handle provided is invalid.
+ */
+OCStackResult OCCancelResponse(OCResponseHandle responseHandle)
+{
+ OCStackResult result = OC_STACK_NOTIMPL;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse"));
+
+ // TODO: validate response handle
+
+ return result;
}
//-----------------------------------------------------------------------------
{
OCDoHandle handle = NULL;
// Generate token here, it will be deleted when the transaction is deleted
- handle = (OCDoHandle) malloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
+ handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
if (handle)
{
OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
//presenceResource.token = OCGenerateCoAPToken();
result = OCCreateResource(&presenceResource.handle,
- "core.presence",
+ OC_RSRVD_RESOURCE_TYPE_PRESENCE,
"core.r",
OC_PRESENCE_URI,
NULL,
while (pointer)
{
temp = pointer->next;
- deleteResource(pointer);
+ #ifdef WITH_PRESENCE
+ if(pointer != (OCResource *) presenceResource.handle)
+ {
+ #endif // WITH_PRESENCE
+ deleteResource(pointer);
+ #ifdef WITH_PRESENCE
+ }
+ #endif // WITH_PRESENCE
pointer = temp;
}
+
+ #ifdef WITH_PRESENCE
+ // Ensure that the last resource to be deleted is the presence resource. This allows for all
+ // presence notification attributed to their deletion to be processed.
+ deleteResource((OCResource *) presenceResource.handle);
+ #endif // WITH_PRESENCE
}
/**
if (temp == resource) {
// Invalidate all Resource Properties.
resource->resourceProperties = (OCResourceProperty) 0;
- OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
-
#ifdef WITH_PRESENCE
+ if(resource != (OCResource *) presenceResource.handle)
+ {
+ #endif // WITH_PRESENCE
+ OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
+ #ifdef WITH_PRESENCE
+ }
+
if(presenceResource.handle)
{
((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
- SendPresenceNotification(resource->rsrcType, OC_LOW_QOS);
+ if(resource != (OCResource *) presenceResource.handle)
+ {
+ SendPresenceNotification(resource->rsrcType);
+ }
+ else
+ {
+ SendPresenceNotification(NULL);
+ }
}
- #endif
+ #endif
if (temp == headResource) {
headResource = temp->next;
}
/**
+ * Finds a resource type in an OCResourceType link-list.
+ *
+ * @param resourceTypeList - the link-list to be searched through
+ * @param resourceTypeName - the key to search for
+ *
+ * @return
+ * resourceType that matches the key (ie. resourceTypeName)
+ * NULL - either an invalid parameter or this function was unable to find the key.
+ */
+OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
+{
+ if(resourceTypeList && resourceTypeName)
+ {
+ OCResourceType * rtPointer = resourceTypeList;
+ while(resourceTypeName && rtPointer)
+ {
+ if(rtPointer->resourcetypename &&
+ strcmp(resourceTypeName, (const char *)
+ (rtPointer->resourcetypename)) == 0)
+ {
+ break;
+ }
+ rtPointer = rtPointer->next;
+ }
+ return rtPointer;
+ }
+ return NULL;
+}
+/**
* Insert a resource interface into a resource's resource interface linked list.
*
* @param resource - resource where resource interface is to be inserted
}
/**
+ * Determine if a request/response must be sent in a block transfer because it is too large to be
+ * sent in a single PDU. This function can be used for either a request or a response
+ *
+ * @param request - NULL or pointer to request
+ * @param response - NULL or pointer to response
+ * @param size - 0 or size of the request/response. If 0, strlen is used for determining
+ * the length of the request/response
+ *
+ * @return
+ * 0 - packet transfer NOT required (i.e. normal request/response)
+ * 1 - packet transfer required (i.e. block transfer needed)
+ */
+uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size)
+{
+ uint8_t result = 0;
+
+ // Determine if we are checking a request or a response
+ if (request)
+ {
+ // If size is greater than 0, use it for the request size value, otherwise
+ // assume request is null terminated and use strlen for size value
+ if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH))
+ {
+ result = 1;
+ }
+ }
+ else if (response)
+ {
+ // If size is greater than 0, use it for the response size value, otherwise
+ // assume response is null terminated and use strlen for size value
+ if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH))
+ {
+ result = 1;
+ }
+ }
+ return result;
+}
+
+/**
* Retrieves a resource type based upon a uri string if the uri string contains only just one
* resource attribute (and that has to be of type "rt").
*
{
return OC_STACK_INVALID_PARAM;
}
- char * ptr = NULL;
char * leftToken = NULL;
- char * tempURI = (char *) OCMalloc(strlen(uri));
+ char * tempURI = (char *) OCMalloc(strlen(uri) + 1);
if(!tempURI)
{
goto exit;
}
- ptr = tempURI;
strcpy(tempURI, uri);
leftToken = strtok((char *)tempURI, "?");
leftToken = strtok(NULL, "?");
}
- *newURI = ptr;
+ *newURI = tempURI;
return OC_STACK_OK;
exit:
return OC_STACK_NO_MEMORY;
}
-
-
CORE_CPPOBJ = main.o Stream.o WMath.o WString.o HardwareSerial.o Print.o SPI.o IPAddress.o wiring_analog.o
ETH_CPPOBJ = Dhcp.o Dns.o Ethernet.o EthernetUdp.o
ETH_UTIL_CPPOBJ = socket.o w5100.o
-OCSTACK_CPPOBJ = ocrandom.o ocresource.o occollection.o ocobserve.o ocstack.o occoaphelper.o occoap.o occlientcb.o
+OCSTACK_CPPOBJ = ocrandom.o ocresource.o occollection.o ocobserve.o ocserverrequest.o ocstack.o occoaphelper.o occoap.o occlientcb.o
OCDEPENDENT_CPPOBJ = wiring_analog.o
CJSON_COBJ = cJSON.o
OUT_DIR := $(PWD)
-OCLOGGER_DIR = $(ROOT_DIR)/logger
+LOGGER_DIR = $(ROOT_DIR)/logger
+OC_LOG_DIR = $(ROOT_DIR)/../oc_logger
OCRANDOM_DIR = $(ROOT_DIR)/ocrandom
OCSOCKET_DIR = $(ROOT_DIR)/ocsocket
-LCOAP_DIR = $(ROOT_DIR)/libcoap-4.1.1
-OCCOAP_DIR = $(ROOT_DIR)/occoap
+LCOAP_DIR = $(ROOT_DIR)/libcoap-4.1.1
+OCCOAP_DIR = $(ROOT_DIR)/occoap
OCTBSTACK_DIR = $(ROOT_DIR)/stack
-OCLOGGER_INC = $(OCLOGGER_DIR)/include
+LOGGER_INC = $(LOGGER_DIR)/include
+OC_LOG_INC = $(OC_LOG_DIR)/include
OCRANDOM_INC = $(OCRANDOM_DIR)/include
OCSOCKET_INC = $(OCSOCKET_DIR)/include
-LCOAP_INC = $(LCOAP_DIR)
-OCCOAP_INC = $(OCCOAP_DIR)/include
+LCOAP_INC = $(LCOAP_DIR)
+OCCOAP_INC = $(OCCOAP_DIR)/include
OCTBSTACK_INC = $(OCTBSTACK_DIR)/include
-INC_DIRS := -I$(OCLOGGER_INC)
+INC_DIRS := -I$(LOGGER_INC)
+INC_DIRS += -I$(OC_LOG_INC)
INC_DIRS += -I$(OCRANDOM_INC)
INC_DIRS += -I$(OCSOCKET_INC)
INC_DIRS += -I$(LCOAP_INC)
INC_DIRS += -I$(OCCOAP_INC)
INC_DIRS += -I$(OCTBSTACK_INC)
INC_DIRS += -I$(OCTBSTACK_INC)/internal
-INC_DIRS += -I$(GTEST_DIR)/include
+INC_DIRS += -I$(GTEST_DIR)/include
CC_FLAGS.debug := -g -O0 -g3 -Wall -ffunction-sections -fdata-sections -fno-exceptions \
- -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) -DTB_LOG
+ -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG
CC_FLAGS.release := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-exceptions \
- -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD)
+ -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD)
LDLIBS += -loctbstack -lpthread -lgtest -lgtest_main
CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(LDLIBS) -L$(GTEST_DIR)/lib/.libs
#include <stdint.h>
using namespace std;
-#define CTX_VAL 0x99
+#define DEFAULT_CONTEXT_VALUE 0x99
//-----------------------------------------------------------------------------
// Private variables
//-----------------------------------------------------------------------------
EXPECT_EQ(OC_STACK_OK, clientResponse->result);
- if(ctx == (void*)CTX_VAL) {
+ if(ctx == (void*)DEFAULT_CONTEXT_VALUE) {
OC_LOG_V(INFO, TAG, "Callback Context recvd successfully");
}
OC_LOG_V(INFO, TAG, "result = %d", clientResponse->result);
char szQueryUri[64] = { 0 };
strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
cbData.cb = asyncDoResourcesCallback;
- cbData.context = (void*)CTX_VAL;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData), NULL, 0);
+
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0));
//EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI));
EXPECT_EQ(OC_STACK_OK, OCStop());
}
char szQueryUri[64] = { 0 };
strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
cbData.cb = asyncDoResourcesCallback;
- cbData.context = (void*)CTX_VAL;
+ cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
cbData.cd = NULL;
- EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData), NULL, 0);
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_LOW_QOS, &cbData, NULL, 0));
//EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0));
EXPECT_EQ(OC_STACK_OK, OCStop());
}
##
# Examples build script
##
-Import('env', 'RELEASE_BUILD', 'BUILD_TARGET', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
# Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-examples_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+
+examples_env = lib_env.Clone()
######################################################################
# Build flags
'../oc_logger/include'
])
-if BUILD_TARGET not in ['windows', 'winrt']:
- examples_env.AppendUnique(CXXFLAGS = ['-std=c++11', '-Wall'])
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+ examples_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+
+ # Note: 'pthread' is in libc for android. On other platform, if use
+ # new gcc(>4.9?) it isn't required, otherwise, it's required
+ if target_os != 'android':
+ examples_env.AppendUnique(LIBS = ['-lpthread'])
-examples_env.AppendUnique(LIBPATH = [BUILD_DIR])
+examples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
examples_env.PrependUnique(LIBS = ['oc', 'octbstack', 'coap', 'oc_logger'])
-if BUILD_TARGET == 'android':
+if target_os == 'android':
examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
examples_env.AppendUnique(LIBS = ['gnustl_static'])
- examples_env.AppendUnique(LINKFLAGS = ['-static'])
examples_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
- if not RELEASE_BUILD:
+ if not env.get('RELEASE'):
examples_env.AppendUnique(LIBS = ['log'])
+
+if target_os in ['darwin', 'ios']:
+ examples_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+
######################################################################
# Source files and Targets
######################################################################
simpleserver = examples_env.Program('simpleserver', 'simpleserver.cpp')
+simpleserverHQ = examples_env.Program('simpleserverHQ', 'simpleserverHQ.cpp')
simpleclient = examples_env.Program('simpleclient', 'simpleclient.cpp')
+simpleclientHQ = examples_env.Program('simpleclientHQ', 'simpleclientHQ.cpp')
+fridgeserver = examples_env.Program('fridgeserver', 'fridgeserver.cpp')
+fridgeclient = examples_env.Program('fridgeclient', 'fridgeclient.cpp')
presenceserver = examples_env.Program('presenceserver', 'presenceserver.cpp')
presenceclient = examples_env.Program('presenceclient', 'presenceclient.cpp')
simpleclientserver = examples_env.Program('simpleclientserver', 'simpleclientserver.cpp')
roomserver = examples_env.Program('roomserver', 'roomserver.cpp')
roomclient = examples_env.Program('roomclient', 'roomclient.cpp')
+garageserver = examples_env.Program('garageserver', 'garageserver.cpp')
+garageclient = examples_env.Program('garageclient', 'garageclient.cpp')
-Alias("examples", [simpleserver, simpleclient, presenceserver, presenceclient,
- simpleclientserver, roomserver, roomclient])
-env.AppendUnique(TS = ['examples'])
+Alias("examples", [simpleserver, simpleserverHQ, simpleclient, simpleclientHQ,
+ fridgeserver, fridgeclient, presenceserver, presenceclient,
+ simpleclientserver, roomserver, roomclient, garageserver,
+ garageclient])
+env.AppendTarget('examples')
-if BUILD_TARGET not in ['ios']:
- SConscript(BUILD_DIR + 'examples/ocicuc/SConscript')
+#ios doesn't allow run application from terminal, so won't build these examples
+if target_os != 'ios':
+ SConscript('ocicuc/SConscript')
OCResource::Ptr light = constructResourceObject(resource->host(),
"/light", false, lightTypes, ifaces);
+ if(!light)
+ {
+ std::cout << "Error: Light Resource Object construction returned null\n";
+ return;
+ }
+
std::vector<std::string> doorTypes = {"intel.fridge.door"};
OCResource::Ptr leftdoor = constructResourceObject(resource->host(),
"/door/left", false, doorTypes, ifaces);
+ if(!leftdoor)
+ {
+ std::cout << "Error: Left Door Resource Object construction returned null\n";
+ return;
+ }
+
OCResource::Ptr rightdoor = constructResourceObject(resource->host(),
"/door/right", false, doorTypes, ifaces);
+ if(!rightdoor)
+ {
+ std::cout << "Error: Right Door Resource Object construction returned null\n";
+ return;
+ }
+
OCResource::Ptr randomdoor = constructResourceObject(resource->host(),
"/door/random", false, doorTypes, ifaces);
+ if(!randomdoor)
+ {
+ std::cout << "Error: Random Door Resource Object construction returned null\n";
+ return;
+ }
// Set header options with API version and token
HeaderOptions headerOptions;
}
case 1:
{
- bool isOn;
+ bool isOn = false;
rep.getValue("on",isOn);
std::cout<<"The fridge light is "<< ((isOn)?"":"not ") <<"on"<<std::endl;
}
case 2:
case 3:
{
- bool isOpen;
+ bool isOpen = false;
std::string side;
rep.getValue("open", isOpen);
rep.getValue("side", side);
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-/// The purpose of this server is to simulate a refridgerator that contains a device resource for
+/// The purpose of this server is to simulate a refrigerator that contains a device resource for
/// its description, a light resource for the internal light, and 2 door resources for the purpose
/// of representing the doors attached to this fridge. This is used by the fridgeclient to
/// demonstrate using std::bind to attach to instances of a class as well as using
protected:
OCResourceHandle m_resourceHandle;
OCRepresentation m_rep;
- virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)=0;
+ virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)=0;
};
class DeviceResource : public Resource
std::string resourceURI = "/device";
std::string resourceTypeName = "intel.fridge";
std::string resourceInterface = DEFAULT_INTERFACE;
- EntityHandler cb = std::bind(&DeviceResource::entityHandler, this,PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&DeviceResource::entityHandler, this,PH::_1);
- EntityHandler defaultEH = std::bind(&DeviceResource::defaultEntityHandler, this,
- PH::_1, PH::_2);
+ EntityHandler defaultEH = std::bind(&DeviceResource::defaultEntityHandler
+ ,this, PH::_1);
std::cout << "Setting device default entity handler\n";
OCPlatform::setDefaultDeviceEntityHandler(defaultEH);
private:
OCRepresentation get()
{
- m_rep.setValue("device_name", std::string("Intel Powered 2 door, 1 light refridgerator"));
+ m_rep.setValue("device_name", std::string("Intel Powered 2 door, 1 light refrigerator"));
return m_rep;
}
- void deleteDeviceResource()
+ OCStackResult deleteDeviceResource()
{
OCStackResult result = OCPlatform::unregisterResource(m_resourceHandle);
if(OC_STACK_OK != result)
throw std::runtime_error(
std::string("Device Resource failed to unregister/delete") + std::to_string(result));
}
+ return result;
}
std::string m_modelName;
protected:
- virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+ virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if(request)
{
// Get the header options from the request
if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
{
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
+ pResponse->setHeaderOptions(serverHeaderOptions);
+
if(request->getRequestType() == "GET")
{
- if(response)
+ std::cout<<"DeviceResource Get Request"<<std::endl;
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(get(), "");
+ if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
{
- std::cout<<"DeviceResource Get Request"<<std::endl;
- response->setErrorCode(200);
- response->setHeaderOptions(serverHeaderOptions);
- response->setResourceRepresentation(get(), "");
+ ehResult = OC_EH_OK;
}
}
- if(request->getRequestType() == "DELETE")
+ else if(request->getRequestType() == "DELETE")
{
- if(response)
+ std::cout<<"DeviceResource Delete Request"<<std::endl;
+ if(deleteDeviceResource() == OC_STACK_OK)
+ {
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_RESOURCE_DELETED);
+ ehResult = OC_EH_OK;
+ }
+ else
{
- std::cout<<"DeviceResource Delete Request"<<std::endl;
- deleteDeviceResource();
- response->setErrorCode(200);
- response->setHeaderOptions(serverHeaderOptions);
+ pResponse->setResponseResult(OC_EH_ERROR);
+ ehResult = OC_EH_ERROR;
}
+ OCPlatform::sendResponse(pResponse);
}
else
{
std::cout <<"DeviceResource unsupported request type "
<< request->getRequestType() << std::endl;
+ pResponse->setResponseResult(OC_EH_ERROR);
+ OCPlatform::sendResponse(pResponse);
+ ehResult = OC_EH_ERROR;
}
}
else
}
}
- return OC_EH_OK;
+ return ehResult;
}
- virtual OCEntityHandlerResult defaultEntityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+ virtual OCEntityHandlerResult defaultEntityHandler(std::shared_ptr<OCResourceRequest> request)
{
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if(request)
{
std::cout << "In Default Entity Handler, uri received: "
if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
{
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
+
if(request->getRequestType() == "GET")
{
- if(response)
+ std::cout<<"Default Entity Handler: Get Request"<<std::endl;
+ pResponse->setErrorCode(200);
+ pResponse->setResourceRepresentation(get(), "");
+ if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
{
- std::cout<<"Default Entity Handler: Get Request"<<std::endl;
- response->setErrorCode(200);
- response->setResourceRepresentation(get(), "");
+ ehResult = OC_EH_OK;
}
}
else
{
std::cout <<"Default Entity Handler: unsupported request type "
<< request->getRequestType() << std::endl;
+ pResponse->setResponseResult(OC_EH_ERROR);
+ OCPlatform::sendResponse(pResponse);
+ ehResult = OC_EH_ERROR;
}
}
else
}
}
- return OC_EH_OK;
+ return ehResult;
}
};
std::string resourceURI = "/light";
std::string resourceTypeName = "intel.fridge.light";
std::string resourceInterface = DEFAULT_INTERFACE;
- EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
uint8_t resourceProperty = 0;
OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
resourceURI,
bool m_isOn;
protected:
- virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+ virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if(request)
{
std::cout << "In entity handler for Light, URI is : "
if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
{
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
+
if(request->getRequestType() == "GET")
{
- if(response)
+ std::cout<<"Light Get Request"<<std::endl;
+ pResponse->setErrorCode(200);
+ pResponse->setResourceRepresentation(get(), "");
+ if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
{
- std::cout<<"Light Get Request"<<std::endl;
- response->setErrorCode(200);
- response->setResourceRepresentation(get(), "");
+ ehResult = OC_EH_OK;
}
}
else if(request->getRequestType() == "PUT")
{
- if(response)
+ std::cout <<"Light Put Request"<<std::endl;
+ put(request->getResourceRepresentation());
+ pResponse->setErrorCode(200);
+ pResponse->setResourceRepresentation(get(), "");
+ if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
{
- std::cout <<"Light Put Request"<<std::endl;
- put(request->getResourceRepresentation());
-
- response->setErrorCode(200);
- response->setResourceRepresentation(get(),"");
+ ehResult = OC_EH_OK;
}
}
else
{
std::cout << "Light unsupported request type"
<< request->getRequestType() << std::endl;
+ pResponse->setResponseResult(OC_EH_ERROR);
+ OCPlatform::sendResponse(pResponse);
+ ehResult = OC_EH_ERROR;
}
}
else
}
}
- return OC_EH_OK;
+ return ehResult;
}
};
std::string resourceURI = "/door/"+ side;
std::string resourceTypeName = "intel.fridge.door";
std::string resourceInterface = DEFAULT_INTERFACE;
- EntityHandler cb = std::bind(&DoorResource::entityHandler, this,PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&DoorResource::entityHandler, this,PH::_1);
uint8_t resourceProperty = 0;
OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
bool m_isOpen;
std::string m_side;
protected:
- virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+ virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
std::cout << "EH of door invoked " << std::endl;
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
if(request)
{
std::cout << "In entity handler for Door, URI is : "
if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
{
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
+
if(request->getRequestType() == "GET")
{
- if(response)
+ // note that we know the side because std::bind gives us the
+ // appropriate object
+ std::cout<< m_side << " Door Get Request"<<std::endl;
+ pResponse->setErrorCode(200);
+ pResponse->setResourceRepresentation(get(), "");
+ if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
{
- // note that we know the side because std::bind gives us the
- // appropriate object
- std::cout<<m_side << " Door Get Request"<<std::endl;
- response->setErrorCode(200);
- response->setResourceRepresentation(get(), "");
+ ehResult = OC_EH_OK;
}
}
else if(request->getRequestType() == "PUT")
{
- if(response)
+ std::cout << m_side <<" Door Put Request"<<std::endl;
+ put(request->getResourceRepresentation());
+ pResponse->setErrorCode(200);
+ pResponse->setResourceRepresentation(get(),"");
+ if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
{
- std::cout <<m_side <<" Door Put Request"<<std::endl;
- put(request->getResourceRepresentation());
- response->setErrorCode(200);
- response->setResourceRepresentation(get(),"");
+ ehResult = OC_EH_OK;
}
}
else
{
std::cout <<m_side<<" Door unsupported request type "
<< request->getRequestType() << std::endl;
+ pResponse->setResponseResult(OC_EH_ERROR);
+ OCPlatform::sendResponse(pResponse);
+ ehResult = OC_EH_ERROR;
}
}
else
}
}
- return OC_EH_OK;
+ return ehResult;
}
};
#include <string>
#include <cstdlib>
+#include <mutex>
+#include <condition_variable>
#include "OCPlatform.h"
#include "OCApi.h"
OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.garage",
&foundResource);
std::cout<< "Finding Resource... " <<std::endl;
- while(true)
- {
- // some operations
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
catch(OCException& e)
{
#include <functional>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
#include "OCPlatform.h"
#include "OCApi.h"
using namespace std;
// Forward declaring the entityHandler
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response);
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
/// This class represents a single resource named 'lightResource'. This resource has
// setting json string
std::string json = "{\"num\":10,\"rno\":23.5,\"aoa\":[[1,2],[3]],\"str\":\"john\",\
\"object\":{\"bl1\":false,\"ar\":[2,3]}, \"objects\":[{\"bl2\":true,\"nl\":null},{\"ar1\":[1,2]}]}";
- m_garageRep.setValue("json", escapeString(json));
+ m_garageRep.setValue("json", json);
}
/* Note that this does not need to be a member function: for classes you do not have
// Create the instance of the resource class (in this case instance of class 'GarageResource').
GarageResource myGarage;
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+ pResponse->setResourceRepresentation(myGarage.get());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ return OCPlatform::sendResponse(pResponse);
+}
+
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
cout << "\tIn Server CPP entity handler:\n";
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if(request)
{
if(requestType == "GET")
{
cout << "\t\t\trequestType : GET\n";
-
- if(response)
+ if(OC_STACK_OK == sendResponse(request))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(myGarage.get());
+ ehResult = OC_EH_OK;
}
}
else if(requestType == "PUT")
{
cout << "\t\t\trequestType : PUT\n";
-
OCRepresentation rep = request->getResourceRepresentation();
-
// Do related operations related to PUT request
-
- // Update the lightResource
myGarage.put(rep);
-
- if(response)
+ if(OC_STACK_OK == sendResponse(request))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(myGarage.get());
+ ehResult = OC_EH_OK;
}
-
}
else if(requestType == "POST")
{
std::cout << "Request invalid" << std::endl;
}
- return OC_EH_OK;
+ return ehResult;
}
int main(int argc, char* argv[1])
// Invoke createResource function of class light.
myGarage.createResource();
- // Perform app tasks
- while(true)
- {
- // some tasks
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
catch(OCException e)
{
// No explicit call to stop the OCPlatform
// When OCPlatform destructor is invoked, internally we do Platform cleanup
+
+ return 0;
}
-I../../csdk/stack/include \
-I../../csdk/ocsocket/include \
-I../../csdk/ocrandom/include \
- -I../../csdk/logger/include
+ -I../../csdk/logger/include \
BOOST_LIBS=-lboost_program_options
#BOOST_LIBS=-L/usr/local/boost/lib/ -lboost_program_options # for boost libraries at the specified path
##
# Examples build script
##
-Import('env', 'RELEASE_BUILD', 'BUILD_TARGET', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
# Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-ocicuc_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+ocicuc_env = lib_env.Clone()
######################################################################
# Build flags
######################################################################
'../../oc_logger/include'
])
-ocicuc_env.AppendUnique(LIBPATH = [BUILD_DIR])
+ocicuc_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
ocicuc_env.PrependUnique(LIBS = ['oc', 'octbstack', 'coap', 'oc_logger'])
-if BUILD_TARGET not in ['windows', 'winrt']:
- ocicuc_env.AppendUnique(CXXFLAGS = ['-std=c++11'])
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+ ocicuc_env.AppendUnique(CXXFLAGS = ['-std=c++0x'])
-if BUILD_TARGET == 'android':
+if target_os == 'android':
ocicuc_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
ocicuc_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
ocicuc_env.AppendUnique(LIBS = ['boost_program_options-gcc-mt-1_49', 'boost_thread-gcc-mt-1_49', 'gnustl_static'])
- ocicuc_env.AppendUnique(LINKFLAGS = ['-static'])
- if not RELEASE_BUILD:
+ if not env.get('RELEASE'):
ocicuc_env.AppendUnique(LIBS = ['log'])
-if BUILD_TARGET == 'darwin':
+if target_os == 'darwin':
ocicuc_env.AppendUnique(LIBS = ['boost_program_options'])
######################################################################
######################################################################
client = ocicuc_env.Program('client', ['client.cpp', 'driver.cpp', 'utility.cpp'])
server = ocicuc_env.Program('server', ['server.cpp', 'driver.cpp', 'utility.cpp', 'light_resource.cpp'])
-monoprocess = ocicuc_env.Program('monoprocess',
- ['monoprocess.cpp', 'driver.cpp', 'utility.cpp', 'light_resource.cpp'])
+monoprocess = ocicuc_env.Program('monoprocess', ['monoprocess.cpp', 'driver.cpp', 'utility.cpp', 'light_resource.cpp'])
+small_example = ocicuc_env.Program('small_example', ['small_example.cpp', 'driver.cpp', 'utility.cpp'])
-Alias("examples_ocicuc", [client, server, monoprocess])
-env.AppendUnique(TS = ['examples_ocicuc'])
+Alias("examples_ocicuc", [client, server, monoprocess, small_example])
+env.AppendTarget('examples_ocicuc')
\ No newline at end of file
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+// This contains the Boost MPL defines required for the boost_variant
+// serialization, so it must go before the boost/program_options
+#include "OCApi.h"
+
#include <map>
#include <string>
#include <memory>
#include <boost/program_options.hpp>
-#include "OCApi.h"
#include "OCResource.h"
#include "OCPlatform.h"
return;
}
- std::cout << "input attributes:\n" << rep.getAttributeMap() << '\n';
+ std::cout << "input attributes:\n";
+ std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue<bool>("state")<<"; ";
+ std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue<int>("power")<<"; \n";
// Now, make a change to the light representation (replacing, rather than parsing):
- OC::AttributeMap attrs {
- { "state", { "true" } },
- { "power", { "10" } }
- };
+ bool state = true;
+ int power = 10;
- std::cout << "output attributes:\n" << attrs << '\n';
+ std::cout << "output attributes:\n";
+ std::cout << "Attribute \"" << "state" << "\": "<< state<<"; ";
+ std::cout << "Attribute \"" << "power" << "\": "<< power<<"; \n";
call_timer.mark("put_resource");
OC::OCRepresentation out_rep;
- out_rep.setAttributeMap(attrs);
+ out_rep.setValue("state", state);
+ out_rep.setValue("power", power);
resource->put(out_rep, OC::QueryParamsMap(),
std::bind(&resource_handle::onResourcePut, this, std::placeholders::_1,
throw OC::OCException(os.str());
}
- std::cout << "input attributes:\n" << rep.getAttributeMap() << '\n';
+ std::cout << "input attributes:\n";
+ std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue<bool>("state")<<"; ";
+ std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue<int>("power")<<"; \n";
call_timer.mark("observe_resource");
call_timer.report_and_reset("observe_resource");
- std::cout << rep.getAttributeMap() << '\n';
+ std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue<bool>("state")<<"; ";
+ std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue<int>("power")<<"; \n";
const auto oc = observe_count();
OCStackResult result = OC::OCPlatform::registerResource(
m_resourceHandle, resourceURI, resourceTypeName,
DEFAULT_INTERFACE,
- std::bind(&LightResource::entityHandler, this, std::placeholders::_1, std::placeholders::_2),
+ std::bind(&LightResource::entityHandler, this, std::placeholders::_1),
OC_DISCOVERABLE | OC_OBSERVABLE);
if (OC_STACK_OK != result)
std::cout << "Resource creation failed.\n";
// This is just a sample implementation of entity handler.
// Entity handler can be implemented in several ways by the manufacturer
-OCEntityHandlerResult LightResource::entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult LightResource::entityHandler(std::shared_ptr<OCResourceRequest> request)
{
if(!request)
{
return OC_EH_ERROR;
}
- if(!response)
- {
- cerr << "entityHandler(): Received invalid response object.\n";
- return OC_EH_ERROR;
- }
-
switch(request->getRequestHandlerFlag())
{
default:
break;
case RequestHandlerFlag::RequestFlag:
- dispatch_request(request->getRequestType(), request, response);
+ dispatch_request(request->getRequestType(), request);
break;
case RequestHandlerFlag::ObserverFlag:
- handle_observe_event(request, response);
+ handle_observe_event(request);
break;
}
return OC_EH_OK;
}
-void LightResource::dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request)
{
std::cout << "dispatch_request(): " << request_type << '\n';
if("GET" == request_type)
- return handle_get_request(request, response);
+ return handle_get_request(request);
if("PUT" == request_type)
- return handle_put_request(request, response);
+ return handle_put_request(request);
if("POST" == request_type)
- return handle_post_request(request, response);
+ return handle_post_request(request);
if("DELETE" == request_type)
- return handle_delete_request(request, response);
+ return handle_delete_request(request);
cerr << "entityHandler(): Invalid request type \"" << request_type << "\".\n";
}
-void LightResource::handle_get_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_get_request(std::shared_ptr<OCResourceRequest> request)
{
cout << "handle_get_request():\n";
// ...do any processing of the query here...
// Get a representation of the resource and send it back as a response:
- response->setErrorCode(200);
- response->setResourceRepresentation(getRepresentation());
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(getRepresentation());
+ OCPlatform::sendResponse(pResponse);
}
-void LightResource::handle_put_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_put_request(std::shared_ptr<OCResourceRequest> request)
{
// Here's how you would get any query parameters:
const auto query_params_map = request->getQueryParameters();
setRepresentation(rep);
- if(!response)
- return;
-
- response->setErrorCode(200);
- response->setResourceRepresentation(getRepresentation());
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(getRepresentation());
+ OCPlatform::sendResponse(pResponse);
}
-void LightResource::handle_post_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_post_request(std::shared_ptr<OCResourceRequest> request)
{
// ...demo-code...
}
-void LightResource::handle_delete_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_delete_request(std::shared_ptr<OCResourceRequest> request)
{
// ...demo-code...
}
// Set up observation in a separate thread:
-void LightResource::handle_observe_event(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+void LightResource::handle_observe_event(std::shared_ptr<OCResourceRequest> request)
{
if(observe_thread.joinable())
return;
void addInterface(const std::string& interface) const;
private:
- OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response);
+ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
private:
void observe_function();
// Request handlers:
private:
- void dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
- void handle_get_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
- void handle_put_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
- void handle_post_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
- void handle_delete_request(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
- void handle_observe_event(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
+ void dispatch_request(const std::string& request_type, std::shared_ptr<OCResourceRequest> request);
+ void handle_get_request(std::shared_ptr<OCResourceRequest> request);
+ void handle_put_request(std::shared_ptr<OCResourceRequest> request);
+ void handle_post_request(std::shared_ptr<OCResourceRequest> request);
+ void handle_delete_request(std::shared_ptr<OCResourceRequest> request);
+ void handle_observe_event(std::shared_ptr<OCResourceRequest> request);
};
}} // namespace Intel::OCDemo
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#include "exec.hpp"
#include "utility.hpp"
+#include "exec.hpp"
#include "light_resource.hpp"
namespace Intel { namespace OCDemo {
namespace Intel { namespace OCDemo {
-// Prettyprinter for AttributeMaps:
-inline std::ostream& operator<<(std::ostream& os, const OC::AttributeMap& attrs)
-{
- for(const auto& attr : attrs)
- os << "Attribute \"" << attr.first << "\": " << attr.second << "; ";
-
- return os;
-}
-
/* A static observation counter: */
int observe_count();
/* Helpers for measuring request times: */
-typedef std::pair<
- std::chrono::time_point<std::chrono::high_resolution_clock>,
- std::chrono::time_point<std::chrono::high_resolution_clock>
+typedef std::pair<
+ std::chrono::time_point<std::chrono::high_resolution_clock>,
+ std::chrono::time_point<std::chrono::high_resolution_clock>
> clock_interval;
struct call_times
call_times(const bool& display_reports_)
: display_reports(display_reports_)
{}
-
+
public:
void reset(const std::string& entry);
void mark(const std::string& name);
void report_and_reset(const std::string& name);
};
-extern call_times call_timer;
-
+extern call_times call_timer;
+
}} // namespace Intel::OCDemo
#endif
#include <string>
#include <cstdlib>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
#include "OCPlatform.h"
#include "OCApi.h"
}
// Callback to presence
-void presenceHandler(OCStackResult result, const unsigned int nonce)
+void presenceHandler(OCStackResult result, const unsigned int nonce, const std::string& hostAddress)
{
+ std::cout << "Received presence notification from : " << hostAddress << std::endl;
std::cout << "In presenceHandler: ";
switch(result)
case OC_STACK_PRESENCE_TIMEOUT:
std::cout << "Presence Timeout\n";
break;
- case OC_STACK_PRESENCE_DO_NOT_HANDLE:
- std::cout << "Presence do not handle\n";
+ case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+ std::cout << "Virtual do not handle\n";
break;
default:
std::cout << "Error\n";
if(resourceURI == "/a/light")
{
curResource = resource;
- OCPlatform::OCPresenceHandle presenceHandle;
+ OCPlatform::OCPresenceHandle presenceHandle = nullptr;
if(TEST_CASE == TEST_UNICAST_PRESENCE_NORMAL)
{
{
std::cout << "Created Platform..."<<std::endl;
- OCPlatform::OCPresenceHandle presenceHandle;
+ OCPlatform::OCPresenceHandle presenceHandle = nullptr;
if(TEST_CASE == TEST_MULTICAST_PRESENCE_NORMAL)
{
OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource);
std::cout<< "Finding Resource... " <<std::endl;
}
- while(true)
- {
- // some operations
- }
+ //
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}catch(OCException& e)
{
#include <functional>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
#include "OCPlatform.h"
#include "OCApi.h"
using namespace std;
// Forward declaring the entityHandler
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response);
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
/// This class represents a single resource named 'lightResource'. This resource has
/// two simple properties named 'state' and 'power'
// Create the instance of the resource class (in this case instance of class 'LightResource').
LightResource myLightResource;
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
cout << "\tIn Server CPP entity handler:\n";
return OC_EH_OK;
myLightResource.createResource3();
- // Perform app tasks
- while(true)
- {
- // some tasks
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
catch(OCException e)
{
// No explicit call to stop the platform.
// When OCPlatform destructor is invoked, internally we do platform cleanup
+
+ return 0;
}
#include <string>
#include <cstdlib>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
#include "OCPlatform.h"
#include "OCApi.h"
// Find all resources
OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource);
std::cout<< "Finding Resource... " <<std::endl;
- while(true)
- {
- // some operations
- }
+
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}catch(OCException& e)
{
#include <functional>
-#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
#include "OCPlatform.h"
#include "OCApi.h"
// Forward declaring the entityHandler (room)
-OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response);
-OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response);
-OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response);
+OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request);
+OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request);
+OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request);
+
+/// Specifies whether default collection entity handler is used or not
+bool useDefaultCollectionEH = false;
class RoomResource
{
/// This function internally calls registerResource API.
void createResources()
{
+ // This function internally creates and registers the resource.
using namespace OC::OCPlatform;
- // This will internally create and register the resource.
- OCStackResult result = registerResource(
+ OCStackResult result = OC_STACK_ERROR;
+
+ // Based on the case, we will use default collection EH (by passing NULL in entity handler
+ // parameter) or use application entity handler.
+ if(useDefaultCollectionEH)
+ {
+ result = registerResource(
+ m_roomHandle, m_roomUri, m_roomTypes[0],
+ m_roomInterfaces[0], NULL,
+ OC_DISCOVERABLE | OC_OBSERVABLE);
+ }
+ else
+ {
+ result = registerResource(
m_roomHandle, m_roomUri, m_roomTypes[0],
m_roomInterfaces[0], entityHandlerRoom,
- OC_DISCOVERABLE | OC_OBSERVABLE
- );
+ OC_DISCOVERABLE | OC_OBSERVABLE);
+ }
if (OC_STACK_OK != result)
{
cout << "Binding TypeName to Resource was unsuccessful\n";
}
- result = registerResource(
- m_lightHandle, m_lightUri, m_lightTypes[0],
- m_lightInterfaces[0], entityHandlerLight,
- OC_DISCOVERABLE | OC_OBSERVABLE
- );
+ result = registerResource(m_lightHandle, m_lightUri, m_lightTypes[0],
+ m_lightInterfaces[0], entityHandlerLight,
+ OC_DISCOVERABLE | OC_OBSERVABLE);
if (OC_STACK_OK != result)
{
cout << "Resource creation (light) was unsuccessful\n";
}
- result = registerResource(
- m_fanHandle, m_fanUri, m_fanTypes[0],
- m_fanInterfaces[0], entityHandlerFan,
- OC_DISCOVERABLE | OC_OBSERVABLE
- );
+ result = registerResource(m_fanHandle, m_fanUri, m_fanTypes[0],
+ m_fanInterfaces[0], entityHandlerFan,
+ OC_DISCOVERABLE | OC_OBSERVABLE);
if (OC_STACK_OK != result)
{
OCRepresentation getRoomRepresentation(void)
{
- std::vector<OCRepresentation> children;
-
- OCRepresentation light = getLightRepresentation();
- children.push_back(light);
-
- OCRepresentation fan = getFanRepresentation();
- children.push_back(fan);
-
- m_roomRep.setChildren(children);
+ m_roomRep.clearChildren();
+ m_roomRep.addChild(getLightRepresentation());
+ m_roomRep.addChild(getFanRepresentation());
return m_roomRep;
}
// Create the instance of the resource class (in this case instance of class 'RoomResource').
RoomResource myRoomResource;
-OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+OCStackResult sendRoomResponse(std::shared_ptr<OCResourceRequest> pRequest)
{
- cout << "\tIn Server CPP entity handler:\n";
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+
+ // Check for query params (if any)
+ QueryParamsMap queryParamsMap = pRequest->getQueryParameters();
+
+ cout << "\t\t\tquery params: \n";
+ for(auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
+ {
+ cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
+ }
+ OCRepresentation rep;
+ rep = myRoomResource.getRoomRepresentation();
+
+ auto findRes = queryParamsMap.find("if");
+
+ if(findRes != queryParamsMap.end())
+ {
+ pResponse->setResourceRepresentation(rep, findRes->second);
+ }
+ else
+ {
+ pResponse->setResourceRepresentation(rep, DEFAULT_INTERFACE);
+ }
+
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ return OCPlatform::sendResponse(pResponse);
+}
+
+// This function prepares a response for any incoming request to Light resource.
+bool prepareLightResponse(std::shared_ptr<OCResourceRequest> request)
+{
+ cout << "\tIn Server CPP (Light) prepareLightResponse:\n";
+ bool result = false;
if(request)
{
// Get the request type and request flag
if(requestType == "GET")
{
cout << "\t\t\trequestType : GET\n";
-
- // Check for query params (if any)
- QueryParamsMap queryParamsMap = request->getQueryParameters();
-
- cout << "\t\t\tquery params: \n";
- for(auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
- {
- cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
- }
-
- OCRepresentation rep;
- rep = myRoomResource.getRoomRepresentation();
-
- if(response)
- {
- // TODO Error Code
- response->setErrorCode(200);
-
- auto findRes = queryParamsMap.find("if");
-
- if(findRes != queryParamsMap.end())
- {
- response->setResourceRepresentation(rep, findRes->second);
- }
- else
- {
- response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
- }
- }
-
+ // GET operations are directly handled while sending the response
+ // in the sendLightResponse function
+ result = true;
}
else if(requestType == "PUT")
{
cout << "\t\t\trequestType : PUT\n";
+ OCRepresentation rep = request->getResourceRepresentation();
- QueryParamsMap queryParamsMap = request->getQueryParameters();
-
- entityHandlerLight(request, response);
- entityHandlerFan(request, response);
-
- OCRepresentation rep;
- rep = myRoomResource.getRoomRepresentation();
-
- if(response)
- {
- response->setErrorCode(200);
-
- auto findRes = queryParamsMap.find("if");
-
- if(findRes != queryParamsMap.end())
- {
- response->setResourceRepresentation(rep, findRes->second);
- }
- else
- {
- response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
- }
- }
+ // Do related operations related to PUT request
+ myRoomResource.setLightRepresentation(rep);
+ result= true;
}
else if(requestType == "POST")
{
std::cout << "Request invalid" << std::endl;
}
- return OC_EH_OK;
+ return result;
}
-OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+// This function prepares a response for any incoming request to Fan resource.
+bool prepareFanResponse(std::shared_ptr<OCResourceRequest> request)
{
- cout << "\tIn Server CPP (Light) entity handler:\n";
+ cout << "\tIn Server CPP (Fan) prepareFanResponse:\n";
+ bool result = false;
if(request)
{
if(requestType == "GET")
{
cout << "\t\t\trequestType : GET\n";
-
- if(response)
- {
- // TODO Error Code
- response->setErrorCode(200);
- response->setResourceRepresentation(myRoomResource.getLightRepresentation());
- }
-
+ // GET operations are directly handled while sending the response
+ // in the sendLightResponse function
+ result = true;
}
else if(requestType == "PUT")
{
OCRepresentation rep = request->getResourceRepresentation();
// Do related operations related to PUT request
- myRoomResource.setLightRepresentation(rep);
-
- if(response)
- {
- // TODO Error Code
- response->setErrorCode(200);
- response->setResourceRepresentation(myRoomResource.getLightRepresentation());
- }
-
+ myRoomResource.setFanRepresentation(rep);
+ result = true;
}
else if(requestType == "POST")
{
std::cout << "Request invalid" << std::endl;
}
- return OC_EH_OK;
+ return result;
}
-OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandlerRoom(std::shared_ptr<OCResourceRequest> request)
{
- cout << "\tIn Server CPP (Fan) entity handler:\n";
+ cout << "\tIn Server CPP entity handler:\n";
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if(request)
{
if(requestType == "GET")
{
cout << "\t\t\trequestType : GET\n";
-
- if(response)
+ if(OC_STACK_OK == sendRoomResponse(request))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(myRoomResource.getFanRepresentation());
+ ehResult = OC_EH_OK;
}
-
}
else if(requestType == "PUT")
{
cout << "\t\t\trequestType : PUT\n";
-
- OCRepresentation rep = request->getResourceRepresentation();
-
- // Do related operations related to PUT request
- myRoomResource.setFanRepresentation(rep);
-
- if(response)
+ // Call these functions to prepare the response for child resources and
+ // then send the final response using sendRoomResponse function
+ prepareLightResponse(request);
+ prepareFanResponse(request);
+ if(OC_STACK_OK == sendRoomResponse(request))
{
- // TODO Error Code
- response->setErrorCode(200);
- response->setResourceRepresentation(myRoomResource.getFanRepresentation());
+ ehResult = OC_EH_OK;
}
}
else if(requestType == "POST")
std::cout << "Request invalid" << std::endl;
}
- return OC_EH_OK;
+ return ehResult;
+}
+
+OCStackResult sendLightResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+ pResponse->setResourceRepresentation(myRoomResource.getLightRepresentation());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ return OCPlatform::sendResponse(pResponse);
+}
+
+
+
+OCEntityHandlerResult entityHandlerLight(std::shared_ptr<OCResourceRequest> request)
+{
+ cout << "\tIn Server CPP (Light) entity handler:\n";
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+ if(prepareLightResponse(request))
+ {
+ if(OC_STACK_OK == sendLightResponse(request))
+ {
+ ehResult = OC_EH_OK;
+ }
+ else
+ {
+ std::cout << "sendLightResponse failed." << std::endl;
+ }
+ }
+ else
+ {
+ std::cout << "PrepareLightResponse failed." << std::endl;
+ }
+ return ehResult;
+}
+
+OCStackResult sendFanResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+ pResponse->setResourceRepresentation(myRoomResource.getFanRepresentation());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ return OCPlatform::sendResponse(pResponse);
}
-int main()
+
+OCEntityHandlerResult entityHandlerFan(std::shared_ptr<OCResourceRequest> request)
{
+ cout << "\tIn Server CPP (Fan) entity handler:\n";
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+ if(prepareFanResponse(request))
+ {
+ if(OC_STACK_OK == sendFanResponse(request))
+ {
+ ehResult = OC_EH_OK;
+ }
+ else
+ {
+ std::cout << "sendFanResponse failed." << std::endl;
+ }
+ }
+ else
+ {
+ std::cout << "PrepareFanResponse failed." << std::endl;
+ }
+
+ return ehResult;
+}
+
+void printUsage()
+{
+ std::cout << std::endl;
+ std::cout << "Usage : roomserver <value>\n";
+ std::cout << "1 : Create room resource with default collection entity handler.\n";
+ std::cout << "2 : Create room resource with application collection entity handler.\n";
+}
+
+int main(int argc, char* argv[])
+{
+ printUsage();
+
+ if(argc == 2)
+ {
+ int value = atoi(argv[1]);
+ switch (value)
+ {
+ case 1:
+ useDefaultCollectionEH = true;
+ break;
+ case 2:
+ default:
+ break;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+
// Create PlatformConfig object
PlatformConfig cfg {
OC::ServiceType::InProc,
myRoomResource.createResources();
- // Perform app tasks
- while(true)
- {
- // some tasks
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
+
}
catch(OCException e)
{
// No explicit call to stop the platform.
// When OCPlatform destructor is invoked, internally we do platform cleanup
+
+ return 0;
}
#include <string>
#include <cstdlib>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
#include "OCPlatform.h"
#include "OCApi.h"
}
else
{
- std::cout << "onPost Response error: " << eCode << std::endl;
+ std::cout << "onPost2 Response error: " << eCode << std::endl;
std::exit(-1);
}
}
OCPlatform::Configure(cfg);
try
{
+ // makes it so that all boolean values are printed as 'true/false' in this stream
+ std::cout.setf(std::ios::boolalpha);
// Find all resources
OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource);
std::cout<< "Finding Resource... " <<std::endl;
- while(true)
- {
- // some operations
- }
+
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}catch(OCException& e)
{
#include <string>
#include <cstdlib>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
#include "OCPlatform.h"
#include "OCApi.h"
}
else
{
- std::cout << "onPost Response error: " << eCode << std::endl;
+ std::cout << "onPost2 Response error: " << eCode << std::endl;
std::exit(-1);
}
}
OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource,
OC::QualityOfService::LowQos);
std::cout<< "Finding Resource... " <<std::endl;
- while(true)
- {
- // some operations
- }
+
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}catch(OCException& e)
{
uint8_t resourceProperty = OC_DISCOVERABLE;
EntityHandler eh(std::bind(&FooResource::entityHandler,
- this, std::placeholders::_1, std::placeholders::_2));
+ this, std::placeholders::_1));
OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
resourceURI, resourceTypeName,
resourceInterface,
rep.getValue("barCount", m_barCount);
}
- OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+ OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
+ {
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+ pResponse->setResourceRepresentation(get(), "");
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ return OCPlatform::sendResponse(pResponse);
+ }
+
+ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
std::cout<<"\tConsumer Entity Handler:"<<std::endl;
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if(request)
{
- // Note: Most of the handlers are not here, since this is for demoing client/server co-process existence.
+ // Note: Most of the handlers are not here, since this is for
+ // demoing client/server co-process existence.
// See simpleserver for a more complete example.
if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
{
if(request->getRequestType() == "GET")
{
std::cout<<"\t\t\trequestType : GET"<<std::endl;
-
- if(response)
+ if(OC_STACK_OK == sendResponse(request))
{
- response->setErrorCode(200);
- response->setResourceRepresentation(get(), "");
+ ehResult = OC_EH_OK;
}
}
else if (request->getRequestType() == "PUT")
OCRepresentation rep = request->getResourceRepresentation();
put(rep);
-
- if(response)
+ if(OC_STACK_OK == sendResponse(request))
{
- response->setErrorCode(200);
- response->setResourceRepresentation(get(), "");
+ ehResult = OC_EH_OK;
}
}
else
{
- std::cout<<"\t\t\trequestType : UNSUPPORTED: "<<request->getRequestType()<<std::endl;
+ std::cout<<"\t\t\trequestType : UNSUPPORTED: "<<
+ request->getRequestType()<<std::endl;
}
}
else
std::cout << "Request Invalid!"<<std::endl;
}
- return OC_EH_OK;
+ return ehResult;
}
};
+
int main()
{
PlatformConfig cfg {
{
std::cout<< "Exception in main: "<<e.what()<<std::endl;
}
+
+ return 0;
}
#include <functional>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
#include "OCPlatform.h"
#include "OCApi.h"
int gObservation = 0;
void * ChangeLightRepresentation (void *param);
+void * handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
// Specifies where to notify all observers or list of observers
// false: notifies all observers
// true: secure resource
bool isSecure = false;
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
+
// Forward declaring the entityHandler
/// This class represents a single resource named 'lightResource'. This resource has
/// This function internally calls registerResource API.
void createResource()
{
- std::string resourceURI = m_lightUri; // URI of the resource
- std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light
+ std::string resourceURI = m_lightUri; //URI of the resource
+ std::string resourceTypeName = "core.light"; //resource type name. In this case, it is light
std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
// OCResourceProperty is defined ocstack.h
{
resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
}
- EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
// This will internally create and register the resource.
OCStackResult result = OCPlatform::registerResource(
{
resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
}
- EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
OCResourceHandle resHandle;
private:
// This is just a sample implementation of entity handler.
// Entity handler can be implemented in several ways by the manufacturer
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
- OCEntityHandlerResult result = OC_EH_OK;
-
cout << "\tIn Server CPP entity handler:\n";
-
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if(request)
{
// Get the request type and request flag
if(requestFlag & RequestHandlerFlag::RequestFlag)
{
cout << "\t\trequestFlag : Request\n";
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
// If the request type is GET
if(requestType == "GET")
{
cout << "\t\t\trequestType : GET\n";
-
- if(response)
+ if(isSlowResponse) // Slow response case
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(get());
+ static int startedThread = 0;
+ if(!startedThread)
+ {
+ std::thread t(handleSlowResponse, (void *)this, request);
+ startedThread = 1;
+ t.detach();
+ }
+ ehResult = OC_EH_SLOW;
+ }
+ else // normal response case.
+ {
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(get());
+ if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
}
}
else if(requestType == "PUT")
{
cout << "\t\t\trequestType : PUT\n";
-
OCRepresentation rep = request->getResourceRepresentation();
// Do related operations related to PUT request
-
// Update the lightResource
put(rep);
-
- if(response)
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(get());
+ if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(get());
+ ehResult = OC_EH_OK;
}
-
}
else if(requestType == "POST")
{
OCRepresentation rep = request->getResourceRepresentation();
// Do related operations related to POST request
-
OCRepresentation rep_post = post(rep);
-
- if(response)
+ pResponse->setResourceRepresentation(rep_post);
+ pResponse->setErrorCode(200);
+ if(rep_post.hasAttribute("createduri"))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(rep_post);
-
- if(rep_post.hasAttribute("createduri"))
- {
- result = OC_EH_RESOURCE_CREATED;
-
- response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
- }
-
+ pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+ pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
}
- // POST request operations
+ if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
}
else if(requestType == "DELETE")
{
pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
startedThread = 1;
}
+ ehResult = OC_EH_OK;
}
}
else
std::cout << "Request invalid" << std::endl;
}
- return result;
+ return ehResult;
}
};
return NULL;
}
+void * handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+ // This function handles slow response case
+ LightResource* lightPtr = (LightResource*) param;
+ // Induce a case for slow response by using sleep
+ std::cout << "SLOW response" << std::endl;
+ sleep (10);
+
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+ pResponse->setResourceRepresentation(lightPtr->get());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ // Set the slow response flag back to false
+ isSlowResponse = false;
+ OCPlatform::sendResponse(pResponse);
+ return NULL;
+}
+
void PrintUsage()
{
std::cout << std::endl;
- std::cout << "Usage : simpleserver < secure resource and observer >\n";
+ std::cout << "Usage : simpleserver <value>\n";
std::cout << " Default - Non-secure resource and notify all observers\n";
std::cout << " 1 - Non-secure resource and notify list of observers\n\n";
std::cout << " 2 - Secure resource and notify all observers\n";
std::cout << " 3 - Secure resource and notify list of observers\n\n";
+ std::cout << " 4 - Non-secure resource, GET slow response, notify all observers\n";
}
-int main(int argc, char* argv[1])
+int main(int argc, char* argv[])
{
PrintUsage();
isListOfObservers = true;
isSecure = true;
break;
+ case 4:
+ isSlowResponse = true;
default:
break;
}
OCPlatform::Configure(cfg);
try
{
- // Create the instance of the resource class (in this case instance of class 'LightResource').
+ // Create the instance of the resource class
+ // (in this case instance of class 'LightResource').
LightResource myLight;
// Invoke createResource function of class light.
myLight.addType(std::string("core.brightlight"));
myLight.addInterface(std::string("oc.mi.ll"));
- // Perform app tasks
- while(true)
- {
- // some tasks
- }
+
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
catch(OCException e)
{
// No explicit call to stop the platform.
// When OCPlatform::destructor is invoked, internally we do platform cleanup
+
+ return 0;
}
#include <functional>
#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
#include "OCPlatform.h"
#include "OCApi.h"
// 1 - notifies list of observers
int isListOfObservers = 0;
-// Forward declaring the entityHandler
-
/// This class represents a single resource named 'lightResource'. This resource has
/// two simple properties named 'state' and 'power'
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
- EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
// This will internally create and register the resource.
OCStackResult result = OCPlatform::registerResource(
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
- EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
OCResourceHandle resHandle;
if(OC_STACK_OK == createResource1())
{
std::cout << "Created a new resource\n";
-
OCRepresentation rep1;
rep1.setValue("createduri", std::string("/a/light1"));
}
private:
+
+OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+ pResponse->setResourceRepresentation(get());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ return OCPlatform::sendResponse(pResponse);
+}
+
+OCStackResult sendPostResponse(std::shared_ptr<OCResourceRequest> pRequest)
+{
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+
+ OCRepresentation rep = pRequest->getResourceRepresentation();
+ OCRepresentation rep_post = post(rep);
+
+ pResponse->setResourceRepresentation(rep_post);
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ return OCPlatform::sendResponse(pResponse);
+}
+
// This is just a sample implementation of entity handler.
// Entity handler can be implemented in several ways by the manufacturer
-OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
cout << "\tIn Server CPP entity handler:\n";
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if(request)
{
if(requestFlag & RequestHandlerFlag::InitFlag)
{
cout << "\t\trequestFlag : Init\n";
-
// entity handler to perform resource initialization operations
}
if(requestFlag & RequestHandlerFlag::RequestFlag)
if(requestType == "GET")
{
cout << "\t\t\trequestType : GET\n";
-
- if(response)
+ if(OC_STACK_OK == sendResponse(request))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(get());
+ ehResult = OC_EH_OK;
}
}
else if(requestType == "PUT")
cout << "\t\t\trequestType : PUT\n";
OCRepresentation rep = request->getResourceRepresentation();
-
// Do related operations related to PUT request
-
// Update the lightResource
put(rep);
-
- if(response)
+ if(OC_STACK_OK == sendResponse(request))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(get());
+ ehResult = OC_EH_OK;
}
-
}
else if(requestType == "POST")
{
cout << "\t\t\trequestType : POST\n";
-
- OCRepresentation rep = request->getResourceRepresentation();
-
- // Do related operations related to POST request
-
- OCRepresentation rep_post = post(rep);
-
- if(response)
+ if(OC_STACK_OK == sendPostResponse(request))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(rep_post);
+ ehResult = OC_EH_OK;
}
-
- // POST request operations
}
else if(requestType == "DELETE")
{
pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
startedThread = 1;
}
+ ehResult = OC_EH_OK;
}
}
else
std::cout << "Request invalid" << std::endl;
}
- return OC_EH_OK;
+ return ehResult;
}
};
}
-int main(int argc, char* argv[1])
+int main(int argc, char* argv[])
{
PrintUsage();
myLight.addType(std::string("core.brightlight"));
myLight.addInterface(std::string("oc.mi.ll"));
- // Perform app tasks
- while(true)
- {
- // some tasks
- }
+
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
catch(OCException e)
{
// No explicit call to stop the platform.
// When OCPlatform destructor is invoked, internally we do platform cleanup
+
+ return 0;
}
uint8_t resourceProperty = OC_DISCOVERABLE;
EntityHandler eh(std::bind(&FooResource::entityHandler, this,
- std::placeholders::_1, std::placeholders::_2));
+ std::placeholders::_1));
OCStackResult result = OCPlatform::registerResource(m_resourceHandle, m_uri,
m_resourceType, resourceInterface, eh, resourceProperty);
if(OC_STACK_OK != result)
rep.getValue("barCount", m_barCount);
}
- OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+ OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
+ {
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+ pResponse->setResourceRepresentation(get(), "");
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ return OCPlatform::sendResponse(pResponse);
+ }
+
+ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
std::cout<<"\tConsumer Entity Handler:"<<std::endl;
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if(request)
{
if(request->getRequestType() == "GET")
{
std::cout<<"\t\t\trequestType : GET"<<std::endl;
-
- if(response)
+ if(OC_STACK_OK == sendResponse(request))
{
- response->setErrorCode(200);
- response->setResourceRepresentation(get(), "");
+ ehResult = OC_EH_OK;
}
}
else if (request->getRequestType() == "PUT")
OCRepresentation rep = request->getResourceRepresentation();
put(rep);
-
- if(response)
+ if(OC_STACK_OK == sendResponse(request))
{
- response->setErrorCode(200);
- response->setResourceRepresentation(get(), "");
+ ehResult = OC_EH_OK;
}
}
else
std::cout << "Request Invalid!"<<std::endl;
}
- return OC_EH_OK;
+ return ehResult;
}
-
};
void putResourceInfo(const HeaderOptions& headerOptions,
const OCRepresentation rep, const OCRepresentation rep2, const int eCode)
{
- bool m_isFoo;
- int m_barCount;
+ bool m_isFoo = false;
+ int m_barCount = 0;
std::cout << "In PutResourceInfo" << std::endl;
std::cout <<"Clientside Put response to get was: "<<std::endl;
const OCRepresentation rep,
const int eCode)
{
- bool m_isFoo;
- int m_barCount;
+ bool m_isFoo = false;
+ int m_barCount = 0;
std::cout << "In getResourceInfo" << std::endl;
std::cout<<"Clientside response to get was: "<<std::endl;
std::cout<<"result1:" << OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.foo",
foundResource1)<< std::endl;
- while(1)
- {
- // client1 related operations
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
void client2()
"coap://224.0.1.187/oc/core?rt=core.foo",
foundResource2)<< std::endl;
- while(1)
- {
- // client2 related operations
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
void server()
return;
}
- while(1)
- {
- // server related operations
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
int main()
std::thread t2(client2);
t2.detach();
- while(1)
- {
- // server related operations
- }
+ // A condition variable will free the mutex it is given, then do a non-
+ // intensive block until 'notify' is called on it. In this case, since we
+ // don't ever call cv.notify, this should be a non-processor intensive version
+ // of while(true);
+ std::mutex blocker;
+ std::condition_variable cv;
+ std::unique_lock<std::mutex> lock(blocker);
+ cv.wait(lock);
}
catch(OCException& e)
{
--- /dev/null
+
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file AttributeValue.h
+
+/// @brief This file contains the definition of the internally used
+// type AttributeValue
+
+#ifndef __ATTRIBUTEVALUE_H
+#define __ATTRIBUTEVALUE_H
+
+// These defines are required to get the boost::variant to hold more than 20 items.
+// documentation requires that you use a power of 10
+#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#define BOOST_MPL_LIMIT_LIST_SIZE 30
+#define BOOST_MPL_LIMIT_VECTOR_SIZE 30
+#include <boost/variant.hpp>
+
+namespace OC
+{
+ class OCRepresentation;
+
+ struct NullType{};
+ // Since null needs to be encoded in a special fashion in JSON, the encoder
+ // needs to know the index of the NullType Sentinel Any time the code does a special
+ // case for the NullType, we use the AttributeValueNullIndex. This MUST be kept up to date
+ // with the variant's which() for NullType.
+ static const int AttributeValueNullIndex = 0;
+ typedef boost::variant<
+
+ // Base values:
+ NullType, // Note: this handles the null-type and must match the above static const
+ int,
+ double,
+ bool,
+ std::string,
+ OC::OCRepresentation,
+
+ // Sequences:
+ std::vector<int>,
+ std::vector<double>,
+ std::vector<bool>,
+ std::vector<std::string>,
+ std::vector<OC::OCRepresentation>,
+
+ // Nested sequences:
+ 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<OC::OCRepresentation>>,
+ std::vector<std::vector<std::vector<OC::OCRepresentation>>>
+ > AttributeValue;
+
+}
+#endif // __ATTRIBUTEVALUE_H
class IClientWrapper : public std::enable_shared_from_this<IClientWrapper>
{
protected:
- OCPlatform_impl& m_owner;
public:
typedef std::shared_ptr<IClientWrapper> Ptr;
- IClientWrapper(OCPlatform_impl& owner)
- : m_owner(owner)
+ IClientWrapper()
{}
virtual OCStackResult ListenForResource(const std::string& serviceUrl,
virtual OCStackResult GetDefaultQos(QualityOfService& qos) = 0;
virtual ~IClientWrapper(){}
-
-
- // Note: this should never be called by anyone but the handler for the listen command.
- // It is public becuase that needs to be a non-instance callback
- virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper,
- OCDevAddr& addr, const boost::property_tree::ptree resourceNode)=0;
- private:
};
}
class IServerWrapper
{
protected:
- OCPlatform_impl& m_owner;
public:
typedef std::shared_ptr<IServerWrapper> Ptr;
- IServerWrapper(OCPlatform_impl& owner)
- : m_owner(owner)
+ IServerWrapper()
{}
virtual ~IServerWrapper(){};
virtual OCStackResult stopPresence() = 0;
virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler) = 0;
+
+ virtual OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse) = 0;
};
}
#include <sstream>
#include <iostream>
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-
#include <OCApi.h>
#include <ocstack.h>
#include <IClientWrapper.h>
namespace OC
{
- class InProcClientWrapper : public IClientWrapper
+ namespace ClientCallbackContext
{
+ struct GetContext
+ {
+ GetCallback callback;
+ };
- public:
- enum OCSecureType
+ struct SetContext
+ {
+ PutCallback callback;
+ };
+
+ struct ListenContext
+ {
+ FindCallback callback;
+ std::weak_ptr<IClientWrapper> clientWrapper;
+ };
+
+ struct SubscribePresenceContext
{
- IPV4Secure,
- IPV4
+ SubscribeCallback callback;
};
- InProcClientWrapper(OC::OCPlatform_impl& owner, std::weak_ptr<std::recursive_mutex> csdkLock,
+ struct DeleteContext
+ {
+ DeleteCallback callback;
+ };
+
+ struct ObserveContext
+ {
+ ObserveCallback callback;
+ };
+ }
+
+ class InProcClientWrapper : public IClientWrapper
+ {
+
+ public:
+
+ InProcClientWrapper(std::weak_ptr<std::recursive_mutex> csdkLock,
PlatformConfig cfg);
virtual ~InProcClientWrapper();
const std::string& resourceType, SubscribeCallback& presenceHandler);
virtual OCStackResult UnsubscribePresence(OCDoHandle handle);
- // Note: this should never be called by anyone but the handler for the listen command.
- // It is public becuase that needs to be a non-instance callback
- virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper,
- OCDevAddr& addr, const boost::property_tree::ptree resourceNode);
-
OCStackResult GetDefaultQos(QualityOfService& QoS);
private:
- std::string convertOCAddrToString(OCDevAddr& addr,
- OCSecureType type, const std::string &portStr = std::string());
void listeningFunc();
std::string assembleSetResourceUri(std::string uri, const QueryParamsMap& queryParams);
std::string assembleSetResourcePayload(const OCRepresentation& attributes);
std::weak_ptr<std::recursive_mutex> m_csdkLock;
private:
- OC::OCPlatform_impl& m_owner;
PlatformConfig m_cfg;
};
}
class InProcServerWrapper : public IServerWrapper
{
public:
- InProcServerWrapper(OC::OCPlatform_impl& owner, std::weak_ptr<std::recursive_mutex> csdkLock,
+ InProcServerWrapper(
+ std::weak_ptr<std::recursive_mutex> csdkLock,
PlatformConfig cfg);
virtual ~InProcServerWrapper();
virtual OCStackResult stopPresence();
virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler);
+
+ virtual OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
private:
void processFunc();
std::thread m_processThread;
#include <memory>
#include <iterator>
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-#include <boost/variant.hpp>
-
#include "ocstack.h"
#include "OCHeaderOption.h"
#include <OCException.h>
#include "StringConstants.h"
#include "oc_logger.hpp"
+#include <OCRepresentation.h>
+
namespace OC
{
class OCResource;
Observe,
ObserveAll
};
-
- // Helper function to escape character in a string.
- std::string escapeString(const std::string& value);
-
- typedef std::map<std::string, std::string> AttributeMap;
-
- class OCRepresentation
- {
- private:
- std::string m_uri;
- AttributeMap m_attributeMap;
- std::vector<std::string> m_resourceTypes;
- std::vector<std::string> m_resourceInterfaces;
- int errorCode;
-
- std::vector<OCRepresentation> m_children;
-
- public:
- OCRepresentation() {}
-
- bool erase(const std::string& str)
- {
- return m_attributeMap.erase(str) != 0;
- }
-
- std::string getUri(void) const
- {
- return m_uri;
- }
-
- template <typename T>
- void setValue(const std::string& str, const T& val);
-
- template <typename T>
- bool getValue(const std::string& str, T& val) const;
-
- template <typename T>
- T getValue(const std::string& str) const;
-
- bool hasAttribute(const std::string& str) const
- {
- return m_attributeMap.find(str) != m_attributeMap.end();
- }
-
- void setNULL(const std::string& str)
- {
- m_attributeMap[str] = "null";
- }
-
- bool isNULL(const std::string& str) const
- {
- auto x = m_attributeMap.find(str);
-
- if(m_attributeMap.end() != x)
- {
- return x->second.compare("null") == 0;
- }
- else
- {
- std::ostringstream message;
- message << "attribute: " << str << " doesn't exist\n";
- throw OCException(message.str());
- }
-
- return false;
- }
-
- int numberOfAttributes() const
- {
- return m_attributeMap.size();
- }
-
- void setUri(std::string uri)
- {
- m_uri = uri;
- }
-
- std::vector<OCRepresentation> getChildren(void) const
- {
- return m_children;
- }
-
- void setChildren(const std::vector<OCRepresentation>& children)
- {
- m_children = children;
- }
-
- std::weak_ptr<OCResource> getResource() const
- {
- // TODO Needs to be implemented
- std::weak_ptr<OCResource> wp;
- return wp;
- }
-
- AttributeMap getAttributeMap() const
- {
- return m_attributeMap;
- }
-
- void setAttributeMap(const AttributeMap& map)
- {
- m_attributeMap = map;
- }
-
- std::string getJSONRepresentation(void) const
- {
- std::ostringstream json;
-
- json << "{";
-
- for(auto itr = m_attributeMap.begin(); itr!= m_attributeMap.end(); ++ itr)
- {
- if(itr != m_attributeMap.begin())
- {
- json << ',';
- }
- json << "\""<<itr->first<<"\":"<< itr->second;
- }
- json << "}";
-
- return json.str();
- }
-
- std::vector<std::string> getResourceTypes() const
- {
- return m_resourceTypes;
- }
-
- void setResourceTypes(const std::vector<std::string>& resourceTypes)
- {
- m_resourceTypes = resourceTypes;
- }
-
- std::vector<std::string> getResourceInterfaces(void) const
- {
- return m_resourceInterfaces;
- }
-
- void setResourceInterfaces(const std::vector<std::string>& resourceInterfaces)
- {
- m_resourceInterfaces = resourceInterfaces;
- }
- };
-
- OCRepresentation parseJSONToRepresentation(const std::string& str);
-
- inline OCRepresentation parseJSONToRepresentation(const std::string& str)
- {
- OCRepresentation rep;
-
- AttributeMap attributeMap;
-
- std::stringstream requestStream;
- requestStream << str;
- boost::property_tree::ptree payload;
- try
- {
- boost::property_tree::read_json(requestStream, payload);
- }
- catch(boost::property_tree::json_parser::json_parser_error &e)
- {
- throw OCException(OC::Exception::GENERAL_JSON_PARSE_FAILED);
- }
-
- for(auto& item: payload)
- {
- std::string name = item.first.data();
- std::string value = item.second.data();
-
- attributeMap[name] = value;
- }
-
- rep.setAttributeMap(attributeMap);
-
- return rep;
- }
-
- typedef boost::variant<
- int,
- double,
- bool,
- OCRepresentation,
- std::string,
- std::vector<int>,
- std::vector<double>,
- std::vector<bool>,
- std::vector<std::string>,
- std::vector<OCRepresentation>
- > AttributeValue;
-
- template <typename T>
- inline std::string getJSONFromVector(const std::vector<T>& v)
- {
- std::ostringstream json;
-
- json << "\"[";
- if(v.size() != 0)
- {
- std::copy(v.begin(), v.end() - 1, std::ostream_iterator<T>(json, ","));
- json << v.back();
- }
- json << "]\"";
-
- return json.str();
- }
-
- class ComposeVisitor : public boost::static_visitor<std::string>
- {
- public:
-
- // TODO different int sizes
- std::string operator() (const int i) const
- {
- return std::to_string(i);
- }
-
- std::string operator() (const double d) const
- {
- return std::to_string(d);
- }
-
- std::string operator() (const std::string& str) const
- {
- std::ostringstream json;
- json << "\"";
- json << str;
- json << "\"";
-
- return json.str();
- }
-
- std::string operator() (const bool b) const
- {
- if(b)
- {
- return "true";
- }
- else
- {
- return "false";
- }
- }
-
- std::string operator() (const std::vector<int>& numbers) const
- {
- return getJSONFromVector(numbers);
- }
-
- std::string operator() (const std::vector<double>& numbers) const
- {
- return getJSONFromVector(numbers);
- }
-
- std::string operator() (const std::vector<bool>& bools) const
- {
- std::ostringstream json;
- int first = 1;
-
- json << "\"[";
- for(auto b: bools)
- {
- if(first)
- {
- b ? json << "true" : json << "false";
- first = 0;
- }
- else
- {
- b ? json << ",true" : json << ",false";
- }
- }
- json << "]\"";
-
- return json.str();
- }
-
- std::string operator() (const std::vector<std::string>& strings) const
- {
- return getJSONFromVector(strings);
- }
-
- std::string operator() (const OCRepresentation& rep) const
- {
- std::ostringstream json;
-
- json << "\"";
-
- json << escapeString(rep.getJSONRepresentation());
-
- json << "\"";
-
- return json.str();
- }
-
- std::string operator() (const std::vector<OCRepresentation>& reps) const
- {
- std::ostringstream json;
- int first = 1;
-
- json << "\"[";
- for(auto rep: reps)
- {
- if(first)
- {
- first = 0;
- json << escapeString(rep.getJSONRepresentation());
- }
- else
- {
- json << ",";
- json << escapeString(rep.getJSONRepresentation());
- }
- }
- json << "]\"";
-
- return json.str();
- }
-
-
- };
-
- inline void split(std::string input, char delimiter, std::vector<std::string>& tokens)
- {
- std::stringstream ss(input);
- std::string item;
-
- while(std::getline(ss, item, delimiter))
- {
- tokens.push_back(item);
- }
- }
-
- class ParseVisitor : public boost::static_visitor<void>
- {
- public:
-
- ParseVisitor(std::string str): m_str(str)
- {
- }
-
- void operator() (int& i) const
- {
- i = std::stoi(m_str);
- }
-
- void operator() (double& d) const
- {
- d = std::stod(m_str);
- }
-
- void operator() (std::string& str) const
- {
- str = m_str;
- }
-
- void operator() (bool& b) const
- {
- b = m_str.compare("true") == 0;
- }
-
- void operator() (std::vector<int>& numbers) const
- {
- numbers.clear();
-
- if(m_str.length() >= 2)
- {
- std::string str = m_str.substr(1, m_str.length()-2);
-
- std::vector<std::string> tokens;
- split(str, ',', tokens);
-
- for(auto s: tokens)
- {
- numbers.push_back(std::stoi(s));
- }
- }
- else
- {
- throw OCException(OC::Exception::INVALID_ARRAY);
- }
-
- }
-
- void operator() (std::vector<double>& numbers) const
- {
- numbers.clear();
-
- if(m_str.length() >= 2)
- {
- std::string str = m_str.substr(1, m_str.length()-2);
- std::vector<std::string> tokens;
- split(str, ',', tokens);
-
- for(auto s: tokens)
- {
- numbers.push_back(std::stod(s));
- }
- }
- else
- {
- throw OCException(OC::Exception::INVALID_ARRAY);
- }
- }
-
- void operator() (std::vector<bool>& bools) const
- {
- bools.clear();
-
- if(m_str.length() >= 2)
- {
- std::string str = m_str.substr(2, m_str.length()-3);
-
- std::vector<std::string> tokens;
- split(str, ',', tokens);
-
- for(auto s: tokens)
- {
- bools.push_back(s.compare("true") == 0);
- }
- }
- else
- {
- throw OCException(OC::Exception::INVALID_ARRAY);
- }
-
- }
-
- void operator() (std::vector<std::string>& strings) const
- {
- strings.clear();
-
- if(m_str.length() >= 2)
- {
- std::string str = m_str.substr(1, m_str.length()-2);
-
- std::vector<std::string> tokens;
- split(str, ',', tokens);
-
- for(auto s: tokens)
- {
- strings.push_back(s);
- }
- }
- else
- {
- throw OCException(OC::Exception::INVALID_ARRAY);
- }
- }
-
- void operator() (std::vector<OCRepresentation>& reps) const
- {
- reps.clear();
-
- if(m_str.length() >= 2)
- {
- std::string str = m_str.substr(1, m_str.length()-2);
-
- std::vector<std::string> tokens;
- split(str, ',', tokens);
-
- for(auto s: tokens)
- {
- reps.push_back(parseJSONToRepresentation(s));
- }
- }
- else
- {
- throw OCException(OC::Exception::INVALID_ARRAY);
- }
- }
-
- void operator() (OCRepresentation& rep) const
- {
- rep = parseJSONToRepresentation(m_str);
- }
-
- private:
- std::string m_str;
- };
-
-
- inline std::string getJSON(const AttributeValue& v)
- {
- return boost::apply_visitor(ComposeVisitor(), v);
- }
-
- inline void parseJSON(AttributeValue& v, std::string str)
- {
- boost::apply_visitor(ParseVisitor(str), v);
- }
-
- template <typename T>
- void OCRepresentation::setValue(const std::string& str, const T& val)
- {
- m_attributeMap[str] = getJSON(val);
- }
-
- template <typename T>
- T OCRepresentation::getValue(const std::string& str) const
- {
- T val = T();
-
- auto x = m_attributeMap.find(str);
-
- if(m_attributeMap.end() != x)
- {
- AttributeValue v = val;
- parseJSON(v, x->second);
- val = boost::get<T>(v);
- }
-
- return val;
- }
-
- template <typename T>
- bool OCRepresentation::getValue(const std::string& str, T& val) const
- {
- auto x = m_attributeMap.find(str);
-
- if(m_attributeMap.end() != x)
- {
- AttributeValue v = val;
- parseJSON(v, x->second);
- val = boost::get<T>(v);
- return true;
- }
- else
- {
- return false;
- }
- }
-
+ //
// Typedef for header option vector
// OCHeaderOption class is in HeaderOption namespace
typedef std::vector<HeaderOption::OCHeaderOption> HeaderOptions;
typedef std::function<void(std::shared_ptr<OCResource>)> FindCallback;
- typedef std::function<OCEntityHandlerResult (const std::shared_ptr<OCResourceRequest>,
- const std::shared_ptr<OCResourceResponse>)> EntityHandler;
+ typedef std::function<OCEntityHandlerResult(
+ const std::shared_ptr<OCResourceRequest>)> EntityHandler;
- typedef std::function<void(OCStackResult, const unsigned int)> SubscribeCallback;
+ typedef std::function<void(OCStackResult, const unsigned int,
+ const std::string&)> SubscribeCallback;
typedef std::function<void(const HeaderOptions&,
const OCRepresentation&, const int)> GetCallback;
bool isObservable, const std::vector<std::string>& resourceTypes,
const std::vector<std::string>& interfaces);
-
-
+ /**
+ * 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>
+ */
+ OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
}
}
bool isObservable, const std::vector<std::string>& resourceTypes,
const std::vector<std::string>& interfaces);
+ /**
+ * 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>
+ */
+ OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
+
private:
PlatformConfig m_cfg;
OCPlatform_impl(const PlatformConfig& config);
/**
- * Private function to initalize the platfrom
+ * Private function to initalize the platfrom
*/
void init(const PlatformConfig& config);
/**
- * Private constructor/operators to prevent copying
- * of this object
- */
+ * Private constructor/operators to prevent copying
+ * of this object
+ */
OCPlatform_impl(const OCPlatform_impl& other)= delete;
OCPlatform_impl& operator=(const OCPlatform_impl&) = delete;
OCPlatform_impl& operator=(const OCPlatform_impl&&) = delete;
/// @file OCRepresentation.h
-/// @brief This file contains the declaration of classes and its members
+/// @brief This file contains the declaration of classes and its members
/// related to OCRepresentation
#ifndef __OCREPRESENTATION_H
#define __OCREPRESENTATION_H
-#include <OCApi.h>
-#include <OCResource.h>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <map>
+
+#include <AttributeValue.h>
+#include <StringConstants.h>
+
+#include <OCException.h>
+
+
+namespace cereal
+{
+ class access;
+}
namespace OC
{
-
+
+ enum class InterfaceType
+ {
+ None,
+ LinkParent,
+ BatchParent,
+ DefaultParent,
+ LinkChild,
+ BatchChild,
+ DefaultChild
+ };
+
+ // The consumer requires resource info to be printed in 2 different ways, both with the "oc":[]
+ // and without. This enum is used to differentiate between the two situations. When the
+ // serialize is called with Include OC, we encode OC, otherwise we skip it and return just the
+ // contents of the array.
+ enum class OCInfoFormat
+ {
+ IncludeOC,
+ ExcludeOC
+ };
+
+ class MessageContainer
+ {
+ public:
+ void setJSONRepresentation(const std::string& payload);
+
+ void setJSONRepresentation(const unsigned char* payload);
+
+ std::string getJSONRepresentation(OCInfoFormat f) const;
+
+ const std::vector<OCRepresentation>& representations() const;
+
+ void addRepresentation(const OCRepresentation& rep);
+
+ const OCRepresentation& operator[](int index) const
+ {
+ return m_reps[index];
+ }
+
+ const OCRepresentation& back() const
+ {
+ return m_reps.back();
+ }
+ private:
+ std::vector<OCRepresentation> m_reps;
+ };
+ class OCRepresentation
+ {
+ public:
+ OCRepresentation();
+ std::string getJSONRepresentation() const;
+
+ void addChild(const OCRepresentation&);
+
+ void clearChildren();
+
+ const std::vector<OCRepresentation>& getChildren() const;
+
+ void setChildren(const std::vector<OCRepresentation>& children);
+
+ void setUri(const std::string& uri);
+
+ std::string getUri() const;
+
+ const std::vector<std::string>& getResourceTypes() const;
+
+ void setResourceTypes(const std::vector<std::string>& resourceTypes);
+
+ const std::vector<std::string>& getResourceInterfaces() const;
+
+ void setResourceInterfaces(const std::vector<std::string>& resourceInterfaces);
+
+ bool empty() const;
+
+ int numberOfAttributes() const;
+
+ bool erase(const std::string& str);
+
+ template <typename T>
+ void setValue(const std::string& str, const T& val)
+ {
+ m_values[str] = val;
+ }
+
+ template <typename T>
+ bool getValue(const std::string& str, T& val) const
+ {
+ auto x = m_values.find(str);
+
+ if(x!= m_values.end())
+ {
+ val = boost::get<T>(x->second);
+ return true;
+ }
+ else
+ {
+ val = T();
+ return false;
+ }
+ }
+
+ template <typename T>
+ T getValue(const std::string& str) const
+ {
+ T val = T();
+ auto x = m_values.find(str);
+ if(x != m_values.end())
+ {
+ val = boost::get<T>(x->second);
+ }
+ return val;
+ }
+
+ bool hasAttribute(const std::string& str) const;
+
+ void setNULL(const std::string& str);
+
+ bool isNULL(const std::string& str) const;
+ private:
+ friend class OCResourceResponse;
+ friend class cereal::access;
+
+ // the root node has a slightly different JSON version
+ // based on the interface type configured in ResourceResponse.
+ // This allows ResourceResponse to set it, so that the save function
+ // doesn't serialize things that it isn't supposed to serialize.
+ void setInterfaceType(InterfaceType ift)
+ {
+ m_interfaceType = ift;
+ }
+
+ // class used to wrap the 'prop' feature of the save/load
+ class Prop
+ {
+ public:
+ Prop(std::vector<std::string>& resourceTypes,
+ std::vector<std::string>& interfaces)
+ : m_types(resourceTypes), m_interfaces(interfaces)
+ {}
+
+ /* Prop(const std::vector<std::string>& resourceTypes,
+ const std::vector<std::string>& interfaces)
+ :m_types(resourceTypes),
+ m_interfaces(interfaces)
+ {}*/
+ private:
+ friend class cereal::access;
+ template <class Archive>
+ void save(Archive& ar) const;
+
+ template<class Archive>
+ void load(Archive& ar);
+
+ std::vector<std::string>& m_types;
+ std::vector<std::string>& m_interfaces;
+ };
+ template<class Archive, class Val>
+ static void optional_load(Archive& ar, Val&& v);
+
+ template<class Archive>
+ void save(Archive& ar) const;
+
+ template<class Archive>
+ void load(Archive& ar);
+
+ private:
+ std::string m_uri;
+ std::vector<OCRepresentation> m_children;
+ std::map<std::string, AttributeValue> m_values;
+ std::vector<std::string> m_resourceTypes;
+ std::vector<std::string> m_interfaces;
+
+ InterfaceType m_interfaceType;
+ };
} // namespace OC
+
#endif //__OCREPRESENTATION_H
#include <random>
#include <algorithm>
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-
#include <OCApi.h>
#include <ResourceInitException.h>
#include <IClientWrapper.h>
class OCResource
{
friend class OCPlatform_impl;
- friend class InProcClientWrapper;
-
+ friend class ListenOCContainer;
public:
typedef std::shared_ptr<OCResource> Ptr;
/**
#ifndef __OCRESOURCEREQUEST_H
#define __OCRESOURCEREQUEST_H
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/json_parser.hpp>
-
#include "OCApi.h"
#include "OCRepresentation.h"
+void formResourceRequest(OCEntityHandlerFlag,
+ OCEntityHandlerRequest*,
+ std::shared_ptr<OC::OCResourceRequest>);
+
+
namespace OC
{
/**
/**
* Provides the entire resource attribute representation
- * @return OCRepresentation reference containing the name value pairs representing the resource's attributes
+ * @return OCRepresentation reference containing the name value pairs
+ * representing the resource's attributes
*/
const OCRepresentation& getResourceRepresentation() const {return m_representation;}
return m_resourceUri;
}
- /** This API retrieves headerOptions which was sent from a client
+ /**
+ * This API retrieves headerOptions which was sent from a client
+ *
* @return std::map HeaderOptions with the header options
*/
- const HeaderOptions& getHeaderOptions() const {return m_headerOptions;}
+ const HeaderOptions& getHeaderOptions() const
+ {
+ return m_headerOptions;
+ }
+
+ /**
+ * This API retrieves the request handle
+ *
+ * @return OCRequestHandle
+ */
+ const OCRequestHandle& getRequestHandle() const
+ {
+ return m_requestHandle;
+ }
+
+ /**
+ * This API retrieves the resource handle
+ *
+ * return OCResourceHandle
+ */
+ const OCResourceHandle& getResourceHandle() const
+ {
+ return m_resourceHandle;
+ }
private:
std::string m_requestType;
OCRepresentation m_representation;
ObservationInfo m_observationInfo;
HeaderOptions m_headerOptions;
+ OCRequestHandle m_requestHandle;
+ OCResourceHandle m_resourceHandle;
- public:
- // TODO: This is not a public API for app developers.
- // This function will not be exposed in future
+
+ private:
+ friend void (::formResourceRequest)(OCEntityHandlerFlag, OCEntityHandlerRequest*,
+ std::shared_ptr<OC::OCResourceRequest>);
void setRequestType(const std::string& requestType)
{
m_requestType = requestType;
}
- // TODO: This is not a public API for app developers.
- // This function will not be exposed in future
void setPayload(const std::string& requestPayload)
{
- AttributeMap attributeMap;
- // TODO: The following JSON Parse implementation should be seperated into utitilites
- // and used wherever required.
- // e.g. parse(std::string& payload, Attributemap& attributeMap)
-
- std::stringstream requestStream;
- requestStream << requestPayload;
- boost::property_tree::ptree root;
- try
+ MessageContainer info;
+ info.setJSONRepresentation(requestPayload);
+
+ const std::vector<OCRepresentation>& reps = info.representations();
+ if(reps.size() >0)
{
- boost::property_tree::read_json(requestStream, root);
+ std::vector<OCRepresentation>::const_iterator itr = reps.begin();
+ std::vector<OCRepresentation>::const_iterator back = reps.end();
+ m_representation = *itr;
+ ++itr;
+
+ for(;itr != back; ++itr)
+ {
+ m_representation.addChild(*itr);
+ }
}
- catch(boost::property_tree::json_parser::json_parser_error &e)
+ else
{
- //TOD: log this
- return;
+ throw OCException(OC::Exception::INVALID_REPRESENTATION);
}
-
- // TODO this expects the representation oc:{} and not oc:[{}]
- // this representation is fine when setting for simple resource.
- boost::property_tree::ptree payload = root.get_child(OC::Key::OCKEY, boost::property_tree::ptree());
-
- for(auto& item: payload)
- {
- std::string name = item.first.data();
- std::string value = item.second.data();
-
- attributeMap[name] = value;
- }
-
- m_representation.setAttributeMap(attributeMap);
}
- // TODO: This is not a public API for app developers.
- // This function will not be exposed in future
void setQueryParams(QueryParamsMap& queryParams)
{
m_queryParameters = queryParams;
}
- // TODO: This is not a public API for app developers.
- // This function will not be exposed in future
void setRequestHandlerFlag(int requestHandlerFlag)
{
m_requestHandlerFlag = requestHandlerFlag;
}
- // TODO: This is not a public API for app developers.
- // This function will not be exposed in future
void setObservationInfo(const ObservationInfo& observationInfo)
{
m_observationInfo = observationInfo;
}
- // TODO: This is not a public API for app developers.
- // This function will not be exposed in future
void setHeaderOptions(const HeaderOptions& headerOptions)
{
m_headerOptions = headerOptions;
}
+
+ /**
+ * This API allows to set request handle
+ * @param requestHandle - OCRequestHandle type used to set the
+ * request handle
+ */
+ void setRequestHandle(const OCRequestHandle& requestHandle)
+ {
+ m_requestHandle = requestHandle;
+ }
+
+ /**
+ * This API allows to set the resource handle
+ * @param resourceHandle - OCResourceHandle type used to set the
+ * resource handle
+ */
+ void setResourceHandle(const OCResourceHandle& resourceHandle)
+ {
+ m_resourceHandle = resourceHandle;
+ }
+
};
}// namespace OC
namespace OC
{
+ class InProcServerWrapper;
+
/**
* @brief OCResourceResponse provides APIs to set the response details
*/
public:
typedef std::shared_ptr<OCResourceResponse> Ptr;
- /**
- * Default destructor
- */
- OCResourceResponse() {}
+ OCResourceResponse()
+ {}
- /**
- * Virtual destructor
- */
virtual ~OCResourceResponse(void) {}
/**
}
/**
+ * This API allows to set request handle
+ *
+ * @param requestHandle - OCRequestHandle type used to set the request handle
+ */
+ void setRequestHandle(const OCRequestHandle& requestHandle)
+ {
+ m_requestHandle = requestHandle;
+ }
+
+ /**
+ * This API allows to set the resource handle
+ *
+ * @param resourceHandle - OCResourceHandle type used to set the resource handle
+ */
+ void setResourceHandle(const OCResourceHandle& resourceHandle)
+ {
+ m_resourceHandle = resourceHandle;
+ }
+
+ /**
+ * This API allows to set the EntityHandler response result
+ *
+ * @param responseResult - OCEntityHandlerResult type to set the result value
+ */
+ void setResponseResult(const OCEntityHandlerResult& responseResult)
+ {
+ m_responseResult = responseResult;
+ }
+
+ /**
* API to set the entire resource attribute representation
* @param attributeMap reference containing the name value pairs representing
* the resource's attributes
* @param interface specifies the interface
*/
void setResourceRepresentation(OCRepresentation& rep, std::string interface) {
- if(!interface.compare(LINK_INTERFACE))
- {
- setResourceRepresentationLL(rep);
- }
- else if(!interface.compare(BATCH_INTERFACE))
- {
- setResourceRepresentationBatch(rep);
- }
- else
- {
- setResourceRepresentationDefault(rep);
- }
- // TODO other interfaces
+ m_interface = interface;
+ m_representation = rep;
}
/**
*/
void setResourceRepresentation(OCRepresentation& rep) {
// Call the default
- setResourceRepresentationDefault(rep);
+ m_interface = DEFAULT_INTERFACE;
+ m_representation = rep;
}
/**
// Call the above function
setResourceRepresentation(rep);
}
+ private:
+ std::string m_newResourceUri;
+ int m_errorCode;
+ HeaderOptions m_headerOptions;
+ std::string m_interface;
+ OCRepresentation m_representation;
+ OCRequestHandle m_requestHandle;
+ OCResourceHandle m_resourceHandle;
+ OCEntityHandlerResult m_responseResult;
- /**
- * API to set the entire resource attribute representation (Linked List Interface))
- * @param attributeMap reference containing the name value pairs representing the resource's
- * attributes
- */
- void setResourceRepresentationLL(OCRepresentation& rep) {
-
- // Default Set
-
- ostringstream payload;
-
- // Parent
- payload << "{";
- payload << "\"href\":";
- payload << "\"" ;
- payload << rep.getUri();
- payload << "\"" ;
- payload << "}";
+ private:
+ friend class InProcServerWrapper;
- // Children stuff
- std::vector<OCRepresentation> children = rep.getChildren();
+ std::string getPayload() const
+ {
+ MessageContainer inf;
+ OCRepresentation first(m_representation);
- for(auto oitr = children.begin(); oitr != children.end(); ++oitr)
+ if(m_interface==LINK_INTERFACE)
{
- payload << ",{\"href\":";
-
- payload << "\"" ;
- payload << oitr->getUri();
- payload << "\"" ;
-
- payload << ",\"prop\":{";
-
- payload << "\"rt\":[";
- std::vector<std::string> types = oitr->getResourceTypes();
- for(auto itr = types.begin(); itr != types.end(); ++itr)
- {
- if(itr != types.begin())
- {
- payload << ',';
- }
-
- payload << *itr;
- }
- payload << "],";
-
- payload << "\"if\":[";
- std::vector<std::string> interfaces = oitr->getResourceInterfaces();
- for(auto itr = interfaces.begin(); itr != interfaces.end(); ++itr)
- {
- if(itr != interfaces.begin())
- {
- payload << ',';
- }
-
- payload << "\"" << *itr << "\"";
- }
- payload << "]";
-
- payload << "}}";
+ first.setInterfaceType(InterfaceType::LinkParent);
}
-
- m_payload = payload.str();
- }
-
- /**
- * API to set the entire resource attribute representation (Default))
- * @param attributeMap reference containing the name value pairs representing the resource's
- * attributes
- */
- void setResourceRepresentationDefault(OCRepresentation& rep) {
-
- // Default Set
-
- ostringstream payload;
-
- // Parent
- payload << "{";
- payload << "\"href\":";
- payload << "\"" ;
- payload << rep.getUri();
- payload << "\"" ;
-
- payload << ",\"rep\":";
-
- payload << rep.getJSONRepresentation();
-
- payload << "}";
-
- // Children stuff
- std::vector<OCRepresentation> children = rep.getChildren();
-
- for(auto oitr = children.begin(); oitr != children.end(); ++oitr)
+ else if(m_interface==BATCH_INTERFACE)
{
- payload << ",{\"href\":";
+ first.setInterfaceType(InterfaceType::BatchParent);
+ }
+ else
+ {
+ first.setInterfaceType(InterfaceType::DefaultParent);
+ }
- payload << "\"" ;
- payload << oitr->getUri();
- payload << "\"" ;
+ inf.addRepresentation(first);
- payload << ",\"prop\":{";
+ for(const OCRepresentation& rep : m_representation.getChildren())
+ {
+ OCRepresentation cur(rep);
- payload << "\"rt\":[";
- std::vector<std::string> types = oitr->getResourceTypes();
- for(auto itr = types.begin(); itr != types.end(); ++itr)
+ if(m_interface==LINK_INTERFACE)
{
- if(itr != types.begin())
- {
- payload << ',';
- }
-
- payload << "\"" << *itr << "\"";
+ cur.setInterfaceType(InterfaceType::LinkChild);
}
- payload << "],";
-
- payload << "\"if\":[";
- std::vector<std::string> interfaces = oitr->getResourceInterfaces();
- for(auto itr = interfaces.begin(); itr != interfaces.end(); ++itr)
+ else if(m_interface==BATCH_INTERFACE)
{
- if(itr != interfaces.begin())
- {
- payload << ',';
- }
-
- payload << "\"" << *itr << "\"";
+ cur.setInterfaceType(InterfaceType::BatchChild);
+ }
+ else
+ {
+ cur.setInterfaceType(InterfaceType::DefaultChild);
}
- payload << "]";
-
- payload << "}}";
- }
-
- m_payload = payload.str();
- }
-
- /**
- * API to set the entire resource attribute representation (BATCH)
- * @param attributeMap reference containing the name value pairs representing the resource's
- * attributes
- */
- void setResourceRepresentationBatch(OCRepresentation& rep) {
- ostringstream payload;
-
- // Parent
- payload << "{";
- payload << "\"href\":";
- payload << "\"" ;
- payload << rep.getUri();
- payload << "\"" ;
- payload << "}";
-
- std::vector<OCRepresentation> children = rep.getChildren();
-
- for(auto oitr = children.begin(); oitr != children.end(); ++oitr)
- {
- payload << ',';
-
- payload << "{";
-
- payload << "\"href\":";
-
- payload << "\"" ;
- payload << oitr->getUri();
- payload << "\"" ;
-
- payload << ",\"rep\":";
- payload << oitr->getJSONRepresentation();
+ inf.addRepresentation(cur);
- payload << "}";
}
- m_payload = payload.str();
+ return inf.getJSONRepresentation(OCInfoFormat::ExcludeOC);
}
-
- private:
- std::string m_newResourceUri;
- std::string m_payload;
- int m_errorCode;
- HeaderOptions m_headerOptions;
-
- // TODO only stack should have visibility and apps should not
public:
/**
int getErrorCode() const;
/**
+ * Get the Response Representation
+ */
+ const OCRepresentation& getResourceRepresentation() const
+ {
+ return m_representation;
+ }
+ /**
* This API allows to retrieve headerOptions from a response
*/
const HeaderOptions& getHeaderOptions() const
}
/**
- * Get the resource attribute representation
+ * This API retrieves the request handle
+ *
+ * @return OCRequestHandle value
*/
- AttributeMap& getResourceRepresentation() const;
+ const OCRequestHandle& getRequestHandle() const
+ {
+ return m_requestHandle;
+ }
- // TODO This should go away & just use getResourceRepresentation
- std::string getPayload()
+ /**
+ * This API retrieves the resource handle
+ *
+ * @return OCResourceHandle value
+ */
+ const OCResourceHandle& getResourceHandle() const
+ {
+ return m_resourceHandle;
+ }
+
+ /**
+ * This API retrieves the entity handle response result
+ *
+ * @return OCEntityHandler result value
+ */
+ const OCEntityHandlerResult getResponseResult() const
{
- return m_payload;
+ return m_responseResult;
}
};
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 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 <cereal/cereal.hpp>
+#include <cereal/types/memory.hpp>
+#include <cereal/types/vector.hpp>
+#include <cereal/archives/json.hpp>
+
+#include <StringConstants.h>
+
+namespace OC
+{
+ class ListenOCContainer
+ {
+ private:
+ enum class OCSecureType
+ {
+ IPv4Secure,
+ IPv4
+ };
+
+ class ListenResourceContainer
+ {
+ class ListenResourcePropertiesContainer
+ {
+ friend class cereal::access;
+ friend class ListenResourceContainer;
+
+ template<class Archive>
+ void serialize(Archive& ar)
+ {
+ try
+ {
+ m_observable=false;
+ int obsTemp;
+ ar(cereal::make_nvp(OC::Key::OBSERVABLEKEY, obsTemp));
+ m_observable = obsTemp != 0;
+ }
+ catch(cereal::Exception&)
+ {
+ // we swallow this exception, since it means the key
+ // doesn't exist, allowing these to be optional
+ ar.setNextName(nullptr);
+ }
+
+ try
+ {
+ m_secure = false;
+ int secureTemp;
+ ar(cereal::make_nvp(OC::Key::SECUREKEY, secureTemp));
+ m_secure = secureTemp != 0;
+
+ m_port = -1;
+ ar(cereal::make_nvp(OC::Key::PORTKEY, m_port));
+ }
+ catch(cereal::Exception&)
+ {
+ ar.setNextName(nullptr);
+ }
+
+ try
+ {
+ ar(cereal::make_nvp(OC::Key::RESOURCETYPESKEY,m_resourceTypes));
+ }
+ catch(cereal::Exception&)
+ {
+ ar.setNextName(nullptr);
+ }
+ try
+ {
+ ar(cereal::make_nvp(OC::Key::INTERFACESKEY, m_interfaces));
+ }
+ catch(cereal::Exception&)
+ {
+ ar.setNextName(nullptr);
+ }
+ }
+
+ bool m_observable;
+ std::vector<std::string> m_resourceTypes;
+ std::vector<std::string> m_interfaces;
+ bool m_secure;
+ int m_port;
+ };
+
+ public:
+ ListenResourceContainer() : m_loaded(false)
+ {}
+
+ private:
+ friend class cereal::access;
+ friend class ListenOCContainer;
+
+ template <class Archive>
+ void serialize(Archive& ar)
+ {
+ try
+ {
+ ar(cereal::make_nvp(OC::Key::URIKEY, m_uri));
+ m_loaded=true;
+ }
+ catch(cereal::Exception&)
+ {
+ ar.setNextName(nullptr);
+ }
+ try
+ {
+ ar(cereal::make_nvp(OC::Key::PROPERTYKEY, m_props));
+ m_loaded=true;
+ }
+ catch(cereal::Exception&)
+ {
+ ar.setNextName(nullptr);
+ }
+ }
+
+
+ std::string m_uri;
+ bool m_loaded;
+ ListenResourcePropertiesContainer m_props;
+
+ bool loaded() const
+ {
+ return m_loaded;
+ }
+
+ bool observable() const
+ {
+ return m_props.m_observable;
+ }
+
+ OCSecureType secureType() const
+ {
+ return m_props.m_secure?OCSecureType::IPv4Secure :OCSecureType::IPv4;
+ }
+
+ int port() const
+ {
+ return m_props.m_port;
+ }
+
+ std::vector<std::string> resourceTypes() const
+ {
+ return m_props.m_resourceTypes;
+ }
+
+ std::vector<std::string> interfaces() const
+ {
+ return m_props.m_interfaces;
+ }
+ };
+
+ private:
+ friend class cereal::access;
+ template <class Archive>
+ void serialize(Archive& ar)
+ {
+ std::vector<ListenResourceContainer> resources;
+ ar(resources);
+ }
+ public:
+ ListenOCContainer(std::weak_ptr<IClientWrapper> cw, const OCDevAddr& address,
+ std::stringstream& json):
+ m_clientWrapper(cw), m_address(address)
+ {
+ LoadFromJson(json);
+ }
+
+ const std::vector<std::shared_ptr<OCResource>>& Resources() const
+ {
+ return m_resources;
+ }
+
+ private:
+ std::string ConvertOCAddrToString(OCSecureType sec, int secureport)
+ {
+ char stringAddress[DEV_ADDR_SIZE_MAX];
+ uint16_t port;
+
+ ostringstream os;
+
+ if(sec== OCSecureType::IPv4)
+ {
+ os<<"coap://";
+ }
+ else if(sec == OCSecureType::IPv4Secure)
+ {
+ os<<"coaps://";
+ }
+ else
+ {
+ oclog() << "ConvertOCAddrToString(): invalid SecureType"<<std::flush;
+ throw ResourceInitException(false, false, false, false, false, true);
+ }
+
+ if(0== OCDevAddrToString(&m_address, stringAddress))
+ {
+ // nothing to do, successful case.
+ }
+ else
+ {
+ oclog() << "ConvertOCAddrToString(): Invalid Ip"
+ << std::flush;
+ throw ResourceInitException(false, false, false, false, false, true);
+ }
+
+ os<<stringAddress;
+
+ if(sec == OCSecureType::IPv4Secure && secureport>0 && secureport<=65535)
+ {
+ port = static_cast<uint16_t>(secureport);
+ }
+ else if(sec == OCSecureType::IPv4 && 0==OCDevAddrToPort(&m_address, &port))
+ {
+ // nothing to do, this is a successful case
+ }
+ else
+ {
+ oclog() << "ConvertOCAddrToString() : Invalid Port"
+ <<std::flush;
+ throw ResourceInitException(false, false, false, false, true, false);
+ }
+
+ os <<":"<< static_cast<int>(port);
+
+ return os.str();
+ }
+
+ void LoadFromJson(std::stringstream& json)
+ {
+ cereal::JSONInputArchive archive(json);
+
+ std::vector<ListenResourceContainer> resources;
+ archive(cereal::make_nvp(OC::Key::OCKEY, resources));
+
+ m_resources.clear();
+
+ for(const auto& res : resources)
+ {
+ try
+ {
+ if(res.loaded())
+ {
+ m_resources.push_back(std::shared_ptr<OCResource>(
+ new OCResource(m_clientWrapper,
+ ConvertOCAddrToString(res.secureType(),res.port()),
+ res.m_uri, res.observable(), res.resourceTypes(),
+ res.interfaces())));
+ }
+
+ }
+ catch(ResourceInitException& e)
+ {
+ oclog() << "listenCallback(): failed to create resource: " << e.what()
+ << std::flush;
+ }
+ }
+ }
+ std::vector<std::shared_ptr<OC::OCResource>> m_resources;
+ std::weak_ptr<IClientWrapper> m_clientWrapper;
+ OCDevAddr m_address;
+ };
+}
--- /dev/null
+/*! \file OicJsonSerializer.hpp
+ \brief JSON input and output archives.
+Note: this has been customized by Intel(R) for usage in the OIC project.
+Nearly the entire file is from Cereal (see copyright notice below) other than specified
+below
+Added:
+#include of AttributeValue Type
+JSONOutputArchive::saveValue() to add JSON null value
+loadAttributeValues to get attribute values out of a map (implemented in OCRepresentation)
+
+*/
+/*
+ Copyright (c) 2014, Randolph Voorhies, Shane Grant
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of cereal 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 ARE
+ DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CEREAL_ARCHIVES_JSON_HPP_
+#define CEREAL_ARCHIVES_JSON_HPP_
+
+#include <AttributeValue.h>
+#include <cereal/cereal.hpp>
+#include <cereal/details/util.hpp>
+namespace cereal
+{
+ //! An exception thrown when rapidjson fails an internal assertion
+ /*! @ingroup Utility */
+ struct RapidJSONException : Exception
+ { RapidJSONException( const char * what_ ) : Exception( what_ ) {} };
+}
+
+// Override rapidjson assertions to throw exceptions by default
+#ifndef RAPIDJSON_ASSERT
+#define RAPIDJSON_ASSERT(x) if(!(x)){ \
+ throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); }
+#endif // RAPIDJSON_ASSERT
+
+#include <cereal/external/rapidjson/writer.h>
+#include <cereal/external/rapidjson/genericstream.h>
+#include <cereal/external/rapidjson/reader.h>
+#include <cereal/external/rapidjson/document.h>
+#include <cereal/external/base64.hpp>
+
+#include <limits>
+#include <sstream>
+#include <stack>
+#include <vector>
+#include <string>
+
+namespace cereal
+{
+ // ######################################################################
+ //! An output archive designed to save data to JSON
+ /*! This archive uses RapidJSON to build serialie data to JSON.
+
+ JSON archives provides a human readable output but at decreased
+ performance (both in time and space) compared to binary archives.
+
+ JSON benefits greatly from name-value pairs, which if present, will
+ name the nodes in the output. If these are not present, each level
+ of the output will be given an automatically generated delimited name.
+
+ The precision of the output archive controls the number of decimals output
+ for floating point numbers and should be sufficiently large (i.e. at least 20)
+ if there is a desire to have binary equality between the numbers output and
+ those read in. In general you should expect a loss of precision when going
+ from floating point to text and back.
+
+ JSON archives do not output the size information for any dynamically sized structure
+ and instead infer it from the number of children for a node. This means that data
+ can be hand edited for dynamic sized structures and will still be readable. This
+ is accomplished through the cereal::SizeTag object, which will cause the archive
+ to output the data as a JSON array (e.g. marked by [] instead of {}), which indicates
+ that the container is variable sized and may be edited.
+
+ \ingroup Archives */
+ class JSONOutputArchive : public OutputArchive<JSONOutputArchive>
+ {
+ enum class NodeType { StartObject, InObject, StartArray, InArray };
+
+ typedef rapidjson::GenericWriteStream WriteStream;
+ typedef rapidjson::Writer<WriteStream> JSONWriter;
+
+ public:
+ /*! @name Common Functionality
+ Common use cases for directly interacting with an JSONOutputArchive */
+ //! @{
+
+ //! A class containing various advanced options for the JSON archive
+ class Options
+ {
+ public:
+ //! Default options
+ static Options Default(){ return Options(); }
+
+ //! Specify specific options for the JSONOutputArchive
+ /*! @param precision The precision used for floating point numbers*/
+ explicit Options( int precision = std::numeric_limits<double>::max_digits10) :
+ itsPrecision( precision ) { }
+
+ private:
+ friend class JSONOutputArchive;
+ int itsPrecision;
+ };
+
+ //! Construct, outputting to the provided stream
+ /*! @param stream The stream to output to.
+ @param options The JSON specific options to use. See the Options struct
+ for the values of default parameters */
+ JSONOutputArchive(std::ostream & stream, Options const & options = Options::Default() ) :
+ OutputArchive<JSONOutputArchive>(this),
+ itsWriteStream(stream),
+ itsWriter(itsWriteStream, options.itsPrecision),
+ itsNextName(nullptr)
+ {
+ itsNameCounter.push(0);
+ itsNodeStack.push(NodeType::StartObject);
+ }
+
+ //! Destructor, flushes the JSON
+ ~JSONOutputArchive()
+ {
+ itsWriter.EndObject();
+ }
+
+ //! Saves some binary data, encoded as a base64 string, with an optional name
+ /*! This will create a new node, optionally named, and insert a value that consists of
+ the data encoded as a base64 string */
+ void saveBinaryValue( const void * data, size_t size, const char * name = nullptr )
+ {
+ setNextName( name );
+ writeName();
+
+ auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
+ saveValue( base64string );
+ };
+
+ //! @}
+ /*! @name Internal Functionality
+ Functionality designed for use by those requiring control over the inner mechanisms of
+ the JSONOutputArchive */
+ //! @{
+
+ //! Starts a new node in the JSON output
+ /*! The node can optionally be given a name by calling setNextName prior
+ to creating the node
+
+ Nodes only need to be started for types that are themselves objects or arrays */
+ void startNode()
+ {
+ writeName();
+ itsNodeStack.push(NodeType::StartObject);
+ itsNameCounter.push(0);
+ }
+
+ //! Designates the most recently added node as finished
+ void finishNode()
+ {
+ // if we ended up serializing an empty object or array, writeName
+ // will never have been called - so start and then immediately end
+ // the object/array.
+ //
+ // We'll also end any object/arrays we happen to be in
+ switch(itsNodeStack.top())
+ {
+ case NodeType::StartArray:
+ itsWriter.StartArray();
+ case NodeType::InArray:
+ itsWriter.EndArray();
+ break;
+ case NodeType::StartObject:
+ itsWriter.StartObject();
+ case NodeType::InObject:
+ itsWriter.EndObject();
+ break;
+ }
+
+ itsNodeStack.pop();
+ itsNameCounter.pop();
+ }
+
+ //! Sets the name for the next node created with startNode
+ void setNextName( const char * name )
+ {
+ itsNextName = name;
+ }
+
+ //! Saves a null to the current node, added by Intel
+ void saveValue() { itsWriter.Null_(); }
+ //! Saves a bool to the current node
+ void saveValue(bool b) { itsWriter.Bool_(b); }
+ //! Saves an int to the current node
+ void saveValue(int i) { itsWriter.Int(i); }
+ //! Saves a uint to the current node
+ void saveValue(unsigned u) { itsWriter.Uint(u); }
+ //! Saves an int64 to the current node
+ void saveValue(int64_t i64) { itsWriter.Int64(i64); }
+ //! Saves a uint64 to the current node
+ void saveValue(uint64_t u64) { itsWriter.Uint64(u64); }
+ //! Saves a double to the current node
+ void saveValue(double d) { itsWriter.Double(d); }
+ //! Saves a string to the current node
+ void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast<rapidjson::SizeType>( s.size() )); }
+ //! Saves a const char * to the current node
+ void saveValue(char const * s) { itsWriter.String(s); }
+
+ public:
+#ifdef _MSC_VER
+ //! MSVC only long overload to current node
+ void saveValue( unsigned long lu ){ saveLong( lu ); };
+#else // _MSC_VER
+ //! Serialize a long if it would not be caught otherwise
+ template <class T> inline
+ typename std::enable_if<std::is_same<T, long>::value &&
+ !std::is_same<T, std::int32_t>::value &&
+ !std::is_same<T, std::int64_t>::value, void>::type
+ saveValue( T t )
+ {
+ saveLong( t );
+ return t;
+ }
+
+ //! Serialize an unsigned long if it would not be caught otherwise
+ template <class T> inline
+ typename std::enable_if<std::is_same<T, unsigned long>::value &&
+ !std::is_same<T, std::uint32_t>::value &&
+ !std::is_same<T, std::uint64_t>::value, void>::type
+ saveValue( T t )
+ {
+ saveLong( t );
+ return t;
+ }
+#endif // _MSC_VER
+
+ //! Save exotic arithmetic as strings to current node
+ /*! Handles long long (if distinct from other types), unsigned long (if distinct), and long double */
+ template<class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value &&
+ !std::is_same<T, long>::value &&
+ !std::is_same<T, unsigned long>::value &&
+ !std::is_same<T, std::int64_t>::value &&
+ !std::is_same<T, std::uint64_t>::value &&
+ (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long)), void>::type
+ saveValue(T const & t)
+ {
+ std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 );
+ ss << t;
+ saveValue( ss.str() );
+ return t;
+ }
+
+ //! Write the name of the upcoming node and prepare object/array state
+ /*! Since writeName is called for every value that is output, regardless of
+ whether it has a name or not, it is the place where we will do a deferred
+ check of our node state and decide whether we are in an array or an object.
+
+ The general workflow of saving to the JSON archive is:
+
+ 1. (optional) Set the name for the next node to be created, usually done by an NVP
+ 2. Start the node
+ 3. (if there is data to save) Write the name of the node (this function)
+ 4. (if there is data to save) Save the data (with saveValue)
+ 5. Finish the node
+ */
+ void writeName()
+ {
+ NodeType const & nodeType = itsNodeStack.top();
+
+ // Start up either an object or an array, depending on state
+ if(nodeType == NodeType::StartArray)
+ {
+ itsWriter.StartArray();
+ itsNodeStack.top() = NodeType::InArray;
+ }
+ else if(nodeType == NodeType::StartObject)
+ {
+ itsNodeStack.top() = NodeType::InObject;
+ itsWriter.StartObject();
+ }
+
+ // Array types do not output names
+ if(nodeType == NodeType::InArray) return;
+
+ if(itsNextName == nullptr)
+ {
+ std::string name = "value" + std::to_string( itsNameCounter.top()++ ) + "\0";
+ saveValue(name);
+ }
+ else
+ {
+ saveValue(itsNextName);
+ itsNextName = nullptr;
+ }
+ }
+
+ //! Designates that the current node should be output as an array, not an object
+ void makeArray()
+ {
+ itsNodeStack.top() = NodeType::StartArray;
+ }
+
+ //! @}
+
+ private:
+ WriteStream itsWriteStream; //!< Rapidjson write stream
+ JSONWriter itsWriter; //!< Rapidjson writer
+ char const * itsNextName; //!< The next name
+ std::stack<uint32_t> itsNameCounter; //!< Counter for creating unique names for unnamed nodes
+ std::stack<NodeType> itsNodeStack;
+ }; // JSONOutputArchive
+
+ // ######################################################################
+ //! An input archive designed to load data from JSON
+ /*! This archive uses RapidJSON to read in a JSON archive.
+
+ Input JSON should have been produced by the JSONOutputArchive. Data can
+ only be added to dynamically sized containers (marked by JSON arrays) -
+ the input archive will determine their size by looking at the number of child nodes.
+ Only JSON originating from a JSONOutputArchive is officially supported, but data
+ from other sources may work if properly formatted.
+
+ The JSONInputArchive does not require that nodes are loaded in the same
+ order they were saved by JSONOutputArchive. Using name value pairs (NVPs),
+ it is possible to load in an out of order fashion or otherwise skip/select
+ specific nodes to load.
+
+ The default behavior of the input archive is to read sequentially starting
+ with the first node and exploring its children. When a given NVP does
+ not match the read in name for a node, the archive will search for that
+ node at the current level and load it if it exists. After loading an out of
+ order node, the archive will then proceed back to loading sequentially from
+ its new position.
+
+ Consider this simple example where loading of some data is skipped:
+
+ @code{cpp}
+ // imagine the input file has someData(1-9) saved in order at the top level node
+ ar( someData1, someData2, someData3 ); // XML loads in the order it sees in the file
+ ar( cereal::make_nvp( "hello", someData6 ) ); // NVP given does not
+ // match expected NVP name, so we search
+ // for the given NVP and load that value
+ ar( someData7, someData8, someData9 ); // with no NVP given, loading resumes at its
+ // current location, proceeding sequentially
+ @endcode
+
+ \ingroup Archives */
+ class JSONInputArchive : public InputArchive<JSONInputArchive>
+ {
+ private:
+ typedef rapidjson::GenericReadStream ReadStream;
+ typedef rapidjson::GenericValue<rapidjson::UTF8<>> JSONValue;
+ typedef JSONValue::ConstMemberIterator MemberIterator;
+ typedef JSONValue::ConstValueIterator ValueIterator;
+ typedef rapidjson::Document::GenericValue GenericValue;
+
+ public:
+ /*! @name Common Functionality
+ Common use cases for directly interacting with an JSONInputArchive */
+ //! @{
+
+ //! Construct, reading from the provided stream
+ /*! @param stream The stream to read from */
+ JSONInputArchive(std::istream & stream) :
+ InputArchive<JSONInputArchive>(this),
+ itsNextName( nullptr ),
+ itsReadStream(stream)
+ {
+ itsDocument.ParseStream<0>(itsReadStream);
+ itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd());
+ }
+
+ //! Loads some binary data, encoded as a base64 string
+ /*! This will automatically start and finish a node to load the data, and can be called directly by
+ users.
+
+ Note that this follows the same ordering rules specified in the class description in regards
+ to loading in/out of order */
+ void loadBinaryValue( void * data, size_t size, const char * name = nullptr )
+ {
+ itsNextName = name;
+
+ std::string encoded;
+ loadValue( encoded );
+ auto decoded = base64::decode( encoded );
+
+ if( size != decoded.size() )
+ throw Exception("Decoded binary data size does not match specified size");
+
+ std::memcpy( data, decoded.data(), decoded.size() );
+ itsNextName = nullptr;
+ };
+
+ // Intel Added this as a custom parsing hook for the AttributeValue map
+ void loadAttributeValues(std::map<std::string, OC::AttributeValue>& map);
+
+ private:
+ //! @}
+ /*! @name Internal Functionality
+ Functionality designed for use by those requiring control over the inner mechanisms of
+ the JSONInputArchive */
+ //! @{
+
+ //! An internal iterator that handles both array and object types
+ /*! This class is a variant and holds both types of iterators that
+ rapidJSON supports - one for arrays and one for objects. */
+ class Iterator
+ {
+ public:
+ friend class cereal::JSONInputArchive;
+ Iterator() : itsIndex( 0 ), itsType(Null_) {}
+
+ Iterator(MemberIterator begin, MemberIterator end) :
+ itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member)
+ { }
+
+ Iterator(ValueIterator begin, ValueIterator end) :
+ itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value)
+ { }
+
+ //! Advance to the next node
+ Iterator & operator++()
+ {
+ ++itsIndex;
+ return *this;
+ }
+
+ //! Get the value of the current node
+ GenericValue const & value()
+ {
+ switch(itsType)
+ {
+ case Value : return itsValueItBegin[itsIndex];
+ case Member: return itsMemberItBegin[itsIndex].value;
+ default: throw cereal::Exception("Invalid Iterator Type!");
+ }
+ }
+
+ //! Get the name of the current node, or nullptr if it has no name
+ const char * name() const
+ {
+ if( itsType == Member && (itsMemberItBegin + itsIndex) != itsMemberItEnd )
+ return itsMemberItBegin[itsIndex].name.GetString();
+ else
+ return nullptr;
+ }
+
+ //! Adjust our position such that we are at the node with the given name
+ /*! @throws Exception if no such named node exists */
+ inline void search( const char * searchName )
+ {
+ const auto len = std::strlen( searchName );
+ size_t index = 0;
+ for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index )
+ if( std::strncmp( searchName, it->name.GetString(), len ) == 0 )
+ {
+ itsIndex = index;
+ return;
+ }
+
+ throw Exception("JSON Parsing failed - provided NVP not found");
+ }
+
+ private:
+ MemberIterator itsMemberItBegin, itsMemberItEnd; //!< The member iterator (object)
+ ValueIterator itsValueItBegin, itsValueItEnd; //!< The value iterator (array)
+ size_t itsIndex; //!< The current index of this iterator
+ enum Type {Value, Member, Null_} itsType; //!< Whether this holds values (array) or members (objects) or nothing
+ };
+
+ //! Searches for the expectedName node if it doesn't match the actualName
+ /*! This needs to be called before every load or node start occurs. This function will
+ check to see if an NVP has been provided (with setNextName) and if so, see if that name matches the actual
+ next name given. If the names do not match, it will search in the current level of the JSON for that name.
+ If the name is not found, an exception will be thrown.
+
+ Resets the NVP name after called.
+
+ @throws Exception if an expectedName is given and not found */
+ inline void search()
+ {
+ // The name an NVP provided with setNextName()
+ if( itsNextName )
+ {
+ // The actual name of the current node
+ auto const actualName = itsIteratorStack.back().name();
+
+ // Do a search if we don't see a name coming up, or if the names don't match
+ if( !actualName || std::strcmp( itsNextName, actualName ) != 0 )
+ itsIteratorStack.back().search( itsNextName );
+ }
+
+ itsNextName = nullptr;
+ }
+
+ public:
+ //! Starts a new node, going into its proper iterator
+ /*! This places an iterator for the next node to be parsed onto the iterator stack. If the next
+ node is an array, this will be a value iterator, otherwise it will be a member iterator.
+
+ By default our strategy is to start with the document root node and then recursively iterate through
+ all children in the order they show up in the document.
+ We don't need to know NVPs to do this; we'll just blindly load in the order things appear in.
+
+ If we were given an NVP, we will search for it if it does not match our the name of the next node
+ that would normally be loaded. This functionality is provided by search(). */
+ void startNode()
+ {
+ search();
+
+ if(itsIteratorStack.back().value().IsArray())
+ itsIteratorStack.emplace_back(itsIteratorStack.back().value().Begin(), itsIteratorStack.back().value().End());
+ else
+ itsIteratorStack.emplace_back(itsIteratorStack.back().value().MemberBegin(), itsIteratorStack.back().value().MemberEnd());
+ }
+
+ //! Finishes the most recently started node
+ void finishNode()
+ {
+ itsIteratorStack.pop_back();
+ ++itsIteratorStack.back();
+ }
+
+ //! Sets the name for the next node created with startNode
+ void setNextName( const char * name )
+ {
+ itsNextName = name;
+ }
+
+ //! Loads a value from the current node - small signed overload
+ template<class T> inline
+ typename std::enable_if<std::is_signed<T>::value && sizeof(T) < sizeof(int64_t), void>::type
+ loadValue(T & val)
+ {
+ search();
+
+ val = itsIteratorStack.back().value().GetInt();
+ ++itsIteratorStack.back();
+ }
+
+ //! Loads a value from the current node - small unsigned overload
+ template<class T> inline
+ typename std::enable_if<(std::is_unsigned<T>::value && sizeof(T) < sizeof(uint64_t)) &&
+ !std::is_same<bool, T>::value, void>::type
+ loadValue(T & val)
+ {
+ search();
+
+ val = itsIteratorStack.back().value().GetUint();
+ ++itsIteratorStack.back();
+ }
+
+ //! Loads a value from the current node - bool overload
+ void loadValue(bool & val) { search(); val = itsIteratorStack.back().value().GetBool_(); ++itsIteratorStack.back(); }
+ //! Loads a value from the current node - int64 overload
+ void loadValue(int64_t & val) { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); }
+ //! Loads a value from the current node - uint64 overload
+ void loadValue(uint64_t & val) { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); }
+ //! Loads a value from the current node - float overload
+ void loadValue(float & val) { search(); val = static_cast<float>(itsIteratorStack.back().value().GetDouble()); ++itsIteratorStack.back(); }
+ //! Loads a value from the current node - double overload
+ void loadValue(double & val) { search(); val = itsIteratorStack.back().value().GetDouble(); ++itsIteratorStack.back(); }
+ //! Loads a value from the current node - string overload
+ void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); }
+
+ private:
+ //! Convert a string to a long long
+ void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); }
+ //! Convert a string to an unsigned long long
+ void stringToNumber( std::string const & str, unsigned long long & val ) { val = std::stoull( str ); }
+ //! Convert a string to a long double
+ void stringToNumber( std::string const & str, long double & val ) { val = std::stold( str ); }
+
+ public:
+ //! Loads a value from the current node - long double and long long overloads
+ template<class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value &&
+ !std::is_same<T, long>::value &&
+ !std::is_same<T, unsigned long>::value &&
+ !std::is_same<T, std::int64_t>::value &&
+ !std::is_same<T, std::uint64_t>::value &&
+ (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long)), void>::type
+ loadValue(T & val)
+ {
+ std::string encoded;
+ loadValue( encoded );
+ stringToNumber( encoded, val );
+ }
+
+ //! Loads the size for a SizeTag
+ void loadSize(size_type & size)
+ {
+ size = (itsIteratorStack.rbegin() + 1)->value().Size();
+ }
+
+ //! @}
+
+ private:
+ const char * itsNextName; //!< Next name set by NVP
+ ReadStream itsReadStream; //!< Rapidjson write stream
+ std::vector<Iterator> itsIteratorStack; //!< 'Stack' of rapidJSON iterators
+ rapidjson::Document itsDocument; //!< Rapidjson document
+ };
+
+ // ######################################################################
+ // JSONArchive prologue and epilogue functions
+ // ######################################################################
+
+ // ######################################################################
+ //! Prologue for NVPs for JSON archives
+ /*! NVPs do not start or finish nodes - they just set up the names */
+ template <class T> inline
+ void prologue( JSONOutputArchive &, NameValuePair<T> const & )
+ { }
+
+ //! Prologue for NVPs for JSON archives
+ template <class T> inline
+ void prologue( JSONInputArchive &, NameValuePair<T> const & )
+ { }
+
+ // ######################################################################
+ //! Epilogue for NVPs for JSON archives
+ /*! NVPs do not start or finish nodes - they just set up the names */
+ template <class T> inline
+ void epilogue( JSONOutputArchive &, NameValuePair<T> const & )
+ { }
+
+ //! Epilogue for NVPs for JSON archives
+ /*! NVPs do not start or finish nodes - they just set up the names */
+ template <class T> inline
+ void epilogue( JSONInputArchive &, NameValuePair<T> const & )
+ { }
+
+ // ######################################################################
+ //! Prologue for SizeTags for JSON archives
+ /*! SizeTags are strictly ignored for JSON, they just indicate
+ that the current node should be made into an array */
+ template <class T> inline
+ void prologue( JSONOutputArchive & ar, SizeTag<T> const & )
+ {
+ ar.makeArray();
+ }
+
+ //! Prologue for SizeTags for JSON archives
+ template <class T> inline
+ void prologue( JSONInputArchive &, SizeTag<T> const & )
+ { }
+
+ // ######################################################################
+ //! Epilogue for SizeTags for JSON archives
+ /*! SizeTags are strictly ignored for JSON */
+ template <class T> inline
+ void epilogue( JSONOutputArchive &, SizeTag<T> const & )
+ { }
+
+ //! Epilogue for SizeTags for JSON archives
+ template <class T> inline
+ void epilogue( JSONInputArchive &, SizeTag<T> const & )
+ { }
+
+ // ######################################################################
+ //! Prologue for all other types for JSON archives (except minimal types)
+ /*! Starts a new node, named either automatically or by some NVP,
+ that may be given data by the type about to be archived
+
+ Minimal types do not start or finish nodes */
+ template <class T> inline
+ typename std::enable_if<!std::is_arithmetic<T>::value &&
+ !traits::has_minimal_output_serialization<T, JSONOutputArchive>::value, void>::type
+ prologue( JSONOutputArchive & ar, T const & )
+ {
+ ar.startNode();
+ }
+
+ //! Prologue for all other types for JSON archives
+ template <class T> inline
+ typename std::enable_if<!std::is_arithmetic<T>::value &&
+ !traits::has_minimal_input_serialization<T, JSONOutputArchive>::value, void>::type
+ prologue( JSONInputArchive & ar, T const & )
+ {
+ ar.startNode();
+ }
+
+ // ######################################################################
+ //! Epilogue for all other types other for JSON archives (except minimal types
+ /*! Finishes the node created in the prologue
+
+ Minimal types do not start or finish nodes */
+ template <class T> inline
+ typename std::enable_if<!std::is_arithmetic<T>::value &&
+ !traits::has_minimal_output_serialization<T, JSONOutputArchive>::value, void>::type
+ epilogue( JSONOutputArchive & ar, T const & )
+ {
+ ar.finishNode();
+ }
+
+ //! Epilogue for all other types other for JSON archives
+ template <class T> inline
+ typename std::enable_if<!std::is_arithmetic<T>::value &&
+ !traits::has_minimal_input_serialization<T, JSONOutputArchive>::value, void>::type
+ epilogue( JSONInputArchive & ar, T const & )
+ {
+ ar.finishNode();
+ }
+
+ // ######################################################################
+ //! Prologue for arithmetic types for JSON archives
+ template <class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+ prologue( JSONOutputArchive & ar, T const & )
+ {
+ ar.writeName();
+ }
+
+ //! Prologue for arithmetic types for JSON archives
+ template <class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+ prologue( JSONInputArchive &, T const & )
+ { }
+
+ // ######################################################################
+ //! Epilogue for arithmetic types for JSON archives
+ template <class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+ epilogue( JSONOutputArchive &, T const & )
+ { }
+
+ //! Epilogue for arithmetic types for JSON archives
+ template <class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+ epilogue( JSONInputArchive &, T const & )
+ { }
+
+ // ######################################################################
+ //! Prologue for strings for JSON archives
+ template<class CharT, class Traits, class Alloc> inline
+ void prologue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const &)
+ {
+ ar.writeName();
+ }
+
+ //! Prologue for strings for JSON archives
+ template<class CharT, class Traits, class Alloc> inline
+ void prologue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
+ { }
+
+ // ######################################################################
+ //! Epilogue for strings for JSON archives
+ template<class CharT, class Traits, class Alloc> inline
+ void epilogue(JSONOutputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
+ { }
+
+ //! Epilogue for strings for JSON archives
+ template<class CharT, class Traits, class Alloc> inline
+ void epilogue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
+ { }
+
+ // ######################################################################
+ // Common JSONArchive serialization functions
+ // ######################################################################
+
+ //! Serializing NVP types to JSON
+ template <class T> inline
+ void save( JSONOutputArchive & ar, NameValuePair<T> const & t )
+ {
+ ar.setNextName( t.name );
+ ar( t.value );
+ }
+
+ template <class T> inline
+ void load( JSONInputArchive & ar, NameValuePair<T> & t )
+ {
+ ar.setNextName( t.name );
+ ar( t.value );
+ }
+
+ //! Saving for arithmetic to JSON
+ template<class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+ save(JSONOutputArchive & ar, T const & t)
+ {
+ ar.saveValue( t );
+ }
+
+ //! Loading arithmetic from JSON
+ template<class T> inline
+ typename std::enable_if<std::is_arithmetic<T>::value, void>::type
+ load(JSONInputArchive & ar, T & t)
+ {
+ ar.loadValue( t );
+ }
+
+ //! saving string to JSON
+ template<class CharT, class Traits, class Alloc> inline
+ void save(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
+ {
+ ar.saveValue( str );
+ }
+
+ //! loading string from JSON
+ template<class CharT, class Traits, class Alloc> inline
+ void load(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
+ {
+ ar.loadValue( str );
+ }
+
+ // ######################################################################
+ //! Saving SizeTags to JSON
+ template <class T> inline
+ void save( JSONOutputArchive &, SizeTag<T> const & )
+ {
+ // nothing to do here, we don't explicitly save the size
+ }
+
+ //! Loading SizeTags from JSON
+ template <class T> inline
+ void load( JSONInputArchive & ar, SizeTag<T> & st )
+ {
+ ar.loadSize( st.size );
+ }
+} // namespace cereal
+
+// register archives for polymorphic support
+CEREAL_REGISTER_ARCHIVE(cereal::JSONInputArchive)
+CEREAL_REGISTER_ARCHIVE(cereal::JSONOutputArchive)
+
+#endif // CEREAL_ARCHIVES_JSON_HPP_
class OutOfProcClientWrapper : public IClientWrapper
{
public:
- OutOfProcClientWrapper(OC::OCPlatform_impl& owner, std::weak_ptr<std::recursive_mutex> csdkLock,
+ OutOfProcClientWrapper(std::weak_ptr<std::recursive_mutex> csdkLock,
PlatformConfig cfg)
- : IClientWrapper(owner)
{}
virtual OCStackResult ListenForResource(const std::string& serviceUrl,
const std::string& uri,
const HeaderOptions& headerOptions, QualityOfService QoS){return OC_STACK_NOTIMPL;}
- virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper,
- OCDevAddr& addr, const boost::property_tree::ptree resourceNode)
- {
- return nullptr;
- }
-
virtual OCStackResult SubscribePresence(OCDoHandle* handle, const std::string& host,
const std::string& resourceType, SubscribeCallback& presenceHandler)
{return OC_STACK_NOTIMPL;}
class OutOfProcServerWrapper : public IServerWrapper
{
public:
- OutOfProcServerWrapper(OC::OCPlatform_impl& owner, PlatformConfig cfg)
- : IServerWrapper(owner)
- {};
+ OutOfProcServerWrapper(PlatformConfig cfg)
+ {}
virtual OCStackResult registerResource(
OCResourceHandle& resourceHandle,
return OC_STACK_NOTIMPL;
}
-
virtual OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler)
{
//Not implemented yet
return OC_STACK_NOTIMPL;
}
+
+ virtual OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
+ {
+ //Not implemented yet
+ return OC_STACK_NOTIMPL;
+ }
};
}
class ResourceInitException : public std::exception
{
public:
- ResourceInitException(bool missingUri, bool missingType, bool missingInterface, bool missingClientWrapper)
- : m_missingUri(missingUri), m_missingType(missingType), m_missingInterface(missingInterface), m_missingClientWrapper(missingClientWrapper)
+ ResourceInitException(
+ bool missingUri,
+ bool missingType,
+ bool missingInterface,
+ bool missingClientWrapper,
+ bool invalidPort,
+ bool invalidIp)
+ : m_missingUri(missingUri),
+ m_missingType(missingType),
+ m_missingInterface(missingInterface),
+ m_missingClientWrapper(missingClientWrapper),
+ m_invalidPort(invalidPort),
+ m_invalidIp(invalidIp)
{
}
+ bool isInvalidPort() const
+ {
+ return m_invalidPort;
+ }
+
+ bool isInvalidIp() const
+ {
+ return m_invalidIp;
+ }
+
bool isClientWrapperMissing() const
{
return m_missingClientWrapper;
ret += OC::InitException::MISSING_CLIENT_WRAPPER;
}
+ if(isInvalidPort())
+ {
+ ret += OC::InitException::INVALID_PORT;
+ }
+
+ if(isInvalidIp())
+ {
+ ret += OC::InitException::INVALID_IP;
+ }
+
return ret.c_str();
}
bool m_missingType;
bool m_missingInterface;
bool m_missingClientWrapper;
+ bool m_invalidPort;
+ bool m_invalidIp;
};
}
static const std::string INVALID_OPTION = "Invalid option";
static const std::string GENERAL_FAULT = "General Fault";
static const std::string MALFORMED_STACK_RESPONSE = "Response from OC_STACK is malformed";
+ static const std::string VIRTUAL_DO_NOT_HANDLE = "Virtual Do Not Handle";
+ static const std::string PERSISTENT_BUFFER_REQUIRED = "Persistent response buffer required";
+ static const std::string STACK_CONTINUE = "Stack continue";
+ static const std::string INVALID_REQUEST_HANDLE = "Invalid request handle";
static const std::string UNKNOWN_ERROR = "Unknown Error";
-
+ static const std::string INVALID_REPRESENTATION = "Invalid Payload JSON";
+ static const std::string INVALID_JSON_TYPE = "Unrecognized JSON Type ";
+ static const std::string INVALID_JSON_NUMERIC = "Unrecognized JSON Numeric ";
+ static const std::string INVALID_JSON_ARRAY_DEPTH = "Max JSON Array Depth exceeded";
+ static const std::string INVALID_JSON_TYPE_TAG = "Invalid JSON Type Tag";
+ static const std::string INVALID_ATTRIBUTE = "Invalid Attribute: ";
}
namespace Error
public:
typedef std::shared_ptr<IWrapperFactory> Ptr;
- virtual IClientWrapper::Ptr CreateClientWrapper(OC::OCPlatform_impl& owner,
+ virtual IClientWrapper::Ptr CreateClientWrapper(
std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg) =0;
- virtual IServerWrapper::Ptr CreateServerWrapper(OC::OCPlatform_impl& owner,
+ virtual IServerWrapper::Ptr CreateServerWrapper(
std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg) =0;
virtual ~IWrapperFactory(){}
};
public:
WrapperFactory(){}
- virtual IClientWrapper::Ptr CreateClientWrapper(OC::OCPlatform_impl& owner,
+ virtual IClientWrapper::Ptr CreateClientWrapper(
std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
{
switch(cfg.serviceType)
{
case ServiceType::InProc:
- return std::make_shared<InProcClientWrapper>(owner, csdkLock, cfg);
+ return std::make_shared<InProcClientWrapper>(csdkLock, cfg);
break;
case ServiceType::OutOfProc:
- return std::make_shared<OutOfProcClientWrapper>(owner, csdkLock, cfg);
+ return std::make_shared<OutOfProcClientWrapper>(csdkLock, cfg);
break;
}
return nullptr;
}
- virtual IServerWrapper::Ptr CreateServerWrapper(OC::OCPlatform_impl& owner,
+ virtual IServerWrapper::Ptr CreateServerWrapper(
std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
{
switch(cfg.serviceType)
{
case ServiceType::InProc:
- return std::make_shared<InProcServerWrapper>(owner, csdkLock, cfg);
+ return std::make_shared<InProcServerWrapper>(csdkLock, cfg);
break;
case ServiceType::OutOfProc:
throw OC::OCException(OC::Exception::SVCTYPE_OUTOFPROC, OC_STACK_NOTIMPL);
PLATFORM := "linux"
endif
+DEPEND_DIR:= $(ROOT_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
OUT_DIR := $(ROOT_DIR)/$(BUILD)
OBJ_DIR := $(OUT_DIR)/obj
CXX_INC += -I./csdk/ocrandom/include
CXX_INC += -I./csdk/logger/include
CXX_INC += -I./csdk/libcoap
-
+CXX_INC += -I$(CEREAL_DIR)/include
# Force metatargets to build:
-all.PHONY: prep_dirs c_sdk oc_logger_target liboc.a examples
+all.PHONY: applyDepPatches prep_dirs c_sdk oc_logger_target liboc.a examples
-buildScript_all.PHONY: prep_dirs oc_logger_target liboc.a
+buildScript_all.PHONY: applyDepPatches prep_dirs oc_logger_target liboc.a
all: all.PHONY
buildScript_all: buildScript_all.PHONY
-prep_dirs:
+prep_dirs: deps
-mkdir -p $(OUT_DIR)
-mkdir -p $(OBJ_DIR)
+# used to fetch all dependencies
+deps:
+ -mkdir -p $(DEPEND_DIR)
+#cereal fetch
+ if [ ! -d "$(CEREAL_DIR)" ]; then\
+ cd $(DEPEND_DIR) && git clone https://github.com/USCiLab/cereal.git;\
+ cd $(CEREAL_DIR) && git checkout 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245;\
+ fi
+
+applyDepPatches: deps
+#reset git to the 'base version', so we can apply our patch without issues
+ cd $(CEREAL_DIR) && git reset --hard 7121e91e6ab8c3e6a6516d9d9c3e6804e6f65245;
+ cd $(CEREAL_DIR) && git apply $(ROOT_DIR)/patches/cereal_gcc46.patch
+
c_sdk:
cd csdk && $(MAKE) "BUILD=$(BUILD)" "PLATFORM=$(PLATFORM)"
examples: liboc.a
cd examples && $(MAKE) apps "BUILD=$(BUILD)"
-liboc.a: OCPlatform_impl.o OCPlatform.o OCResource.o OCException.o OCUtilities.o InProcServerWrapper.o InProcClientWrapper.o
- ar -cvq $(OBJ_DIR)/liboc.a $(OBJ_DIR)/OCPlatform_impl.o $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCException.o $(OBJ_DIR)/OCUtilities.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o
+liboc.a: OCPlatform_impl.o OCPlatform.o OCResource.o OCException.o OCUtilities.o InProcServerWrapper.o InProcClientWrapper.o OCRepresentation.o
+ ar -cvq $(OBJ_DIR)/liboc.a $(OBJ_DIR)/OCPlatform_impl.o $(OBJ_DIR)/OCPlatform.o $(OBJ_DIR)/OCResource.o $(OBJ_DIR)/OCException.o $(OBJ_DIR)/OCUtilities.o $(OBJ_DIR)/InProcServerWrapper.o $(OBJ_DIR)/InProcClientWrapper.o $(OBJ_DIR)/OCRepresentation.o
OCPlatform_impl.o: src/OCPlatform_impl.cpp
$(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCPlatform_impl.cpp $(CXX_INC)
OCPlatform.o: src/OCPlatform.cpp
$(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCPlatform.cpp $(CXX_INC)
+OCRepresentation.o: src/OCRepresentation.cpp
+ $(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCRepresentation.cpp $(CXX_INC)
+
OCResource.o: src/OCResource.cpp
$(CXX) $(CXX_FLAGS.$(BUILD)) -o $(OBJ_DIR)/$@ -c src/OCResource.cpp $(CXX_INC)
##
-# liboctbstack (static library) build script
+# liboc_logger (share library) build script
##
-Import('env', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
-# Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-
-liboc_logger_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+liboc_logger_env = lib_env.Clone()
######################################################################
# Build flags
######################################################################
liboc_logger_env.PrependUnique(CPPPATH = ['include'])
-if BUILD_TARGET == 'android':
+target_os = env.get('TARGET_OS')
+if target_os == 'android':
liboc_logger_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
liboc_logger_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+ liboc_logger_env.AppendUnique(LIBS = ['gnustl_static', 'log'])
-if BUILD_TARGET not in ['arduino', 'windows', 'winrt']:
- liboc_logger_env.AppendUnique(CFLAGS = ['-Wall', '-std=c99'])
- liboc_logger_env.AppendUnique(CXXFLAGS = ['-Wall', '-std=c++0x'])
+if target_os not in ['arduino', 'windows', 'winrt']:
+ liboc_logger_env.AppendUnique(CFLAGS = ['-Wall', '-std=c99', '-fPIC'])
+ liboc_logger_env.AppendUnique(CXXFLAGS = ['-Wall', '-std=c++0x', '-fPIC'])
######################################################################
# Source files and Targets
######################################################################
-liboc_logger_core = liboc_logger_env.StaticLibrary('oc_logger_core', 'c/oc_logger.c', OBJPREFIX='core')
-liboc_logger = liboc_logger_env.StaticLibrary('oc_logger',
+liboc_logger_core = liboc_logger_env.SharedLibrary('oc_logger_core', 'c/oc_logger.c', OBJPREFIX='core_')
+liboc_logger = liboc_logger_env.SharedLibrary('oc_logger',
['c/oc_logger.c', 'c/oc_console_logger.c', 'cpp/oc_ostream_logger.cpp'])
-i_loggers = liboc_logger_env.Install(BUILD_DIR, [liboc_logger_core, liboc_logger])
-Alias('liboc_logger', i_loggers)
-env.AppendUnique(TS = ['liboc_logger'])
\ No newline at end of file
+
+liboc_logger_env.InstallTarget([liboc_logger_core, liboc_logger], 'liboc_logger')
+
+if target_os not in ['ios']:
+ SConscript('examples/SConscript')
--- /dev/null
+##
+# liboc_logger examples build script
+##
+
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+
+examples_env = lib_env.Clone()
+######################################################################
+# Build flags
+######################################################################
+examples_env.PrependUnique(CPPPATH = ['../include'])
+examples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+examples_env.AppendUnique(LIBS = ['oc_logger', 'stdc++'])
+
+target_os = env.get('TARGET_OS')
+if target_os == 'android':
+ examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+ examples_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+ examples_env.AppendUnique(LIBS = ['gnustl_static'])
+
+if target_os not in ['arduino', 'windows', 'winrt']:
+ examples_env.AppendUnique(CFLAGS = Split('-Wall -std=c99 -Werror'))
+ examples_env.AppendUnique(CXXFLAGS = Split('-Wall -std=c++0x'))
+
+######################################################################
+# Source files and Targets
+######################################################################
+examples_c = examples_env.Program('examples_c', 'test_logging.c', OBJPREFIX='c_')
+examples_cpp = examples_env.Program('examples_cpp', 'test_logging.cpp')
+
+Alias('liboc_logger_examples', [examples_c, examples_cpp])
+examples_env.AppendTarget('liboc_logger_examples')
\ No newline at end of file
basic_demo();
c_demo();
alternative_demo();
+ return 0;
}
--- /dev/null
+From 17300ee96e42f8848d27db6fc97f04de293662d8 Mon Sep 17 00:00:00 2001
+From: Erich Keane <erich.keane@intel.com>
+Date: Thu, 6 Nov 2014 14:37:00 -0800
+Subject: [PATCH] Get this to work on g++4.6.3
+
+---
+ include/cereal/cereal.hpp | 2 +-
+ include/cereal/details/helpers.hpp | 32 ++++++++--------
+ include/cereal/details/traits.hpp | 61 +++++++++++++++++-------------
+ include/cereal/external/rapidjson/reader.h | 13 ++-----
+ include/cereal/external/rapidjson/writer.h | 12 ++----
+ include/cereal/types/common.hpp | 19 +++++++---
+ include/cereal/types/memory.hpp | 10 ++---
+ 7 files changed, 77 insertions(+), 72 deletions(-)
+
+diff --git a/include/cereal/cereal.hpp b/include/cereal/cereal.hpp
+index b2858af..a219729 100644
+--- a/include/cereal/cereal.hpp
++++ b/include/cereal/cereal.hpp
+@@ -856,7 +856,7 @@ namespace cereal
+ std::uint32_t version;
+
+ process( make_nvp<ArchiveType>("cereal_class_version", version) );
+- itsVersionedTypes.emplace_hint( lookupResult, hash, version );
++ itsVersionedTypes.insert( lookupResult, std::pair<std::size_t, std::uint32_t>(hash, version) );
+
+ return version;
+ }
+diff --git a/include/cereal/details/helpers.hpp b/include/cereal/details/helpers.hpp
+index e792d44..60e13c8 100644
+--- a/include/cereal/details/helpers.hpp
++++ b/include/cereal/details/helpers.hpp
+@@ -55,7 +55,7 @@ namespace cereal
+ /*! To ensure compatability between 32, 64, etc bit machines, we need to use
+ * a fixed size type instead of size_t, which may vary from machine to
+ * machine. */
+- using size_type = uint64_t;
++ typedef uint64_t size_type;
+
+ // forward decls
+ class BinaryOutputArchive;
+@@ -138,12 +138,12 @@ namespace cereal
+ // otherwise, we store a reference. If we were passed an array, don't
+ // decay the type - keep it as an array, and then proceed as normal
+ // with the RValue business
+- using DT = typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
++ typedef typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
+ typename std::remove_cv<T>::type,
+- typename std::decay<T>::type>::type;
+- using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
++ typename std::decay<T>::type>::type DT;
++ typedef typename std::conditional<std::is_rvalue_reference<T>::value,
+ DT,
+- typename std::add_lvalue_reference<DT>::type>::type;
++ typename std::add_lvalue_reference<DT>::type>::type Type;
+ // prevent nested nvps
+ static_assert( !std::is_base_of<detail::NameValuePairCore, T>::value,
+ "Cannot pair a name to a NameValuePair" );
+@@ -207,9 +207,9 @@ namespace cereal
+ {
+ //! Internally store the pointer as a void *, keeping const if created with
+ //! a const pointer
+- using PT = typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
++ typedef typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
+ const void *,
+- void *>::type;
++ void *>::type PT;
+
+ BinaryData( T && d, uint64_t s ) : data(d), size(s) {}
+
+@@ -248,10 +248,10 @@ namespace cereal
+ private:
+ // If we get passed an RValue, we'll just make a local copy if it here
+ // otherwise, we store a reference
+- using DT = typename std::decay<T>::type;
+- using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
++ typedef typename std::decay<T>::type DT;
++ typedef typename std::conditional<std::is_rvalue_reference<T>::value,
+ DT,
+- typename std::add_lvalue_reference<DT>::type>::type;
++ typename std::add_lvalue_reference<DT>::type>::type Type;
+
+ public:
+ SizeTag( T && sz ) : size(const_cast<Type>(sz)) {}
+@@ -283,17 +283,17 @@ namespace cereal
+ template <class Key, class Value>
+ struct MapItem
+ {
+- using DecayKey = typename std::decay<Key>::type;
+- using KeyType = typename std::conditional<
++ typedef typename std::decay<Key>::type DecayKey;
++ typedef typename std::conditional<
+ std::is_rvalue_reference<Key>::value,
+ DecayKey,
+- typename std::add_lvalue_reference<DecayKey>::type>::type;
++ typename std::add_lvalue_reference<DecayKey>::type>::type KeyType;
+
+- using DecayValue = typename std::decay<Value>::type;
+- using ValueType = typename std::conditional<
++ typedef typename std::decay<Value>::type DecayValue;
++ typedef typename std::conditional<
+ std::is_rvalue_reference<Value>::value,
+ DecayValue,
+- typename std::add_lvalue_reference<DecayValue>::type>::type;
++ typename std::add_lvalue_reference<DecayValue>::type>::type ValueType;
+
+ //! Construct a MapItem from a key and a value
+ /*! @internal */
+diff --git a/include/cereal/details/traits.hpp b/include/cereal/details/traits.hpp
+index 871886f..011054b 100644
+--- a/include/cereal/details/traits.hpp
++++ b/include/cereal/details/traits.hpp
+@@ -411,12 +411,12 @@ namespace cereal
+ };
+
+ template <class T, class A, bool Valid>
+- struct get_member_save_minimal_type { using type = void; };
++ struct get_member_save_minimal_type { typedef void type; };
+
+ template <class T, class A>
+ struct get_member_save_minimal_type<T, A, true>
+ {
+- using type = decltype( cereal::access::member_save_minimal( std::declval<A const &>(), std::declval<T const &>() ) );
++ typedef decltype( cereal::access::member_save_minimal( std::declval<A const &>(), std::declval<T const &>() ) ) type;
+ };
+ } // end namespace detail
+
+@@ -428,7 +428,7 @@ namespace cereal
+ "cereal detected a non-const member save_minimal. "
+ "save_minimal member functions must always be const" );
+
+- using type = typename detail::get_member_save_minimal_type<T, A, check::value>::type;
++ typedef typename detail::get_member_save_minimal_type<T, A, check::value>::type type;
+ static_assert( (check::value && is_minimal_type<type>::value) || !check::value,
+ "cereal detected a member save_minimal with an invalid return type. "
+ "return type must be arithmetic or string" );
+@@ -473,12 +473,12 @@ namespace cereal
+ };
+
+ template <class T, class A, bool Valid>
+- struct get_member_versioned_save_minimal_type { using type = void; };
++ struct get_member_versioned_save_minimal_type { typedef void type; };
+
+ template <class T, class A>
+ struct get_member_versioned_save_minimal_type<T, A, true>
+ {
+- using type = decltype( cereal::access::member_save_minimal( std::declval<A const &>(), std::declval<T const &>(), 0 ) );
++ typedef decltype( cereal::access::member_save_minimal( std::declval<A const &>(), std::declval<T const &>(), 0 ) ) type;
+ };
+ } // end namespace detail
+
+@@ -490,7 +490,7 @@ namespace cereal
+ "cereal detected a versioned non-const member save_minimal. "
+ "save_minimal member functions must always be const" );
+
+- using type = typename detail::get_member_versioned_save_minimal_type<T, A, check::value>::type;
++ typedef typename detail::get_member_versioned_save_minimal_type<T, A, check::value>::type type;
+ static_assert( (check::value && is_minimal_type<type>::value) || !check::value,
+ "cereal detected a versioned member save_minimal with an invalid return type. "
+ "return type must be arithmetic or string" );
+@@ -519,12 +519,12 @@ namespace cereal
+ };
+
+ template <class T, class A, bool Valid>
+- struct get_non_member_save_minimal_type { using type = void; };
++ struct get_non_member_save_minimal_type { typedef void type; };
+
+ template <class T, class A>
+ struct get_non_member_save_minimal_type <T, A, true>
+ {
+- using type = decltype( save_minimal( std::declval<A const &>(), std::declval<T const &>() ) );
++ typedef decltype( save_minimal( std::declval<A const &>(), std::declval<T const &>() ) ) type;
+ };
+ } // end namespace detail
+
+@@ -536,7 +536,7 @@ namespace cereal
+ "cereal detected a non-const type parameter in non-member save_minimal. "
+ "save_minimal non-member functions must always pass their types as const" );
+
+- using type = typename detail::get_non_member_save_minimal_type<T, A, check::value>::type;
++ typedef typename detail::get_non_member_save_minimal_type<T, A, check::value>::type type;
+ static_assert( (check::value && is_minimal_type<type>::value) || !check::value,
+ "cereal detected a non-member save_minimal with an invalid return type. "
+ "return type must be arithmetic or string" );
+@@ -565,12 +565,12 @@ namespace cereal
+ };
+
+ template <class T, class A, bool Valid>
+- struct get_non_member_versioned_save_minimal_type { using type = void; };
++ struct get_non_member_versioned_save_minimal_type { typedef void type; };
+
+ template <class T, class A>
+ struct get_non_member_versioned_save_minimal_type <T, A, true>
+ {
+- using type = decltype( save_minimal( std::declval<A const &>(), std::declval<T const &>(), 0 ) );
++ typedef decltype( save_minimal( std::declval<A const &>(), std::declval<T const &>(), 0 ) ) type;
+ };
+ } // end namespace detail
+
+@@ -582,7 +582,7 @@ namespace cereal
+ "cereal detected a non-const type parameter in versioned non-member save_minimal. "
+ "save_minimal non-member functions must always pass their types as const" );
+
+- using type = typename detail::get_non_member_versioned_save_minimal_type<T, A, check::value>::type;
++ typedef typename detail::get_non_member_versioned_save_minimal_type<T, A, check::value>::type type;
+ static_assert( (check::value && is_minimal_type<type>::value) || !check::value,
+ "cereal detected a non-member versioned save_minimal with an invalid return type. "
+ "return type must be arithmetic or string" );
+@@ -608,7 +608,7 @@ namespace cereal
+ template <class Source>
+ struct NoConvertConstRef : NoConvertBase
+ {
+- using type = Source; //!< Used to get underlying type easily
++ typedef Source type; //!< Used to get underlying type easily
+
+ template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
+ operator Dest () = delete;
+@@ -626,7 +626,7 @@ namespace cereal
+ template <class Source>
+ struct NoConvertRef : NoConvertBase
+ {
+- using type = Source; //!< Used to get underlying type easily
++ typedef Source type; //!< Used to get underlying type easily
+
+ template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
+ operator Dest () = delete;
+@@ -698,7 +698,7 @@ namespace cereal
+ "cereal detected member load_minimal but no valid member save_minimal. "
+ "cannot evaluate correctness of load_minimal without valid save_minimal." );
+
+- using SaveType = typename detail::get_member_save_minimal_type<T, A, true>::type;
++ typedef typename detail::get_member_save_minimal_type<T, A, true>::type SaveType;
+ const static bool value = has_member_load_minimal_impl<T, A>::value;
+ const static bool valid = has_member_load_minimal_type_impl<T, A, SaveType>::value;
+
+@@ -759,7 +759,7 @@ namespace cereal
+ "cereal detected member versioned load_minimal but no valid member versioned save_minimal. "
+ "cannot evaluate correctness of load_minimal without valid save_minimal." );
+
+- using SaveType = typename detail::get_member_versioned_save_minimal_type<T, A, true>::type;
++ typedef typename detail::get_member_versioned_save_minimal_type<T, A, true>::type SaveType;
+ const static bool value = has_member_versioned_load_minimal_impl<T, A>::value;
+ const static bool valid = has_member_versioned_load_minimal_type_impl<T, A, SaveType>::value;
+
+@@ -814,8 +814,8 @@ namespace cereal
+ "cereal detected non-member load_minimal but no valid non-member save_minimal. "
+ "cannot evaluate correctness of load_minimal without valid save_minimal." );
+
+- using SaveType = typename detail::get_non_member_save_minimal_type<T, A, true>::type;
+- using check = has_non_member_load_minimal_impl<T, A, SaveType>;
++ typedef typename detail::get_non_member_save_minimal_type<T, A, true>::type SaveType;
++ typedef has_non_member_load_minimal_impl<T, A, SaveType> check;
+ static const bool value = check::exists;
+
+ static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member load_minimal and save_minimal functions. "
+@@ -866,8 +866,8 @@ namespace cereal
+ "cereal detected non-member versioned load_minimal but no valid non-member versioned save_minimal. "
+ "cannot evaluate correctness of load_minimal without valid save_minimal." );
+
+- using SaveType = typename detail::get_non_member_versioned_save_minimal_type<T, A, true>::type;
+- using check = has_non_member_versioned_load_minimal_impl<T, A, SaveType>;
++ typedef typename detail::get_non_member_versioned_save_minimal_type<T, A, true>::type SaveType;
++ typedef has_non_member_versioned_load_minimal_impl<T, A, SaveType> check;;
+ static const bool value = check::exists;
+
+ static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member versioned load_minimal and save_minimal functions. "
+@@ -1182,9 +1182,16 @@ namespace cereal
+ };
+ }
+
++ // works around the lack of decltype inheritance in GCC 4.6
++ template<class T>
++ struct shared_wrapper
++ {
++ typedef decltype(detail::shared_from_this_wrapper::check(std::declval<T>())) type;
++
++ };
+ //! Determine if T or any base class of T has inherited from std::enable_shared_from_this
+ template<class T>
+- struct has_shared_from_this : decltype(detail::shared_from_this_wrapper::check(std::declval<T>()))
++ struct has_shared_from_this : shared_wrapper<T>::type
+ { };
+
+ //! Get the type of the base class of T which inherited from std::enable_shared_from_this
+@@ -1192,10 +1199,10 @@ namespace cereal
+ struct get_shared_from_this_base
+ {
+ private:
+- using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>()));
++ typedef decltype(detail::shared_from_this_wrapper::get(std::declval<T>())) PtrType;
+ public:
+ //! The type of the base of T that inherited from std::enable_shared_from_this
+- using type = typename std::decay<typename PtrType::element_type>::type;
++ typedef typename std::decay<typename PtrType::element_type>::type type;
+ };
+
+ // ######################################################################
+@@ -1209,14 +1216,14 @@ namespace cereal
+ template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value>
+ struct strip_minimal
+ {
+- using type = T;
++ typedef T type;
+ };
+
+ //! Specialization for types wrapped in a NoConvert
+ template <class T>
+ struct strip_minimal<T, true>
+ {
+- using type = typename T::type;
++ typedef typename T::type type;
+ };
+ } // namespace traits
+
+@@ -1232,10 +1239,12 @@ namespace cereal
+ { return nullptr; }
+ };
+
++ template<class T>
++ struct is_default_constructible : std::is_constructible<T>{};
+ template <class T, class A>
+ struct Construct<T, A, false, false>
+ {
+- static_assert( std::is_default_constructible<T>::value,
++ static_assert( is_default_constructible<T>::value,
+ "Trying to serialize a an object with no default constructor. \n\n "
+ "Types must either be default constructible or define either a member or non member Construct function. \n "
+ "Construct functions generally have the signature: \n\n "
+diff --git a/include/cereal/external/rapidjson/reader.h b/include/cereal/external/rapidjson/reader.h
+index 7790907..3ee838c 100644
+--- a/include/cereal/external/rapidjson/reader.h
++++ b/include/cereal/external/rapidjson/reader.h
+@@ -402,20 +402,13 @@ private:
+ }
+
+ // cereal Temporary until constexpr support is added in RTM
+-#ifdef _MSC_VER
++//#ifdef _MSC_VER
+ template <class Ch>
+ bool characterOk( Ch c )
+ {
+ return c < 256;
+ }
+-
+- template <>
+- bool characterOk<char>( Ch )
+- {
+- return true;
+- }
+-
+-#else
++/*#else
+ // As part of a fix for GCC 4.7
+ template <class T>
+ static constexpr int to_int( T t ){ return t; }
+@@ -432,7 +425,7 @@ private:
+ characterOk(Ch c)
+ { return c < 256; }
+ #endif
+-
++*/
+ // Parse string, handling the prefix and suffix double quotes and escaping.
+ template<unsigned parseFlags, typename Stream, typename Handler>
+ void ParseString(Stream& stream, Handler& handler) {
+diff --git a/include/cereal/external/rapidjson/writer.h b/include/cereal/external/rapidjson/writer.h
+index 0f87255..e02c27a 100644
+--- a/include/cereal/external/rapidjson/writer.h
++++ b/include/cereal/external/rapidjson/writer.h
+@@ -177,20 +177,14 @@ protected:
+ }
+
+ // cereal Temporary until constexpr support is added in RTM
+-#ifdef _MSC_VER
++//#ifdef _MSC_VER
+ template <class Ch>
+ bool characterOk( Ch c )
+ {
+ return c < 256;
+ }
+
+- template <>
+- bool characterOk<char>( Ch )
+- {
+- return true;
+- }
+-
+-#else
++/*#else
+ // As part of a fix for GCC 4.7
+ template <class T>
+ static constexpr int to_int( T t ){ return t; }
+@@ -206,7 +200,7 @@ protected:
+ typename std::enable_if< to_int(std::numeric_limits<Ch>::max()) >= to_int(256), bool>::type
+ characterOk(Ch c)
+ { return c < 256; }
+-#endif
++#endif*/
+
+ //! \todo Optimization with custom double-to-string converter.
+ void WriteDouble(double d) {
+diff --git a/include/cereal/types/common.hpp b/include/cereal/types/common.hpp
+index abb8bfd..5c014cd 100644
+--- a/include/cereal/types/common.hpp
++++ b/include/cereal/types/common.hpp
+@@ -55,6 +55,15 @@ namespace cereal
+
+ namespace
+ {
++ template<class en>
++ struct underlying_type
++ {
++ typedef typename std::conditional<
++ en(-1)<en(0),
++ typename std::make_signed<en>::type,
++ typename std::make_unsigned<en>::type
++ > ::type type;
++ };
+ //! Gets the underlying type of an enum
+ /*! @internal */
+ template <class T, bool IsEnum>
+@@ -64,7 +73,7 @@ namespace cereal
+ /*! Specialization for when we actually have an enum
+ @internal */
+ template <class T>
+- struct enum_underlying_type<T, true> { using type = typename std::underlying_type<T>::type; };
++ struct enum_underlying_type<T, true> { typedef typename underlying_type<T>::type type; };
+ } // anon namespace
+
+ //! Checks if a type is an enum
+@@ -78,13 +87,13 @@ namespace cereal
+ class is_enum
+ {
+ private:
+- using DecayedT = typename std::decay<T>::type;
+- using StrippedT = typename ::cereal::traits::strip_minimal<DecayedT>::type;
++ typedef typename std::decay<T>::type DecayedT;
++ typedef typename ::cereal::traits::strip_minimal<DecayedT>::type StrippedT;
+
+ public:
+ static const bool value = std::is_enum<StrippedT>::value;
+- using type = StrippedT;
+- using base_type = typename enum_underlying_type<StrippedT, value>::type;
++ typedef StrippedT type;
++ typedef typename enum_underlying_type<StrippedT, value>::type base_type;
+ };
+ }
+
+diff --git a/include/cereal/types/memory.hpp b/include/cereal/types/memory.hpp
+index bf56c92..d2357ff 100644
+--- a/include/cereal/types/memory.hpp
++++ b/include/cereal/types/memory.hpp
+@@ -115,9 +115,9 @@ namespace cereal
+ class EnableSharedStateHelper
+ {
+ // typedefs for parent type and storage type
+- using BaseType = typename ::cereal::traits::get_shared_from_this_base<T>::type;
+- using ParentType = std::enable_shared_from_this<BaseType>;
+- using StorageType = typename std::aligned_storage<sizeof(ParentType)>::type;
++ typedef typename ::cereal::traits::get_shared_from_this_base<T>::type BaseType;
++ typedef std::enable_shared_from_this<BaseType> ParentType;
++ typedef typename std::aligned_storage<sizeof(ParentType)>::type StorageType;
+
+ public:
+ //! Saves the state of some type inheriting from enable_shared_from_this
+@@ -257,7 +257,7 @@ namespace cereal
+ {
+ // Storage type for the pointer - since we can't default construct this type,
+ // we'll allocate it using std::aligned_storage and use a custom deleter
+- using ST = typename std::aligned_storage<sizeof(T)>::type;
++ typedef typename std::aligned_storage<sizeof(T)>::type ST;
+
+ // Valid flag - set to true once construction finishes
+ // This prevents us from calling the destructor on
+@@ -345,7 +345,7 @@ namespace cereal
+ {
+ // Storage type for the pointer - since we can't default construct this type,
+ // we'll allocate it using std::aligned_storage
+- using ST = typename std::aligned_storage<sizeof(T)>::type;
++ typedef typename std::aligned_storage<sizeof(T)>::type ST;
+
+ // Allocate storage - note the ST type so that deleter is correct if
+ // an exception is thrown before we are initialized
+--
+1.9.3
+
--- /dev/null
+Release notes
+****************************************************************************
+Release date: Dec 6th, 2014.
+OS: Ubuntu 12.0.4 and above
+Requires boost version 1.55 to build.
+Code buildable in gcc 4.6.3 and above.
+NOTE: Boost is not distributed but should be installed in the Ubuntu machine.
+*****************************************************************************
+
+Release commit number: de31af
+
+What is new?
+
+Features:
+---------
+
+Slow Response:
+--------------
+This release includes slow response feature which allows a resource entity handler to provide
+a 'slow response' to a client request. If a request is received but the server cannot response
+immediately (example, response data is not available), then the server can response at a later
+time. The same API is used for both immediate and slow response.
+
+GET/PUT request on the batch interface of a collection resource using the default collection
+entity handler will result in each pointed resource’s entity handler being invoked, after which:
+a) if all pointed resources of the collection are local and not-slow, an aggregated
+response will be sent
+b) if collection includes slow local resource(s), an aggregated response is sent only after
+the slowest resource’s entity handler responds with a payload. If one or more slow resource
+entity handlers do not respond, no response is sent to the request, i.e. there is no timeout
+mechanism in current release
+
+Samples demonstrating slow response:
+simpleserver and simpleclient in C++
+ocserverslow and occlientslow in C
+
+Security:
+----------
+1. OCStack is compiled with security only if a valid libtinydtls.a is available
+under oic-resource/resource/csdk/tinydtls directory.
+2. This release provides an API to set device identity and PSK credentials.
+3. Security is NOT supported for Arduino platform.
+
+JSON serialization using Cereal libray
+--------------------------------------
+This release includes modifications which consists of using
+open source library cereal to perform JSON serialization
+and de-serialization in C++ layer. (NOTE: previously we were
+using boost::property tree for JSON parsing)
+
+NOTE: For a nested (array of array of array..) JSON value, we limit to 3-level deep nesting.
+Refer AttributeValue.h for more details.
+
+------------
+API changes:
+------------
+
+--------------------------------------------
+Class OCPlatform (Header file: OCPlatform.h)
+--------------------------------------------
+
+*****************
+sendResponse API
+*****************
+
+This new API allows the application entity handler to send response to a request.
+This API is used in sending a response immediately (if available) or in cases of
+slow response. Due to this change, signature of application entity handler has
+been modified. This introduces changes in application entity handler code.
+Please see below.
+All C++ samples demonstrate the use of sendResponse API.
+
+--------------------------------------------
+Header file: OCApi.h
+--------------------------------------------
+
+typedef std::function<OCEntityHandlerResult(
+ const std::shared_ptr<OCResourceRequest>)> EntityHandler;
+
+Signature of application entity handler has changed. New signature consists only of
+one parameter which is OCResourceRequest pointer. Response is formed and sent via
+sendResponse API. All C++ samples are updated to showcase this modification.
+
+----------------------------------------------------------
+Class OCResourceRequest (Header file: OCResourceRequest.h)
+----------------------------------------------------------
+
+********************
+getRequestHandle API
+********************
+
+This new API allows the application entity handler to retrieve request handle
+from the incoming request.
+All C++ samples demonstrate the use of getRequestHandle API.
+
+*********************
+getResourceHandle API
+*********************
+
+This new API allows the application entity handler to retrieve resource handle
+from the incoming request.
+All C++ samples demonstrate the use of getResourceHandle API.
+
+-------------------------------------------------------------
+Class OCResourceResponse (Header file: OCResourceResponse.h)
+-------------------------------------------------------------
+
+********************
+setRequestHandle API
+********************
+
+This new API allows the application entity handler to set request handle in
+the response.
+All C++ samples demonstrate the use of setRequestHandle API.
+
+*********************
+setResourceHandle API
+*********************
+
+This new API allows the application entity handler to set resource handle in
+the response.
+All C++ samples demonstrate the use of setResourceHandle API.
+
+*********************
+setResponseResult API
+*********************
+
+This new API allows the application entity handler to set result in
+the response.
+All C++ samples demonstrate the use of setResponseResult API.
+
+-------------------------------------------------------------
+Header file: OCStack.h
+-------------------------------------------------------------
+
+***************************
+OCDoResponse API
+***************************
+
+This new C API allows the application entity handler to send response to a request.
+This API is used in sending a response immediately (if available) or in cases of
+slow response.
+
+-------------------------------------------------------------
+Header file: OCSecurity.h
+-------------------------------------------------------------
+
+***************************
+OCSetDtlsPskCredentials API
+***************************
+
+This new API allows to set DTLS PSK credentials.
+
+------------
+Notes:
+------------
+
+Known issues:
+-------------
+1. When observation is used, server shutdown causes an error (segmentation fault).
+
+Active discovery-
+1. In case of unicast presence with rt, only one rt is permitted per IP address for
+subscribePresence. If multiple subscriptions are done, only first subscribePresence’s rt is used.
+2. For multicast presence, server shutdown (ungraceful) scenario is not notified to the client,
+but graceful shutdowns are notified.
+3. IOT 85
+
+Issues Fixed:
+-------------
+1. IOT 65 (Stopping presence subscription gets infinite callback to handlePresence)
+2. IOT 79 (3 Presence Notifications when a resource is created on the server)
+
+General notes:
+--------------
+Maximum length of URI supported is 64 bytes (sent from the client)
+Maximum length of query supported is 64 bytes (sent from the client)
+Maximum length of request from client and response from server for Arduino is is 256 bytes
+Maximum length of request from client and response from server for non-Ardunio is is 1024 bytes
+
+OIC base supports Arduino WiFi shield.
+This support has been tested with Arduino Mega 2560 and with Arduino 1.0.5 WiFi library.
+Please refer to oic-resource/csdk/README file for building OIC base with WiFi support.
+
+-------------
+How to build:
+-------------
+
+REFER https://oic-review.01.org/gerrit for more details on getting oic-resource repo.
+If the code is not cloned:
+Clone the oic-resource repo using this command: git clone oic:oic-resource
+
+NOTE: If the repo is already cloned, use 'git pull' inside oic-resource folder to get the
+latest code.
+
+In repo oic-resource, root folder consists of 'resource' folder. Inside OIC folder there
+is a Makefile.
+
+Inside oic-resource directory, use 'make'to build the entire OIC code. This would build the C++ SDK,
+core(i.e base) and samples.
+
+Use 'make BUILD=debug' to build the entire OIC code in debug mode. This would build the C++ SDK,
+core(i.e base) and samples.
+
+--------
+Samples:
+--------
+
+A basic sample for hosting a resource on a server and a sample for client for discovering resources
+are provided here:
+Simple server sample location: oic-resource/examples/simpleserver.cpp
+Simple client sample location: oic-resource/examples/simpleclient.cpp
+Server and client mode (mode type both) location: oic-resource/examples/simpleclientserver.cpp
+Simpleserver and simpleclient samples also provide examples for doing POST operation.
+Simpleserver also demonstrates slow response case for a GET request.
+
+Garage samples provide usage of OCRepresentation, get/set attribute values
+oic-resource/examples/garageclient.cpp
+oic-resource/examples/garageserver.cpp
+
+Fridge samples provide usage of constructResourceObject API, std bind
+(for mapping request and responses), default
+device entity handler, header options support and Delete operation.
+oic-resource/examples/fridgeclient.cpp
+oic-resource/examples/fridgeserver.cpp
+
+Presence samples provides examples to use presence APIs
+Sample with basic presence feature for server side: oic-resource/examples/presenceserver.cpp
+Sample with basic presence feature for client side: oic-resource/examples/presenceclient.cpp
+
+Room samples provides examples to use resource collection.
+oic-resource/examples/roomclient.cpp
+oic-resource/examples/roomserver.cpp
+
+After building the code in oic-resource, executables for samples are in directory named
+'oic-resource/samples/release'.
+After building the code in oic-resource, executables are in directory named 'oic-resource/release'.
+
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#include <new>
-
#include "InProcClientWrapper.h"
#include "ocstack.h"
#include "OCPlatform.h"
#include "OCResource.h"
-
+#include <OCSerialization.h>
using namespace std;
namespace OC
{
- InProcClientWrapper::InProcClientWrapper(OC::OCPlatform_impl& owner,
+ InProcClientWrapper::InProcClientWrapper(
std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
- : IClientWrapper(owner),
- m_threadRun(false), m_csdkLock(csdkLock),
- m_owner(owner),
+ : m_threadRun(false), m_csdkLock(csdkLock),
m_cfg { cfg }
{
// if the config type is server, we ought to never get called. If the config type
m_listeningThread.join();
}
- OCStop();
+ // only stop if we are the ones who actually called 'init'. We are counting
+ // on the server to do the stop.
+ if(m_cfg.mode == ModeType::Client)
+ {
+ OCStop();
+ }
}
void InProcClientWrapper::listeningFunc()
}
}
- std::string InProcClientWrapper::convertOCAddrToString(OCDevAddr& addr,
- OCSecureType type, const std::string &portStr)
- {
- // TODO: we currently assume this is a IPV4 address, need to figure out the actual value
-
- uint8_t a, b, c, d;
- uint16_t port;
-
- if(OCDevAddrToIPv4Addr(&addr, &a, &b, &c, &d) ==0 && OCDevAddrToPort(&addr, &port)==0)
- {
- ostringstream os;
- if(type == OCSecureType::IPV4)
- {
- os << "coap://" << static_cast<int>(a) << '.' <<
- static_cast<int>(b) << '.' << static_cast<int>(c) <<
- '.' << static_cast<int>(d) << ':' <<static_cast<int>(port);
- }
- else if(type == OCSecureType::IPV4Secure)
- {
- os << "coaps://" << static_cast<int>(a) <<'.' <<
- static_cast<int>(b) <<'.' << static_cast<int>(c) <<
- '.' << static_cast<int>(d) << ':' << portStr;
- }
- return os.str();
- }
- else
- {
- return OC::Error::INVALID_IP;
- }
- }
-
- struct ListenContext
- {
- FindCallback callback;
- IClientWrapper::Ptr clientWrapper;
- };
-
-
- std::shared_ptr<OCResource> InProcClientWrapper::parseOCResource(
- IClientWrapper::Ptr clientWrapper, OCDevAddr& addr,
- const boost::property_tree::ptree resourceNode)
- {
- std::string uri = resourceNode.get<std::string>(OC::Key::URIKEY, "");
- bool obs = resourceNode.get<int>(OC::Key::OBSERVABLEKEY,0) == 1;
- std::vector<std::string> rTs;
- std::vector<std::string> ifaces;
-
- boost::property_tree::ptree properties =
- resourceNode.get_child(OC::Key::PROPERTYKEY, boost::property_tree::ptree());
-
- boost::property_tree::ptree rT =
- properties.get_child(OC::Key::RESOURCETYPESKEY, boost::property_tree::ptree());
- for(auto itr : rT)
- {
- rTs.push_back(itr.second.data());
- }
- bool secure = properties.get<int>(OC::Key::SECUREKEY,0) == 1;
-
- boost::property_tree::ptree iF =
- properties.get_child(OC::Key::INTERFACESKEY, boost::property_tree::ptree());
- for(auto itr : iF)
- {
- ifaces.push_back(itr.second.data());
- }
-
- std::string host;
- if(secure)
- {
- string port = properties.get<string>(OC::Key::PORTKEY,"");
- host= convertOCAddrToString(addr, OCSecureType::IPV4Secure, port);
- }
- else
- {
- host= convertOCAddrToString(addr, OCSecureType::IPV4);
- }
-
- return std::shared_ptr<OCResource>(
- new OCResource(clientWrapper, host, uri, obs, rTs, ifaces));
- }
-
OCStackApplicationResult listenCallback(void* ctx, OCDoHandle handle,
OCClientResponse* clientResponse)
{
- ListenContext* context = static_cast<ListenContext*>(ctx);
+ ClientCallbackContext::ListenContext* context =
+ static_cast<ClientCallbackContext::ListenContext*>(ctx);
if(clientResponse->result != OC_STACK_OK)
{
return OC_STACK_KEEP_TRANSACTION;
}
+ auto clientWrapper = context->clientWrapper.lock();
+
+ if(!clientWrapper)
+ {
+ oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper"
+ << std::flush;
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
std::stringstream requestStream;
requestStream << clientResponse->resJSONPayload;
- boost::property_tree::ptree root;
-
try
{
- boost::property_tree::read_json(requestStream, root);
- }
- catch(boost::property_tree::json_parser::json_parser_error &e)
- {
- oclog() << "listenCallback(): read_json() failed: " << e.what()
- << std::flush;
+ ListenOCContainer container(clientWrapper, *clientResponse->addr,
+ requestStream);
- return OC_STACK_KEEP_TRANSACTION;
- }
-
- boost::property_tree::ptree payload =
- root.get_child(OC::Key::OCKEY, boost::property_tree::ptree());
+ // loop to ensure valid construction of all resources
+ for(auto resource : container.Resources())
+ {
+ std::thread exec(context->callback, resource);
+ exec.detach();
+ }
- for(auto payloadItr : payload)
+ }
+ catch(const std::exception& e)
{
- try
- {
- std::shared_ptr<OCResource> resource =
- context->clientWrapper->parseOCResource(context->clientWrapper,
- *clientResponse->addr,
- payloadItr.second);
-
- // Note: the call to detach allows the underlying thread to continue until
- // completion and allows us to destroy the exec object. This is apparently NOT
- // a memory leak, as the thread will apparently take care of itself.
- // Additionally, the only parameter here is a shared ptr, so OCResource will be
- // disposed of properly upon completion of the callback handler.
- std::thread exec(context->callback,resource);
- exec.detach();
- }
- catch(ResourceInitException& e)
- {
- oclog() << "listenCallback(): failed to create resource: " << e.what()
- << std::flush;
- }
+ oclog() << "listenCallback failed to parse a malformed message: "
+ << e.what()
+ << std::endl <<std::endl
+ << clientResponse->result
+ << std::flush;
+ return OC_STACK_KEEP_TRANSACTION;
}
return OC_STACK_KEEP_TRANSACTION;
+
}
OCStackResult InProcClientWrapper::ListenForResource(const std::string& serviceUrl,
OCCallbackData cbdata = {0};
- ListenContext* context = new ListenContext();
+ ClientCallbackContext::ListenContext* context = new ClientCallbackContext::ListenContext();
context->callback = callback;
context->clientWrapper = shared_from_this();
cbdata.context = static_cast<void*>(context);
cbdata.cb = listenCallback;
- cbdata.cd = [](void* c){delete static_cast<ListenContext*>(c);};
+ cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::ListenContext*>(c);};
auto cLock = m_csdkLock.lock();
if(cLock)
}
else
{
+ delete context;
result = OC_STACK_ERROR;
}
return result;
}
- struct GetContext
- {
- GetCallback callback;
- };
-
- struct SetContext
- {
- PutCallback callback;
- };
-
-
OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse)
{
- std::stringstream requestStream;
- requestStream<<clientResponse->resJSONPayload;
- if(strlen((char*)clientResponse->resJSONPayload) == 0)
+ if(clientResponse->resJSONPayload == nullptr || clientResponse->resJSONPayload[0] == '\0')
{
return OCRepresentation();
}
- boost::property_tree::ptree root;
- try
- {
- boost::property_tree::read_json(requestStream, root);
- }
- catch(boost::property_tree::json_parser::json_parser_error &e)
+ MessageContainer oc;
+ oc.setJSONRepresentation(clientResponse->resJSONPayload);
+
+ std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
+ if(it == oc.representations().end())
{
return OCRepresentation();
}
- boost::property_tree::ptree payload = root.get_child(OC::Key::OCKEY, boost::property_tree::ptree());
- OCRepresentation root_resource;
- std::vector<OCRepresentation> children;
- bool isRoot = true;
- for ( auto payloadItr : payload)
- {
- OCRepresentation child;
- try
- {
- auto resourceNode = payloadItr.second;
- std::string uri = resourceNode.get<std::string>(OC::Key::URIKEY, "");
-
- if (isRoot)
- {
- root_resource.setUri(uri);
- }
- else
- {
- child.setUri(uri);
- }
-
- if( resourceNode.count(OC::Key::PROPERTYKEY) != 0 )
- {
- std::vector<std::string> rTs;
- std::vector<std::string> ifaces;
- boost::property_tree::ptree properties =
- resourceNode.get_child(OC::Key::PROPERTYKEY, boost::property_tree::ptree());
-
- boost::property_tree::ptree rT =
- properties.get_child(OC::Key::RESOURCETYPESKEY,
- boost::property_tree::ptree());
- for(auto itr : rT)
- {
- rTs.push_back(itr.second.data());
- }
-
- boost::property_tree::ptree iF =
- properties.get_child(OC::Key::INTERFACESKEY, boost::property_tree::ptree());
- for(auto itr : iF)
- {
- ifaces.push_back(itr.second.data());
- }
- if (isRoot)
- {
- root_resource.setResourceInterfaces(ifaces);
- root_resource.setResourceTypes(rTs);
- }
- else
- {
- child.setResourceInterfaces(ifaces);
- child.setResourceTypes(rTs);
- }
- }
-
- if( resourceNode.count(OC::Key::REPKEY) != 0 )
- {
- boost::property_tree::ptree rep =
- resourceNode.get_child(OC::Key::REPKEY, boost::property_tree::ptree());
- AttributeMap attrs;
- for( auto item : rep)
- {
- std::string name = item.first.data();
- std::string value = item.second.data();
- attrs[name] = value;
- }
- if (isRoot)
- {
- root_resource.setAttributeMap(attrs);
- }
- else
- {
- child.setAttributeMap(attrs);
- }
- }
-
- if (!isRoot)
- children.push_back(child);
- }
- catch (...)
- {
- // TODO
- }
- isRoot = false;
- }
+ // first one is considered the root, everything else is considered a child of this one.
+ OCRepresentation root = *it;
+ ++it;
- root_resource.setChildren(children);
+ std::for_each(it, oc.representations().end(),
+ [&root](const OCRepresentation& repItr)
+ {root.addChild(repItr);});
+ return root;
- return root_resource;
}
void parseServerHeaderOptions(OCClientResponse* clientResponse,
OCStackApplicationResult getResourceCallback(void* ctx, OCDoHandle handle,
OCClientResponse* clientResponse)
{
- GetContext* context = static_cast<GetContext*>(ctx);
+ ClientCallbackContext::GetContext* context =
+ static_cast<ClientCallbackContext::GetContext*>(ctx);
OCRepresentation rep;
HeaderOptions serverHeaderOptions;
OCStackResult result;
OCCallbackData cbdata = {0};
- GetContext* ctx = new GetContext();
+ ClientCallbackContext::GetContext* ctx = new ClientCallbackContext::GetContext();
ctx->callback = callback;
cbdata.context = static_cast<void*>(ctx);
cbdata.cb = &getResourceCallback;
- cbdata.cd = [](void* c){delete static_cast<GetContext*>(c);};
+ cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::GetContext*>(c);};
auto cLock = m_csdkLock.lock();
}
else
{
+ delete ctx;
result = OC_STACK_ERROR;
}
return result;
OCStackApplicationResult setResourceCallback(void* ctx, OCDoHandle handle,
OCClientResponse* clientResponse)
{
- SetContext* context = static_cast<SetContext*>(ctx);
+ ClientCallbackContext::SetContext* context =
+ static_cast<ClientCallbackContext::SetContext*>(ctx);
OCRepresentation attrs;
HeaderOptions serverHeaderOptions;
std::string InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
{
- ostringstream payload;
- // TODO need to change the format to "{"oc":[]}"
- payload << "{\"oc\":";
-
- payload << rep.getJSONRepresentation();
-
- payload << "}";
- return payload.str();
+ MessageContainer ocInfo;
+ ocInfo.addRepresentation(rep);
+ return ocInfo.getJSONRepresentation(OCInfoFormat::IncludeOC);
}
OCStackResult InProcClientWrapper::PostResourceRepresentation(const std::string& host,
OCStackResult result;
OCCallbackData cbdata = {0};
- SetContext* ctx = new SetContext();
+ ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext();
ctx->callback = callback;
cbdata.cb = &setResourceCallback;
- cbdata.cd = [](void* c){delete static_cast<SetContext*>(c);};
+ cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::SetContext*>(c);};
cbdata.context = static_cast<void*>(ctx);
// TODO: in the future the cstack should be combining these two strings!
}
else
{
+ delete ctx;
result = OC_STACK_ERROR;
}
OCStackResult result;
OCCallbackData cbdata = {0};
- SetContext* ctx = new SetContext();
+ ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext();
ctx->callback = callback;
cbdata.cb = &setResourceCallback;
- cbdata.cd = [](void* c){delete static_cast<SetContext*>(c);};
+ cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::SetContext*>(c);};
cbdata.context = static_cast<void*>(ctx);
// TODO: in the future the cstack should be combining these two strings!
}
else
{
+ delete ctx;
result = OC_STACK_ERROR;
}
return result;
}
- struct DeleteContext
- {
- DeleteCallback callback;
- };
-
OCStackApplicationResult deleteResourceCallback(void* ctx, OCDoHandle handle,
OCClientResponse* clientResponse)
{
- DeleteContext* context = static_cast<DeleteContext*>(ctx);
- OCRepresentation attrs;
+ ClientCallbackContext::DeleteContext* context =
+ static_cast<ClientCallbackContext::DeleteContext*>(ctx);
HeaderOptions serverHeaderOptions;
if(clientResponse->result == OC_STACK_OK)
OCStackResult result;
OCCallbackData cbdata = {0};
- DeleteContext* ctx = new DeleteContext();
+ ClientCallbackContext::DeleteContext* ctx = new ClientCallbackContext::DeleteContext();
ctx->callback = callback;
cbdata.cb = &deleteResourceCallback;
- cbdata.cd = [](void* c){delete static_cast<DeleteContext*>(c);};
+ cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::DeleteContext*>(c);};
cbdata.context = static_cast<void*>(ctx);
ostringstream os;
}
else
{
+ delete ctx;
result = OC_STACK_ERROR;
}
return result;
}
- struct ObserveContext
- {
- ObserveCallback callback;
- };
-
OCStackApplicationResult observeResourceCallback(void* ctx, OCDoHandle handle,
OCClientResponse* clientResponse)
{
- ObserveContext* context = static_cast<ObserveContext*>(ctx);
+ ClientCallbackContext::ObserveContext* context =
+ static_cast<ClientCallbackContext::ObserveContext*>(ctx);
OCRepresentation attrs;
HeaderOptions serverHeaderOptions;
uint32_t sequenceNumber = clientResponse->sequenceNumber;
OCStackResult result;
OCCallbackData cbdata = {0};
- ObserveContext* ctx = new ObserveContext();
+ ClientCallbackContext::ObserveContext* ctx = new ClientCallbackContext::ObserveContext();
ctx->callback = callback;
cbdata.context = static_cast<void*>(ctx);
cbdata.cb = &observeResourceCallback;
- cbdata.cd = [](void* c){delete static_cast<ObserveContext*>(c);};
+ cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::ObserveContext*>(c);};
OCMethod method;
if (observeType == ObserveType::Observe)
}
else
{
+ delete ctx;
return OC_STACK_ERROR;
}
OCHeaderOption options[MAX_HEADER_OPTIONS];
assembleHeaderOptions(options, headerOptions);
- result = OCCancel(handle, static_cast<OCQualityOfService>(QoS), options, headerOptions.size());
+ result = OCCancel(handle, static_cast<OCQualityOfService>(QoS), options,
+ headerOptions.size());
}
else
{
return result;
}
- struct SubscribePresenceContext
- {
- SubscribeCallback callback;
- };
-
OCStackApplicationResult subscribePresenceCallback(void* ctx, OCDoHandle handle,
- OCClientResponse* clientResponse)
+ OCClientResponse* clientResponse)
{
- SubscribePresenceContext* context = static_cast<SubscribePresenceContext*>(ctx);
- std::thread exec(context->callback, clientResponse->result, clientResponse->sequenceNumber);
+ char stringAddress[DEV_ADDR_SIZE_MAX];
+ ostringstream os;
+ uint16_t port;
- exec.detach();
+ if(OCDevAddrToString(clientResponse->addr, stringAddress) == 0 &&
+ OCDevAddrToPort(clientResponse->addr, &port) == 0)
+ {
+ os<<stringAddress<<":"<<port;
+
+ ClientCallbackContext::SubscribePresenceContext* context =
+ static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
+
+ std::thread exec(context->callback, clientResponse->result,
+ clientResponse->sequenceNumber, os.str());
+
+ exec.detach();
+ }
+ else
+ {
+ oclog() << "subscribePresenceCallback(): OCDevAddrToString() or OCDevAddrToPort() "
+ <<"failed"<< std::flush;
+ }
return OC_STACK_KEEP_TRANSACTION;
}
{
OCCallbackData cbdata = {0};
- SubscribePresenceContext* ctx = new SubscribePresenceContext();
+ ClientCallbackContext::SubscribePresenceContext* ctx =
+ new ClientCallbackContext::SubscribePresenceContext();
ctx->callback = presenceHandler;
cbdata.cb = &subscribePresenceCallback;
cbdata.context = static_cast<void*>(ctx);
- cbdata.cd = [](void* c){delete static_cast<SubscribePresenceContext*>(c);};
+ cbdata.cd = [](void* c)
+ {delete static_cast<ClientCallbackContext::SubscribePresenceContext*>(c);};
auto cLock = m_csdkLock.lock();
std::ostringstream os;
}
if(!cLock)
+ {
+ delete ctx;
return OC_STACK_ERROR;
+ }
return OCDoResource(handle, OC_REST_PRESENCE, os.str().c_str(), nullptr, nullptr,
OC_LOW_QOS, &cbdata, NULL, 0);
OCEntityHandlerRequest * entityHandlerRequest,
std::shared_ptr<OCResourceRequest> pRequest)
{
+ pRequest->setRequestHandle(entityHandlerRequest->requestHandle);
+ pRequest->setResourceHandle(entityHandlerRequest->resource);
+
if(flag & OC_INIT_FLAG)
{
pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag);
{
pRequest->setRequestHandlerFlag(
OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
- if(entityHandlerRequest->obsInfo)
+
+ if(entityHandlerRequest)
{
OC::ObservationInfo observationInfo;
- observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo->action;
- observationInfo.obsId = entityHandlerRequest->obsInfo->obsId;
+ observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
+ observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
pRequest->setObservationInfo(observationInfo);
}
}
}
-void processResourceResponse(OCEntityHandlerFlag flag,
- OCEntityHandlerRequest * entityHandlerRequest,
- std::shared_ptr<OCResourceResponse> pResponse)
-{
- if(flag & OC_REQUEST_FLAG)
- {
- // TODO we could use const reference
- std::string payLoad;
- HeaderOptions serverHeaderOptions;
-
- if(pResponse)
- {
- payLoad = pResponse->getPayload();
- serverHeaderOptions = pResponse->getHeaderOptions();
- }
- else
- {
- throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
- }
-
- if (payLoad.size() < entityHandlerRequest->resJSONPayloadLen)
- {
- int i = 0;
- entityHandlerRequest->numSendVendorSpecificHeaderOptions =
- serverHeaderOptions.size();
- for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
- {
- entityHandlerRequest->sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
- entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionID =
- static_cast<uint16_t>(it->getOptionID());
- entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionLength =
- (it->getOptionData()).length() + 1;
- memcpy(entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionData,
- (it->getOptionData()).c_str(),
- (it->getOptionData()).length() + 1);
- i++;
- }
-
- strncpy((char*)entityHandlerRequest->resJSONPayload,
- payLoad.c_str(),
- entityHandlerRequest->resJSONPayloadLen);
- }
- else
- {
- throw OCException(OC::Exception::STR_PAYLOAD_OVERFLOW, OC_STACK_MALFORMED_RESPONSE);
- }
- }
-
-}
-
OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
OCEntityHandlerRequest * entityHandlerRequest,
char* uri)
}
auto pRequest = std::make_shared<OC::OCResourceRequest>();
- auto pResponse = std::make_shared<OC::OCResourceResponse>();
formResourceRequest(flag, entityHandlerRequest, pRequest);
if(defaultDeviceEntityHandler)
{
- result = defaultDeviceEntityHandler(pRequest, pResponse);
+ result = defaultDeviceEntityHandler(pRequest);
}
else
{
return OC_EH_ERROR;
}
- processResourceResponse(flag, entityHandlerRequest, pResponse);
-
return result;
}
}
auto pRequest = std::make_shared<OC::OCResourceRequest>();
- auto pResponse = std::make_shared<OC::OCResourceResponse>();
formResourceRequest(flag, entityHandlerRequest, pRequest);
// Call CPP Application Entity Handler
if(entityHandlerEntry->second)
{
- result = entityHandlerEntry->second(pRequest, pResponse);
-
- if(OC_EH_RESOURCE_CREATED == result)
- {
- std::string createdUri = pResponse->getNewResourceUri();
- strncpy(reinterpret_cast<char*>(entityHandlerRequest->newResourceUri),
- createdUri.c_str(),
- createdUri.length() + 1);
- }
+ result = entityHandlerEntry->second(pRequest);
}
else
{
return OC_EH_ERROR;
}
- processResourceResponse(flag, entityHandlerRequest, pResponse);
-
return result;
}
namespace OC
{
- InProcServerWrapper::InProcServerWrapper(OC::OCPlatform_impl& owner,
+ InProcServerWrapper::InProcServerWrapper(
std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
- : IServerWrapper(owner),
- m_csdkLock(csdkLock)
+ : m_csdkLock(csdkLock)
{
OCMode initType;
return result;
}
+
OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
(EntityHandler entityHandler)
{
return result;
}
+ OCStackResult InProcServerWrapper::sendResponse(
+ const std::shared_ptr<OCResourceResponse> pResponse)
+ {
+ auto cLock = m_csdkLock.lock();
+ OCStackResult result = OC_STACK_ERROR;
+
+ if(!pResponse)
+ {
+ result = OC_STACK_MALFORMED_RESPONSE;
+ throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
+ }
+ else
+ {
+ OCEntityHandlerResponse response;
+ std::string payLoad;
+ HeaderOptions serverHeaderOptions;
+
+ payLoad = pResponse->getPayload();
+ serverHeaderOptions = pResponse->getHeaderOptions();
+
+ response.requestHandle = pResponse->getRequestHandle();
+ response.resourceHandle = pResponse->getResourceHandle();
+ response.ehResult = pResponse->getResponseResult();
+ response.payload = (unsigned char*) payLoad.c_str();
+ response.payloadSize = payLoad.length() + 1;
+ response.persistentBufferFlag = 0;
+
+ response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
+ int i = 0;
+ for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
+ {
+ response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
+ response.sendVendorSpecificHeaderOptions[i].optionID =
+ static_cast<uint16_t>(it->getOptionID());
+ response.sendVendorSpecificHeaderOptions[i].optionLength =
+ (it->getOptionData()).length() + 1;
+ memcpy(response.sendVendorSpecificHeaderOptions[i].optionData,
+ (it->getOptionData()).c_str(),
+ (it->getOptionData()).length() + 1);
+ i++;
+ }
+
+ if(OC_EH_RESOURCE_CREATED == response.ehResult)
+ {
+ std::string createdUri = pResponse->getNewResourceUri();
+ strncpy(reinterpret_cast<char*>(response.resourceUri),
+ createdUri.c_str(),
+ createdUri.length() + 1);
+ }
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCDoResponse(&response);
+ }
+ else
+ {
+ result = OC_STACK_ERROR;
+ }
+
+ if(result != OC_STACK_OK)
+ {
+ oclog() << "Error sending response\n";
+ }
+ return result;
+ }
+ }
+
InProcServerWrapper::~InProcServerWrapper()
{
if(m_processThread.joinable())
return OC::Exception::NO_OBSERVERS;
case OC_STACK_OBSERVER_NOT_FOUND:
return OC::Exception::OBSV_NO_FOUND;
- case OC_STACK_OBSERVER_NOT_ADDED:
- return OC::Exception::OBSV_NOT_ADDED;
- case OC_STACK_OBSERVER_NOT_REMOVED:
- return OC::Exception::OBSV_NOT_REMOVED;
#ifdef WITH_PRESENCE
case OC_STACK_PRESENCE_STOPPED:
return OC::Exception::PRESENCE_STOPPED;
- case OC_STACK_PRESENCE_DO_NOT_HANDLE:
- return OC::Exception::PRESENCE_NOT_HANDLED;
#endif
+ case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+ return OC::Exception::VIRTUAL_DO_NOT_HANDLE;
case OC_STACK_INVALID_OPTION:
return OC::Exception::INVALID_OPTION;
case OC_STACK_MALFORMED_RESPONSE:
return OC::Exception::MALFORMED_STACK_RESPONSE;
+ case OC_STACK_PERSISTENT_BUFFER_REQUIRED:
+ return OC::Exception::PERSISTENT_BUFFER_REQUIRED;
+ case OC_STACK_CONTINUE:
+ return OC::Exception::STACK_CONTINUE;
+ case OC_STACK_INVALID_REQUEST_HANDLE:
+ return OC::Exception::INVALID_REQUEST_HANDLE;
case OC_STACK_ERROR:
return OC::Exception::GENERAL_FAULT;
}
{
return OCPlatform_impl::Instance().unsubscribePresence(presenceHandle);
}
+
+ OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
+ {
+ return OCPlatform_impl::Instance().sendResponse(pResponse);
+ }
} // namespace OCPlatform
} //namespace OC
switch(config.mode)
{
case ModeType::Server:
- m_server = m_WrapperInstance->CreateServerWrapper(*this, m_csdkLock, config);
+ m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config);
break;
case ModeType::Client:
- m_client = m_WrapperInstance->CreateClientWrapper(*this, m_csdkLock, config);
+ m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config);
break;
case ModeType::Both:
- m_server = m_WrapperInstance->CreateServerWrapper(*this, m_csdkLock, config);
- m_client = m_WrapperInstance->CreateClientWrapper(*this, m_csdkLock, config);
+ m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config);
+ m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config);
break;
}
}
}
OCStackResult OCPlatform_impl::notifyListOfObservers(OCResourceHandle resourceHandle,
- ObservationIds& observationIds,
- const std::shared_ptr<OCResourceResponse> pResponse)
+ ObservationIds& observationIds,
+ const std::shared_ptr<OCResourceResponse> pResponse)
{
return notifyListOfObservers(resourceHandle, observationIds, pResponse, m_cfg.QoS);
}
OCStackResult OCPlatform_impl::notifyListOfObservers(OCResourceHandle resourceHandle,
- ObservationIds& observationIds,
- const std::shared_ptr<OCResourceResponse> pResponse,
- QualityOfService QoS)
+ ObservationIds& observationIds,
+ const std::shared_ptr<OCResourceResponse> pResponse,
+ QualityOfService QoS)
{
if(!pResponse)
{
return result_guard(OC_STACK_ERROR);
}
- std::string payload(pResponse->getPayload());
+ std::string payload(pResponse->getResourceRepresentation().getJSONRepresentation());
return result_guard(
OCNotifyListOfObservers(resourceHandle,
ref(presenceHandle));
}
+ OCStackResult OCPlatform_impl::sendResponse(const std::shared_ptr<OCResourceResponse> pResponse)
+ {
+ return checked_guard(m_server, &IServerWrapper::sendResponse,
+ pResponse);
+ }
} //namespace OC
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file OCRepresentation.cpp
+
+/// @brief This file contains the implementation of classes and its members
+/// related to OCRepresentation
+
+
+#include <OCRepresentation.h>
+
+#include <cereal/cereal.hpp>
+#include <cereal/types/map.hpp>
+#include <cereal/types/vector.hpp>
+#include <cereal/types/utility.hpp>
+#include <OicJsonSerializer.hpp>
+#include <algorithm>
+
+// code needed to serialize a string::Attribute value map
+namespace OC
+{
+ namespace detail
+ {
+ template<class Archive>
+ class WriteAttributeValue : public boost::static_visitor<>
+ {
+ public:
+ WriteAttributeValue(const std::string& name, Archive& ar)
+ :m_name(name), m_archive(ar)
+ {}
+
+ template<class T>
+ void operator()(const T& value) const
+ {
+ m_archive(cereal::make_nvp(m_name, value));
+ }
+ private:
+ std::string m_name;
+ Archive& m_archive;
+ };
+ }
+}
+
+namespace cereal
+{
+ // take no action when serializing the null type, because the 'save' below
+ // doesn't use the visitor for this type.
+ template <class Archive>
+ void serialize(Archive&, OC::NullType t)
+ {}
+
+ template<class Archive>
+ void save(Archive& ar, const std::map<std::string, OC::AttributeValue>& vals)
+ {
+ for(const auto& kv : vals)
+ {
+ const auto& k = kv.first;
+ const auto& v = kv.second;
+
+ if(v.which() != OC::AttributeValueNullIndex)
+ {
+ OC::detail::WriteAttributeValue<Archive> writer(k,ar);
+ boost::apply_visitor(writer, v);
+ }
+ else
+ {
+ ar.setNextName(k.c_str());
+ ar.writeName();
+ ar.saveValue();
+ }
+ }
+ }
+
+ template<class Archive>
+ void load(Archive& ar, std::map<std::string, OC::AttributeValue>& vals)
+ {
+ ar.loadAttributeValues(vals);
+ }
+}
+
+namespace OC
+{
+ typedef cereal::JSONOutputArchive OutputArchiveType;
+ typedef cereal::JSONInputArchive InputArchiveType;
+
+ void MessageContainer::setJSONRepresentation(const std::string& payload)
+ {
+ std::stringstream os(payload);
+ {
+ InputArchiveType archive(os);
+ archive(cereal::make_nvp(OC::Key::OCKEY, m_reps));
+ }
+ }
+
+ void MessageContainer::setJSONRepresentation(const unsigned char* payload)
+ {
+ setJSONRepresentation(std::string(reinterpret_cast<const char*>(payload)));
+ }
+
+ std::string MessageContainer::getJSONRepresentation(OCInfoFormat f) const
+ {
+ std::stringstream os;
+
+ // note: the block is required because cereal closes the JSON string
+ // upon destruction, so the archive needs to be destroyed before accessing
+ // the data
+ {
+ if(f == OCInfoFormat::IncludeOC)
+ {
+ OutputArchiveType archive(os);
+ archive(cereal::make_nvp(OC::Key::OCKEY, m_reps));
+ }
+ else if(f== OCInfoFormat::ExcludeOC)
+ {
+ bool firstPrinted = false;
+ for(std::vector<OCRepresentation>::size_type i = 0; i< m_reps.size();++i)
+ {
+ if(!m_reps[i].empty())
+ {
+ if(firstPrinted)
+ {
+ os<<',';
+ }
+ firstPrinted=true;
+ os << m_reps[i].getJSONRepresentation();
+ }
+ }
+ }
+ }
+ return os.str();
+ }
+
+ const std::vector<OCRepresentation>& MessageContainer::representations() const
+ {
+ return m_reps;
+ }
+
+ void MessageContainer::addRepresentation(const OCRepresentation& rep)
+ {
+ m_reps.push_back(rep);
+ }
+}
+
+namespace OC
+{
+ OCRepresentation::OCRepresentation()
+ :m_interfaceType(InterfaceType::None)
+ { }
+ std::string OCRepresentation::getJSONRepresentation() const
+ {
+ std::stringstream os;
+
+ // note: the block is required because cereal closes the JSON string
+ // upon destruction, so the archive needs to be destroyed before accessing
+ // the data
+ {
+ OutputArchiveType archive (os);
+ save(archive);
+ }
+
+ return os.str();
+ }
+
+ void OCRepresentation::addChild(const OCRepresentation& rep)
+ {
+ m_children.push_back(rep);
+ }
+
+ void OCRepresentation::clearChildren()
+ {
+ m_children.clear();
+ }
+
+ const std::vector<OCRepresentation>& OCRepresentation::getChildren() const
+ {
+ return m_children;
+ }
+
+ void OCRepresentation::setUri(const std::string& uri)
+ {
+ m_uri = uri;
+ }
+
+ std::string OCRepresentation::getUri() const
+ {
+ return m_uri;
+ }
+
+ const std::vector<std::string>& OCRepresentation::getResourceTypes() const
+ {
+ return m_resourceTypes;
+ }
+
+ void OCRepresentation::setResourceTypes(const std::vector<std::string>& resourceTypes)
+ {
+ m_resourceTypes = resourceTypes;
+ }
+
+ const std::vector<std::string>& OCRepresentation::getResourceInterfaces() const
+ {
+ return m_interfaces;
+ }
+
+ void OCRepresentation::setResourceInterfaces(const std::vector<std::string>& resourceInterfaces)
+ {
+ m_interfaces = resourceInterfaces;
+ }
+
+ bool OCRepresentation::hasAttribute(const std::string& str) const
+ {
+ return m_values.find(str) != m_values.end();
+ }
+
+ bool OCRepresentation::empty() const
+ {
+ // This logic is meant to determine whether based on the JSON serialization rules
+ // if this object will result in empty JSON. URI is only serialized if there is valid
+ // data, ResourceType and Interfaces are only serialized if we are a nothing, a
+ // child of a default or link item.
+ // Our values array is only printed in the if we are the child of a Batch resource,
+ // the parent in a 'default' situation, or not in a child/parent relationship.
+ if(!m_uri.empty())
+ {
+ return false;
+ }
+ else if ((m_interfaceType == InterfaceType::None
+ || m_interfaceType==InterfaceType::DefaultChild
+ || m_interfaceType==InterfaceType::LinkChild)
+ && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
+ {
+ return false;
+ }
+ else if((m_interfaceType == InterfaceType::None
+ || m_interfaceType == InterfaceType::BatchChild
+ || m_interfaceType == InterfaceType::DefaultParent)
+ && m_values.size()>0)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ int OCRepresentation::numberOfAttributes() const
+ {
+ return m_values.size();
+ }
+
+ bool OCRepresentation::erase(const std::string& str)
+ {
+ return m_values.erase(str);
+ }
+
+ void OCRepresentation::setNULL(const std::string& str)
+ {
+ m_values[str] = OC::NullType();
+ }
+
+ bool OCRepresentation::isNULL(const std::string& str) const
+ {
+ auto x = m_values.find(str);
+
+ if(m_values.end() != x)
+ {
+ return x->second.which() == AttributeValueNullIndex;
+ }
+ else
+ {
+ throw OCException(OC::Exception::INVALID_ATTRIBUTE+ str);
+ }
+ }
+}
+
+namespace OC
+{
+ template <class Archive, class Val>
+ void OCRepresentation::optional_load(Archive& ar, Val&& v)
+ {
+ try
+ {
+ ar(v);
+ }
+ catch(cereal::Exception& e)
+ {
+ ar.setNextName(nullptr);
+ // Loading a key that doesn't exist results in an exception
+ // Since "Not Found" is a valid condition for us, we swallow
+ // this exception and the archive will not load anything
+ }
+ }
+
+ template<class Archive>
+ void OCRepresentation::save(Archive& ar) const
+ {
+ // printed for all interface types
+ if(!m_uri.empty())
+ {
+ ar(cereal::make_nvp(Key::URIKEY, m_uri));
+ }
+
+ if((m_interfaceType == InterfaceType::None
+ || m_interfaceType==InterfaceType::DefaultChild
+ || m_interfaceType==InterfaceType::LinkChild)
+ && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
+ {
+ // The Prop object requires that it refer to non-const vectors
+ // so that it can alter them in the 'load' case. In the save case
+ // (initiated here) it will not modify the object. So, to keep the
+ // compiler happy, removing the 'const' context here is necessary.
+ const std::vector<std::string>& rt(m_resourceTypes);
+ const std::vector<std::string>& intf(m_interfaces);
+ Prop temp(const_cast<std::vector<std::string>&>(rt),
+ const_cast<std::vector<std::string>&>(intf));
+ ar(cereal::make_nvp(Key::PROPERTYKEY, temp));
+ }
+
+ // printed only for BatchChildren and DefaultParent
+ if((m_interfaceType == InterfaceType::None
+ || m_interfaceType == InterfaceType::BatchChild
+ || m_interfaceType == InterfaceType::DefaultParent)
+ && m_values.size()>0)
+ {
+ ar(cereal::make_nvp(Key::REPKEY, m_values));
+ }
+ }
+
+ template<class Archive>
+ void OCRepresentation::load(Archive& ar)
+ {
+ optional_load(ar, cereal::make_nvp(Key::URIKEY, m_uri));
+ {
+ Prop temp(m_resourceTypes, m_interfaces);
+ optional_load(ar, cereal::make_nvp(Key::PROPERTYKEY, temp));
+ }
+ optional_load(ar, cereal::make_nvp(Key::REPKEY, m_values));
+ }
+
+ template<class Archive>
+ void OCRepresentation::Prop::save(Archive& ar) const
+ {
+ if(m_types.size() > 0)
+ {
+ ar(cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
+ }
+
+ if(m_interfaces.size()>0)
+ {
+ ar(cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
+ }
+ }
+
+ template<class Archive>
+ void OCRepresentation::Prop::load(Archive& ar)
+ {
+ optional_load(ar, cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
+ optional_load(ar, cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
+ }
+}
+
+// note: the below is used to load an AttributeValue map out of JSON
+namespace OC
+{
+ namespace detail
+ {
+ enum class typeTag:uint8_t
+ {
+ NOTHING = 0,
+ _string,
+ _int,
+ _double,
+ _bool,
+ _representation
+ };
+
+ typedef rapidjson::Document::GenericValue GenericValue;
+
+ AttributeValue parseAttributeValue(const GenericValue& v);
+ AttributeValue parseAttributeValue(const GenericValue& v,
+ const unsigned int curLevel, unsigned int& maxDepth, typeTag& t);
+ AttributeValue parseAttributeValueObject(const GenericValue& v, typeTag& t);
+ AttributeValue parseAttributeValueArray(const GenericValue& v,
+ const unsigned int curLevel, unsigned int& maxDepth, typeTag& t);
+ AttributeValue parseAttributeValuePrimitive(const GenericValue& v, typeTag& t);
+
+ AttributeValue parseAttributeValue(const GenericValue& v)
+ {
+ // base entrance, start everything at '0'
+ unsigned int max_depth {0};
+ typeTag t {typeTag::NOTHING};
+
+ return parseAttributeValue(v, 0, max_depth, t);
+ }
+
+ AttributeValue parseAttributeValue(const GenericValue& v,
+ const unsigned int curLevel, unsigned int& maxDepth, typeTag& t)
+ {
+ if(v.IsObject())
+ {
+ return parseAttributeValueObject(v, t);
+ }
+ else if(v.IsArray())
+ {
+ return parseAttributeValueArray(v, curLevel + 1, maxDepth, t);
+ }
+ else
+ {
+ return parseAttributeValuePrimitive(v,t);
+ }
+ }
+
+ AttributeValue parseAttributeValueObject(const GenericValue& v, typeTag& t)
+ {
+ typedef rapidjson::Value::ConstMemberIterator CMI;
+ t = typeTag::_representation;
+ OC::OCRepresentation rep;
+
+ for(CMI itr = v.MemberBegin(); itr!= v.MemberEnd(); ++itr)
+ {
+ std::string keyName = itr->name.GetString();
+
+ if(keyName == OC::Key::URIKEY)
+ {
+ rep.setUri(boost::get<std::string>(parseAttributeValue(itr->value)));
+ }
+ else if (keyName == OC::Key::PROPERTYKEY)
+ {
+ for(CMI itr2 = itr->value.MemberBegin();
+ itr->value.MemberEnd()!=itr2;
+ ++itr2)
+ {
+ if(keyName == OC::Key::RESOURCETYPESKEY)
+ {
+ rep.setResourceTypes(
+ boost::get<std::vector<std::string>>(
+ parseAttributeValue(itr->value)));
+ }
+ else if(keyName == OC::Key::PROPERTYKEY)
+ {
+ rep.setResourceInterfaces(
+ boost::get<std::vector<std::string>>(
+ parseAttributeValue(itr->value)));
+ }
+ }
+ }
+ else if (keyName == OC::Key::REPKEY)
+ {
+ for(CMI itr2 = itr->value.MemberBegin();
+ itr->value.MemberEnd()!=itr2;
+ ++itr2)
+ {
+ rep.setValue(itr2->name.GetString(),
+ parseAttributeValue(itr2->value));
+ }
+ }
+ }
+
+ return rep;
+ }
+
+ AttributeValue parseAttributeValuePrimitive(const GenericValue& v, typeTag& t)
+ {
+ if(v.IsString())
+ {
+ t = typeTag::_string;
+ return std::string(v.GetString());
+ }
+ else if (v.IsNumber())
+ {
+ if(v.IsDouble())
+ {
+ t = typeTag::_double;
+ return double(v.GetDouble());
+ }
+ else if (v.IsInt())
+ {
+ t = typeTag::_int;
+ return int(v.GetInt());
+ }
+ else
+ {
+ throw OC::OCException(OC::Exception::INVALID_JSON_NUMERIC
+ + std::to_string(v.GetType()));
+ }
+ }
+ else if(v.IsBool_())
+ {
+ t=typeTag::_bool;
+ return bool(v.GetBool_());
+ }
+ else if(v.IsNull_())
+ {
+ return OC::NullType();
+ }
+ else
+ {
+ throw OC::OCException(OC::Exception::INVALID_JSON_TYPE
+ + std::to_string(v.GetType()));
+ }
+ }
+
+ std::vector<AttributeValue> gatherArrayContents(const GenericValue& v,
+ const unsigned int curLevel, unsigned int& maxDepth, typeTag& t)
+ {
+ std::vector<AttributeValue> out;
+
+ std::transform(v.Begin(), v.End(), back_inserter(out),
+ [curLevel, &maxDepth, &t](const GenericValue& x)
+ {
+ return parseAttributeValue(x, curLevel, maxDepth, t);
+ });
+ return out;
+ }
+
+ template<class OutT>
+ struct valueToConcrete
+ {
+ OutT operator()(const AttributeValue& v)
+ {
+ return boost::get<OutT>(v);
+ }
+
+ };
+
+ template <class OutSeqT>
+ OutSeqT valuesToConcreteVectors(const std::vector<AttributeValue>& vs)
+ {
+ OutSeqT ret;
+
+ std::transform(begin(vs),end(vs), back_inserter(ret),
+ valueToConcrete<typename OutSeqT::value_type>());
+ return ret;
+ }
+
+ template<class valueType>
+ AttributeValue remapArrayDepth(const unsigned int curLevel,
+ const std::vector<OC::AttributeValue>& vs)
+ {
+ switch(curLevel)
+ {
+ default:
+ throw OC::OCException(OC::Exception::INVALID_JSON_ARRAY_DEPTH);
+ break;
+ case 1:
+ return valuesToConcreteVectors<std::vector<valueType>>(vs);
+ break;
+ case 2:
+ return valuesToConcreteVectors<std::vector<std::vector<valueType>>>(vs);
+ break;
+ case 3:
+ return valuesToConcreteVectors
+ <std::vector<std::vector<std::vector<valueType>>>>(vs);
+ break;
+ }
+ }
+
+ AttributeValue convertArrayToConcretes(const typeTag t,
+ const unsigned int curLevel, const std::vector<OC::AttributeValue>& vs)
+ {
+ // This function converts a std::vector of AttributeValue to a std::vector
+ // of concrete types. Since we don't use a recursive Variant, we need
+ // to get back to a 'base' primitive type
+ switch(t)
+ {
+ default:
+ case typeTag::NOTHING:
+ throw OC::OCException(OC::Exception::INVALID_JSON_TYPE_TAG);
+ break;
+ case typeTag::_string:
+ return remapArrayDepth<std::string>(curLevel, vs);
+ break;
+ case typeTag::_int:
+ return remapArrayDepth<int>(curLevel, vs);
+ break;
+ case typeTag::_double:
+ return remapArrayDepth<double>(curLevel, vs);
+ break;
+ case typeTag::_bool:
+ return remapArrayDepth<bool>(curLevel, vs);
+ break;
+ case typeTag::_representation:
+ return remapArrayDepth<OCRepresentation>(curLevel, vs);
+ break;
+ }
+ }
+
+ AttributeValue parseAttributeValueArray(const GenericValue& v,
+ const unsigned int curLevel, unsigned int& maxDepth, typeTag& t)
+ {
+ const unsigned int max_level = 3;
+
+ if(curLevel > max_level)
+ {
+ throw OC::OCException(OC::Exception::INVALID_JSON_ARRAY_DEPTH);
+ }
+
+ if(curLevel > maxDepth)
+ {
+ maxDepth = curLevel;
+ }
+
+ auto arrayItems = gatherArrayContents(v, curLevel, maxDepth, t);
+ const int remapLevel = maxDepth - (curLevel -1);
+ return convertArrayToConcretes(t, remapLevel, arrayItems);
+ }
+ }
+}
+
+namespace cereal
+{
+ void JSONInputArchive::loadAttributeValues(std::map<std::string, OC::AttributeValue>& map)
+ {
+ for(auto&b = itsIteratorStack.back();
+ b.Member && b.itsMemberItEnd != b.itsMemberItBegin+b.itsIndex;
+ ++b)
+ {
+ std::string key = b.itsMemberItBegin[b.itsIndex].name.GetString();
+ const GenericValue& v = itsIteratorStack.back().value();
+ map[key] = OC::detail::parseAttributeValue(v);
+ }
+ }
+}
m_clientWrapper.expired())
{
throw ResourceInitException(m_uri.empty(), resourceTypes.empty(),
- interfaces.empty(), m_clientWrapper.expired());
+ interfaces.empty(), m_clientWrapper.expired(), false, false);
}
}
case OC_STACK_SLOW_RESOURCE:
case OC_STACK_NO_OBSERVERS:
case OC_STACK_OBSERVER_NOT_FOUND:
- case OC_STACK_OBSERVER_NOT_ADDED:
- case OC_STACK_OBSERVER_NOT_REMOVED:
#ifdef WITH_PRESENCE
case OC_STACK_PRESENCE_STOPPED:
- case OC_STACK_PRESENCE_DO_NOT_HANDLE:
#endif
break;
##
-# OCLib (static library) build script
+# OCLib (share library) build script
##
-Import('env', 'BUILD_TARGET', 'BUILD_DIR', 'SRC_TOP_DIR')
+Import('env')
# Add third party libraries
-SConscript(SRC_TOP_DIR + '/third_party_libs.scons')
-
-oclib_env = env.Clone()
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+oclib_env = lib_env.Clone()
######################################################################
# Build flags
######################################################################
'../oc_logger/include'
])
-if BUILD_TARGET not in ['windows', 'winrt']:
- oclib_env.AppendUnique(CXXFLAGS = ['-std=c++11', '-Wall'])
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+ oclib_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-fPIC'])
-if BUILD_TARGET == 'android':
+if target_os == 'android':
oclib_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
oclib_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+ oclib_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+ oclib_env.AppendUnique(LIBS = ['octbstack', 'coap', 'oc_logger', 'boost_thread-gcc-mt-1_49', 'gnustl_static', 'log'])
+
+if target_os in ['darwin', 'ios']:
+ oclib_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+ oclib_env.AppendUnique(LIBS = ['octbstack', 'coap', 'oc_logger'])
######################################################################
# Source files and Targets
######################################################################
oclib_src = [
'OCPlatform.cpp',
+ 'OCPlatform_impl.cpp',
'OCResource.cpp',
'OCUtilities.cpp',
'OCException.cpp',
+ 'OCRepresentation.cpp',
'InProcServerWrapper.cpp',
'InProcClientWrapper.cpp'
]
-oclib = oclib_env.StaticLibrary('oc', oclib_src)
-i_ocl = oclib_env.Install(BUILD_DIR, oclib)
-Alias('liboc', i_ocl)
-env.AppendUnique(TS = ['liboc'])
\ No newline at end of file
+oclib = oclib_env.SharedLibrary('oc', oclib_src)
+oclib_env.InstallTarget(oclib, 'liboc')
#Note: The paths must keep consistent with oic-utilities
######################################################################
import os
+import platform
-Import('env', 'BUILD_TARGET', 'TARGET_CPU_ARCH', 'SRC_TOP_DIR')
+Import('env', 'lib_env')
-# Add 'OIC_UTILS' build option for user to set oic-utilities project path
-default_dir = os.path.abspath(SRC_TOP_DIR + '/../oic-utilities')
-OIC_UTILS = ARGUMENTS.get('OIC_UTILS', default_dir)
-if not os.path.exists(OIC_UTILS):
- print '''
-*********************************** Error: ************************************
-* oic-utilities project directory(OIC_UTILS) isn't set properly, please set *
-* enviornment variable OIC_UTILS or set it in command line: *
-* # scons OIC_UTILS=<path to oic-utilities> ... *
-*******************************************************************************
-'''
- Exit(1)
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+src_dir = env.get('SRC_DIR')
-if env.get('OIC_UTILS') is None:
- vars = Variables()
- vars.Add(PathVariable('OIC_UTILS', 'oic-utilities project path', OIC_UTILS))
- vars.Update(env)
- Help(vars.GenerateHelpText(env))
- Export('OIC_UTILS')
+if target_os not in ['linux', 'darwin']:
+ utils_path = env.get('OIC_UTILS')
- ######################################################################
- # Check dependent packages (Linux)
- ######################################################################
- if BUILD_TARGET == 'linux':
- # Delete the temp files of configuration
- if env.GetOption('clean'):
- if os.path.exists(SRC_TOP_DIR + 'config.log'):
- Execute(Delete(SRC_TOP_DIR + 'config.log'))
- Execute(Delete(SRC_TOP_DIR + '.sconsign.dblite'))
- Execute(Delete(SRC_TOP_DIR + '.sconf_temp'))
- elif not env.GetOption('help'):
- conf = Configure(env)
+######################################################################
+# Check dependent packages (Linux only)
+######################################################################
+if target_os == 'linux':
+ if not env.GetOption('help'):
+ if not target_arch == platform.machine():
+ print '''
+*********************************** Warning ***********************************
+* You are trying cross build, please make sure (%s) version libraries are
+* installed! *
+*******************************************************************************
+''' % target_arch
- if not conf.CheckLib('boost_program_options'):
- print 'Did not find boost_program_options, exiting!'
- Exit(1)
+ conf = Configure(lib_env)
- conf.Finish()
+ if not conf.CheckLib('boost_program_options'):
+ print 'Did not find boost_program_options, exiting!'
+ Exit(1)
- ######################################################################
- # The 'include' path of third party libraries
- ######################################################################
+ conf.Finish()
- if BUILD_TARGET == 'android':
- env.AppendUnique(CPPPATH = [OIC_UTILS + '/android/boost/include'])
+######################################################################
+# The 'include' path of third party libraries
+######################################################################
+if target_os == 'android':
+ lib_env.AppendUnique(CPPPATH = [utils_path + '/android/boost/include'])
- ######################################################################
- # The path of third party libraries binary
- ######################################################################
- if BUILD_TARGET == 'android':
- arch = TARGET_CPU_ARCH
- if arch == 'armeabi-v7a-hard':
- arch = 'armeabi-v7a'
+######################################################################
+# The path of third party libraries binary
+######################################################################
+if target_os == 'android':
+ if target_arch == 'armeabi-v7a-hard':
+ target_arch = 'armeabi-v7a'
- if arch not in ['x86', 'armeabi', 'armeabi-v7a']:
+ if target_arch not in ['x86', 'armeabi', 'armeabi-v7a']:
+ if not env.GetOption('help') and not env.GetOption('clean'):
print '''
*********************************** Warning ***********************************
-* current only x86, armeabi, armeabi-v7a libraries are offered! *
+* current only x86, armeabi, armeabi-v7a libraries are provided! *
*******************************************************************************
'''
- else:
- env.AppendUnique(LIBPATH = [OIC_UTILS + '/android/boost/libs/' + arch])
+ else:
+ lib_env.AppendUnique(LIBPATH = [utils_path + '/android/boost/libs/' + target_arch])
+ # Too much boost warning, suppress the warning
+ lib_env.AppendUnique(CCFLAGS = ['-w'])
- elif BUILD_TARGET == 'ios':
- env.AppendUnique(FRAMEWORKPATH = [OIC_UTILS + '/ios/frameworks/'])
- env.AppendUnique(FRAMEWORKS = ['boost'])
- elif BUILD_TARGET == 'darwin':
- env.AppendUnique(CPPPATH = ['/usr/local/include'])
- env.AppendUnique(LIBPATH = ['/usr/local/lib'])
\ No newline at end of file
+elif target_os == 'ios':
+ lib_env.AppendUnique(FRAMEWORKPATH = [utils_path + '/ios/frameworks/'])
+ lib_env.AppendUnique(FRAMEWORKS = ['boost'])
+elif target_os == 'darwin':
+ lib_env.AppendUnique(CPPPATH = ['/usr/local/include'])
+ lib_env.AppendUnique(LIBPATH = ['/usr/local/lib'])
\ No newline at end of file
OUT_DIR := $(BUILD)
+ifeq ($(ROOT_DIR),)
+ ROOT_DIR:=$(PWD)
+endif
+
INC_DIRS := -I../include/
INC_DIRS += -I../oc_logger/include
INC_DIRS += -I../csdk/stack/include
using namespace std;
// Entity handler used for register and find test
-OCEntityHandlerResult entityHandler_rf(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+OCEntityHandlerResult entityHandler_rf(std::shared_ptr<OCResourceRequest> request)
{
return OC_EH_OK;
}
--- /dev/null
+== How to write iotivity build script ==
+
+Iotivity projects are built with Scons. Scons is a cross-platform build tool,
+it's quite similar to 'make'. 'SConstruct' is the entrance of scons build, it's
+equivalent to 'Makefile' to 'make'.
+
+This document only a brief reference. Detail about how to write scons script,
+please refer to:
+ http://www.scons.org/doc/production/HTML/scons-user.html#
+
+== Background: How to control source code compiling ==
+
+Environment is a base conception of Scons. An environment is a collection of
+values that can affect how a program is built.
+
+e.g. There is a C file named hello.c, enter the following into a file named
+SConstruct:
+ env = Environment()
+ env.Program('H', 'hello.c')
+
+When run Scons in console, following will be executed:
+cc -o hello.o -c hello.c
+cc -o H hello.o
+
+If you would like keep debug information in the binary, '-g' flag should be added
+when build the source code. To do this, append a C compiler flags as following:
+ env = Environment()
+ env.AppendUnique(CFLAGS = ['-g'])
+ env.Program('H', 'hello.c')
+
+When run Scons, following will be executed:
+cc -o hello.o -c -g hello.c
+cc -o H hello.o
+
+In above example, 'CFLAGS' is changed. Following list the frequently used keys:
+
+CFLAGS: General options that are passed to the C compiler
+CCFLAGS: General options that are passed to the C & C++ compiler
+CXXFLAGS: General options that are passed to the C++ compiler
+CPPPATH: The directories that the preprocessor will search for include headers.
+CPPDEFINES: Platform independent specification of C preprocessor definitions.
+
+Note: CPPPATH and CPPDEFINES is common for all compiler. But others are
+compiler specific, when change the key value, it may requried to specify the
+target platform(actually the compiler).
+
+e.g.
+ env.AppendUnique(CPPPATH = ['.', 'include'])
+ env.AppendUnique(CPPDEFINES = ['NDEBUG', 'VER_TEST'])
+Above two lines are fine for all target platform. but below line:
+ env.AppenUnique(CXXFLAGS = ['-g'])
+is only fine for gcc compiler, as '-g' is a gcc flag, other compiler may don't
+understand it. so it may should be:
+ if target_os not in ['windows', 'winrt']:
+ env.AppenUnique(CXXFLAGS = ['-g'])
+
+Still take the hello.c as example. Assume hello.h is in ./include/ directory,
+#include "hello.h"
+int main(int argc, char** argv)
+{
+#ifdef LANG_FR
+ printf("Bonjour\n");
+#else
+ printf("Hello\n");
+#endif
+}
+
+The Scons configure file should as following:
+ env = Environment()
+ env.AppendUnique(CFLAGS = ['-g'])
+ env.AppendUnique(CPPPATH = ['include'])
+ env.AppendUnique(CPPDEFINES = ['LANG_FR'])
+ env.Program('H', 'hello.c')
+
+When run Scons, following will be executed:
+cc -o hello.o -c -g -Iinclude -DLANG_FR hello.c
+cc -o H hello.o
+
+=== Get extra information ===
+
+In above example, 'target_os' is used. How to get it?
+
+User can build iotivity project on linux / windows / MAC OSX for various
+targets(Linux, Tizen, Android, Arduino, Windows, MAC OSX, IOS ...). Most
+platform specific configures have been done in the common scripts whitch are in
+build_common. The common scripts prepare an environment named 'env' with
+target platform specific configuration.
+
+When write iotivity project build script, you can get this environment as
+following:
+ Import('env')
+
+You can use 'env' directly after import it. You can also clone a new environment
+and update its keys.
+
+ new_env1 = Clone('env')
+ new_env2 = Clone('env')
+ new_env1.AppendUnqiue(xxx = [...])
+ new_env2.AppendUnqiue(xxx = [...])
+
+The 'env' environment contains platform specific configuration, besides, there is
+some common information. You can get the information with following line:
+ env.get('XXX')
+
+XXX is the information name, below are the extra information added by iotivity
+common scrirpts:
+BUILD_DIR: the path of the build directory
+SRC_DIR: the path of the top directory of the source code
+OIC_UTILS: the path of oic-utilities project
+RELEASE: boolean. True - release build, False - debug build
+TARGET_OS: the name of the target OS. The possible value depends on the host
+ platform. Bellow is the list of host and possible target OS. (darwin means
+ MAC OSX)
+ linux: linux / android / arduino
+(the line means on linux, you can build the project for linux/android/arduino)
+ windows: windows / winrt / android / arduino
+ darwin: darwin / ios / android / arduino
+
+TARGET_ARCH: the target CPU arch. Its possible value depend on the target OS
+ Bellow list the target OS and allowed CPU architecture.
+ linux: x86 / x86_64 / arm / arm64
+(above line means if the target OS is linux, the CPU arch can be x86/x86_64/arm/arm64)
+ android: x86 / x86_64 / armeabi / armeabi-v7a / armeabi-v7a-hard / arm64-v8a
+ windows: x86 / amd64 / arm
+ winrt: arm
+ darwin: i386 / x86_64
+ ios: i386 / x86_64 / armv7 / armv7s / arm64,
+ arduino: avr / arm
+
+=== Extra functions ===
+
+For convenience, in the common scripts, some extra functions are added.
+
+PrintTargets(): print all targets in the help information.
+AppendTarget(target): add 'target' into targets list, when use PrintTargets,
+ the 'target' will be print.
+InstallTarget(files, name): it takes the same action as AppendTarget, besides,
+ it installs the 'files' to BUILD_DIR.
+
+Following functions are only for Arduino:
+ImportLib(lib): Arduino IDE includes many libraries. To control the binary size,
+by default, no library is used. If your project use some libraries, you can
+import the lib with this function. 'lib' is the name of the lib to import.
+The include path will be auto added to the environment and the library will be
+built and linked into the final binary.
+
+CreateBin('bin', src): For Arduino, after build the program, it's required to
+be converted into specific format (e.g .hex). This function will genearate the
+required .hex (and .eep if target arch is avr) file.
+
+UploadHelp(): For different board, the upload command line is different, this
+function print the recommended upload command line. You can see the recommended
+upload command line in the help information.
+
+==== Scripts Hierarchy ====
+
+Scons provides a function 'SConscript(scripts, [exports, variant_dir, duplicate])'
+It tells scons to execute one or more subsidiary configuration files(A script,
+usually named SConscript). Take below project hierarchy as example to show how
+to organize the scripts.
+
+ prj
+ |-------prj_1
+ | |--------sub_prj_11
+ | |--------sub_prj_..
+ | |--------sub_prj_1n
+ |-------prj_2
+ |
+ | ... ...
+ |
+ |-------prj_n
+
+As above project hierarchy, in 'SConstruct' file in the 'prj' directory, there
+should include some lines like these:
+
+#Please change this part according to the organization of your projects.
+#Note: To make the output is in build_dir, the path of the scripts should
+#be relevant to build_dir
+SConscript(build_dir + 'prj_1/SConscript')
+SConscript(build_dir + 'prj_2/SConscript')
+... ...
+SConscript(build_dir + 'prj_n/SConscript')
+
+
+It's the same, in the 'prj_1/SConscript', there should include lines like
+these:
+SConscript('sub_prj_11/SConscript')
+... ...
+SConscript('sub_prj_1n/SConscript')
+
+The path is relevant to 'prj_1/SConscript'. You can also use the full path
+build_dir + 'prj_1/sub_prj_1x/SConscript', but it's not recommended.
+
+Above just to show a usual way to manage subsidiary scripts. You don't need
+restrictly follow it.
+
+==== The content of a typical script ====
+
+After run the scripts in build_common (usally it's done at the beginning of
+SConstruct), an global environment 'env' is exported, 'env' has include the
+default configuration of the target OS and arch. 'env' is used in all projects,
+should avoid to change its keys. To avoid change 'env', usually clone 'env' and
+update it accroding to the requirement of cuurent sub project. Then specify the
+target(usually binary) to build.
+
+Below is an example:
+ # import the global enviroment 'env'
+ Import('env')
+
+ # Clone a new enviroment from 'env'
+ new_env = env.Clone()
+
+ # Update the new enviroment, usally include add header file paths,
+ # library path, libs to link and other compiler flags. This part is
+ # optional. If not present, the default configuration will be used
+ new_env.AppeneUnique(xxx = [ .... ])
+
+ # Specify the target(application, library, object or others) to build
+ ts = new_env.Program('progam_name', [source_list])
+
+ # Install the target (optional)
+ new_env.InstallTarget(ts, 'target_name')
+or
+ new_env.Alias('target_name', ts)
+ new_env.AppendTarget('target_name')
+
+==== Tips ====
+1. library order: if A lib use B lib, both A and B are linked to target T, the
+ when specify libraries, A should in front of B, otherwise there may be link
+ error.
+2. On android:
+ (1)'pthread' is in libc. So don't use '-lpthread' for android
+ (2)By default 'rtti' and 'exception' is disabled, to enable it, you need
+ add flags '-frtti' and '-fexceptions'
+ (3)If STL is used, need link 'gnustl_static' library
--- /dev/null
+##
+# 'service' sub-project main build script
+#
+##
+Import('env')
+
+target_os = env.get('TARGET_OS')
+
+if target_os != 'arduino':
+ # Build things manager project
+ SConscript('things-manager/SConscript')
+
+ # Build soft sensor manager project
+ SConscript('soft-sensor-manager/SConscript')
+
+ # Build protocol plugin project
+ # protocol-plugin use 'sys/inotify.h', this header file doesn't
+ # exist on MAC OSX
+ if target_os not in ['darwin', 'ios']:
+ SConscript('protocol-plugin/SConscript')
+
+ # Build notification manager project
+ SConscript('notification-manager/SConscript')
+else:
+ SConscript('notification-manager/SampleApp/arduino/SConscript')
--- /dev/null
+##
+# NotificationManager build script
+##
+
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+notimgr_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+notimgr_env.AppendUnique(CPPPATH = ['NotificationManager/include'])
+notimgr_env.PrependUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'coap'])
+
+if target_os not in ['windows', 'winrt']:
+ notimgr_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-fmessage-length=0', '-std=c++0x'])
+
+if target_os == 'linux':
+ notimgr_env.AppendUnique(LIBS = ['pthread'])
+
+if target_os == 'android':
+ notimgr_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+ notimgr_env.AppendUnique(LIBS = ['gnustl_static'])
+ notimgr_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+
+ if not env.get('RELEASE'):
+ notimgr_env.AppendUnique(LIBS = ['log'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+NOTI_SRC_DIR = 'NotificationManager/src/'
+notimgr_src = [
+ NOTI_SRC_DIR + 'LinuxMain.cpp',
+ NOTI_SRC_DIR + 'NotificationManager.cpp',
+ NOTI_SRC_DIR + 'RegistrationManager.cpp',
+ NOTI_SRC_DIR + 'ResourceManager.cpp',
+ NOTI_SRC_DIR + 'VirtualRepresentation.cpp']
+
+notificationmanager = notimgr_env.Program('noti_manager', notimgr_src)
+
+notimgr_env.InstallTarget(notificationmanager, 'notificationmanager')
+
+# Go to build sample apps
+SConscript('SampleApp/SConscript')
--- /dev/null
+##
+# Examples build script
+##
+Import('env')
+
+target_os = env.get('TARGET_OS')
+if target_os == 'linux':
+ SConscript('linux/SConscript')
+elif target_os == 'arduino':
+ SConscript('arduino/SConscript')
\ No newline at end of file
--- /dev/null
+##
+# NotificationManager build script
+##
+
+Import('env')
+
+notimgr_env = env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+resource_path = env.get('SRC_DIR') + '/resource'
+
+notimgr_env.AppendUnique(CPPPATH = [
+ resource_path + '/oc_logger/include',
+ resource_path + '/csdk/stack/include',
+ resource_path + '/csdk/ocsocket/include',
+ resource_path + '/csdk/logger/include'
+ ])
+
+notimgr_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+notimgr_env.PrependUnique(LIBS = ['octbstack', 'coap'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+thserver = notimgr_env.Program('thserver', 'thserver.cpp')
+notimgr_env.CreateBin('thserver')
+
+i_thserver = notimgr_env.Install(env.get('BUILD_DIR'), thserver)
+
+Alias('thserver_arduino', i_thserver)
+env.AppendTarget('thserver_arduino')
\ No newline at end of file
--- /dev/null
+##
+# NotificationManager build script
+##
+
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+notimgr_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+notimgr_env.AppendUnique(CPPPATH = ['../../NotificationManager/include'])
+notimgr_env.AppendUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'coap', 'pthread'])
+notimgr_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-fmessage-length=0', '-std=c++0x'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+sampleprovider = notimgr_env.Program('sampleprovider', 'sampleProvider/SampleProvider.cpp')
+sampleconsumer = notimgr_env.Program('sampleconsumer', 'sampleConsumer/SampleConsumer.cpp')
\ No newline at end of file
--- /dev/null
+##
+# protocol plugin build script
+##
+Import('env')
+
+SConscript('lib/cpluff/SConscript')
+SConscript('plugin-manager/SConscript')
+
+#The code include pthread_cancel method, can't build on android
+if env.get('TARGET_OS') != 'android':
+ SConscript('plugins/SConscript')
+
+SConscript('sample-app/SConscript')
cd $(PROTOCOL_ROOT)plugins/mqtt-light/build/linux && $(MAKE)
sample-app:
- cd $(PROTOCOL_ROOT)sample-app/linux/fan-control && $(MAKE)
- cp -Rdp $(PROTOCOL_ROOT)sample-app/linux/fan-control/fanclient release/
+ cd $(PROTOCOL_ROOT)sample-app/linux/mqtt && $(MAKE)
+ cp -Rdp $(PROTOCOL_ROOT)plugin-manager/build/linux/libpmimpl.so $(PROTOCOL_ROOT)sample-app/linux/mqtt/
+ cp -Rdp $(PROTOCOL_ROOT)sample-app/linux/mqtt/mqttclient release/
clean:
cd $(PROTOCOL_ROOT)plugin-manager/build/linux && $(MAKE) clean
cd $(PROTOCOL_ROOT)plugins/mqtt-fan/build/linux && $(MAKE) clean
cd $(PROTOCOL_ROOT)plugins/mqtt-light/build/linux && $(MAKE) clean
- cd $(PROTOCOL_ROOT)plugins/hue/build/linux && $(MAKE) clean
- cd $(PROTOCOL_ROOT)sample-app/linux/fan-control && $(MAKE) clean
+ cd $(PROTOCOL_ROOT)sample-app/linux/mqtt && $(MAKE) clean
rm -rf release
--- /dev/null
+##
+#c-pluff build script
+##
+import platform,os
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+cpluff_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+cpluff_env.AppendUnique(CPPPATH = ['libcpluff/'])
+if target_os not in ['windows', 'winrt']:
+ cpluff_env.AppendUnique(CFLAGS = ['-g','-fPIC', '-DPIC',
+ '-DDLOPEN_POSIX',
+ '-DCP_HOST=\\"' + platform.platform() + '\\"',
+ '-DCP_SHREXT=\\".so\\"',
+ '-DCP_FNAMESEP_CHAR=\\"\'/\'\\"',
+ '-DCP_THREADS=\\"Posix\\"'])
+ cpluff_env.AppendUnique(LIBS = ['dl'])
+######################################################################
+# Source files and Targets
+######################################################################
+cpluff_src = [f for f in env.Glob('libcpluff/*.c') if os.path.basename(f.path) not in ['thread_windows.c']]
+cpluff_src.extend(env.Glob('kazlib/*.c'))
+
+cpluff = cpluff_env.StaticLibrary('cpluff', cpluff_src)
+cpluff_env.InstallTarget(cpluff, 'libcpluff')
\ No newline at end of file
--- /dev/null
+#ifndef RAPIDXML_HPP_INCLUDED
+#define RAPIDXML_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation
+
+// If standard library is disabled, user must provide implementations of required functions and typedefs
+#if !defined(RAPIDXML_NO_STDLIB)
+ #include <cstdlib> // For std::size_t
+ #include <cassert> // For assert
+ #include <new> // For placement new
+#endif
+
+// On MSVC, disable "conditional expression is constant" warning (level 4).
+// This warning is almost impossible to avoid with certain types of templated code
+#ifdef _MSC_VER
+ #pragma warning(push)
+ #pragma warning(disable:4127) // Conditional expression is constant
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// RAPIDXML_PARSE_ERROR
+
+#if defined(RAPIDXML_NO_EXCEPTIONS)
+
+#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); }
+
+namespace rapidxml
+{
+ //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS,
+ //! this function is called to notify user about the error.
+ //! It must be defined by the user.
+ //! <br><br>
+ //! This function cannot return. If it does, the results are undefined.
+ //! <br><br>
+ //! A very simple definition might look like that:
+ //! <pre>
+ //! void %rapidxml::%parse_error_handler(const char *what, void *where)
+ //! {
+ //! std::cout << "Parse error: " << what << "\n";
+ //! std::abort();
+ //! }
+ //! </pre>
+ //! \param what Human readable description of the error.
+ //! \param where Pointer to character data where error was detected.
+ void parse_error_handler(const char *what, void *where);
+}
+
+#else
+
+#include <exception> // For std::exception
+
+#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where)
+
+namespace rapidxml
+{
+
+ //! Parse error exception.
+ //! This exception is thrown by the parser when an error occurs.
+ //! Use what() function to get human-readable error message.
+ //! Use where() function to get a pointer to position within source text where error was detected.
+ //! <br><br>
+ //! If throwing exceptions by the parser is undesirable,
+ //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.
+ //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.
+ //! This function must be defined by the user.
+ //! <br><br>
+ //! This class derives from <code>std::exception</code> class.
+ class parse_error: public std::exception
+ {
+
+ public:
+
+ //! Constructs parse error
+ parse_error(const char *what, void *where)
+ : m_what(what)
+ , m_where(where)
+ {
+ }
+
+ //! Gets human readable description of error.
+ //! \return Pointer to null terminated description of the error.
+ virtual const char *what() const throw()
+ {
+ return m_what;
+ }
+
+ //! Gets pointer to character data where error happened.
+ //! Ch should be the same as char type of xml_document that produced the error.
+ //! \return Pointer to location within the parsed string where error occured.
+ template<class Ch>
+ Ch *where() const
+ {
+ return reinterpret_cast<Ch *>(m_where);
+ }
+
+ private:
+
+ const char *m_what;
+ void *m_where;
+
+ };
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// Pool sizes
+
+#ifndef RAPIDXML_STATIC_POOL_SIZE
+ // Size of static memory block of memory_pool.
+ // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+ // No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
+ #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_DYNAMIC_POOL_SIZE
+ // Size of dynamic memory block of memory_pool.
+ // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+ // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
+ #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_ALIGNMENT
+ // Memory allocation alignment.
+ // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
+ // All memory allocations for nodes, attributes and strings will be aligned to this value.
+ // This must be a power of 2 and at least 1, otherwise memory_pool will not work.
+ #define RAPIDXML_ALIGNMENT sizeof(void *)
+#endif
+
+namespace rapidxml
+{
+ // Forward declarations
+ template<class Ch> class xml_node;
+ template<class Ch> class xml_attribute;
+ template<class Ch> class xml_document;
+
+ //! Enumeration listing all node types produced by the parser.
+ //! Use xml_node::type() function to query node type.
+ enum node_type
+ {
+ node_document, //!< A document node. Name and value are empty.
+ node_element, //!< An element node. Name contains element name. Value contains text of first data node.
+ node_data, //!< A data node. Name is empty. Value contains data text.
+ node_cdata, //!< A CDATA node. Name is empty. Value contains data text.
+ node_comment, //!< A comment node. Name is empty. Value contains comment text.
+ node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
+ node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
+ node_pi //!< A PI node. Name contains target. Value contains instructions.
+ };
+
+ ///////////////////////////////////////////////////////////////////////
+ // Parsing flags
+
+ //! Parse flag instructing the parser to not create data nodes.
+ //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_data_nodes = 0x1;
+
+ //! Parse flag instructing the parser to not use text of first data node as a value of parent element.
+ //! Can be combined with other flags by use of | operator.
+ //! Note that child data nodes of element node take precendence over its value when printing.
+ //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.
+ //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_element_values = 0x2;
+
+ //! Parse flag instructing the parser to not place zero terminators after strings in the source text.
+ //! By default zero terminators are placed, modifying source text.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_string_terminators = 0x4;
+
+ //! Parse flag instructing the parser to not translate entities in the source text.
+ //! By default entities are translated, modifying source text.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_entity_translation = 0x8;
+
+ //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.
+ //! By default, UTF-8 handling is enabled.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_utf8 = 0x10;
+
+ //! Parse flag instructing the parser to create XML declaration node.
+ //! By default, declaration node is not created.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_declaration_node = 0x20;
+
+ //! Parse flag instructing the parser to create comments nodes.
+ //! By default, comment nodes are not created.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_comment_nodes = 0x40;
+
+ //! Parse flag instructing the parser to create DOCTYPE node.
+ //! By default, doctype node is not created.
+ //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_doctype_node = 0x80;
+
+ //! Parse flag instructing the parser to create PI nodes.
+ //! By default, PI nodes are not created.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_pi_nodes = 0x100;
+
+ //! Parse flag instructing the parser to validate closing tag names.
+ //! If not set, name inside closing tag is irrelevant to the parser.
+ //! By default, closing tags are not validated.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_validate_closing_tags = 0x200;
+
+ //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.
+ //! By default, whitespace is not trimmed.
+ //! This flag does not cause the parser to modify source text.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_trim_whitespace = 0x400;
+
+ //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.
+ //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.
+ //! By default, whitespace is not normalized.
+ //! If this flag is specified, source text will be modified.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_normalize_whitespace = 0x800;
+
+ // Compound flags
+
+ //! Parse flags which represent default behaviour of the parser.
+ //! This is always equal to 0, so that all other flags can be simply ored together.
+ //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.
+ //! This also means that meaning of each flag is a <i>negation</i> of the default setting.
+ //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,
+ //! and using the flag will disable it.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_default = 0;
+
+ //! A combination of parse flags that forbids any modifications of the source text.
+ //! This also results in faster parsing. However, note that the following will occur:
+ //! <ul>
+ //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>
+ //! <li>entities will not be translated</li>
+ //! <li>whitespace will not be normalized</li>
+ //! </ul>
+ //! See xml_document::parse() function.
+ const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
+
+ //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
+
+ //! A combination of parse flags resulting in largest amount of data being extracted.
+ //! This usually results in slowest parsing.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internals
+
+ //! \cond internal
+ namespace internal
+ {
+
+ // Struct that contains lookup tables for the parser
+ // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).
+ template<int Dummy>
+ struct lookup_tables
+ {
+ static const unsigned char lookup_whitespace[256]; // Whitespace table
+ static const unsigned char lookup_node_name[256]; // Node name table
+ static const unsigned char lookup_text[256]; // Text table
+ static const unsigned char lookup_text_pure_no_ws[256]; // Text table
+ static const unsigned char lookup_text_pure_with_ws[256]; // Text table
+ static const unsigned char lookup_attribute_name[256]; // Attribute name table
+ static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote
+ static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote
+ static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes
+ static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes
+ static const unsigned char lookup_digits[256]; // Digits
+ static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters
+ };
+
+ // Find length of the string
+ template<class Ch>
+ inline std::size_t measure(const Ch *p)
+ {
+ const Ch *tmp = p;
+ while (*tmp)
+ ++tmp;
+ return tmp - p;
+ }
+
+ // Compare strings for equality
+ template<class Ch>
+ inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive)
+ {
+ if (size1 != size2)
+ return false;
+ if (case_sensitive)
+ {
+ for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+ if (*p1 != *p2)
+ return false;
+ }
+ else
+ {
+ for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+ if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])
+ return false;
+ }
+ return true;
+ }
+ }
+ //! \endcond
+
+ ///////////////////////////////////////////////////////////////////////
+ // Memory pool
+
+ //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.
+ //! In most cases, you will not need to use this class directly.
+ //! However, if you need to create nodes manually or modify names/values of nodes,
+ //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory.
+ //! Not only is this faster than allocating them by using <code>new</code> operator,
+ //! but also their lifetime will be tied to the lifetime of document,
+ //! possibly simplyfing memory management.
+ //! <br><br>
+ //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool.
+ //! You can also call allocate_string() function to allocate strings.
+ //! Such strings can then be used as names or values of nodes without worrying about their lifetime.
+ //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called,
+ //! or when the pool is destroyed.
+ //! <br><br>
+ //! It is also possible to create a standalone memory_pool, and use it
+ //! to allocate nodes, whose lifetime will not be tied to any document.
+ //! <br><br>
+ //! Pool maintains <code>RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory.
+ //! Until static memory is exhausted, no dynamic memory allocations are done.
+ //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> each,
+ //! by using global <code>new[]</code> and <code>delete[]</code> operators.
+ //! This behaviour can be changed by setting custom allocation routines.
+ //! Use set_allocator() function to set them.
+ //! <br><br>
+ //! Allocations for nodes, attributes and strings are aligned at <code>RAPIDXML_ALIGNMENT</code> bytes.
+ //! This value defaults to the size of pointer on target architecture.
+ //! <br><br>
+ //! To obtain absolutely top performance from the parser,
+ //! it is important that all nodes are allocated from a single, contiguous block of memory.
+ //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.
+ //! If required, you can tweak <code>RAPIDXML_STATIC_POOL_SIZE</code>, <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>RAPIDXML_ALIGNMENT</code>
+ //! to obtain best wasted memory to performance compromise.
+ //! To do it, define their values before rapidxml.hpp file is included.
+ //! \param Ch Character type of created nodes.
+ template<class Ch = char>
+ class memory_pool
+ {
+
+ public:
+
+ //! \cond internal
+ typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory
+ typedef void (free_func)(void *); // Type of user-defined function used to free memory
+ //! \endcond
+
+ //! Constructs empty pool with default allocator functions.
+ memory_pool()
+ : m_alloc_func(0)
+ , m_free_func(0)
+ {
+ init();
+ }
+
+ //! Destroys pool and frees all the memory.
+ //! This causes memory occupied by nodes allocated by the pool to be freed.
+ //! Nodes allocated from the pool are no longer valid.
+ ~memory_pool()
+ {
+ clear();
+ }
+
+ //! Allocates a new node from the pool, and optionally assigns name and value to it.
+ //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+ //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+ //! will call rapidxml::parse_error_handler() function.
+ //! \param type Type of node to create.
+ //! \param name Name to assign to the node, or 0 to assign no name.
+ //! \param value Value to assign to the node, or 0 to assign no value.
+ //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+ //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+ //! \return Pointer to allocated node. This pointer will never be NULL.
+ xml_node<Ch> *allocate_node(node_type type,
+ const Ch *name = 0, const Ch *value = 0,
+ std::size_t name_size = 0, std::size_t value_size = 0)
+ {
+ void *memory = allocate_aligned(sizeof(xml_node<Ch>));
+ xml_node<Ch> *node = new(memory) xml_node<Ch>(type);
+ if (name)
+ {
+ if (name_size > 0)
+ node->name(name, name_size);
+ else
+ node->name(name);
+ }
+ if (value)
+ {
+ if (value_size > 0)
+ node->value(value, value_size);
+ else
+ node->value(value);
+ }
+ return node;
+ }
+
+ //! Allocates a new attribute from the pool, and optionally assigns name and value to it.
+ //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+ //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+ //! will call rapidxml::parse_error_handler() function.
+ //! \param name Name to assign to the attribute, or 0 to assign no name.
+ //! \param value Value to assign to the attribute, or 0 to assign no value.
+ //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+ //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+ //! \return Pointer to allocated attribute. This pointer will never be NULL.
+ xml_attribute<Ch> *allocate_attribute(const Ch *name = 0, const Ch *value = 0,
+ std::size_t name_size = 0, std::size_t value_size = 0)
+ {
+ void *memory = allocate_aligned(sizeof(xml_attribute<Ch>));
+ xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;
+ if (name)
+ {
+ if (name_size > 0)
+ attribute->name(name, name_size);
+ else
+ attribute->name(name);
+ }
+ if (value)
+ {
+ if (value_size > 0)
+ attribute->value(value, value_size);
+ else
+ attribute->value(value);
+ }
+ return attribute;
+ }
+
+ //! Allocates a char array of given size from the pool, and optionally copies a given string to it.
+ //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+ //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+ //! will call rapidxml::parse_error_handler() function.
+ //! \param source String to initialize the allocated memory with, or 0 to not initialize it.
+ //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.
+ //! \return Pointer to allocated char array. This pointer will never be NULL.
+ Ch *allocate_string(const Ch *source = 0, std::size_t size = 0)
+ {
+ assert(source || size); // Either source or size (or both) must be specified
+ if (size == 0)
+ size = internal::measure(source) + 1;
+ Ch *result = static_cast<Ch *>(allocate_aligned(size * sizeof(Ch)));
+ if (source)
+ for (std::size_t i = 0; i < size; ++i)
+ result[i] = source[i];
+ return result;
+ }
+
+ //! Clones an xml_node and its hierarchy of child nodes and attributes.
+ //! Nodes and attributes are allocated from this memory pool.
+ //! Names and values are not cloned, they are shared between the clone and the source.
+ //! Result node can be optionally specified as a second parameter,
+ //! in which case its contents will be replaced with cloned source node.
+ //! This is useful when you want to clone entire document.
+ //! \param source Node to clone.
+ //! \param result Node to put results in, or 0 to automatically allocate result node
+ //! \return Pointer to cloned node. This pointer will never be NULL.
+ xml_node<Ch> *clone_node(const xml_node<Ch> *source, xml_node<Ch> *result = 0)
+ {
+ // Prepare result node
+ if (result)
+ {
+ result->remove_all_attributes();
+ result->remove_all_nodes();
+ result->type(source->type());
+ }
+ else
+ result = allocate_node(source->type());
+
+ // Clone name and value
+ result->name(source->name(), source->name_size());
+ result->value(source->value(), source->value_size());
+
+ // Clone child nodes and attributes
+ for (xml_node<Ch> *child = source->first_node(); child; child = child->next_sibling())
+ result->append_node(clone_node(child));
+ for (xml_attribute<Ch> *attr = source->first_attribute(); attr; attr = attr->next_attribute())
+ result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));
+
+ return result;
+ }
+
+ //! Clears the pool.
+ //! This causes memory occupied by nodes allocated by the pool to be freed.
+ //! Any nodes or strings allocated from the pool will no longer be valid.
+ void clear()
+ {
+ while (m_begin != m_static_memory)
+ {
+ char *previous_begin = reinterpret_cast<header *>(align(m_begin))->previous_begin;
+ if (m_free_func)
+ m_free_func(m_begin);
+ else
+ delete[] m_begin;
+ m_begin = previous_begin;
+ }
+ init();
+ }
+
+ //! Sets or resets the user-defined memory allocation functions for the pool.
+ //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.
+ //! Allocation function must not return invalid pointer on failure. It should either throw,
+ //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program.
+ //! If it returns invalid pointer, results are undefined.
+ //! <br><br>
+ //! User defined allocation functions must have the following forms:
+ //! <br><code>
+ //! <br>void *allocate(std::size_t size);
+ //! <br>void free(void *pointer);
+ //! </code><br>
+ //! \param af Allocation function, or 0 to restore default function
+ //! \param ff Free function, or 0 to restore default function
+ void set_allocator(alloc_func *af, free_func *ff)
+ {
+ assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet
+ m_alloc_func = af;
+ m_free_func = ff;
+ }
+
+ private:
+
+ struct header
+ {
+ char *previous_begin;
+ };
+
+ void init()
+ {
+ m_begin = m_static_memory;
+ m_ptr = align(m_begin);
+ m_end = m_static_memory + sizeof(m_static_memory);
+ }
+
+ char *align(char *ptr)
+ {
+ std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1));
+ return ptr + alignment;
+ }
+
+ char *allocate_raw(std::size_t size)
+ {
+ // Allocate
+ void *memory;
+ if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[]
+ {
+ memory = m_alloc_func(size);
+ assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp
+ }
+ else
+ {
+ memory = new char[size];
+#ifdef RAPIDXML_NO_EXCEPTIONS
+ if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc
+ RAPIDXML_PARSE_ERROR("out of memory", 0);
+#endif
+ }
+ return static_cast<char *>(memory);
+ }
+
+ void *allocate_aligned(std::size_t size)
+ {
+ // Calculate aligned pointer
+ char *result = align(m_ptr);
+
+ // If not enough memory left in current pool, allocate a new pool
+ if (result + size > m_end)
+ {
+ // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE)
+ std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE;
+ if (pool_size < size)
+ pool_size = size;
+
+ // Allocate
+ std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation
+ char *raw_memory = allocate_raw(alloc_size);
+
+ // Setup new pool in allocated memory
+ char *pool = align(raw_memory);
+ header *new_header = reinterpret_cast<header *>(pool);
+ new_header->previous_begin = m_begin;
+ m_begin = raw_memory;
+ m_ptr = pool + sizeof(header);
+ m_end = raw_memory + alloc_size;
+
+ // Calculate aligned pointer again using new pool
+ result = align(m_ptr);
+ }
+
+ // Update pool and return aligned pointer
+ m_ptr = result + size;
+ return result;
+ }
+
+ char *m_begin; // Start of raw memory making up current pool
+ char *m_ptr; // First free byte in current pool
+ char *m_end; // One past last available byte in current pool
+ char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory
+ alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used
+ free_func *m_free_func; // Free function, or 0 if default is to be used
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // XML base
+
+ //! Base class for xml_node and xml_attribute implementing common functions:
+ //! name(), name_size(), value(), value_size() and parent().
+ //! \param Ch Character type to use
+ template<class Ch = char>
+ class xml_base
+ {
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ // Construct a base with empty name, value and parent
+ xml_base()
+ : m_name(0)
+ , m_value(0)
+ , m_parent(0)
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node data access
+
+ //! Gets name of the node.
+ //! Interpretation of name depends on type of node.
+ //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+ //! <br><br>
+ //! Use name_size() function to determine length of the name.
+ //! \return Name of node, or empty string if node has no name.
+ Ch *name() const
+ {
+ return m_name ? m_name : nullstr();
+ }
+
+ //! Gets size of node name, not including terminator character.
+ //! This function works correctly irrespective of whether name is or is not zero terminated.
+ //! \return Size of node name, in characters.
+ std::size_t name_size() const
+ {
+ return m_name ? m_name_size : 0;
+ }
+
+ //! Gets value of node.
+ //! Interpretation of value depends on type of node.
+ //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+ //! <br><br>
+ //! Use value_size() function to determine length of the value.
+ //! \return Value of node, or empty string if node has no value.
+ Ch *value() const
+ {
+ return m_value ? m_value : nullstr();
+ }
+
+ //! Gets size of node value, not including terminator character.
+ //! This function works correctly irrespective of whether value is or is not zero terminated.
+ //! \return Size of node value, in characters.
+ std::size_t value_size() const
+ {
+ return m_value ? m_value_size : 0;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node modification
+
+ //! Sets name of node to a non zero-terminated string.
+ //! See \ref ownership_of_strings.
+ //! <br><br>
+ //! Note that node does not own its name or value, it only stores a pointer to it.
+ //! It will not delete or otherwise free the pointer on destruction.
+ //! It is reponsibility of the user to properly manage lifetime of the string.
+ //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+ //! on destruction of the document the string will be automatically freed.
+ //! <br><br>
+ //! Size of name must be specified separately, because name does not have to be zero terminated.
+ //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+ //! \param name Name of node to set. Does not have to be zero terminated.
+ //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
+ void name(const Ch *name, std::size_t size)
+ {
+ m_name = const_cast<Ch *>(name);
+ m_name_size = size;
+ }
+
+ //! Sets name of node to a zero-terminated string.
+ //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
+ //! \param name Name of node to set. Must be zero terminated.
+ void name(const Ch *name)
+ {
+ this->name(name, internal::measure(name));
+ }
+
+ //! Sets value of node to a non zero-terminated string.
+ //! See \ref ownership_of_strings.
+ //! <br><br>
+ //! Note that node does not own its name or value, it only stores a pointer to it.
+ //! It will not delete or otherwise free the pointer on destruction.
+ //! It is reponsibility of the user to properly manage lifetime of the string.
+ //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+ //! on destruction of the document the string will be automatically freed.
+ //! <br><br>
+ //! Size of value must be specified separately, because it does not have to be zero terminated.
+ //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+ //! <br><br>
+ //! If an element has a child node of type node_data, it will take precedence over element value when printing.
+ //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
+ //! \param value value of node to set. Does not have to be zero terminated.
+ //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
+ void value(const Ch *value, std::size_t size)
+ {
+ m_value = const_cast<Ch *>(value);
+ m_value_size = size;
+ }
+
+ //! Sets value of node to a zero-terminated string.
+ //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
+ //! \param value Vame of node to set. Must be zero terminated.
+ void value(const Ch *value)
+ {
+ this->value(value, internal::measure(value));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Related nodes access
+
+ //! Gets node parent.
+ //! \return Pointer to parent node, or 0 if there is no parent.
+ xml_node<Ch> *parent() const
+ {
+ return m_parent;
+ }
+
+ protected:
+
+ // Return empty string
+ static Ch *nullstr()
+ {
+ static Ch zero = Ch('\0');
+ return &zero;
+ }
+
+ Ch *m_name; // Name of node, or 0 if no name
+ Ch *m_value; // Value of node, or 0 if no value
+ std::size_t m_name_size; // Length of node name, or undefined of no name
+ std::size_t m_value_size; // Length of node value, or undefined if no value
+ xml_node<Ch> *m_parent; // Pointer to parent node, or 0 if none
+
+ };
+
+ //! Class representing attribute node of XML document.
+ //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
+ //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing.
+ //! Thus, this text must persist in memory for the lifetime of attribute.
+ //! \param Ch Character type to use.
+ template<class Ch = char>
+ class xml_attribute: public xml_base<Ch>
+ {
+
+ friend class xml_node<Ch>;
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ //! Constructs an empty attribute with the specified type.
+ //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.
+ xml_attribute()
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Related nodes access
+
+ //! Gets document of which attribute is a child.
+ //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.
+ xml_document<Ch> *document() const
+ {
+ if (xml_node<Ch> *node = this->parent())
+ {
+ while (node->parent())
+ node = node->parent();
+ return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+ }
+ else
+ return 0;
+ }
+
+ //! Gets previous attribute, optionally matching attribute name.
+ //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_attribute<Ch> *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return this->m_parent ? m_prev_attribute : 0;
+ }
+
+ //! Gets next attribute, optionally matching attribute name.
+ //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_attribute<Ch> *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return this->m_parent ? m_next_attribute : 0;
+ }
+
+ private:
+
+ xml_attribute<Ch> *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
+ xml_attribute<Ch> *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
+
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // XML node
+
+ //! Class representing a node of XML document.
+ //! Each node may have associated name and value strings, which are available through name() and value() functions.
+ //! Interpretation of name and value depends on type of the node.
+ //! Type of node can be determined by using type() function.
+ //! <br><br>
+ //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing.
+ //! Thus, this text must persist in the memory for the lifetime of node.
+ //! \param Ch Character type to use.
+ template<class Ch = char>
+ class xml_node: public xml_base<Ch>
+ {
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ //! Constructs an empty node with the specified type.
+ //! Consider using memory_pool of appropriate document to allocate nodes manually.
+ //! \param type Type of node to construct.
+ xml_node(node_type type)
+ : m_type(type)
+ , m_first_node(0)
+ , m_first_attribute(0)
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node data access
+
+ //! Gets type of node.
+ //! \return Type of node.
+ node_type type() const
+ {
+ return m_type;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Related nodes access
+
+ //! Gets document of which node is a child.
+ //! \return Pointer to document that contains this node, or 0 if there is no parent document.
+ xml_document<Ch> *document() const
+ {
+ xml_node<Ch> *node = const_cast<xml_node<Ch> *>(this);
+ while (node->parent())
+ node = node->parent();
+ return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+ }
+
+ //! Gets first child node, optionally matching node name.
+ //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found child, or 0 if not found.
+ xml_node<Ch> *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling())
+ if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+ return child;
+ return 0;
+ }
+ else
+ return m_first_node;
+ }
+
+ //! Gets last child node, optionally matching node name.
+ //! Behaviour is undefined if node has no children.
+ //! Use first_node() to test if node has children.
+ //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found child, or 0 if not found.
+ xml_node<Ch> *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ assert(m_first_node); // Cannot query for last child if node has no children
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_node<Ch> *child = m_last_node; child; child = child->previous_sibling())
+ if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+ return child;
+ return 0;
+ }
+ else
+ return m_last_node;
+ }
+
+ //! Gets previous sibling node, optionally matching node name.
+ //! Behaviour is undefined if node has no parent.
+ //! Use parent() to test if node has a parent.
+ //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found sibling, or 0 if not found.
+ xml_node<Ch> *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ assert(this->m_parent); // Cannot query for siblings if node has no parent
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_node<Ch> *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)
+ if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+ return sibling;
+ return 0;
+ }
+ else
+ return m_prev_sibling;
+ }
+
+ //! Gets next sibling node, optionally matching node name.
+ //! Behaviour is undefined if node has no parent.
+ //! Use parent() to test if node has a parent.
+ //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found sibling, or 0 if not found.
+ xml_node<Ch> *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ assert(this->m_parent); // Cannot query for siblings if node has no parent
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_node<Ch> *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)
+ if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+ return sibling;
+ return 0;
+ }
+ else
+ return m_next_sibling;
+ }
+
+ //! Gets first attribute of node, optionally matching attribute name.
+ //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_attribute<Ch> *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return m_first_attribute;
+ }
+
+ //! Gets last attribute of node, optionally matching attribute name.
+ //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_attribute<Ch> *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return m_first_attribute ? m_last_attribute : 0;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node modification
+
+ //! Sets type of node.
+ //! \param type Type of node to set.
+ void type(node_type type)
+ {
+ m_type = type;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node manipulation
+
+ //! Prepends a new child node.
+ //! The prepended child becomes the first child, and all existing children are moved one position back.
+ //! \param child Node to prepend.
+ void prepend_node(xml_node<Ch> *child)
+ {
+ assert(child && !child->parent() && child->type() != node_document);
+ if (first_node())
+ {
+ child->m_next_sibling = m_first_node;
+ m_first_node->m_prev_sibling = child;
+ }
+ else
+ {
+ child->m_next_sibling = 0;
+ m_last_node = child;
+ }
+ m_first_node = child;
+ child->m_parent = this;
+ child->m_prev_sibling = 0;
+ }
+
+ //! Appends a new child node.
+ //! The appended child becomes the last child.
+ //! \param child Node to append.
+ void append_node(xml_node<Ch> *child)
+ {
+ assert(child && !child->parent() && child->type() != node_document);
+ if (first_node())
+ {
+ child->m_prev_sibling = m_last_node;
+ m_last_node->m_next_sibling = child;
+ }
+ else
+ {
+ child->m_prev_sibling = 0;
+ m_first_node = child;
+ }
+ m_last_node = child;
+ child->m_parent = this;
+ child->m_next_sibling = 0;
+ }
+
+ //! Inserts a new child node at specified place inside the node.
+ //! All children after and including the specified node are moved one position back.
+ //! \param where Place where to insert the child, or 0 to insert at the back.
+ //! \param child Node to insert.
+ void insert_node(xml_node<Ch> *where, xml_node<Ch> *child)
+ {
+ assert(!where || where->parent() == this);
+ assert(child && !child->parent() && child->type() != node_document);
+ if (where == m_first_node)
+ prepend_node(child);
+ else if (where == 0)
+ append_node(child);
+ else
+ {
+ child->m_prev_sibling = where->m_prev_sibling;
+ child->m_next_sibling = where;
+ where->m_prev_sibling->m_next_sibling = child;
+ where->m_prev_sibling = child;
+ child->m_parent = this;
+ }
+ }
+
+ //! Removes first child node.
+ //! If node has no children, behaviour is undefined.
+ //! Use first_node() to test if node has children.
+ void remove_first_node()
+ {
+ assert(first_node());
+ xml_node<Ch> *child = m_first_node;
+ m_first_node = child->m_next_sibling;
+ if (child->m_next_sibling)
+ child->m_next_sibling->m_prev_sibling = 0;
+ else
+ m_last_node = 0;
+ child->m_parent = 0;
+ }
+
+ //! Removes last child of the node.
+ //! If node has no children, behaviour is undefined.
+ //! Use first_node() to test if node has children.
+ void remove_last_node()
+ {
+ assert(first_node());
+ xml_node<Ch> *child = m_last_node;
+ if (child->m_prev_sibling)
+ {
+ m_last_node = child->m_prev_sibling;
+ child->m_prev_sibling->m_next_sibling = 0;
+ }
+ else
+ m_first_node = 0;
+ child->m_parent = 0;
+ }
+
+ //! Removes specified child from the node
+ // \param where Pointer to child to be removed.
+ void remove_node(xml_node<Ch> *where)
+ {
+ assert(where && where->parent() == this);
+ assert(first_node());
+ if (where == m_first_node)
+ remove_first_node();
+ else if (where == m_last_node)
+ remove_last_node();
+ else
+ {
+ where->m_prev_sibling->m_next_sibling = where->m_next_sibling;
+ where->m_next_sibling->m_prev_sibling = where->m_prev_sibling;
+ where->m_parent = 0;
+ }
+ }
+
+ //! Removes all child nodes (but not attributes).
+ void remove_all_nodes()
+ {
+ for (xml_node<Ch> *node = first_node(); node; node = node->m_next_sibling)
+ node->m_parent = 0;
+ m_first_node = 0;
+ }
+
+ //! Prepends a new attribute to the node.
+ //! \param attribute Attribute to prepend.
+ void prepend_attribute(xml_attribute<Ch> *attribute)
+ {
+ assert(attribute && !attribute->parent());
+ if (first_attribute())
+ {
+ attribute->m_next_attribute = m_first_attribute;
+ m_first_attribute->m_prev_attribute = attribute;
+ }
+ else
+ {
+ attribute->m_next_attribute = 0;
+ m_last_attribute = attribute;
+ }
+ m_first_attribute = attribute;
+ attribute->m_parent = this;
+ attribute->m_prev_attribute = 0;
+ }
+
+ //! Appends a new attribute to the node.
+ //! \param attribute Attribute to append.
+ void append_attribute(xml_attribute<Ch> *attribute)
+ {
+ assert(attribute && !attribute->parent());
+ if (first_attribute())
+ {
+ attribute->m_prev_attribute = m_last_attribute;
+ m_last_attribute->m_next_attribute = attribute;
+ }
+ else
+ {
+ attribute->m_prev_attribute = 0;
+ m_first_attribute = attribute;
+ }
+ m_last_attribute = attribute;
+ attribute->m_parent = this;
+ attribute->m_next_attribute = 0;
+ }
+
+ //! Inserts a new attribute at specified place inside the node.
+ //! All attributes after and including the specified attribute are moved one position back.
+ //! \param where Place where to insert the attribute, or 0 to insert at the back.
+ //! \param attribute Attribute to insert.
+ void insert_attribute(xml_attribute<Ch> *where, xml_attribute<Ch> *attribute)
+ {
+ assert(!where || where->parent() == this);
+ assert(attribute && !attribute->parent());
+ if (where == m_first_attribute)
+ prepend_attribute(attribute);
+ else if (where == 0)
+ append_attribute(attribute);
+ else
+ {
+ attribute->m_prev_attribute = where->m_prev_attribute;
+ attribute->m_next_attribute = where;
+ where->m_prev_attribute->m_next_attribute = attribute;
+ where->m_prev_attribute = attribute;
+ attribute->m_parent = this;
+ }
+ }
+
+ //! Removes first attribute of the node.
+ //! If node has no attributes, behaviour is undefined.
+ //! Use first_attribute() to test if node has attributes.
+ void remove_first_attribute()
+ {
+ assert(first_attribute());
+ xml_attribute<Ch> *attribute = m_first_attribute;
+ if (attribute->m_next_attribute)
+ {
+ attribute->m_next_attribute->m_prev_attribute = 0;
+ }
+ else
+ m_last_attribute = 0;
+ attribute->m_parent = 0;
+ m_first_attribute = attribute->m_next_attribute;
+ }
+
+ //! Removes last attribute of the node.
+ //! If node has no attributes, behaviour is undefined.
+ //! Use first_attribute() to test if node has attributes.
+ void remove_last_attribute()
+ {
+ assert(first_attribute());
+ xml_attribute<Ch> *attribute = m_last_attribute;
+ if (attribute->m_prev_attribute)
+ {
+ attribute->m_prev_attribute->m_next_attribute = 0;
+ m_last_attribute = attribute->m_prev_attribute;
+ }
+ else
+ m_first_attribute = 0;
+ attribute->m_parent = 0;
+ }
+
+ //! Removes specified attribute from node.
+ //! \param where Pointer to attribute to be removed.
+ void remove_attribute(xml_attribute<Ch> *where)
+ {
+ assert(first_attribute() && where->parent() == this);
+ if (where == m_first_attribute)
+ remove_first_attribute();
+ else if (where == m_last_attribute)
+ remove_last_attribute();
+ else
+ {
+ where->m_prev_attribute->m_next_attribute = where->m_next_attribute;
+ where->m_next_attribute->m_prev_attribute = where->m_prev_attribute;
+ where->m_parent = 0;
+ }
+ }
+
+ //! Removes all attributes of node.
+ void remove_all_attributes()
+ {
+ for (xml_attribute<Ch> *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute)
+ attribute->m_parent = 0;
+ m_first_attribute = 0;
+ }
+
+ private:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Restrictions
+
+ // No copying
+ xml_node(const xml_node &);
+ void operator =(const xml_node &);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Data members
+
+ // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.
+ // This is required for maximum performance, as it allows the parser to omit initialization of
+ // unneded/redundant values.
+ //
+ // The rules are as follows:
+ // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively
+ // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage
+ // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage
+
+ node_type m_type; // Type of node; always valid
+ xml_node<Ch> *m_first_node; // Pointer to first child node, or 0 if none; always valid
+ xml_node<Ch> *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero
+ xml_attribute<Ch> *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid
+ xml_attribute<Ch> *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero
+ xml_node<Ch> *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+ xml_node<Ch> *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // XML document
+
+ //! This class represents root of the DOM hierarchy.
+ //! It is also an xml_node and a memory_pool through public inheritance.
+ //! Use parse() function to build a DOM tree from a zero-terminated XML text string.
+ //! parse() function allocates memory for nodes and attributes by using functions of xml_document,
+ //! which are inherited from memory_pool.
+ //! To access root node of the document, use the document itself, as if it was an xml_node.
+ //! \param Ch Character type to use.
+ template<class Ch = char>
+ class xml_document: public xml_node<Ch>, public memory_pool<Ch>
+ {
+
+ public:
+
+ //! Constructs empty XML document
+ xml_document()
+ : xml_node<Ch>(node_document)
+ {
+ }
+
+ //! Parses zero-terminated XML string according to given flags.
+ //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used.
+ //! The string must persist for the lifetime of the document.
+ //! In case of error, rapidxml::parse_error exception will be thrown.
+ //! <br><br>
+ //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning.
+ //! Make sure that data is zero-terminated.
+ //! <br><br>
+ //! Document can be parsed into multiple times.
+ //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.
+ //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.
+ template<int Flags>
+ void parse(Ch *text)
+ {
+ assert(text);
+
+ // Remove current contents
+ this->remove_all_nodes();
+ this->remove_all_attributes();
+
+ // Parse BOM, if any
+ parse_bom<Flags>(text);
+
+ // Parse children
+ while (1)
+ {
+ // Skip whitespace before node
+ skip<whitespace_pred, Flags>(text);
+ if (*text == 0)
+ break;
+
+ // Parse and append new child
+ if (*text == Ch('<'))
+ {
+ ++text; // Skip '<'
+ if (xml_node<Ch> *node = parse_node<Flags>(text))
+ this->append_node(node);
+ }
+ else
+ RAPIDXML_PARSE_ERROR("expected <", text);
+ }
+
+ }
+
+ //! Clears the document by deleting all nodes and clearing the memory pool.
+ //! All nodes owned by document pool are destroyed.
+ void clear()
+ {
+ this->remove_all_nodes();
+ this->remove_all_attributes();
+ memory_pool<Ch>::clear();
+ }
+
+ private:
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internal character utility functions
+
+ // Detect whitespace character
+ struct whitespace_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_whitespace[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect node name character
+ struct node_name_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_node_name[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect attribute name character
+ struct attribute_name_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_attribute_name[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect text character (PCDATA)
+ struct text_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_text[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect text character (PCDATA) that does not require processing
+ struct text_pure_no_ws_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect text character (PCDATA) that does not require processing
+ struct text_pure_with_ws_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect attribute value character
+ template<Ch Quote>
+ struct attribute_value_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ if (Quote == Ch('\''))
+ return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast<unsigned char>(ch)];
+ if (Quote == Ch('\"'))
+ return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast<unsigned char>(ch)];
+ return 0; // Should never be executed, to avoid warnings on Comeau
+ }
+ };
+
+ // Detect attribute value character
+ template<Ch Quote>
+ struct attribute_value_pure_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ if (Quote == Ch('\''))
+ return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast<unsigned char>(ch)];
+ if (Quote == Ch('\"'))
+ return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast<unsigned char>(ch)];
+ return 0; // Should never be executed, to avoid warnings on Comeau
+ }
+ };
+
+ // Insert coded character, using UTF8 or 8-bit ASCII
+ template<int Flags>
+ static void insert_coded_character(Ch *&text, unsigned long code)
+ {
+ if (Flags & parse_no_utf8)
+ {
+ // Insert 8-bit ASCII character
+ // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
+ text[0] = static_cast<unsigned char>(code);
+ text += 1;
+ }
+ else
+ {
+ // Insert UTF8 sequence
+ if (code < 0x80) // 1 byte sequence
+ {
+ text[0] = static_cast<unsigned char>(code);
+ text += 1;
+ }
+ else if (code < 0x800) // 2 byte sequence
+ {
+ text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[0] = static_cast<unsigned char>(code | 0xC0);
+ text += 2;
+ }
+ else if (code < 0x10000) // 3 byte sequence
+ {
+ text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[0] = static_cast<unsigned char>(code | 0xE0);
+ text += 3;
+ }
+ else if (code < 0x110000) // 4 byte sequence
+ {
+ text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[0] = static_cast<unsigned char>(code | 0xF0);
+ text += 4;
+ }
+ else // Invalid, only codes up to 0x10FFFF are allowed in Unicode
+ {
+ RAPIDXML_PARSE_ERROR("invalid numeric character entity", text);
+ }
+ }
+ }
+
+ // Skip characters until predicate evaluates to true
+ template<class StopPred, int Flags>
+ static void skip(Ch *&text)
+ {
+ Ch *tmp = text;
+ while (StopPred::test(*tmp))
+ ++tmp;
+ text = tmp;
+ }
+
+ // Skip characters until predicate evaluates to true while doing the following:
+ // - replacing XML character entity references with proper characters (' & " < > &#...;)
+ // - condensing whitespace sequences to single space character
+ template<class StopPred, class StopPredPure, int Flags>
+ static Ch *skip_and_expand_character_refs(Ch *&text)
+ {
+ // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
+ if (Flags & parse_no_entity_translation &&
+ !(Flags & parse_normalize_whitespace) &&
+ !(Flags & parse_trim_whitespace))
+ {
+ skip<StopPred, Flags>(text);
+ return text;
+ }
+
+ // Use simple skip until first modification is detected
+ skip<StopPredPure, Flags>(text);
+
+ // Use translation skip
+ Ch *src = text;
+ Ch *dest = src;
+ while (StopPred::test(*src))
+ {
+ // If entity translation is enabled
+ if (!(Flags & parse_no_entity_translation))
+ {
+ // Test if replacement is needed
+ if (src[0] == Ch('&'))
+ {
+ switch (src[1])
+ {
+
+ // & '
+ case Ch('a'):
+ if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';'))
+ {
+ *dest = Ch('&');
+ ++dest;
+ src += 5;
+ continue;
+ }
+ if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';'))
+ {
+ *dest = Ch('\'');
+ ++dest;
+ src += 6;
+ continue;
+ }
+ break;
+
+ // "
+ case Ch('q'):
+ if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';'))
+ {
+ *dest = Ch('"');
+ ++dest;
+ src += 6;
+ continue;
+ }
+ break;
+
+ // >
+ case Ch('g'):
+ if (src[2] == Ch('t') && src[3] == Ch(';'))
+ {
+ *dest = Ch('>');
+ ++dest;
+ src += 4;
+ continue;
+ }
+ break;
+
+ // <
+ case Ch('l'):
+ if (src[2] == Ch('t') && src[3] == Ch(';'))
+ {
+ *dest = Ch('<');
+ ++dest;
+ src += 4;
+ continue;
+ }
+ break;
+
+ // &#...; - assumes ASCII
+ case Ch('#'):
+ if (src[2] == Ch('x'))
+ {
+ unsigned long code = 0;
+ src += 3; // Skip &#x
+ while (1)
+ {
+ unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+ if (digit == 0xFF)
+ break;
+ code = code * 16 + digit;
+ ++src;
+ }
+ insert_coded_character<Flags>(dest, code); // Put character in output
+ }
+ else
+ {
+ unsigned long code = 0;
+ src += 2; // Skip &#
+ while (1)
+ {
+ unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+ if (digit == 0xFF)
+ break;
+ code = code * 10 + digit;
+ ++src;
+ }
+ insert_coded_character<Flags>(dest, code); // Put character in output
+ }
+ if (*src == Ch(';'))
+ ++src;
+ else
+ RAPIDXML_PARSE_ERROR("expected ;", src);
+ continue;
+
+ // Something else
+ default:
+ // Ignore, just copy '&' verbatim
+ break;
+
+ }
+ }
+ }
+
+ // If whitespace condensing is enabled
+ if (Flags & parse_normalize_whitespace)
+ {
+ // Test if condensing is needed
+ if (whitespace_pred::test(*src))
+ {
+ *dest = Ch(' '); ++dest; // Put single space in dest
+ ++src; // Skip first whitespace char
+ // Skip remaining whitespace chars
+ while (whitespace_pred::test(*src))
+ ++src;
+ continue;
+ }
+ }
+
+ // No replacement, only copy character
+ *dest++ = *src++;
+
+ }
+
+ // Return new end
+ text = src;
+ return dest;
+
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internal parsing functions
+
+ // Parse BOM, if any
+ template<int Flags>
+ void parse_bom(Ch *&text)
+ {
+ // UTF-8?
+ if (static_cast<unsigned char>(text[0]) == 0xEF &&
+ static_cast<unsigned char>(text[1]) == 0xBB &&
+ static_cast<unsigned char>(text[2]) == 0xBF)
+ {
+ text += 3; // Skup utf-8 bom
+ }
+ }
+
+ // Parse XML declaration (<?xml...)
+ template<int Flags>
+ xml_node<Ch> *parse_xml_declaration(Ch *&text)
+ {
+ // If parsing of declaration is disabled
+ if (!(Flags & parse_declaration_node))
+ {
+ // Skip until end of declaration
+ while (text[0] != Ch('?') || text[1] != Ch('>'))
+ {
+ if (!text[0])
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ text += 2; // Skip '?>'
+ return 0;
+ }
+
+ // Create declaration
+ xml_node<Ch> *declaration = this->allocate_node(node_declaration);
+
+ // Skip whitespace before attributes or ?>
+ skip<whitespace_pred, Flags>(text);
+
+ // Parse declaration attributes
+ parse_node_attributes<Flags>(text, declaration);
+
+ // Skip ?>
+ if (text[0] != Ch('?') || text[1] != Ch('>'))
+ RAPIDXML_PARSE_ERROR("expected ?>", text);
+ text += 2;
+
+ return declaration;
+ }
+
+ // Parse XML comment (<!--...)
+ template<int Flags>
+ xml_node<Ch> *parse_comment(Ch *&text)
+ {
+ // If parsing of comments is disabled
+ if (!(Flags & parse_comment_nodes))
+ {
+ // Skip until end of comment
+ while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+ {
+ if (!text[0])
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ text += 3; // Skip '-->'
+ return 0; // Do not produce comment node
+ }
+
+ // Remember value start
+ Ch *value = text;
+
+ // Skip until end of comment
+ while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+ {
+ if (!text[0])
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+
+ // Create comment node
+ xml_node<Ch> *comment = this->allocate_node(node_comment);
+ comment->value(value, text - value);
+
+ // Place zero terminator after comment value
+ if (!(Flags & parse_no_string_terminators))
+ *text = Ch('\0');
+
+ text += 3; // Skip '-->'
+ return comment;
+ }
+
+ // Parse DOCTYPE
+ template<int Flags>
+ xml_node<Ch> *parse_doctype(Ch *&text)
+ {
+ // Remember value start
+ Ch *value = text;
+
+ // Skip to >
+ while (*text != Ch('>'))
+ {
+ // Determine character type
+ switch (*text)
+ {
+
+ // If '[' encountered, scan for matching ending ']' using naive algorithm with depth
+ // This works for all W3C test files except for 2 most wicked
+ case Ch('['):
+ {
+ ++text; // Skip '['
+ int depth = 1;
+ while (depth > 0)
+ {
+ switch (*text)
+ {
+ case Ch('['): ++depth; break;
+ case Ch(']'): --depth; break;
+ case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ default: break;
+ }
+ ++text;
+ }
+ break;
+ }
+
+ // Error on end of text
+ case Ch('\0'):
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+
+ // Other character, skip it
+ default:
+ ++text;
+
+ }
+ }
+
+ // If DOCTYPE nodes enabled
+ if (Flags & parse_doctype_node)
+ {
+ // Create a new doctype node
+ xml_node<Ch> *doctype = this->allocate_node(node_doctype);
+ doctype->value(value, text - value);
+
+ // Place zero terminator after value
+ if (!(Flags & parse_no_string_terminators))
+ *text = Ch('\0');
+
+ text += 1; // skip '>'
+ return doctype;
+ }
+ else
+ {
+ text += 1; // skip '>'
+ return 0;
+ }
+
+ }
+
+ // Parse PI
+ template<int Flags>
+ xml_node<Ch> *parse_pi(Ch *&text)
+ {
+ // If creation of PI nodes is enabled
+ if (Flags & parse_pi_nodes)
+ {
+ // Create pi node
+ xml_node<Ch> *pi = this->allocate_node(node_pi);
+
+ // Extract PI target name
+ Ch *name = text;
+ skip<node_name_pred, Flags>(text);
+ if (text == name)
+ RAPIDXML_PARSE_ERROR("expected PI target", text);
+ pi->name(name, text - name);
+
+ // Skip whitespace between pi target and pi
+ skip<whitespace_pred, Flags>(text);
+
+ // Remember start of pi
+ Ch *value = text;
+
+ // Skip to '?>'
+ while (text[0] != Ch('?') || text[1] != Ch('>'))
+ {
+ if (*text == Ch('\0'))
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+
+ // Set pi value (verbatim, no entity expansion or whitespace normalization)
+ pi->value(value, text - value);
+
+ // Place zero terminator after name and value
+ if (!(Flags & parse_no_string_terminators))
+ {
+ pi->name()[pi->name_size()] = Ch('\0');
+ pi->value()[pi->value_size()] = Ch('\0');
+ }
+
+ text += 2; // Skip '?>'
+ return pi;
+ }
+ else
+ {
+ // Skip to '?>'
+ while (text[0] != Ch('?') || text[1] != Ch('>'))
+ {
+ if (*text == Ch('\0'))
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ text += 2; // Skip '?>'
+ return 0;
+ }
+ }
+
+ // Parse and append data
+ // Return character that ends data.
+ // This is necessary because this character might have been overwritten by a terminating 0
+ template<int Flags>
+ Ch parse_and_append_data(xml_node<Ch> *node, Ch *&text, Ch *contents_start)
+ {
+ // Backup to contents start if whitespace trimming is disabled
+ if (!(Flags & parse_trim_whitespace))
+ text = contents_start;
+
+ // Skip until end of data
+ Ch *value = text, *end;
+ if (Flags & parse_normalize_whitespace)
+ end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text);
+ else
+ end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text);
+
+ // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >
+ if (Flags & parse_trim_whitespace)
+ {
+ if (Flags & parse_normalize_whitespace)
+ {
+ // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end
+ if (*(end - 1) == Ch(' '))
+ --end;
+ }
+ else
+ {
+ // Backup until non-whitespace character is found
+ while (whitespace_pred::test(*(end - 1)))
+ --end;
+ }
+ }
+
+ // If characters are still left between end and value (this test is only necessary if normalization is enabled)
+ // Create new data node
+ if (!(Flags & parse_no_data_nodes))
+ {
+ xml_node<Ch> *data = this->allocate_node(node_data);
+ data->value(value, end - value);
+ node->append_node(data);
+ }
+
+ // Add data to parent node if no data exists yet
+ if (!(Flags & parse_no_element_values))
+ if (*node->value() == Ch('\0'))
+ node->value(value, end - value);
+
+ // Place zero terminator after value
+ if (!(Flags & parse_no_string_terminators))
+ {
+ Ch ch = *text;
+ *end = Ch('\0');
+ return ch; // Return character that ends data; this is required because zero terminator overwritten it
+ }
+
+ // Return character that ends data
+ return *text;
+ }
+
+ // Parse CDATA
+ template<int Flags>
+ xml_node<Ch> *parse_cdata(Ch *&text)
+ {
+ // If CDATA is disabled
+ if (Flags & parse_no_data_nodes)
+ {
+ // Skip until end of cdata
+ while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+ {
+ if (!text[0])
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ text += 3; // Skip ]]>
+ return 0; // Do not produce CDATA node
+ }
+
+ // Skip until end of cdata
+ Ch *value = text;
+ while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+ {
+ if (!text[0])
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+
+ // Create new cdata node
+ xml_node<Ch> *cdata = this->allocate_node(node_cdata);
+ cdata->value(value, text - value);
+
+ // Place zero terminator after value
+ if (!(Flags & parse_no_string_terminators))
+ *text = Ch('\0');
+
+ text += 3; // Skip ]]>
+ return cdata;
+ }
+
+ // Parse element node
+ template<int Flags>
+ xml_node<Ch> *parse_element(Ch *&text)
+ {
+ // Create element node
+ xml_node<Ch> *element = this->allocate_node(node_element);
+
+ // Extract element name
+ Ch *name = text;
+ skip<node_name_pred, Flags>(text);
+ if (text == name)
+ RAPIDXML_PARSE_ERROR("expected element name", text);
+ element->name(name, text - name);
+
+ // Skip whitespace between element name and attributes or >
+ skip<whitespace_pred, Flags>(text);
+
+ // Parse attributes, if any
+ parse_node_attributes<Flags>(text, element);
+
+ // Determine ending type
+ if (*text == Ch('>'))
+ {
+ ++text;
+ parse_node_contents<Flags>(text, element);
+ }
+ else if (*text == Ch('/'))
+ {
+ ++text;
+ if (*text != Ch('>'))
+ RAPIDXML_PARSE_ERROR("expected >", text);
+ ++text;
+ }
+ else
+ RAPIDXML_PARSE_ERROR("expected >", text);
+
+ // Place zero terminator after name
+ if (!(Flags & parse_no_string_terminators))
+ element->name()[element->name_size()] = Ch('\0');
+
+ // Return parsed element
+ return element;
+ }
+
+ // Determine node type, and parse it
+ template<int Flags>
+ xml_node<Ch> *parse_node(Ch *&text)
+ {
+ // Parse proper node type
+ switch (text[0])
+ {
+
+ // <...
+ default:
+ // Parse and append element node
+ return parse_element<Flags>(text);
+
+ // <?...
+ case Ch('?'):
+ ++text; // Skip ?
+ if ((text[0] == Ch('x') || text[0] == Ch('X')) &&
+ (text[1] == Ch('m') || text[1] == Ch('M')) &&
+ (text[2] == Ch('l') || text[2] == Ch('L')) &&
+ whitespace_pred::test(text[3]))
+ {
+ // '<?xml ' - xml declaration
+ text += 4; // Skip 'xml '
+ return parse_xml_declaration<Flags>(text);
+ }
+ else
+ {
+ // Parse PI
+ return parse_pi<Flags>(text);
+ }
+
+ // <!...
+ case Ch('!'):
+
+ // Parse proper subset of <! node
+ switch (text[1])
+ {
+
+ // <!-
+ case Ch('-'):
+ if (text[2] == Ch('-'))
+ {
+ // '<!--' - xml comment
+ text += 3; // Skip '!--'
+ return parse_comment<Flags>(text);
+ }
+ break;
+
+ // <![
+ case Ch('['):
+ if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') &&
+ text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('['))
+ {
+ // '<![CDATA[' - cdata
+ text += 8; // Skip '![CDATA['
+ return parse_cdata<Flags>(text);
+ }
+ break;
+
+ // <!D
+ case Ch('D'):
+ if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') &&
+ text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') &&
+ whitespace_pred::test(text[8]))
+ {
+ // '<!DOCTYPE ' - doctype
+ text += 9; // skip '!DOCTYPE '
+ return parse_doctype<Flags>(text);
+ }
+ break;
+
+ default:
+ break;
+
+ } // switch
+
+ // Attempt to skip other, unrecognized node types starting with <!
+ ++text; // Skip !
+ while (*text != Ch('>'))
+ {
+ if (*text == 0)
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ ++text;
+ }
+ ++text; // Skip '>'
+ return 0; // No node recognized
+
+ }
+ }
+
+ // Parse contents of the node - children, data etc.
+ template<int Flags>
+ void parse_node_contents(Ch *&text, xml_node<Ch> *node)
+ {
+ // For all children and text
+ while (1)
+ {
+ // Skip whitespace between > and node contents
+ Ch *contents_start = text; // Store start of node contents before whitespace is skipped
+ skip<whitespace_pred, Flags>(text);
+ Ch next_char = *text;
+
+ // After data nodes, instead of continuing the loop, control jumps here.
+ // This is because zero termination inside parse_and_append_data() function
+ // would wreak havoc with the above code.
+ // Also, skipping whitespace after data nodes is unnecessary.
+ after_data_node:
+
+ // Determine what comes next: node closing, child node, data node, or 0?
+ switch (next_char)
+ {
+
+ // Node closing or child node
+ case Ch('<'):
+ if (text[1] == Ch('/'))
+ {
+ // Node closing
+ text += 2; // Skip '</'
+ if (Flags & parse_validate_closing_tags)
+ {
+ // Skip and validate closing tag name
+ Ch *closing_name = text;
+ skip<node_name_pred, Flags>(text);
+ if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))
+ RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
+ }
+ else
+ {
+ // No validation, just skip name
+ skip<node_name_pred, Flags>(text);
+ }
+ // Skip remaining whitespace after node name
+ skip<whitespace_pred, Flags>(text);
+ if (*text != Ch('>'))
+ RAPIDXML_PARSE_ERROR("expected >", text);
+ ++text; // Skip '>'
+ return; // Node closed, finished parsing contents
+ }
+ else
+ {
+ // Child node
+ ++text; // Skip '<'
+ if (xml_node<Ch> *child = parse_node<Flags>(text))
+ node->append_node(child);
+ }
+ break;
+
+ // End of data - error
+ case Ch('\0'):
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+
+ // Data node
+ default:
+ next_char = parse_and_append_data<Flags>(node, text, contents_start);
+ goto after_data_node; // Bypass regular processing after data nodes
+
+ }
+ }
+ }
+
+ // Parse XML attributes of the node
+ template<int Flags>
+ void parse_node_attributes(Ch *&text, xml_node<Ch> *node)
+ {
+ // For all attributes
+ while (attribute_name_pred::test(*text))
+ {
+ // Extract attribute name
+ Ch *name = text;
+ ++text; // Skip first character of attribute name
+ skip<attribute_name_pred, Flags>(text);
+ if (text == name)
+ RAPIDXML_PARSE_ERROR("expected attribute name", name);
+
+ // Create new attribute
+ xml_attribute<Ch> *attribute = this->allocate_attribute();
+ attribute->name(name, text - name);
+ node->append_attribute(attribute);
+
+ // Skip whitespace after attribute name
+ skip<whitespace_pred, Flags>(text);
+
+ // Skip =
+ if (*text != Ch('='))
+ RAPIDXML_PARSE_ERROR("expected =", text);
+ ++text;
+
+ // Add terminating zero after name
+ if (!(Flags & parse_no_string_terminators))
+ attribute->name()[attribute->name_size()] = 0;
+
+ // Skip whitespace after =
+ skip<whitespace_pred, Flags>(text);
+
+ // Skip quote and remember if it was ' or "
+ Ch quote = *text;
+ if (quote != Ch('\'') && quote != Ch('"'))
+ RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+ ++text;
+
+ // Extract attribute value and expand char refs in it
+ Ch *value = text, *end;
+ const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes
+ if (quote == Ch('\''))
+ end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text);
+ else
+ end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text);
+
+ // Set attribute value
+ attribute->value(value, end - value);
+
+ // Make sure that end quote is present
+ if (*text != quote)
+ RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+ ++text; // Skip quote
+
+ // Add terminating zero after value
+ if (!(Flags & parse_no_string_terminators))
+ attribute->value()[attribute->value_size()] = 0;
+
+ // Skip whitespace after attribute value
+ skip<whitespace_pred, Flags>(text);
+ }
+ }
+
+ };
+
+ //! \cond internal
+ namespace internal
+ {
+
+ // Whitespace (space \n \r \t)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
+ };
+
+ // Node name (anything but space \n \r \t / > ? \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_node_name[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Text (i.e. PCDATA) (anything but < \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_text[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled
+ // (anything but < \0 &)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled
+ // (anything but < \0 & space \n \r \t)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute name (anything but space \n \r \t / < > = ? ! \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with single quote (anything but ' \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with single quote that does not require processing (anything but ' \0 &)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with double quote (anything but " \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with double quote that does not require processing (anything but " \0 &)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Digits (dec and hex, 255 denotes end of numeric character reference)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_digits[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3
+ 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5
+ 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F
+ };
+
+ // Upper case conversion
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_upcase[256] =
+ {
+ // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127, // 7
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 8
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 9
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // A
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // B
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // C
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // D
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // E
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // F
+ };
+ }
+ //! \endcond
+
+}
+
+// Undefine internal macros
+#undef RAPIDXML_PARSE_ERROR
+
+// On MSVC, restore warnings state
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
+
+#endif
--- /dev/null
+#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED
+#define RAPIDXML_ITERATORS_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_iterators.hpp This file contains rapidxml iterators
+
+#include "rapidxml.hpp"
+
+namespace rapidxml
+{
+
+ //! Iterator of child nodes of xml_node
+ template<class Ch>
+ class node_iterator
+ {
+
+ public:
+
+ typedef typename xml_node<Ch> value_type;
+ typedef typename xml_node<Ch> &reference;
+ typedef typename xml_node<Ch> *pointer;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ node_iterator()
+ : m_node(0)
+ {
+ }
+
+ node_iterator(xml_node<Ch> *node)
+ : m_node(node->first_node())
+ {
+ }
+
+ reference operator *() const
+ {
+ assert(m_node);
+ return *m_node;
+ }
+
+ pointer operator->() const
+ {
+ assert(m_node);
+ return m_node;
+ }
+
+ node_iterator& operator++()
+ {
+ assert(m_node);
+ m_node = m_node->next_sibling();
+ return *this;
+ }
+
+ node_iterator operator++(int)
+ {
+ node_iterator tmp = *this;
+ ++this;
+ return tmp;
+ }
+
+ node_iterator& operator--()
+ {
+ assert(m_node && m_node->previous_sibling());
+ m_node = m_node->previous_sibling();
+ return *this;
+ }
+
+ node_iterator operator--(int)
+ {
+ node_iterator tmp = *this;
+ ++this;
+ return tmp;
+ }
+
+ bool operator ==(const node_iterator<Ch> &rhs)
+ {
+ return m_node == rhs.m_node;
+ }
+
+ bool operator !=(const node_iterator<Ch> &rhs)
+ {
+ return m_node != rhs.m_node;
+ }
+
+ private:
+
+ xml_node<Ch> *m_node;
+
+ };
+
+ //! Iterator of child attributes of xml_node
+ template<class Ch>
+ class attribute_iterator
+ {
+
+ public:
+
+ typedef typename xml_attribute<Ch> value_type;
+ typedef typename xml_attribute<Ch> &reference;
+ typedef typename xml_attribute<Ch> *pointer;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+
+ attribute_iterator()
+ : m_attribute(0)
+ {
+ }
+
+ attribute_iterator(xml_node<Ch> *node)
+ : m_attribute(node->first_attribute())
+ {
+ }
+
+ reference operator *() const
+ {
+ assert(m_attribute);
+ return *m_attribute;
+ }
+
+ pointer operator->() const
+ {
+ assert(m_attribute);
+ return m_attribute;
+ }
+
+ attribute_iterator& operator++()
+ {
+ assert(m_attribute);
+ m_attribute = m_attribute->next_attribute();
+ return *this;
+ }
+
+ attribute_iterator operator++(int)
+ {
+ attribute_iterator tmp = *this;
+ ++this;
+ return tmp;
+ }
+
+ attribute_iterator& operator--()
+ {
+ assert(m_attribute && m_attribute->previous_attribute());
+ m_attribute = m_attribute->previous_attribute();
+ return *this;
+ }
+
+ attribute_iterator operator--(int)
+ {
+ attribute_iterator tmp = *this;
+ ++this;
+ return tmp;
+ }
+
+ bool operator ==(const attribute_iterator<Ch> &rhs)
+ {
+ return m_attribute == rhs.m_attribute;
+ }
+
+ bool operator !=(const attribute_iterator<Ch> &rhs)
+ {
+ return m_attribute != rhs.m_attribute;
+ }
+
+ private:
+
+ xml_attribute<Ch> *m_attribute;
+
+ };
+
+}
+
+#endif
--- /dev/null
+#ifndef RAPIDXML_PRINT_HPP_INCLUDED
+#define RAPIDXML_PRINT_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_print.hpp This file contains rapidxml printer implementation
+
+#include "rapidxml.hpp"
+
+// Only include streams if not disabled
+#ifndef RAPIDXML_NO_STREAMS
+ #include <ostream>
+ #include <iterator>
+#endif
+
+namespace rapidxml
+{
+
+ ///////////////////////////////////////////////////////////////////////
+ // Printing flags
+
+ const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internal
+
+ //! \cond internal
+ namespace internal
+ {
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Internal character operations
+
+ // Copy characters from given range to given output iterator
+ template<class OutIt, class Ch>
+ inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
+ {
+ while (begin != end)
+ *out++ = *begin++;
+ return out;
+ }
+
+ // Copy characters from given range to given output iterator and expand
+ // characters into references (< > ' " &)
+ template<class OutIt, class Ch>
+ inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
+ {
+ while (begin != end)
+ {
+ if (*begin == noexpand)
+ {
+ *out++ = *begin; // No expansion, copy character
+ }
+ else
+ {
+ switch (*begin)
+ {
+ case Ch('<'):
+ *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
+ break;
+ case Ch('>'):
+ *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
+ break;
+ case Ch('\''):
+ *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
+ break;
+ case Ch('"'):
+ *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
+ break;
+ case Ch('&'):
+ *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';');
+ break;
+ default:
+ *out++ = *begin; // No expansion, copy character
+ }
+ }
+ ++begin; // Step to next character
+ }
+ return out;
+ }
+
+ // Fill given output iterator with repetitions of the same character
+ template<class OutIt, class Ch>
+ inline OutIt fill_chars(OutIt out, int n, Ch ch)
+ {
+ for (int i = 0; i < n; ++i)
+ *out++ = ch;
+ return out;
+ }
+
+ // Find character
+ template<class Ch, Ch ch>
+ inline bool find_char(const Ch *begin, const Ch *end)
+ {
+ while (begin != end)
+ if (*begin++ == ch)
+ return true;
+ return false;
+ }
+
+ template<class OutIt, class Ch>
+ inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
+
+ // Print children of the node
+ template<class OutIt, class Ch>
+ inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
+ out = print_node(out, child, flags, indent);
+ return out;
+ }
+
+ // Print attributes of the node
+ template<class OutIt, class Ch>
+ inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
+ {
+ for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
+ {
+ if (attribute->name() && attribute->value())
+ {
+ // Print attribute name
+ *out = Ch(' '), ++out;
+ out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
+ *out = Ch('='), ++out;
+ // Print attribute value using appropriate quote type
+ if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
+ {
+ *out = Ch('\''), ++out;
+ out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
+ *out = Ch('\''), ++out;
+ }
+ else
+ {
+ *out = Ch('"'), ++out;
+ out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
+ *out = Ch('"'), ++out;
+ }
+ }
+ }
+ return out;
+ }
+
+ // Print data node
+ template<class OutIt, class Ch>
+ inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ assert(node->type() == node_data);
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
+ return out;
+ }
+
+ // Print data node
+ template<class OutIt, class Ch>
+ inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ assert(node->type() == node_cdata);
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ *out = Ch('<'); ++out;
+ *out = Ch('!'); ++out;
+ *out = Ch('['); ++out;
+ *out = Ch('C'); ++out;
+ *out = Ch('D'); ++out;
+ *out = Ch('A'); ++out;
+ *out = Ch('T'); ++out;
+ *out = Ch('A'); ++out;
+ *out = Ch('['); ++out;
+ out = copy_chars(node->value(), node->value() + node->value_size(), out);
+ *out = Ch(']'); ++out;
+ *out = Ch(']'); ++out;
+ *out = Ch('>'); ++out;
+ return out;
+ }
+
+ // Print element node
+ template<class OutIt, class Ch>
+ inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ assert(node->type() == node_element);
+
+ // Print element name and attributes, if any
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ *out = Ch('<'), ++out;
+ out = copy_chars(node->name(), node->name() + node->name_size(), out);
+ out = print_attributes(out, node, flags);
+
+ // If node is childless
+ if (node->value_size() == 0 && !node->first_node())
+ {
+ // Print childless node tag ending
+ *out = Ch('/'), ++out;
+ *out = Ch('>'), ++out;
+ }
+ else
+ {
+ // Print normal node tag ending
+ *out = Ch('>'), ++out;
+
+ // Test if node contains a single data node only (and no other nodes)
+ xml_node<Ch> *child = node->first_node();
+ if (!child)
+ {
+ // If node has no children, only print its value without indenting
+ out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
+ }
+ else if (child->next_sibling() == 0 && child->type() == node_data)
+ {
+ // If node has a sole data child, only print its value without indenting
+ out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
+ }
+ else
+ {
+ // Print all children with full indenting
+ if (!(flags & print_no_indenting))
+ *out = Ch('\n'), ++out;
+ out = print_children(out, node, flags, indent + 1);
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ }
+
+ // Print node end
+ *out = Ch('<'), ++out;
+ *out = Ch('/'), ++out;
+ out = copy_chars(node->name(), node->name() + node->name_size(), out);
+ *out = Ch('>'), ++out;
+ }
+ return out;
+ }
+
+ // Print declaration node
+ template<class OutIt, class Ch>
+ inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ // Print declaration start
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ *out = Ch('<'), ++out;
+ *out = Ch('?'), ++out;
+ *out = Ch('x'), ++out;
+ *out = Ch('m'), ++out;
+ *out = Ch('l'), ++out;
+
+ // Print attributes
+ out = print_attributes(out, node, flags);
+
+ // Print declaration end
+ *out = Ch('?'), ++out;
+ *out = Ch('>'), ++out;
+
+ return out;
+ }
+
+ // Print comment node
+ template<class OutIt, class Ch>
+ inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ assert(node->type() == node_comment);
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ *out = Ch('<'), ++out;
+ *out = Ch('!'), ++out;
+ *out = Ch('-'), ++out;
+ *out = Ch('-'), ++out;
+ out = copy_chars(node->value(), node->value() + node->value_size(), out);
+ *out = Ch('-'), ++out;
+ *out = Ch('-'), ++out;
+ *out = Ch('>'), ++out;
+ return out;
+ }
+
+ // Print doctype node
+ template<class OutIt, class Ch>
+ inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ assert(node->type() == node_doctype);
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ *out = Ch('<'), ++out;
+ *out = Ch('!'), ++out;
+ *out = Ch('D'), ++out;
+ *out = Ch('O'), ++out;
+ *out = Ch('C'), ++out;
+ *out = Ch('T'), ++out;
+ *out = Ch('Y'), ++out;
+ *out = Ch('P'), ++out;
+ *out = Ch('E'), ++out;
+ *out = Ch(' '), ++out;
+ out = copy_chars(node->value(), node->value() + node->value_size(), out);
+ *out = Ch('>'), ++out;
+ return out;
+ }
+
+ // Print pi node
+ template<class OutIt, class Ch>
+ inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ assert(node->type() == node_pi);
+ if (!(flags & print_no_indenting))
+ out = fill_chars(out, indent, Ch('\t'));
+ *out = Ch('<'), ++out;
+ *out = Ch('?'), ++out;
+ out = copy_chars(node->name(), node->name() + node->name_size(), out);
+ *out = Ch(' '), ++out;
+ out = copy_chars(node->value(), node->value() + node->value_size(), out);
+ *out = Ch('?'), ++out;
+ *out = Ch('>'), ++out;
+ return out;
+ }
+ ///////////////////////////////////////////////////////////////////////////
+ // Internal printing operations
+
+ // Print node
+ template<class OutIt, class Ch>
+ inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+ {
+ // Print proper node type
+ switch (node->type())
+ {
+
+ // Document
+ case node_document:
+ out = print_children(out, node, flags, indent);
+ break;
+
+ // Element
+ case node_element:
+ out = print_element_node(out, node, flags, indent);
+ break;
+
+ // Data
+ case node_data:
+ out = print_data_node(out, node, flags, indent);
+ break;
+
+ // CDATA
+ case node_cdata:
+ out = print_cdata_node(out, node, flags, indent);
+ break;
+
+ // Declaration
+ case node_declaration:
+ out = print_declaration_node(out, node, flags, indent);
+ break;
+
+ // Comment
+ case node_comment:
+ out = print_comment_node(out, node, flags, indent);
+ break;
+
+ // Doctype
+ case node_doctype:
+ out = print_doctype_node(out, node, flags, indent);
+ break;
+
+ // Pi
+ case node_pi:
+ out = print_pi_node(out, node, flags, indent);
+ break;
+
+ // Unknown
+ default:
+ assert(0);
+ break;
+ }
+
+ // If indenting not disabled, add line break after node
+ if (!(flags & print_no_indenting))
+ *out = Ch('\n'), ++out;
+
+ // Return modified iterator
+ return out;
+ }
+ }
+ //! \endcond
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Printing
+
+ //! Prints XML to given output iterator.
+ //! \param out Output iterator to print to.
+ //! \param node Node to be printed. Pass xml_document to print entire document.
+ //! \param flags Flags controlling how XML is printed.
+ //! \return Output iterator pointing to position immediately after last character of printed text.
+ template<class OutIt, class Ch>
+ inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
+ {
+ return internal::print_node(out, &node, flags, 0);
+ }
+
+#ifndef RAPIDXML_NO_STREAMS
+
+ //! Prints XML to given output stream.
+ //! \param out Output stream to print to.
+ //! \param node Node to be printed. Pass xml_document to print entire document.
+ //! \param flags Flags controlling how XML is printed.
+ //! \return Output stream.
+ template<class Ch>
+ inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
+ {
+ print(std::ostream_iterator<Ch>(out), node, flags);
+ return out;
+ }
+
+ //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
+ //! \param out Output stream to print to.
+ //! \param node Node to be printed.
+ //! \return Output stream.
+ template<class Ch>
+ inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
+ {
+ return print(out, node);
+ }
+
+#endif
+
+}
+
+#endif
--- /dev/null
+#ifndef RAPIDXML_UTILS_HPP_INCLUDED
+#define RAPIDXML_UTILS_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
+//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
+
+#include "rapidxml.hpp"
+#include <vector>
+#include <string>
+#include <fstream>
+#include <stdexcept>
+
+namespace rapidxml
+{
+
+ //! Represents data loaded from a file
+ template<class Ch = char>
+ class file
+ {
+
+ public:
+
+ //! Loads file into the memory. Data will be automatically destroyed by the destructor.
+ //! \param filename Filename to load.
+ file(const char *filename)
+ {
+ using namespace std;
+
+ // Open stream
+ basic_ifstream<Ch> stream(filename, ios::binary);
+ if (!stream)
+ throw runtime_error(string("cannot open file ") + filename);
+ stream.unsetf(ios::skipws);
+
+ // Determine stream size
+ stream.seekg(0, ios::end);
+ size_t size = stream.tellg();
+ stream.seekg(0);
+
+ // Load data and add terminating 0
+ m_data.resize(size + 1);
+ stream.read(&m_data.front(), static_cast<streamsize>(size));
+ m_data[size] = 0;
+ }
+
+ //! Loads file into the memory. Data will be automatically destroyed by the destructor
+ //! \param stream Stream to load from
+ file(std::basic_istream<Ch> &stream)
+ {
+ using namespace std;
+
+ // Load data and add terminating 0
+ stream.unsetf(ios::skipws);
+ m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
+ if (stream.fail() || stream.bad())
+ throw runtime_error("error reading stream");
+ m_data.push_back(0);
+ }
+
+ //! Gets file data.
+ //! \return Pointer to data of file.
+ Ch *data()
+ {
+ return &m_data.front();
+ }
+
+ //! Gets file data.
+ //! \return Pointer to data of file.
+ const Ch *data() const
+ {
+ return &m_data.front();
+ }
+
+ //! Gets file data size.
+ //! \return Size of file data, in characters.
+ std::size_t size() const
+ {
+ return m_data.size();
+ }
+
+ private:
+
+ std::vector<Ch> m_data; // File data
+
+ };
+
+ //! Counts children of node. Time complexity is O(n).
+ //! \return Number of children of node
+ template<class Ch>
+ inline std::size_t count_children(xml_node<Ch> *node)
+ {
+ xml_node<Ch> *child = node->first_node();
+ std::size_t count = 0;
+ while (child)
+ {
+ ++count;
+ child = child->next_sibling();
+ }
+ return count;
+ }
+
+ //! Counts attributes of node. Time complexity is O(n).
+ //! \return Number of attributes of node
+ template<class Ch>
+ inline std::size_t count_attributes(xml_node<Ch> *node)
+ {
+ xml_attribute<Ch> *attr = node->first_attribute();
+ std::size_t count = 0;
+ while (attr)
+ {
+ ++count;
+ attr = attr->next_attribute();
+ }
+ return count;
+ }
+
+}
+
+#endif
--- /dev/null
+##
+# plugin-manager project build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+plugin_manager_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+plugin_manager_env.AppendUnique(CPPPATH = [
+ '../lib/cpluff/libcpluff',
+ 'src'
+ ])
+
+if target_os not in ['windows', 'winrt']:
+ plugin_manager_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall',
+ '-fpermissive', '-Wsign-compare'])
+
+if target_os == 'android':
+ plugin_manager_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+ plugin_manager_env.AppendUnique(LIBS = ['boost_thread-gcc-mt-1_49', 'gnustl_static'])
+
+plugin_manager_env.AppendUnique(LIBS = ['oc', 'octbstack', 'expat', 'dl'])
+######################################################################
+# Source files and Targets
+######################################################################
+ppm_src = ['src/Plugin.cpp', 'src/PluginManager.cpp']
+ppm = plugin_manager_env.StaticLibrary('ppm', ppm_src)
+
+pmimpl_src = [
+ 'src/CpluffAdapter.cpp',
+ 'src/FelixAdapter.cpp',
+ 'src/Plugin.cpp',
+ 'src/PluginManagerImpl.cpp']
+
+pmimpl_env = plugin_manager_env.Clone()
+pmimpl_env.PrependUnique(CCFLAGS = ['-fPIC'])
+pmimpl_env.PrependUnique(LIBS = File(env.get('BUILD_DIR') + '/libcpluff.a'))
+pmimpl = pmimpl_env.SharedLibrary('pmimpl', pmimpl_src)
+
+plugin_manager_env.InstallTarget([ppm, pmimpl], 'libppm')
CXX = g++
CXX_FLAGS = -std=c++0x -Wall
-
-CPLUFF_DIR = ../../../lib/cpluff/libcpluff
+LIB = ../../../lib
+CPLUFF_DIR = $(LIB)/cpluff/libcpluff
SRC = ../../src/
CXX_INC = -I. -I$(CPLUFF_DIR)
+CXX_INC += -I$(LIB)/rapidxml
LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread
CXX_LIBS = $(CPLUFF_DIR)/.libs/libcpluff.a
$(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManager.cpp
-libpmimpl.so:PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o $(CPLUFF_DIR)/.libs/libcpluff.a
- $(CXX) -shared -o libpmimpl.so PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o $(CXX_LIBS) $(LINK_LIB)
+libpmimpl.so:PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o Config.o $(CPLUFF_DIR)/.libs/libcpluff.a
+ $(CXX) -shared -o libpmimpl.so PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o Config.o $(CXX_LIBS) $(LINK_LIB)
PluginManagerImpl.o : $(SRC)PluginManagerImpl.cpp
$(CXX) $(CXX_INC) -fPIC -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManagerImpl.cpp
Plugin.o : $(SRC)Plugin.cpp
$(CXX) $(CXX_INC) -fPIC -c $(SRC)Plugin.cpp
+Config.o : $(SRC)Config.cpp
+ $(CXX) $(CXX_INC) -fPIC -c $(SRC)Config.cpp
+
CpluffAdapter.o : $(SRC)CpluffAdapter.cpp
$(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)CpluffAdapter.cpp
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file Config.cpp
+
+/// @brief
+
+
+#include "Config.h"
+
+
+using namespace OIC;
+using namespace rapidxml;
+using namespace std;
+
+Config *Config::s_configinstance = NULL;
+
+Config::Config()
+{
+ if (loadConfigFile("./pluginmanager.xml") != PM_S_OK)
+ {
+ fprintf(stderr, "PM Configuration file is not exist current Folder.\n" );
+ exit(EXIT_FAILURE);
+ }
+}
+
+Config::~Config(void)
+{
+ s_configinstance->deleteinstance();
+ s_configinstance = NULL;
+}
+
+PMRESULT Config::loadConfigFile(const std::string configfilepath)
+{
+ // Read the xml file
+ std::ifstream xmlFile(configfilepath.c_str());
+ xml_document<> doc;
+ //into a vector
+ std::vector<char> buffer((istreambuf_iterator<char>(xmlFile)), istreambuf_iterator<char>());
+ buffer.push_back('\0');
+
+ // Parse the buffer using the xml file parsing library into doc
+ parsing(buffer, &doc);
+
+ // Find our root node
+ xml_node<> *root_node = doc.first_node("pluginManager");
+ xml_node<> *pluginInfo = root_node->first_node("pluginInfo");
+
+ getXmlData(pluginInfo, "pluginPath");
+ getXmlData(pluginInfo, "maxMEM");
+ getXmlData(pluginInfo, "version");
+ getXmlData(pluginInfo, "name");
+
+ return PM_S_OK;
+}
+
+PMRESULT Config::parsing(std::vector<char> buffer, xml_document<> *doc)
+{
+ // Parse the buffer using the xml file parsing library into doc
+ try
+ {
+ doc->parse<0>(&buffer[0]);
+ }
+ catch (rapidxml::parse_error err)
+ {
+ //print errors to screen
+ fprintf(stderr, "PM Configuration file parsing error \n");
+ exit(EXIT_FAILURE); //then exit
+ }
+ return PM_S_OK;
+}
+
+PMRESULT Config::getXmlData(xml_node<> *pluginInfo, std::string key)
+{
+ xml_attribute<> *iAttr = NULL;
+ std::string value = "";
+ if (iAttr = pluginInfo->first_attribute(key.c_str()))
+ {
+ value = iAttr->value();
+ setValue(key, value);
+ return PM_S_OK;
+ }
+ else
+ {
+ return PM_S_FALSE;
+ }
+}
+
+void Config::setValue(const std::string key, const std::string value)
+{
+ m_configurationMap.insert( std::pair<std::string, std::string>(key, value));
+}
+
+std::string Config::getValue(const std::string key)
+{
+ std::map<std::string, std::string>::iterator m_iterator;
+
+ m_iterator = m_configurationMap.find(key.c_str());
+
+ if (m_iterator != m_configurationMap.end())
+ {
+ return m_iterator->second;
+ }
+ else
+ {
+ return "";
+ }
+}
+
+std::string Config::getVersion()
+{
+ std::map<std::string, std::string>::iterator m_iterator;
+
+ m_iterator = m_configurationMap.find("version");
+
+ if (m_iterator != m_configurationMap.end())
+ {
+ return m_iterator->second;
+ }
+ else
+ {
+ return "";
+ }
+}
+
+std::string Config::getPluginPath()
+{
+ std::map<std::string, std::string>::iterator m_iterator;
+
+ m_iterator = m_configurationMap.find("pluginPath");
+
+ if (m_iterator != m_configurationMap.end())
+ {
+ return m_iterator->second;
+ }
+ else
+ {
+ return "";
+ }
+}
\ No newline at end of file
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file Config.h
+
+/// @brief
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+#include <map>
+#include <string>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "rapidxml.hpp"
+#include <fstream>
+#include <vector>
+
+using namespace rapidxml;
+
+namespace OIC
+{
+
+ enum PMRESULT
+ {
+ PM_S_OK
+ , PM_S_FALSE
+ , PM_E_POINTER
+ , PM_E_OUTOFMEMORY
+ , PM_E_FAIL
+ , PM_E_NOINTERFACE
+ , PM_E_NOTIMPL
+ };
+ /**
+ * @brief Configuration class
+ *
+ *
+ */
+ class Config
+ {
+ public:
+ /**
+ * A function to register pluins in the path.
+ * This function will load plugins in plugin manager table.
+ *
+ * @param path plugin file path to be registered.
+ * @return int, 1 is success, 0 is fail.
+ *
+ * NOTE:
+ *
+ */
+ /**
+ *
+ * new Singleton pattern instance.
+ *
+ * @return config pointer Address.
+ */
+ static Config *Getinstance()
+ {
+ if (NULL == s_configinstance)
+ {
+ s_configinstance = new Config();
+ }
+
+ return s_configinstance;
+ }
+ std::string getPluginPath();
+ std::string getVersion();
+ std::string getValue(const std::string key);
+
+ private:
+ static Config *s_configinstance;
+ typedef std::map<std::string, std::string> configmap;
+ configmap m_configurationMap;
+ /**
+ * Constructor for Config.
+ * During construction time, configuration file will be loaded.
+ *
+ */
+ Config();
+
+ /**
+ * Virtual destructor
+ */
+ virtual ~Config(void);
+
+ /**
+ * delete Singleton pattern instance.
+ */
+ static void deleteinstance()
+ {
+ if (NULL != s_configinstance)
+ {
+ delete s_configinstance;
+ s_configinstance = NULL;
+ }
+ }
+ void setValue(const std::string key, const std::string value);
+ PMRESULT loadConfigFile(const std::string configfilepath);
+ PMRESULT parsing(std::vector<char> buffer, xml_document<> *doc);
+ PMRESULT getXmlData( xml_node<> *pluginInfo, std::string key);
+ };
+}
+
+#endif
\ No newline at end of file
m_context = cp_create_context(&m_status);
m_cp_plugins = nullptr;
m_plugin = nullptr;
- registerAllPlugin("../../../plugins");
+
+ config = Config::Getinstance();
+ std::string pluginpath = config->getPluginPath();
+ if (pluginpath != "")
+ {
+ printf("Current path is %s\n", pluginpath.c_str());
+ }
+ else
+ {
+ fprintf(stderr, "Pluing path does not exist\n");
+ pluginpath = "";
+ }
+ registerAllPlugin(pluginpath);
}
CpluffAdapter::~CpluffAdapter(void)
{
cp_release_info(m_context, m_cp_plugins);
- m_thread_g.interrupt_all();
- m_thread_g.join_all();
+ //Auto plugin detection is disabled
+ //m_thread_g.interrupt_all();
+ //m_thread_g.join_all();
s_pinstance->deleteinstance();
s_pinstance = nullptr;
}
}
else if ((m_status = cp_install_plugin(m_context, m_plugin)) != 0)
{
- printf("cp_install_plugin failed\n");
+ if (m_status == CP_ERR_CONFLICT)
+ {
+ printf("Plugin is already installed or conflicts symbol.\n");
+ }
+ printf("cp_install_plugin failed : %d \n" , m_status);
+
return false;
}
File_list file_list;
getFileList(file_list, path);
File_list::iterator itr;
- int flag = FALSE;
-
+ int flag = TRUE;
for (itr = file_list.begin(); itr != file_list.end(); itr++)
{
if (itr->second == true)
}
}
std::string filename = filepath.substr(0, count );
- //char *temp_char = const_cast<char *>(filename.c_str());
- flag = installPlugin(filename);
- //printf("plugin file path %s \n", plugin->plugin_path);
+ if (!installPlugin(filename))
+ {
+ printf("installPlugin failed path : %s \n", filename.c_str());
+ }
}
}
}
else
{
- printPluginList(m_cp_plugins);
+ printPluginList();
}
for (int i = 0 ; m_cp_plugins[i] != nullptr; i++)
}
if (plugin_compare_flag)
{
- m_plugins.push_back(*plugin);
+ //Auto plugin detection is disabled
+ /*
try
{
boost::thread *t = new boost::thread(boost::bind(&CpluffAdapter::observePluginPath,
{
printf("thread throw exception\n");
}
+ */
+ m_plugins.push_back(*plugin);
delete(plugin);
}
//printf("plugin size = %d\n",m_plugins.size());
}
//non recursive
-
- flag = installPlugin(path);
-
- flag = loadPluginInfoToManager(path);
-
+ if (installPlugin(path))
+ {
+ flag = loadPluginInfoToManager(path);
+ }
return flag;
}
}
//recursive
-
- flag = findPluginRecursive(path);
-
- flag = loadPluginInfoToManager(path);
-
+ if (findPluginRecursive(path))
+ {
+ flag = loadPluginInfoToManager(path);
+ }
return flag;
}
}
}
-void CpluffAdapter::printPluginList(cp_plugin_info_t **plugins)
+void CpluffAdapter::printPluginList()
{
const char format[] = " %-30s %-15s %-15s %-20s\n";
printf("\n====== Plugins List ======\n");
}
return FALSE;
}
-
+//Auto plugin detection is disabled
+/*
void CpluffAdapter::observePluginPath(void *str)
{
//printf("start observePluginPath\n");
( void ) close( fd );
//printf("observePluginPath end\n");
}
-
+*/
const std::string CpluffAdapter::getState(const std::string plugID)
{
return state_to_string(cp_get_plugin_state(m_context, plugID.c_str()));
#include <internal.h>
#include "Plugin.h"
+#include "Config.h"
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define BUF_LEN (int)( 1024 * ( EVENT_SIZE + 16 ) )
*/
const std::string getState(const std::string plugID);
+ /**
+ * print whole plugin info.
+ *
+ * @param cpluff plugins
+ */
+ void printPluginList();
+
/**
*
private:
+ Config *config;
typedef std::map<std::string, bool> File_list;
std::vector<Plugin> m_plugins;
cp_context_t *m_context;
cp_status_t m_status;
cp_plugin_info_t **m_cp_plugins;
cp_plugin_info_t *m_plugin;
- boost::thread m_file_detect_thread;
- boost::thread_group m_thread_g;
- std::string m_path;
+ //boost::thread_group m_thread_g;
static CpluffAdapter *s_pinstance;
/**
* @param plugin file path.
* @return void
*/
- void observePluginPath(void *);
+ //void observePluginPath(void *);
/**
bool getFileList(File_list &list, const std::string strDir);
/**
- * print whole plugin info.
- *
- * @param cpluff plugins
- */
- void printPluginList(cp_plugin_info_t **plugins);
-
- /**
* install plugin using c-pluff.
*
* @param Root path.
FelixAdapter::FelixAdapter()
{
-
+ config = Config::Getinstance();
+ std::string pluginpath = config->getPluginPath();
+ if (pluginpath != "")
+ {
+ printf("Current path is %s\n", pluginpath.c_str());
+ }
+ else
+ {
+ fprintf(stderr, "Pluing path is not exist\n");
+ pluginpath = "";
+ }
+ registerAllPlugin(pluginpath);
}
FelixAdapter::~FelixAdapter(void)
{
return FALSE;
}
-
+/*
void FelixAdapter::observePluginPath(void *str)
{
}
-
+*/
const std::string FelixAdapter::getState(const std::string plugID)
{
return "";
#include <internal.h>
#include "Plugin.h"
+#include "Config.h"
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define BUF_LEN (int)( 1024 * ( EVENT_SIZE + 16 ) )
private:
-
+ Config *config;
typedef std::map<std::string, bool> File_list;
std::vector<Plugin> m_plugins;
boost::thread m_file_detect_thread;
* @param plugin file path.
* @return void
*/
- void observePluginPath(void *);
+ //void observePluginPath(void *);
/**
* Get whole "SO" file list.
return false;
}
}
-
- std::vector<std::string> Plugin::getSupportedType(void)
- {
- return m_supportedType;
- }
-
- void Plugin::addSupportedType(const std::string rscType)
- {
- m_supportedType.push_back(rscType);
- }
}
*/
bool operator==(Plugin &plugin);
- /**
- * Get supported resourc type
- *
- *
- * @return vector of surported resource type
- */
- std::vector<std::string> getSupportedType(void);
- /**
- * Add supported resource type for a plugin
- *
- * @param resource type string
- * @return void
- *
- */
- void addSupportedType(const std::string rscType);
-
private:
std::map<std::string, AttributeValue> m_attributeMap;
std::vector<std::string> m_supportedType;
return pluginManagerImpl->stopPlugins(key, value);
}
-int PluginManager::startPlugins(Plugin *const plugin)
+int PluginManager::rescanPlugin()
{
- printf("PluginManager::startPlugins\n");
- return pluginManagerImpl->startPlugins(plugin);
+ return pluginManagerImpl->rescanPlugin();
}
-int PluginManager::stopPlugins(Plugin *const plugin)
+std::vector<Plugin> PluginManager::getPlugins(void)
{
- return pluginManagerImpl->stopPlugins(plugin);
+ return pluginManagerImpl->getAllPlugins();
}
-std::vector<Plugin> PluginManager::getPlugins(void)
+std::string PluginManager::getState(const std::string plugID)
{
- return pluginManagerImpl->getAllPlugins();
+ return pluginManagerImpl->getState(plugID);
}
\ No newline at end of file
int stopPlugins(const std::string key, const std::string value);
/**
- * Start plugin
- * This function will load dynamic plugin library on memory and call start function of plugin to be initialized.
+ * Rescan Plugin.
+ * This function will call rescan function of plugins in the configuration folder
*
* @param Plugin
* @return int, 1 is success, 0 is fail.
*/
- int startPlugins(Plugin *const plugin);
-
-
- /**
- * Stop Plugin.
- * This function will call stop function of plugin and unload dynamic plugin library from memory.
- *
- * @param Plugin
- * @return int, 1 is success, 0 is fail.
- */
- int stopPlugins(Plugin *const plugin);
+ int rescanPlugin();
/**
* Get Plugin list.
*/
std::vector<Plugin> getPlugins(void);
+ /**
+ * Get Plugin state.
+ *
+ * @param Plugin ID
+ * @return Plugin state.
+ */
+ std::string getState(const std::string plugID);
+
private:
PluginManagerImpl *pluginManagerImpl;
void (*destroy)(PluginManagerImpl *);
return flag;
}
+int PluginManagerImpl::rescanPlugin()
+{
+ Config *config = Config::Getinstance();
+ std::string pluginpath = config->getPluginPath();
+ if (pluginpath != "")
+ {
+ printf("Current path is %s\n", pluginpath.c_str());
+ }
+ else
+ {
+ fprintf(stderr, "Pluing path does not exist\n");
+ pluginpath = "";
+ }
+ int result = registerAllPlugin(pluginpath);
+ return result;
+}
+
std::vector<Plugin> &PluginManagerImpl::getAllPlugins(void)
{
* @param Plugin ID
* @return Plugin state.
*/
- std::string getState(const std::string plugID);
+ virtual std::string getState(const std::string plugID);
/**
* Start plugins by resource type
* @param Plugin
* @return int, 1 is success, 0 is fail.
*/
- virtual int startPlugins(Plugin *const plugin);
+ int startPlugins(Plugin *const plugin);
/**
* @param Plugin
* @return int, 1 is success, 0 is fail.
*/
- virtual int stopPlugins(Plugin *const plugin);
+ int stopPlugins(Plugin *const plugin);
+
+ /**
+ * Rescan Plugin.
+ * This function will call rescan function of plugins in the configuration folder
+ *
+ * @param Plugin
+ * @return int, 1 is success, 0 is fail.
+ */
+ virtual int rescanPlugin();
/**
* get all plugins which currently registered.
--- /dev/null
+##
+# Plugins build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+plugins_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+plugins_env.AppendUnique(CPPPATH = ['../lib/cpluff/libcpluff'])
+
+if target_os not in ['windows', 'winrt']:
+ plugins_env.AppendUnique(CXXFLAGS = ['-g3', '-Wall', '-pthread', '-std=c++0x'])
+ plugins_env.AppendUnique(LINKFLAGS = ['-fPIC'])
+
+ if target_os not in ['arduino', 'android']:
+ plugins_env.AppendUnique(LIBS = ['pthread'])
+
+if target_os == 'android':
+ plugins_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+ plugins_env.AppendUnique(LIBS = ['gnustl_static'])
+ plugins_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+mqtt_fan_src = Glob('mqtt-fan/src/' + '*.cpp')
+fanserver = plugins_env.SharedLibrary('fanserver_mqtt_plugin', mqtt_fan_src)
+
+mqtt_light_src = Glob('mqtt-light/src/' + '*.cpp')
+lightserver = plugins_env.SharedLibrary('lightserver_mqtt_plugin', mqtt_light_src)
+
+SConscript('mqtt-fan/lib/SConscript')
-include ../../../../config.mk
-
CXX = g++
CXX_FLAGS = -std=c++0x -Wall -pthread
+TOP_DIR = ../../../../../..
LIB_DIR = ../../../../../../resource
SRC_DIR = ../../src
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
CXX_INC := -I$(LIB_DIR)/include/
CXX_INC += -I$(LIB_DIR)/oc_logger/include/
CXX_INC += -I$(LIB_DIR)/csdk/stack/include/
CXX_INC += -I$(BOOST_DIR)
CXX_INC += -I../../lib
CXX_INC += -I../../../../lib/cpluff/libcpluff
+CXX_INC += -I../csdk/libcoap
+CXX_INC += -I$(CEREAL_DIR)/include
LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
-CXX_LIBS := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
+CXX_LIBS := ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
.PHONY: lib release_build ./release/fanserver_mqtt_plugin.so
cp plugin.xml release
./release/fanserver_mqtt_plugin.so: ./release/obj/fanserver_mqtt_plugin.o ./release/obj/fanserver.o
- $(CXX) -shared -o ./release/fanserver_mqtt_plugin.so ./release/obj/fanserver_mqtt_plugin.o ./release/obj/fanserver.o $(CXX_LIBS) -L../../lib -lmosquitto -lssl -lrt
+ $(CXX) -shared -o ./release/fanserver_mqtt_plugin.so ./release/obj/fanserver_mqtt_plugin.o ./release/obj/fanserver.o $(CXX_LIBS) -L../../lib -L$(TOP_DIR)/out/linux/x86/release -lmosquitto -lssl -lrt -loc -loctbstack -loc_logger -lcoap
./release/obj/fanserver_mqtt_plugin.o: $(SRC_DIR)/fanserver_mqtt_plugin.cpp
$(CXX) $(CXX_INC) -fPIC -o ./release/obj/fanserver_mqtt_plugin.o -c $(SRC_DIR)/fanserver_mqtt_plugin.cpp
-include config.mk
+include config.mk
.PHONY : really clean install
--- /dev/null
+##
+# mosquitto build script
+##
+import platform,os
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+mosquitto_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+mosquitto_env.AppendUnique(CPPPATH = ['./'])
+if target_os not in ['windows', 'winrt']:
+ mosquitto_env.AppendUnique(CFLAGS = ['-Wall', '-ggdb', '-fPIC',
+ '-DWITH_TLS', '-DWITH_TLS_PSK', '-DWITH_THREADING'])
+######################################################################
+# Source files and Targets
+######################################################################
+mosquitto_src = env.Glob('*.c')
+
+mosquitto = mosquitto_env.StaticLibrary('mosquitto', mosquitto_src)
+mosquitto_env.InstallTarget(mosquitto, 'libmosquitto')
+
+SConscript('cpp/SConscript')
--- /dev/null
+##
+# mosquittopp build script
+##
+import platform,os
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+mosquittopp_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+mosquittopp_env.AppendUnique(CPPPATH = ['./', '../'])
+if target_os not in ['windows', 'winrt']:
+ mosquittopp_env.AppendUnique(CFLAGS = ['-Wall', '-ggdb', '-O2', '-fPIC'])
+
+mosquittopp_env.AppendUnique(LIBS = ['mosquitto', 'ssl', 'crypto'])
+######################################################################
+# Source files and Targets
+######################################################################
+mosquittopp = mosquittopp_env.SharedLibrary('mosquittopp', 'mosquittopp.cpp')
+mosquittopp_env.InstallTarget(mosquittopp, 'libmosquittopp')
-include ../config.mk
-
# Set DESTDIR if it isn't given
DESTDIR?=/
int gObservation = 0;
void *ChangeFanRepresentation (void *param);
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
// Specifies where to notify all observers or list of observers
-// 0 - notifies all observers
-// 1 - notifies list of observers
-int isListOfObservers = 0;
-
-// Forward declaring the entityHandler
-
-/// This class represents a single resource named 'fanResource'. This resource has
-/// two simple properties named 'state' and 'power'
+// false: notifies all observers
+// true: notifies list of observers
+bool isListOfObservers = false;
+// Specifies secure or non-secure
+// false: non-secure resource
+// true: secure resource
+bool isSecure = false;
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
// Forward declaring the entityHandler
-// void entityHandler(std::shared_ptr<OCResourceRequest> request,
-// std::shared_ptr<OCResourceResponse> response);
-
/// This class represents a single resource named 'fanResource'. This resource has
/// two simple properties named 'state' and 'power'
typedef struct plugin_data_t plugin_data_t;
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
- EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1);
// This will internally create and register the resource.
OCStackResult result = OCPlatform::registerResource(
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
- EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1);
OCResourceHandle resHandle;
private:
// This is just a sample implementation of entity handler.
// Entity handler can be implemented in several ways by the manufacturer
- OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
- OCEntityHandlerResult result = OC_EH_OK;
-
cout << "\tIn Server CPP entity handler:\n";
-
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if (request)
{
// Get the request type and request flag
}
if (requestFlag & RequestHandlerFlag::RequestFlag)
{
- cout << "\t\trequestFlag : Request === Handle by FanServer\n";
+ cout << "\t\trequestFlag : Request === Handle by FanServer\n";
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
// If the request type is GET
if (requestType == "GET")
{
cout << "\t\t\trequestType : GET\n";
-
- if (response)
+ if (isSlowResponse) // Slow response case
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(get());
+ static int startedThread = 0;
+ if (!startedThread)
+ {
+ std::thread t(handleSlowResponse, (void *)this, request);
+ startedThread = 1;
+ t.detach();
+ }
+ ehResult = OC_EH_SLOW;
+ }
+ else // normal response case.
+ {
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(get());
+ if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
}
}
else if (requestType == "PUT")
{
cout << "\t\t\trequestType : PUT\n";
-
OCRepresentation rep = request->getResourceRepresentation();
// Do related operations related to PUT request
-
// Update the fanResource
put(rep);
-
- if (response)
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(get());
+ if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(get());
+ ehResult = OC_EH_OK;
}
-
}
else if (requestType == "POST")
{
OCRepresentation rep = request->getResourceRepresentation();
// Do related operations related to POST request
-
OCRepresentation rep_post = post(rep);
-
- if (response)
+ pResponse->setResourceRepresentation(rep_post);
+ pResponse->setErrorCode(200);
+ if (rep_post.hasAttribute("createduri"))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(rep_post);
-
- if (rep_post.hasAttribute("createduri"))
- {
- result = OC_EH_RESOURCE_CREATED;
-
- response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
- }
-
+ pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+ pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
}
- // POST request operations
+ if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
}
else if (requestType == "DELETE")
{
pthread_create (&threadId, NULL, ChangeFanRepresentation, (void *)this);
startedThread = 1;
}
+ ehResult = OC_EH_OK;
}
}
else
std::cout << "Request invalid" << std::endl;
}
- return result;
+ return ehResult;
}
};
return NULL;
}
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+ // This function handles slow response case
+ FanResource *fanPtr = (FanResource *) param;
+ // Induce a case for slow response by using sleep
+ std::cout << "SLOW response" << std::endl;
+ sleep (10);
+
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+ pResponse->setResourceRepresentation(fanPtr->get());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ // Set the slow response flag back to false
+ isSlowResponse = false;
+ OCPlatform::sendResponse(pResponse);
+ return NULL;
+}
+
//int start_fanserver(void*) // 1
void *start_fanserver(void *d) // 2
{
- /*PlatformConfig cfg;
- cfg.ipAddress = "192.168.2.5";
- cfg.port = 56832;
- cfg.mode = ModeType::Server;
- cfg.serviceType = ServiceType::InProc;*/
- // PlatformConfig cfg
- // {
- // OC::ServiceType::InProc,
- // OC::ModeType::Server,
- // "192.168.2.5",
- // 56832,
- // OC::QualityOfService::NonConfirmable
- // };
-
- // Create PlatformConfig object
-
- // Create a OCPlatform instance.
- // Note: Platform creation is synchronous call.
-
// Create PlatformConfig object
PlatformConfig cfg
{
OC::ServiceType::InProc,
- OC::ModeType::Server,
+ OC::ModeType::Both,
"0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
0, // Uses randomly available port
OC::QualityOfService::LowQos
printf("Mosquitto is working\n");
}
- //plugin_data_t *data = (plugin_data_t *)d;
- //OCPlatform *platform = (OCPlatform*)data->str;
- //myFanResource.m_platform = (OCPlatform*)data->str;
- //OCPlatform platform(cfg);
- // Invoke createResource function of class fan.
-
- //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
printf("Mosquitto Connection is done\n");
myFanResource.createResource();
- //myFanResource.addType(std::string("core.fan"));
- //myFanResource.addInterface(std::string("oc.mi.ll"));
// Get time of day
timer = time(NULL);
// Converts date/time to a structure
-include ../../../../config.mk
-
CXX = g++
CXX_FLAGS = -std=c++0x -Wall -pthread
+TOP_DIR = ../../../../../..
LIB_DIR = ../../../../../../resource
SRC_DIR = ../../src
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
CXX_INC := -I$(LIB_DIR)/include/
CXX_INC += -I$(LIB_DIR)/oc_logger/include/
CXX_INC += -I$(LIB_DIR)/csdk/stack/include/
CXX_INC += -I$(BOOST_DIR)
CXX_INC += -I../../lib
CXX_INC += -I../../../../lib/cpluff/libcpluff
+CXX_INC += -I../csdk/libcoap
+CXX_INC += -I$(CEREAL_DIR)/include
LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
-CXX_LIBS := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
+CXX_LIBS := ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
.PHONY: lib release_build ./release/lightserver_mqtt_plugin.so
cp plugin.xml release
./release/lightserver_mqtt_plugin.so: ./release/obj/lightserver_mqtt_plugin.o ./release/obj/lightserver.o
- $(CXX) -shared -o ./release/lightserver_mqtt_plugin.so ./release/obj/lightserver_mqtt_plugin.o ./release/obj/lightserver.o $(CXX_LIBS) -L../../lib -lmosquitto -lssl -lrt
+ $(CXX) -shared -o ./release/lightserver_mqtt_plugin.so ./release/obj/lightserver_mqtt_plugin.o ./release/obj/lightserver.o $(CXX_LIBS) -L../../lib -L$(TOP_DIR)/out/linux/x86/release -lmosquitto -lssl -lrt -loc -loctbstack -loc_logger -lcoap
./release/obj/lightserver_mqtt_plugin.o: $(SRC_DIR)/lightserver_mqtt_plugin.cpp
$(CXX) $(CXX_INC) -fPIC -o ./release/obj/lightserver_mqtt_plugin.o -c $(SRC_DIR)/lightserver_mqtt_plugin.cpp
-include config.mk
+include config.mk
.PHONY : really clean install
-include ../config.mk
-
# Set DESTDIR if it isn't given
DESTDIR?=/
int gObservation = 0;
void *ChangeLightRepresentation (void *param);
-
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
// Specifies where to notify all observers or list of observers
-// 0 - notifies all observers
-// 1 - notifies list of observers
-int isListOfObservers = 0;
-
-// Forward declaring the entityHandler
-
-/// This class represents a single resource named 'lightResource'. This resource has
-/// two simple properties named 'state' and 'power'
+// false: notifies all observers
+// true: notifies list of observers
+bool isListOfObservers = false;
+// Specifies secure or non-secure
+// false: non-secure resource
+// true: secure resource
+bool isSecure = false;
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
// Forward declaring the entityHandler
// void entityHandler(std::shared_ptr<OCResourceRequest> request,
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
- EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1);
// This will internally create and register the resource.
OCStackResult result = OCPlatform::registerResource(
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
- EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
+ EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1);
OCResourceHandle resHandle;
private:
// This is just a sample implementation of entity handler.
// Entity handler can be implemented in several ways by the manufacturer
- OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
- std::shared_ptr<OCResourceResponse> response)
+ OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
{
- OCEntityHandlerResult result = OC_EH_OK;
-
cout << "\tIn Server CPP entity handler:\n";
-
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
if (request)
{
// Get the request type and request flag
}
if (requestFlag & RequestHandlerFlag::RequestFlag)
{
- cout << "\t\trequestFlag : Request === Handle by LightServer\n";
+ cout << "\t\trequestFlag : Request === Handle by FanServer\n";
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(request->getRequestHandle());
+ pResponse->setResourceHandle(request->getResourceHandle());
// If the request type is GET
if (requestType == "GET")
{
cout << "\t\t\trequestType : GET\n";
-
- if (response)
+ if (isSlowResponse) // Slow response case
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(get());
+ static int startedThread = 0;
+ if (!startedThread)
+ {
+ std::thread t(handleSlowResponse, (void *)this, request);
+ startedThread = 1;
+ t.detach();
+ }
+ ehResult = OC_EH_SLOW;
+ }
+ else // normal response case.
+ {
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(get());
+ if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
}
}
else if (requestType == "PUT")
{
cout << "\t\t\trequestType : PUT\n";
-
OCRepresentation rep = request->getResourceRepresentation();
// Do related operations related to PUT request
-
// Update the lightResource
put(rep);
-
- if (response)
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+ pResponse->setResourceRepresentation(get());
+ if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(get());
+ ehResult = OC_EH_OK;
}
-
}
else if (requestType == "POST")
{
OCRepresentation rep = request->getResourceRepresentation();
// Do related operations related to POST request
-
OCRepresentation rep_post = post(rep);
-
- if (response)
+ pResponse->setResourceRepresentation(rep_post);
+ pResponse->setErrorCode(200);
+ if (rep_post.hasAttribute("createduri"))
{
- // TODO Error Code
- response->setErrorCode(200);
-
- response->setResourceRepresentation(rep_post);
-
- if (rep_post.hasAttribute("createduri"))
- {
- result = OC_EH_RESOURCE_CREATED;
-
- response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
- }
-
+ pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+ pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
}
- // POST request operations
+ if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+ {
+ ehResult = OC_EH_OK;
+ }
}
else if (requestType == "DELETE")
{
pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
startedThread = 1;
}
+ ehResult = OC_EH_OK;
}
}
else
std::cout << "Request invalid" << std::endl;
}
- return result;
+ return ehResult;
}
};
return NULL;
}
-
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+ // This function handles slow response case
+ LightResource *lightPtr = (LightResource *) param;
+ // Induce a case for slow response by using sleep
+ std::cout << "SLOW response" << std::endl;
+ sleep (10);
+
+ auto pResponse = std::make_shared<OC::OCResourceResponse>();
+ pResponse->setRequestHandle(pRequest->getRequestHandle());
+ pResponse->setResourceHandle(pRequest->getResourceHandle());
+ pResponse->setResourceRepresentation(lightPtr->get());
+ pResponse->setErrorCode(200);
+ pResponse->setResponseResult(OC_EH_OK);
+
+ // Set the slow response flag back to false
+ isSlowResponse = false;
+ OCPlatform::sendResponse(pResponse);
+ return NULL;
+}
//int start_lightserver(void*) // 1
void *start_lightserver(void *d) // 2
{
- /*PlatformConfig cfg;
- cfg.ipAddress = "192.168.2.5";
- cfg.port = 56832;
- cfg.mode = ModeType::Server;
- cfg.serviceType = ServiceType::InProc;*/
- // PlatformConfig cfg
- // {
- // OC::ServiceType::InProc,
- // OC::ModeType::Server,
- // "192.168.2.5",
- // 56832,
- // OC::QualityOfService::NonConfirmable
- // };
-
- // Create PlatformConfig object
-
- // Create a OCPlatform instance.
- // Note: Platform creation is synchronous call.
-
// Create PlatformConfig object
PlatformConfig cfg
{
OC::ServiceType::InProc,
- OC::ModeType::Server,
+ OC::ModeType::Both,
"0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
0, // Uses randomly available port
OC::QualityOfService::LowQos
printf("Mosquitto is working\n");
}
- //plugin_data_t *data = (plugin_data_t *)d;
- //OCPlatform *platform = (OCPlatform*)data->str;
- //myLightResource.m_platform = (OCPlatform*)data->str;
- //OCPlatform platform(cfg);
- // Invoke createResource function of class light.
-
- //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
printf("Mosquitto Connection is done\n");
myLightResource.createResource();
- //myLightResource.addType(std::string("core.light"));
- //myLightResource.addInterface(std::string("oc.mi.ll"));
// Get time of day
timer = time(NULL);
// Converts date/time to a structure
+This guide will help you setup your developing environment for Protocol plug-in Manager and Protocol plug-ins in Ubuntu.
+
+1. Preparings
+Before starting, following tools should be installed.
+
+Automake
+Automake is a tool for automatically generating Makefile.in files compiliant with the GNU Coding Standards. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+$ sudo apt-get install automake
+
+Libtool
+GNU libtool is a generic library support script. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+ $ sudo apt-get install libtool
+
+gettext
+GNU `gettext' utilities are a set of tools that provides a framework to help other GNU packages produce multi-lingual messages. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+ $ sudo apt-get install gettext
+
+Expat
+Expat is a stream-oriented XML parser library. This library is used for compiling C-Pluff open source which used in Plug-in Manager.
+ $ sudo apt-get install expat
+
+Building and Using Protocol Plug-in Manager
+
+Once the source code is downloaded into a specific folder, oic in this context, you may follow the steps to build and execute Protocol Plug-in Manager.
+The path for Protocol Plugin is as following;
+
+~/oic/oic-resource/service/protocol-plugin $_
+
+
+The Protocol Plug-in directory includes following sub directories;
+
+/plugin-manager Directory for Plug-in Manager
+/plugins Directory for Reference Plugins
+/lib Directory for Common Library
+/sample-app Directory for Iotivity Sample Application
+/doc Directory for Developers Document
+/build Directory for Building and Binary Release
+
+
+2. Compiling C-Pluff library
+Before building Protocol-Plugin Manager, C-Pluff library should be compiled as follows.
+
+~/oic/oic-service/protocol-plugin/lib/cpluff$ aclocal
+~/oic/oic-service/protocol-plugin/lib/cpluff$ autoconf
+~/oic/oic-service/protocol-plugin/lib/cpluff$ autoheader
+~/oic/oic-service/protocol-plugin/lib/cpluff$ automake
+~/oic/oic-service/protocol-plugin/lib/cpluff$ ./configure
+~/oic/oic-service/protocol-plugin/lib/cpluff$ make
+
+
+3. Run make
+By running make in the protocol-plugin path, protocol-plugin manager, all plugins and sample applications will be created.
+
+NOTE: To build plugins in 64-bit Ubuntu Linux, OCLib.a and libcoap.a library should be re-compiled with ?fPIC option.
+
+~/oic/oic-service/protocol-plugin/build/linux$make
+
+
+4. Using Plugins
This version of protocol plug-in source code has following functionality.
-1. provides plug-in manager which can register, unregister, start and stop plug-in library.
-2. provides plug-in library which can communicate with MQTT protocol FAN.
-3. provides OIC Sample Client which can turn on/off FAN.
+1) provides plug-in manager which can start and stop plug-in library.
+2) provides plug-in library which can communicate with MQTT protocol Fan and Light.
+3) provides OIC Sample Client which can get info about Fan and Light with configuration file(pluginmanager.xml).
So, to test a plug-in, follow below steps.
-1. Locate shared plug-in library and XML file in a specific folder.
-2. Register the plug-in with directory path input from plug-in manager sample.
-3. Start the plug-in from plug-in manager sample.
-4. Run OIC sample client.
-
-If you have any questions about protocol plug-in component, please contact with following addresses.
+1) Locate shared plug-in library and XML file in a specific folder.
+2) Register the plug-in with directory path input from plug-in manager sample.
+3) Start the plug-in from plug-in manager sample.
+4) Run OIC sample client.
+ ex)service/protocol-plugin/sample-app/linux/mqtt$./mqttclient
+ (mqtt broker is already installed in the local system.)
-kc7576.park@samsung.com
-heesung84.kim@samsung.com
-junho13.lee@samsung.com
-yh_.joo@samsung.com
\ No newline at end of file
--- /dev/null
+##
+#sample-app build script
+##
+
+Import('env')
+
+target_os = env.get('TARGET_OS')
+
+if target_os == 'linux':
+ SConscript('linux/SConscript')
--- /dev/null
+##
+#sample-app build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+sample_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+sample_env.AppendUnique(CPPPATH = ['../../plugin-manager/src/',
+ '../../lib/cpluff/libcpluff/'])
+if target_os not in ['windows', 'winrt']:
+ sample_env.AppendUnique(CXXFLAGS = ['-Wall', '-pthread', '-std=c++0x'])
+
+sample_env.AppendUnique(LIBS = ['oc', 'oc_logger', 'octbstack', 'coap', 'ppm', 'pmimpl', 'dl'])
+######################################################################
+# Source files and Targets
+######################################################################
+fanclient = sample_env.Program('fanclient', 'fan-control/fanclient.cpp')
+
+Alias('fanclient', fanclient)
+env.AppendTarget('fanclient')
\ No newline at end of file
+++ /dev/null
-CXX = g++
-
-CXX_FLAGS = -std=c++0x -Wall -pthread
-
-LIB_DIR = ../../../../../resource
-
-CXX_INC := -I$(LIB_DIR)/include/
-CXX_INC += -I$(LIB_DIR)/oc_logger/include/
-CXX_INC += -I$(LIB_DIR)/csdk/stack/include/
-CXX_INC += -I$(LIB_DIR)/csdk/ocsocket/include/
-CXX_INC += -I$(LIB_DIR)/csdk/ocrandom/include/
-CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
-CXX_INC += -I$(BOOST_DIR)
-CXX_INC += -I../../lib
-CXX_INC += -I../../../lib/cpluff/libcpluff
-CXX_INC += -I../../../plugin-manager/src
-
-LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
-CXX_LIBS := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../build/linux/release/libppm.a ../../../lib/cpluff/libcpluff/.libs/libcpluff.a
-LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread
-
-.PHONY: fanclient
-
-all: .PHONY
-
-fanclient: fanclient.o
- $(CXX) $(CXX_FLAGS) -o fanclient fanclient.o $(CXX_LIBS) $(LINK_LIB)
-
-fanclient.o: fanclient.cpp
- $(CXX) $(CXX_FLAGS) -c fanclient.cpp $(CXX_INC)
-
-
-clean:
- rm -f *.o
- rm -f fanclient
--- /dev/null
+CXX = g++
+
+CXX_FLAGS = -std=c++0x -Wall -pthread
+
+TOP_DIR = ../../../../..
+LIB_DIR = ../../../../../resource
+
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
+CXX_INC := -I$(LIB_DIR)/include/
+CXX_INC += -I$(LIB_DIR)/oc_logger/include/
+CXX_INC += -I$(LIB_DIR)/csdk/stack/include/
+CXX_INC += -I$(LIB_DIR)/csdk/ocsocket/include/
+CXX_INC += -I$(LIB_DIR)/csdk/ocrandom/include/
+CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
+CXX_INC += -I$(BOOST_DIR)
+CXX_INC += -I../../lib
+CXX_INC += -I../../../lib/cpluff/libcpluff
+CXX_INC += -I../../../plugin-manager/src
+CXX_INC += -I$(CEREAL_DIR)/include
+CXX_INC += -I../../../lib/rapidxml
+
+LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
+CXX_LIBS := ../../../build/linux/release/libppm.a ../../../lib/cpluff/libcpluff/.libs/libcpluff.a
+LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread -L$(TOP_DIR)/out/linux/x86/release -loc -loctbstack -loc_logger -lcoap
+
+.PHONY: mqttclient
+
+all: .PHONY
+
+mqttclient: mqttclient.o
+ $(CXX) $(CXX_FLAGS) -o mqttclient mqttclient.o $(CXX_LIBS) $(LINK_LIB)
+
+mqttclient.o: mqttclient.cpp
+ $(CXX) $(CXX_FLAGS) -c mqttclient.cpp $(CXX_INC)
+
+
+clean:
+ rm -f *.o
+ rm -f *.so
+ rm -f mqttclient
using namespace OC;
using namespace OIC;
-std::shared_ptr<OCResource> curResource;
+std::shared_ptr<OCResource> curFanResource;
+std::shared_ptr<OCResource> curLightResource;
static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
time_t timer; // Define the timer
if (observe_count() > 30)
{
std::cout << "Cancelling Observe..." << std::endl;
- OCStackResult result = curResource->cancelObserve();
+ OCStackResult result = curFanResource->cancelObserve();
std::cout << "Cancel result: " << result << std::endl;
sleep(10);
else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
std::cout << endl << "ObserveAll is used." << endl << endl;
- curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
+ //curFanResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
}
else
rep2.setValue("state", myfan.m_state);
rep2.setValue("power", myfan.m_power);
- curResource->post(rep2, QueryParamsMap(), &onPost2);
+ curFanResource->post(rep2, QueryParamsMap(), &onPost2);
}
else
{
std::cout << "\tpower: " << myfan.m_power << std::endl;
std::cout << "\tname: " << myfan.m_name << std::endl;
- postFanRepresentation(curResource);
+ postFanRepresentation(curFanResource);
}
else
{
std::cout << "\tpower: " << myfan.m_power << std::endl;
std::cout << "\tname: " << myfan.m_name << std::endl;
- putFanRepresentation(curResource);
+ putFanRepresentation(curFanResource);
}
else
{
// Callback to found resources
void foundResourceFan(std::shared_ptr<OCResource> resource)
{
- if (curResource)
+ if (curFanResource)
{
std::cout << "Found another resource, ignoring" << std::endl;
}
if (resourceURI == "/a/fan")
{
- curResource = resource;
+ curFanResource = resource;
// Call a local function which will internally invoke get API on the resource pointer
getFanRepresentation(resource);
}
// Callback to found resources
void foundResourceLight(std::shared_ptr<OCResource> resource)
{
- if (curResource)
+ if (curLightResource)
{
std::cout << "Found another resource, ignoring" << std::endl;
}
if (resourceURI == "/a/light")
{
- curResource = resource;
+ curLightResource = resource;
// Call a local function which will internally invoke get API on the resource pointer
getLightRepresentation(resource);
}
std::cout << "Finding Fan Resource... time : " << asctime(tblock) << std::endl;
while (1)
{
- // client1 related operations
+ std::cout << "Get Fan Resource....." << std::endl;
+ sleep(5);
+ getFanRepresentation(curFanResource);
}
}
while (1)
{
- // client2 related operations
+ std::cout << "Get Light Resource....." << std::endl;
+ sleep(5);
+ getLightRepresentation(curLightResource);
}
}
int main(int argc, char *argv[])
{
+ std::string name;
+ std::string key = "Name";
+ std::string state = "";
+ std::string id = "";
+
if (argc == 1)
{
OBSERVE_TYPE_TO_USE = ObserveType::Observe;
std::cout << "Created Platform..." << std::endl;
-
PluginManager *m_pm = new PluginManager();
+ std::cout << "==== 1st TEST CASE ===" << std::endl;
std::cout << "======================" << std::endl;
-
std::cout << "start light Plugin by Resource Type" << std::endl;
+
m_pm->startPlugins("ResourceType", "oic.light");
sleep(2);
+ std::cout << "\n==== 2nd TEST CASE =====" << std::endl;
std::cout << "======================" << std::endl;
- std::cout << "get Plugin List" << std::endl;
+ std::cout << "Get Plugin List\n" << std::endl;
std::vector<Plugin> user_plugin;
+
user_plugin = m_pm->getPlugins();
+
for (unsigned int i = 0; i < user_plugin.size(); i++)
{
- printf("value Name = %s\n", user_plugin[i].getName().c_str());
- printf("value ID = %s\n", user_plugin[i].getID().c_str());
+ std::cout << "value Name = " << user_plugin[i].getName() << std::endl;
+ std::cout << "value ID = " << user_plugin[i].getID() << std::endl;
+ id = user_plugin[i].getID();
}
-
+ std::cout << "\n===== 3rd TEST CASE =====" << std::endl;
std::cout << "======================" << std::endl;
- std::cout << "start Fan Plugin by Name" << std::endl;
- m_pm->startPlugins("Name", "mqtt-fan");
+ std::cout << "Start Fan Plugin by Name\n" << std::endl;
+
+ name = user_plugin[0].getName().c_str();
+ m_pm->startPlugins(key, name);
+
+ sleep(5);
+
+ std::cout << "\n====== 4th TEST CASE ======" << std::endl;
+ std::cout << "========================" << std::endl;
+ std::cout << "Get Plugin Status\n" << std::endl;
+
+ state = m_pm->getState(id);
+ std::cout << "last plugin status : " << state << std::endl;
+ std::cout << "sleep 15 seconds please add new plugin in the plugin folder " << std::endl;
+ sleep(15);
+
+ std::cout << "\n==== 5th TEST CASE ====" << std::endl;
+ std::cout << "========================" << std::endl;
+ std::cout << "Rescan Plugins.........\n" << std::endl;
+
+ m_pm->rescanPlugin();
+
+ std::cout << "\n==== 6th TEST CASE ====" << std::endl;
+ std::cout << "========================" << std::endl;
+ std::cout << "Try to start new resource type.........\n" << std::endl;
+ std::cout << "start oic.test resource" << std::endl;
+
+ sleep(5);
+
+ int flag = m_pm->startPlugins("ResourceType", "oic.test");
+
+ if (!flag)
+ std::cout << "There are no resouce type. Start plugin failed" << std::endl;
// Start each client in a seperate thread
-// std::thread t1(client1);
-// t1.detach();
-///*
-// sleep(5);
+ sleep(10);
+
+ std::cout << "\n====== 7th TEST CASE =======" << std::endl;
+ std::cout << "========================" << std::endl;
+ std::cout << " start client to find resource" << std::endl;
+
+ std::thread t1(client1);
+ t1.detach();
+
+ sleep(5);
+
// Start each client in a seperate thread
-// std::thread t2(client2);
-// t2.detach();
-//*/
+ std::thread t2(client2);
+ t2.detach();
+
while (true)
{
// some operations
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<pluginManager>
+ <pluginInfo
+ pluginPath="../../../plugins"
+ maxMEM="64M"
+ maxPlugin=""
+ version="1.0"
+ name="pluginmanager">
+ </pluginInfo>
+ <specailpluginInfo>
+ </specailpluginInfo>
+</pluginManager>
--- /dev/null
+##
+# soft-sensor-manager project build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+soft_sensor_manager_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+# As in the source code, it includes arduino Time library (C++)
+# It requires compile the .c with g++
+if target_os == 'arduino':
+ soft_sensor_manager_env.Replace(CC = env.get('CXX'))
+ soft_sensor_manager_env.Replace(CFLAGS = env.get('CXXFLAGS'))
+
+######################################################################
+# Build flags
+######################################################################
+if target_os not in ['windows', 'winrt']:
+ soft_sensor_manager_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-DLINUX'])
+ if target_os != 'android':
+ soft_sensor_manager_env.AppendUnique(CXXFLAGS = ['-pthread'])
+
+#######################################################################
+## build SSM SDK
+#######################################################################
+sdk_env = soft_sensor_manager_env.Clone()
+sdk_env.AppendUnique(CPPPATH = ['SSMCore/include'])
+sdk_env.AppendUnique(CPPPATH = ['SSMCore/src'])
+sdk_env.AppendUnique(CPPPATH = ['SDK/include'])
+
+ssm_sdk_cpp_src = [
+ Glob('SDK/src/*.cpp')
+ ]
+
+env.AppendTarget('libSSMSDK')
+libssmsdk = sdk_env.StaticLibrary(
+ target = 'libSSMSDK',
+ source = [ssm_sdk_cpp_src]
+ )
+sdk_env.InstallTarget(libssmsdk, 'libSSMCORE')
+
+######################################################################
+# build DiscomfortIndexSensor plugin
+######################################################################
+DiscomfortIndexSensor_env = soft_sensor_manager_env.Clone()
+
+DiscomfortIndexSensor_env.AppendUnique(CCFLAGS = ['-fPIC'])
+DISCOMFORTINDEXSENSOR_DIR = 'SoftSensorPlugin/DiscomfortIndexSensor/'
+DiscomfortIndexSensor_env.AppendUnique(CPPPATH = [
+ DISCOMFORTINDEXSENSOR_DIR + 'include',
+ 'SSMCore/src/SSMInterface/'
+ ])
+
+DiscomfortIndexSensor_src = [ Glob(DISCOMFORTINDEXSENSOR_DIR + 'src/*.cpp')]
+
+DiscomfortIndexSensor = DiscomfortIndexSensor_env.SharedLibrary('DiscomfortIndexSensor', DiscomfortIndexSensor_src)
+DiscomfortIndexSensor_env.InstallTarget(DiscomfortIndexSensor, 'libDiscomfortIndexSensor')
+
+######################################################################
+# build SSM CORE
+######################################################################
+ssmcore_env = soft_sensor_manager_env.Clone()
+
+ssmcore_env.AppendUnique(CPPPATH = [
+ 'SSMCore/include/',
+ 'SSMCore/src/',
+ 'SSMCore/src/Common/'
+ 'SSMCore/src/QueryProcessor/'
+ 'SSMCore/src/SensorProcessor/'
+ 'SSMCore/src/SSMInterface/'
+ ])
+
+import os.path
+
+if target_os != 'android':
+ SSMINTERFACE_PATH = 'SSMCore/src/SSMInterface/'
+ omit_src = ['SSMCore_JNI.cpp']
+ ssminterface_src = [f for f in env.Glob(SSMINTERFACE_PATH + '*.cpp') if os.path.basename(f.path) not in omit_src]
+else :
+ ssminterface_src = Glob(SSMINTERFACE_PATH + '*.cpp')
+
+ssm_core_cpp_src = [
+ Glob('SSMCore/src/Common/*.cpp'),
+ Glob('SSMCore/src/QueryProcessor/*.cpp'),
+ Glob('SSMCore/src/SensorProcessor/*.cpp'),
+ ssminterface_src,
+ ]
+
+ssm_core_c_src = [
+ 'SSMCore/src/Common/sqlite3.c'
+]
+
+libssmcore = ssmcore_env.StaticLibrary(
+ target = 'SSMCore',
+ source = [ssm_core_cpp_src, ssm_core_c_src]
+ )
+
+ssmcore_env.InstallTarget(libssmcore, 'libSSMCORE')
+
+#######################################################################
+## build SampleApp
+#######################################################################
+SConscript('SampleApp/SConscript')
\ No newline at end of file
-
+-include ../../../build/linux/root_path.inc
-include ../../../build/linux/environment.mk
BOOST=${BOOST_BASE}
INC_PATH=../../include
RST_NAME=release
+GAR=ar
+
# Insert your project name.
-TARGET=SDKlib
+TARGET=${SSM_LIB}
CXX=g++
CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX
-CXX_INC=-I../../ -I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I../../ -I${INC_PATH}/ -I${FD_SSMCORE}/include -I${FD_SSMCORE}/src -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
CXX_LIB=
SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
@echo " "
${TARGET}: ${OBJLIST}
- @cp -Rdp ./*.o ./${RST_NAME}/
+ ${GAR} -r ./${RST_NAME}/$@ ./*.o
@cp -Rdp ${INC_PATH}/*.h ./${RST_NAME}/
@echo " "
public:
/**
* @brief onRegisterQuery is a pure virtual operation which should be implemented in applications to get callback messages.
- * @param [in] attributeMap - A data map in which SoftSensorManager service sends sensor data with cqid.
+ * @param [in] jsonData - A data map in which SoftSensorManager service sends sensor data with cqid.
* @param [in] eCode - The address of listener class. When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
* SSMClient can callback message to the appication.
* @param [out] cqid - A query id generated from SoftSensorManager service for the queryString request.
* @return SSMReturn
*/
- virtual void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eCode) = 0;
+ virtual void onRegisterQuery(const std::string &jsonData, SSMReturn &eCode) = 0;
virtual ~ISSMClientListener()
{
}
{
private:
SSMReturn m_retResponse;
- OCPlatform *m_pPlatform;
CSemaphore m_sem;
/**
* @brief SoftSensorManager Resource.
/**
* @brief attribute map .
*/
- AttributeMap m_responseAttributeMap;
+ std::map<std::string, std::string> m_responseAttributeMap;
/**
* @brief query engine.
*/
// friend option. for callback from SSMResource
void onFoundResource(std::shared_ptr< OCResource > resource);
- void onCreateQueryEngine(const OCRepresentation &rep, const int eCode);
- void onReleaseQueryEngine(const OCRepresentation &rep, const int eCode);
- void onRegisterQuery(const OCRepresentation &rep, const int eCode);
- void onUnregisterQuery(const OCRepresentation &rep, const int eCode);
- void onObserve(const OCRepresentation &rep, const int &eCode);
+ void onCreateQueryEngine(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode);
+ void onReleaseQueryEngine(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode);
+ void onRegisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode);
+ void onUnregisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode);
+ void onObserve(const HeaderOptions &headerOptions, const OCRepresentation &rep, const int &eCode,
+ const int &sequenceNumber);
};
#endif /* RESOURCECLIENT_H_ */
--- /dev/null
+#include "SSMInterface.h"
+#include "SSMInterface/SSMCore.h"
+#include "Common/PlatformLayer.h"
+
+class SSMCoreEventReceiver : public IQueryEngineEvent
+{
+ public:
+ SSMCoreEventReceiver()
+ {
+ }
+
+ SSMRESULT onQueryEngineEvent(IN int cqid, IN IDataReader *pResult)
+ {
+ SSMRESULT res = SSM_E_FAIL;
+
+ m_mtxListener.lock();
+
+ if (m_mapListener.find(cqid) == m_mapListener.end())
+ {
+ SSM_CLEANUP_ASSERT(res);
+ }
+
+ m_mapListener[cqid]->onQueryEngineEvent(cqid, pResult);
+
+ res = SSM_S_OK;
+
+CLEANUP:
+ m_mtxListener.unlock();
+ return res;
+ }
+
+ void lockListener()
+ {
+ m_mtxListener.lock();
+ }
+
+ void unlockListener()
+ {
+ m_mtxListener.unlock();
+ }
+
+ void addListener(IN int cqid, IN IQueryEngineEvent *pEngineEvent)
+ {
+ m_mapListener[cqid] = pEngineEvent;
+ }
+
+ void removeListener(IN int cqid)
+ {
+ m_mapListener.erase(cqid);
+ }
+
+ private:
+ CSimpleMutex m_mtxListener;
+ std::map<int, IQueryEngineEvent *> m_mapListener;
+};
+
+IQueryEngine *g_pQueryEngineInstance = NULL;
+SSMCoreEventReceiver *g_pEventReceiver = NULL;
+
+SSMInterface::SSMInterface()
+{
+ std::string xmlDescription = "<SSMCore>"
+ "<Device>"
+ "<UDN>abcde123-31f8-11b4-a222-08002b34c003</UDN>"
+ "<Name>MyPC</Name>"
+ "<Type>PC</Type>"
+ "</Device>"
+ "</SSMCore>";
+
+ SSMRESULT res = SSM_E_FAIL;
+
+ g_pEventReceiver = new SSMCoreEventReceiver();
+ SSM_CLEANUP_NULL_ASSERT(g_pEventReceiver);
+ SSM_CLEANUP_ASSERT(InitializeSSMCore(xmlDescription));
+ SSM_CLEANUP_ASSERT(StartSSMCore());
+ SSM_CLEANUP_ASSERT(CreateQueryEngine(&g_pQueryEngineInstance));
+ SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->registerQueryEvent(g_pEventReceiver));
+CLEANUP:
+ ;
+}
+
+SSMInterface::~SSMInterface()
+{
+ SSMRESULT res = SSM_E_FAIL;
+
+ SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->unregisterQueryEvent(g_pEventReceiver));
+ ReleaseQueryEngine(g_pQueryEngineInstance);
+ g_pQueryEngineInstance = NULL;
+ SSM_CLEANUP_ASSERT(StopSSMCore());
+ SSM_CLEANUP_ASSERT(TerminateSSMCore());
+
+CLEANUP:
+ SAFE_DELETE(g_pEventReceiver);
+}
+
+SSMRESULT SSMInterface::registerQuery(IN std::string queryString, IN IQueryEngineEvent *listener,
+ IN int &cqid)
+{
+ SSMRESULT res = SSM_E_FAIL;
+
+ g_pEventReceiver->lockListener();
+ SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->executeContextQuery(queryString, &cqid));
+ g_pEventReceiver->addListener(cqid, listener);
+
+CLEANUP:
+ g_pEventReceiver->unlockListener();
+ return res;
+}
+
+SSMRESULT SSMInterface::unregisterQuery(IN int cqid)
+{
+ SSMRESULT res = SSM_E_FAIL;
+
+ g_pEventReceiver->lockListener();
+ SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->killContextQuery(cqid));
+ g_pEventReceiver->removeListener(cqid);
+
+CLEANUP:
+ g_pEventReceiver->unlockListener();
+ return res;
+}
\ No newline at end of file
#define SSM_RESOURCE_TYPE = "core.SoftSensorManager"
-#define COAP_IP "134.134.161.33"
-#define COAP_PORT 5683
-#define COAP_MODE ModeType::Client
-#define COAP_SRVTYPE ServiceType::InProc
-
#define COAP_SERVER_ADDR "coap://224.0.1.187/oc/core?rt=core.SoftSensorManager"
SSMClient::SSMClient()
{
m_sem.create(100000);
- m_pPlatform = NULL;
m_appListener = NULL;
m_retResponse = SSM_ERROR;
_findResource();
SSMClient::~SSMClient()
{
_releaseQueryEngine(m_queryEngineId);
- if (m_pPlatform)
- {
- delete m_pPlatform;
- m_pPlatform = NULL;
- }
}
void SSMClient::_findResource()
{
// Create PlatformConfig object
- PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::NonConfirmable);
+ PlatformConfig cfg(OC::ServiceType::InProc, OC::ModeType::Both,
+ "0.0.0.0", 0, OC::QualityOfService::LowQos);
// Create a OCPlatform instance.
// Note: Platform creation is synchronous call.
try
{
- m_pPlatform = new OCPlatform(cfg);
+ OCPlatform::Configure(cfg);
// Find all resources
OCStackResult result;
- if ((result = m_pPlatform->findResource("", COAP_SERVER_ADDR,
- std::bind(&SSMClient::onFoundResource, this, std::placeholders::_1)))
+ if ((result = OCPlatform::findResource("", COAP_SERVER_ADDR,
+ std::bind(&SSMClient::onFoundResource, this, std::placeholders::_1)))
!= OC_STACK_OK)
{
- delete m_pPlatform;
- m_pPlatform = NULL;
+ std::cout << "Faile to Find Resource... " << std::endl;
return;
}
+ std::cout << "Find Resource... " << std::endl;
m_sem.wait();
{
OCRepresentation rep;
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
-
QueryParamsMap queryParamsMap;
- commandValue.push_back("CreateQueryEngine");
-
- requestAttributeMap["command"] = commandValue;
-
- rep.setAttributeMap(requestAttributeMap);
+ rep.setValue("command", std::string("CreateQueryEngine"));
if (m_SSMResource->put(rep, queryParamsMap,
std::bind(&SSMClient::onCreateQueryEngine, this, std::placeholders::_1,
- std::placeholders::_2)) != OC_STACK_OK)
+ std::placeholders::_2, std::placeholders::_3)) != OC_STACK_OK)
{
return;
}
{
OCRepresentation rep;
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
- AttributeValues queryEngineIdValue;
-
QueryParamsMap queryParamsMap;
- commandValue.push_back("ReleaseQueryEngine");
-
- requestAttributeMap["command"] = commandValue;
-
- queryEngineIdValue.push_back(queryEngineId);
-
- requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
- rep.setAttributeMap(requestAttributeMap);
+ rep.setValue("command", std::string("ReleaseQueryEngine"));
+ rep.setValue("queryEngineId", queryEngineId);
m_SSMResource->put(rep, queryParamsMap,
std::bind(&SSMClient::onReleaseQueryEngine, this, std::placeholders::_1,
- std::placeholders::_2));
+ std::placeholders::_2, std::placeholders::_3));
m_sem.wait();
}
{
OCRepresentation rep;
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
- AttributeValues queryEngineIdValue;
- AttributeValues contextQueryValue;
-
QueryParamsMap queryParamsMap;
- commandValue.push_back("ExecuteContextQuery");
-
- requestAttributeMap["command"] = commandValue;
-
- queryEngineIdValue.push_back(m_queryEngineId);
-
- requestAttributeMap["queryEngineId"] = queryEngineIdValue;
- contextQueryValue.push_back(queryString);
-
- requestAttributeMap["contextQuery"] = contextQueryValue;
+ rep.setValue("command", std::string("ExecuteContextQuery"));
+ rep.setValue("queryEngineId", m_queryEngineId);
+ rep.setValue("contextQuery", queryString);
m_appListener = listener;
- rep.setAttributeMap(requestAttributeMap);
-
if (m_SSMResource->put(rep, queryParamsMap,
std::bind(&SSMClient::onRegisterQuery, this, std::placeholders::_1,
- std::placeholders::_2)) != OC_STACK_OK)
+ std::placeholders::_2, std::placeholders::_3)) != OC_STACK_OK)
return SSM_ERROR_NETWORK;
m_sem.wait();
if (m_retResponse == SSM_SUCCESS)
{
- cqid = m_responseAttributeMap["CQID"].back();
+ cqid = m_responseAttributeMap["CQID"];
}
return m_retResponse;
{
OCRepresentation rep;
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
- AttributeValues queryEngineIdValue;
- AttributeValues cqidValue;
-
QueryParamsMap queryParamsMap;
- commandValue.push_back("KillContextQuery");
-
- requestAttributeMap["command"] = commandValue;
-
- queryEngineIdValue.push_back(m_queryEngineId);
-
- requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
- cqidValue.push_back(cqid);
-
- requestAttributeMap["CQID"] = cqidValue;
-
- rep.setAttributeMap(requestAttributeMap);
+ rep.setValue("command", std::string("KillContextQuery"));
+ rep.setValue("queryEngineId", m_queryEngineId);
+ rep.setValue("CQID", cqid);
if (m_SSMResource->put(rep, queryParamsMap,
std::bind(&SSMClient::onUnregisterQuery, this, std::placeholders::_1,
- std::placeholders::_2)) != OC_STACK_OK)
+ std::placeholders::_2, std::placeholders::_3)) != OC_STACK_OK)
return SSM_ERROR_NETWORK;
m_sem.wait();
m_sem.release();
}
-void SSMClient::onCreateQueryEngine(const OCRepresentation &rep, const int eCode)
+void SSMClient::onCreateQueryEngine(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode)
{
if (eCode != 0)
{
goto CLEANUP;
}
- m_responseAttributeMap = rep.getAttributeMap();
- m_queryEngineId = m_responseAttributeMap["queryEngineId"].back();
- m_responseAttributeMap["queryEngineId"].pop_back();
+ m_queryEngineId = rep.getValue<std::string>("queryEngineId");
m_retResponse = SSM_SUCCESS;
CLEANUP: m_sem.release();
}
-void SSMClient::onRegisterQuery(const OCRepresentation &rep, const int eCode)
+void SSMClient::onRegisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode)
{
QueryParamsMap queryParamsMap;
goto CLEANUP;
}
- m_responseAttributeMap = rep.getAttributeMap();
-
- if (m_responseAttributeMap.find("error") != m_responseAttributeMap.end())
+ if (rep.hasAttribute("error"))
{
m_retResponse = SSM_ERROR_QUERY_PARSING;
goto CLEANUP;
}
m_SSMResource->observe(ObserveType::Observe, queryParamsMap,
- std::bind(&SSMClient::onObserve, this, std::placeholders::_1, std::placeholders::_2));
+ std::bind(&SSMClient::onObserve, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
+
+ m_responseAttributeMap.clear();
+
+ m_responseAttributeMap["CQID"] = rep.getValue<std::string>("CQID");
m_retResponse = SSM_SUCCESS;
CLEANUP: m_sem.release();
}
-void SSMClient::onUnregisterQuery(const OCRepresentation &rep, const int eCode)
+void SSMClient::onUnregisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int eCode)
{
if (eCode != 0)
{
goto CLEANUP;
}
- m_responseAttributeMap = rep.getAttributeMap();
-
- if (m_responseAttributeMap.find("error") != m_responseAttributeMap.end())
+ if (rep.hasAttribute("error"))
{
m_retResponse = SSM_ERROR_NO_QUERY;
goto CLEANUP;
}
+ m_responseAttributeMap.clear();
+
m_retResponse = SSM_SUCCESS;
CLEANUP: m_sem.release();
}
-void SSMClient::onReleaseQueryEngine(const OCRepresentation &rep, const int eCode)
+void SSMClient::onReleaseQueryEngine(const HeaderOptions &headerOptions,
+ const OCRepresentation &rep, const int eCode)
{
if (eCode != 0)
{
goto CLEANUP;
}
- m_responseAttributeMap = rep.getAttributeMap();
-
m_retResponse = SSM_SUCCESS;
CLEANUP: m_sem.release();
}
-void SSMClient::onObserve(const OCRepresentation &rep, const int &eCode)
+void SSMClient::onObserve(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+ const int &eCode, const int &sequenceNumber)
{
SSMReturn ret = SSM_SUCCESS;
ret = SSM_ERROR_NETWORK;
}
- m_appListener->onRegisterQuery(rep.getAttributeMap(), ret);
+ m_appListener->onRegisterQuery(rep.getJSONRepresentation(), ret);
}
-
+-include ../../../build/linux/root_path.inc
-include ../../../build/linux/environment.mk
BOOST=${BOOST_BASE}
RST_NAME=release
# Insert your project name.
-TARGET=SSMCoreUbuntu
+TARGET=${SSMCORE_LIB}
EXCLUDE_LIST=SSMCore_JNI.cpp
# C++ type Compile Flag define.
CXX=g++
-CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX -DMODEL_DIRECTORY=${MODEL_DIR} -DHIGH_LOCATION=${HIGH_LOCATION} -ldl
-CXX_INC=-I../../ -I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST} -I${SRC_PATH} -I${SRC_PATH}/Common -I${SRC_PATH}/QueryProcessor -I${SRC_PATH}/SensorProcessor -I${SRC_PATH}/SSMInterface
+CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX -ldl
+CXX_INC=-I${INC_PATH}/ -I${SRC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
CXX_LIB=-L""
CXX_SRCPATH=${wildcard ${SRC_PATH}/**/*.cpp}
# Linker FLAGS define.
LD_FLAGS=-std=c++0x -Wall -DLINUX
-# GAR=ar
-LD_LIB=${IOT_RELEASE}/${IOT_LIB} ${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} -lpthread -ldl
+GAR=ar
+# LD_LIB=${IOT_RELEASE}/${IOT_LIB} ${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} ${IOT_LOG_DIR}/lib/${IOT_LOG_LIB} -lpthread -ldl
# Force metatargets to build:
@echo "${MODEL_DIR}"
${TARGET}: ${GCC_OBJLIST} ${CXX_OBJLIST}
- $(CXX) $(LD_FLAGS) -o ./${RST_NAME}/$@ $^ ${LD_LIB}
- # ${GAR} -r ./${RST_NAME}/$@ ./*.o
+ # $(CXX) $(LD_FLAGS) -o ./${RST_NAME}/$@ $^ ${LD_LIB}
+ ${GAR} -r ./${RST_NAME}/$@ ./*.o
@echo " "
%.o : ${SRC_PATH}/**/%.c
post_job:
@echo " "
cp -Rdp ./${RST_NAME}/${TARGET} ${OUTPUTS_DIR}/
+ cp -Rdp ${INC_PATH}/SSMInterface.h ${OUTPUTS_DIR}/
cp -Rdp ${SRC_PATH}/SSMInterface/SSMModelDefinition.h ${OUTPUTS_DIR}/
@echo "---------------- SSMCore Build Successful. ---------------"
@echo "Enter to ${RST_NAME} folder."
--- /dev/null
+#ifndef _SSMInterface_H_
+#define _SSMInterface_H_
+
+#include <string>
+#include <vector>
+
+enum SSMRESULT
+{
+ SSM_S_OK
+ , SSM_S_FALSE
+ , SSM_E_POINTER
+ , SSM_E_OUTOFMEMORY
+ , SSM_E_FAIL
+ , SSM_E_NOINTERFACE
+ , SSM_E_NOTIMPL
+};
+
+/**
+* @class IModelData
+* @brief IModelData Interface
+* This class represents context model data package
+*
+* @see
+*/
+class IModelData
+{
+ public:
+ /**
+ * @fn getDataId
+ * @brief Get affected DataId. ContextModel has plenty of data so \n
+ * returned data is matched from given condition
+ *
+ * @param None
+ *
+ * @return int
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual int getDataId() = 0;
+
+ /**
+ * @fn GetPropertyCount
+ * @brief ContextModel has at least one property that contains data \n
+ * property is described from its specification.
+ *
+ * @param None
+ *
+ * @return int
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual int getPropertyCount() = 0;
+
+ /**
+ * @fn getPropertyName
+ * @brief Retrieve propertyName
+ *
+ * @param [in] int propertyIndex - index of property to read
+ *
+ * @return std::string
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual std::string getPropertyName(int propertyIndex) = 0;
+
+ /**
+ * @fn getPropertyValue
+ * @brief Retrieve propertyValue
+ *
+ * @param [in] int propertyIndex - index of property to read
+ *
+ * @return std::string
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual std::string getPropertyValue(int propertyIndex) = 0;
+
+ /**
+ * @fn getPropertyValueByName
+ * @brief Retrieve propertyValue using given name
+ *
+ * @param [in] std::string propertyName - property name looking for
+ *
+ * @return std::string
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual std::string getPropertyValueByName(std::string propertyName) = 0;
+ protected:
+ virtual ~IModelData() {};
+};
+
+/**
+* @class IDataReader
+* @brief IDataReader Interface
+* This class represents context model data package's reader
+*
+* @see
+*/
+class IDataReader
+{
+ public:
+ /**
+ * @fn getAffectedModels
+ * @brief Get affected ContextModels. The CQL can specify multiple ContextModels for retrieving data.
+ *
+ * @param [out] std::vector<std::string> *pAffectedModels - affected ContextModel list
+ *
+ * @return SSMRESULT
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual SSMRESULT getAffectedModels(std::vector<std::string> *pAffectedModels) = 0;
+
+ /**
+ * @fn getModelDataCount
+ * @brief Get affected data count. There are multiple data can exist from given condition.
+ *
+ * @param [in] std::string modelName - affected ContextModel name
+ *
+ * @param [out] int *pDataCount - affected dataId count
+ *
+ * @return SSMRESULT
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual SSMRESULT getModelDataCount(std::string modelName, int *pDataCount) = 0;
+
+ /**
+ * @fn getModelData
+ * @brief Get actual Context Model data
+ *
+ * @param [in] std::string modelName - affected ContextModel name
+ *
+ *
+ * @param [in] int dataIndex - affected dataId index
+ *
+ *
+ * @param [out] IModelData **ppModelData - affected ContextModel data reader
+ *
+ * @return SSMRESULT
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual SSMRESULT getModelData(std::string modelName, int dataIndex, IModelData **ppModelData) = 0;
+ protected:
+ virtual ~IDataReader() {};
+};
+
+/**
+* @class IQueryEngineEvent
+* @brief IQueryEngineEvent Interface
+* This class represents Query Engine's event that contains results
+*
+* @see
+*/
+class IQueryEngineEvent
+{
+ public:
+ /**
+ * @fn onQueryEngineEvent
+ * @brief Transmit result of SSMCore to Application layer
+ *
+ * @param [in] int cqid - entered ContextQuery ID
+ *
+ * @param [in] IDataReader *pResult - result of SSMCore
+ *
+ * @return SSMRESULT
+ * @warning
+ * @exception
+ * @see
+ */
+ virtual SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult) = 0;
+ protected:
+ virtual ~IQueryEngineEvent() {};
+};
+
+class SSMInterface
+{
+ public:
+ SSMInterface();
+ ~SSMInterface();
+
+ SSMRESULT registerQuery(std::string queryString, IQueryEngineEvent *listener, int &cqid);
+ SSMRESULT unregisterQuery(int cqid);
+};
+#endif
\ No newline at end of file
;
/**
- * @fn setCurrentDeviceInfo
- * @brief set device information
+ * @fn initRepository
+ * @brief initialize repository using given info
*
* @param [in] std::string name - Device name
* @param [in] std::string type - Device Type
* @param [in] std::string pathSoftSensors - SoftSensors Repository path
* @param [in] std::string pathDescription - SoftSensors Description path
- * @return void
+ * @return SSMRESULT
*
* @warning
* @exception
* @see
*/
- virtual void setCurrentDeviceInfo(IN std::string name, IN std::string type,
- IN std::string pathSoftSensors, IN std::string pathDescription) = 0;
+ virtual SSMRESULT initRepository(IN std::string name, IN std::string type,
+ IN std::string pathSoftSensors, IN std::string pathDescription) = 0;
virtual SSMRESULT registerResourceFinderEvent(IN IResourceEvent *pResourceEvent) = 0;
virtual SSMRESULT startResourceFinder() = 0;
IEvent *pEvent) = 0;
};
-static const OID OID_IResponseReactor = { 0x3140a3dc, 0xf912, 0x4d88, { 0x97, 0x3c, 0x86, 0xe8, 0x35, 0x69, 0xa7, 0xf8 } };
+static const OID OID_ISensingEngine = { 0x3140a3dc, 0xf912, 0x4d88, { 0x97, 0x3c, 0x86, 0xe8, 0x35, 0x69, 0xa7, 0xf8 } };
/**
- * @class IResponseReactor
- * @brief Interface for implement of reactor pattern
- * Delegate requested context to context executor layer.
+ * @class ISensingEngine
+ * @brief Class for implementing main abstration of SensorProcessor
*
*
* @see
*/
-class IResponseReactor : public IBase
+class ISensingEngine : public IBase
, public IEvent
{
public:
* @exception
* @see
*/
- virtual void registerContext(TypeofEvent callType, ISSMResource *pSSMResouce, IEvent *pEvent) = 0;
+ virtual SSMRESULT registerContext(TypeofEvent callType, ISSMResource *pSSMResouce,
+ IEvent *pEvent) = 0;
/**
* @fn unregisterContext
* @exception
* @see
*/
- virtual void unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
- IEvent *pEvent) = 0;
+ virtual SSMRESULT unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
+ IEvent *pEvent) = 0;
/**
* @fn getList
* @exception
* @see
*/
- virtual void getList(std::vector<ISSMResource *> *pList) = 0;
+ virtual SSMRESULT getList(std::vector<ISSMResource *> *pList) = 0;
};
class IResourceFinderEvent
virtual SSMRESULT stopObserveResource(IN ISSMResource *pSensor) = 0;
};
-static const OID OID_IResourceConnectivity = { 0x8e42b098, 0x9aa5, 0x43f3, { 0x84, 0xa, 0x21, 0x44, 0xc9, 0x4c, 0xc7, 0x99 } };
-class IResourceConnectivity : public IBase
-{
- public:
- virtual void *getPlatform() = 0;
-};
-
/**
* @class ISoftSensorManager
* @brief ISoftSensorManager Interface
#include <map>
#include <fstream>
-#define LOCATION_SSM_DB ":memory:"
-#define RAPIDXML_STATIC_POOL_SIZE 4*1024
-
#if defined(WIN32)
+
#include <Windows.h>
#include <Shlwapi.h>
-
#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "../Outputs/sqlite3.lib")
#elif defined(LINUX)
+
#include <stdio.h>
#include <errno.h>
#include <sys/time.h>
#include <dlfcn.h>
#include <semaphore.h>
-#elif defined(ANDROID)
+#if defined(ANDROID)
+
#include <android/log.h>
#elif defined(TIZEN)
-#include <FBase.h>
#endif
-#define DEFAULT_PATH_SOFT_SENSORS "SoftSensorDescription.xml"
+#endif
-//#define LOCATION_SSM_DB_DUMP "myBackup.db"
+
+#define LOCATION_SSM_DB ":memory:"
+#define RAPIDXML_STATIC_POOL_SIZE 4*1024
+#define DEFAULT_PATH_SOFT_SENSORS "SoftSensorDescription.xml"
#define LOCATION_SSM_DB_DUMP ""
+//#define LOCATION_SSM_DB_DUMP "myBackup.db"
-#if defined(WIN32) || defined(LINUX)
-#define REPORT_MESSAGE(tag, msg) {printf("[%s] %s\n", tag, msg);}
+#if defined(WIN32)
-#define SSM_VOID_ASSERT(Exp, STRErrorMsg) \
- { \
- if(!(Exp)) \
- { \
- printf("[SSM] %s:%d Return message: %s\n", __FUNCTION__, __LINE__, STRErrorMsg); \
- assert(0); \
- return; \
- } \
- }
+#define PRINT_LOG(strError) printf("[SSM] %s:%d %s\n", __FUNCTION__, __LINE__, strError)
+#define REPORT_MESSAGE(tag, msg) printf("[%s] %s\n", tag, msg)
-#define SSM_RESULT_ASSERT(Exp, STRErrorMsg, Result) \
- { \
- if(!(Exp)) \
- { \
- printf("[SSM] %s:%d Return message: %s\n", __FUNCTION__, __LINE__, STRErrorMsg); \
- assert(0); \
- return Result; \
- } \
- }
+#elif defined(LINUX)
-#define SSM_CLEANUP_ASSERT(Exp) \
- { \
- if((res = (Exp)) != SSM_S_OK) \
- { \
- printf("[SSM] %s:%d Return message: %s\n", __FUNCTION__, __LINE__, GetSSMError(res)); \
- assert(0); \
- goto CLEANUP; \
- } \
- }
+#if defined(ANDROID)
-#define SSM_CLEANUP_COND_ASSERT(Exp, Cond, STRErrorMsg) \
- { \
- if(Exp != Cond) \
- { \
- printf("[SSM] %s:%d Return message: %s\n", __FUNCTION__, __LINE__, STRErrorMsg); \
- assert(0); \
- goto CLEANUP; \
- } \
- }
+void ReportMessage(const char *tag, const char *msg);
+#define REPORT_MESSAGE(tag, msg) ReportMessage(tag, msg)
+#define PRINT_LOG(strError) __android_log_print(ANDROID_LOG_ERROR, "[SSM]", "%s:%d %s", __PRETTY_FUNCTION__, __LINE__, strError)
-#define SSM_CLEANUP_NULL_ASSERT(Val) \
- { \
- if(!(Val)) \
- { \
- printf("[SSM] %s:%d Return message: NULL value\n", __FUNCTION__, __LINE__); \
- assert(Val); \
- goto CLEANUP; \
- } \
- }
+#elif defined(TIZEN)
-#elif defined(ANDROID)
+#define REPORT_MESSAGE(tag, msg) printf("[%s] %s\n", tag, msg)
+#define PRINT_LOG(strError) printf("[SSM] %s:%d %s\n", __FUNCTION__, __LINE__, strError)
-void ReportMessage(const char *tag, const char *msg);
-#define REPORT_MESSAGE(tag, msg) {ReportMessage(tag, msg);}
+#else //Default linux
-#define SSM_VOID_ASSERT(Exp, STRErrorMsg) \
- { \
- if(!(Exp)) \
- { \
- __android_log_print(ANDROID_LOG_ERROR, "[SSM]", "%s:%d Return message: %s", __PRETTY_FUNCTION__, __LINE__, STRErrorMsg); \
- assert(0); \
- return; \
- } \
- }
+#define REPORT_MESSAGE(tag, msg) printf("[%s] %s\n", tag, msg)
+#define PRINT_LOG(strError) printf("[SSM] %s:%d %s\n", __FUNCTION__, __LINE__, strError)
-#define SSM_RESULT_ASSERT(Exp, STRErrorMsg, Result) \
- { \
- if(!(Exp)) \
- { \
- __android_log_print(ANDROID_LOG_ERROR, "[SSM]", "%s:%d Return message: %s", __PRETTY_FUNCTION__, __LINE__, STRErrorMsg); \
- assert(0); \
- return Result; \
- } \
- }
-
-#define SSM_CLEANUP_ASSERT(Exp) \
- { \
- if((res = (Exp)) != SSM_S_OK) \
- { \
- __android_log_print(ANDROID_LOG_ERROR, "[SSM]", "%s:%d Return message: %s", __PRETTY_FUNCTION__, __LINE__, GetSSMError(res)); \
- assert(0); \
- goto CLEANUP; \
- } \
- }
+#endif
-#define SSM_CLEANUP_COND_ASSERT(Exp, Cond, STRErrorMsg) \
- { \
- if(Exp != Cond) \
- { \
- __android_log_print(ANDROID_LOG_ERROR, "[SSM]", "%s:%d Return message: %s", __PRETTY_FUNCTION__, __LINE__, STRErrorMsg); \
- assert(0); \
- goto CLEANUP; \
- } \
- }
+#endif
-#define SSM_CLEANUP_NULL_ASSERT(Val) \
- { \
- if(!(Val)) \
- { \
- __android_log_print(ANDROID_LOG_ERROR, "[SSM]", "%s:%d Return message: NULL value", __PRETTY_FUNCTION__, __LINE__); \
- assert(Val); \
- goto CLEANUP; \
- } \
- }
-#elif defined(TIZEN)
-#define REPORT_MESSAGE(tag, msg)
#define SSM_VOID_ASSERT(Exp, STRErrorMsg) \
{ \
if(!(Exp)) \
{ \
- AppLog("%s", STRErrorMsg); \
+ PRINT_LOG(STRErrorMsg); \
assert(0); \
return; \
} \
{ \
if(!(Exp)) \
{ \
- AppLog("%s", STRErrorMsg); \
+ PRINT_LOG(STRErrorMsg); \
assert(0); \
return Result; \
} \
{ \
if((res = (Exp)) != SSM_S_OK) \
{ \
- AppLog("%s", GetSSMError(res)); \
+ PRINT_LOG(GetSSMError(res)); \
assert(0); \
goto CLEANUP; \
} \
{ \
if(Exp != Cond) \
{ \
- AppLog("%s", STRErrorMsg); \
+ PRINT_LOG(STRErrorMsg); \
assert(0); \
goto CLEANUP; \
} \
{ \
if(!(Val)) \
{ \
- AppLog("NULL value"); \
+ PRINT_LOG("NULL value"); \
assert(Val); \
goto CLEANUP; \
} \
}
-#endif
-
#define CLEAN_STACKVARIABLE(val) memset(&val, 0, sizeof(val))
#define SAFE_RELEASE(p) {if(p != NULL){p->release();p = NULL;}else{;/*NULL*/}}
#define SAFE_DELETE(p) {if(p != NULL){delete p;p = NULL;}else{;/*NULL*/}}
+/******************************************************************
+*
+* Copyright 2014 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
#include "ThreadManager.h"
CSimpleMutex::CSimpleMutex()
** 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
- typedef SQLITE_INT64_TYPE sqlite_int64;
- typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
+typedef SQLITE_INT64_TYPE sqlite_int64;
+typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
#elif defined(_MSC_VER) || defined(__BORLANDC__)
- typedef __int64 sqlite_int64;
- typedef unsigned __int64 sqlite_uint64;
+typedef __int64 sqlite_int64;
+typedef unsigned __int64 sqlite_uint64;
#else
- typedef long long int sqlite_int64;
- typedef unsigned long long int sqlite_uint64;
+typedef long long int sqlite_int64;
+typedef unsigned long long int sqlite_uint64;
#endif
typedef sqlite_int64 sqlite3_int64;
typedef sqlite_uint64 sqlite3_uint64;
** 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
** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
** argument is a harmless no-op.
*/
-SQLITE_API int sqlite3_close(sqlite3*);
-SQLITE_API int sqlite3_close_v2(sqlite3*);
+SQLITE_API int sqlite3_close(sqlite3 *);
+SQLITE_API int sqlite3_close_v2(sqlite3 *);
/*
** The type for a callback function.
** This is legacy and deprecated. It is included for historical
** compatibility and is not documented.
*/
-typedef int (*sqlite3_callback)(void*,int,char**, char**);
+typedef int (*sqlite3_callback)(void *, int, char **, char **);
/*
** CAPI3REF: One-Step Query Execution Interface
** 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.
**
** </ul>
*/
SQLITE_API int sqlite3_exec(
- sqlite3*, /* An open database */
- const char *sql, /* SQL to be evaluated */
- int (*callback)(void*,int,char**,char**), /* Callback function */
- void *, /* 1st argument to callback */
- char **errmsg /* Error msg written here */
+ sqlite3 *, /* An open database */
+ const char *sql, /* SQL to be evaluated */
+ int (*callback)(void *, int, char **, char **), /* Callback function */
+ void *, /* 1st argument to callback */
+ char **errmsg /* Error msg written here */
);
/*
/*
** 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
** I/O operations on the open file.
*/
typedef struct sqlite3_file sqlite3_file;
-struct sqlite3_file {
- const struct sqlite3_io_methods *pMethods; /* Methods for an open file */
+struct sqlite3_file
+{
+ const struct sqlite3_io_methods *pMethods; /* Methods for an open file */
};
/*
** 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]
** database corruption.
*/
typedef struct sqlite3_io_methods sqlite3_io_methods;
-struct sqlite3_io_methods {
- int iVersion;
- int (*xClose)(sqlite3_file*);
- int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
- int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
- int (*xTruncate)(sqlite3_file*, sqlite3_int64 size);
- int (*xSync)(sqlite3_file*, int flags);
- int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
- int (*xLock)(sqlite3_file*, int);
- int (*xUnlock)(sqlite3_file*, int);
- int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
- int (*xFileControl)(sqlite3_file*, int op, void *pArg);
- int (*xSectorSize)(sqlite3_file*);
- int (*xDeviceCharacteristics)(sqlite3_file*);
- /* Methods above are valid for version 1 */
- int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
- int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
- void (*xShmBarrier)(sqlite3_file*);
- int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
- /* Methods above are valid for version 2 */
- int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
- int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
- /* Methods above are valid for version 3 */
- /* Additional methods may be added in future releases */
+struct sqlite3_io_methods
+{
+ int iVersion;
+ int (*xClose)(sqlite3_file *);
+ int (*xRead)(sqlite3_file *, void *, int iAmt, sqlite3_int64 iOfst);
+ int (*xWrite)(sqlite3_file *, const void *, int iAmt, sqlite3_int64 iOfst);
+ int (*xTruncate)(sqlite3_file *, sqlite3_int64 size);
+ int (*xSync)(sqlite3_file *, int flags);
+ int (*xFileSize)(sqlite3_file *, sqlite3_int64 *pSize);
+ int (*xLock)(sqlite3_file *, int);
+ int (*xUnlock)(sqlite3_file *, int);
+ int (*xCheckReservedLock)(sqlite3_file *, int *pResOut);
+ int (*xFileControl)(sqlite3_file *, int op, void *pArg);
+ int (*xSectorSize)(sqlite3_file *);
+ int (*xDeviceCharacteristics)(sqlite3_file *);
+ /* Methods above are valid for version 1 */
+ int (*xShmMap)(sqlite3_file *, int iPg, int pgsz, int, void volatile **);
+ int (*xShmLock)(sqlite3_file *, int offset, int n, int flags);
+ void (*xShmBarrier)(sqlite3_file *);
+ int (*xShmUnmap)(sqlite3_file *, int deleteFlag);
+ /* Methods above are valid for version 2 */
+ int (*xFetch)(sqlite3_file *, sqlite3_int64 iOfst, int iAmt, void **pp);
+ int (*xUnfetch)(sqlite3_file *, sqlite3_int64 iOfst, void *p);
+ /* Methods above are valid for version 3 */
+ /* Additional methods may be added in future releases */
};
/*
** <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
*/
typedef struct sqlite3_vfs sqlite3_vfs;
typedef void (*sqlite3_syscall_ptr)(void);
-struct sqlite3_vfs {
- int iVersion; /* Structure version number (currently 3) */
- int szOsFile; /* Size of subclassed sqlite3_file */
- int mxPathname; /* Maximum file pathname length */
- sqlite3_vfs *pNext; /* Next registered VFS */
- const char *zName; /* Name of this virtual file system */
- void *pAppData; /* Pointer to application-specific data */
- int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
- int flags, int *pOutFlags);
- int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
- int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
- int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
- void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
- void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
- void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
- void (*xDlClose)(sqlite3_vfs*, void*);
- int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
- int (*xSleep)(sqlite3_vfs*, int microseconds);
- int (*xCurrentTime)(sqlite3_vfs*, double*);
- int (*xGetLastError)(sqlite3_vfs*, int, char *);
- /*
- ** The methods above are in version 1 of the sqlite_vfs object
- ** definition. Those that follow are added in version 2 or later
- */
- int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
- /*
- ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
- ** Those below are for version 3 and greater.
- */
- int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr);
- sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName);
- const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName);
- /*
- ** 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.
- */
+struct sqlite3_vfs
+{
+ int iVersion; /* Structure version number (currently 3) */
+ int szOsFile; /* Size of subclassed sqlite3_file */
+ int mxPathname; /* Maximum file pathname length */
+ sqlite3_vfs *pNext; /* Next registered VFS */
+ const char *zName; /* Name of this virtual file system */
+ void *pAppData; /* Pointer to application-specific data */
+ int (*xOpen)(sqlite3_vfs *, const char *zName, sqlite3_file *,
+ int flags, int *pOutFlags);
+ int (*xDelete)(sqlite3_vfs *, const char *zName, int syncDir);
+ int (*xAccess)(sqlite3_vfs *, const char *zName, int flags, int *pResOut);
+ int (*xFullPathname)(sqlite3_vfs *, const char *zName, int nOut, char *zOut);
+ void *(*xDlOpen)(sqlite3_vfs *, const char *zFilename);
+ void (*xDlError)(sqlite3_vfs *, int nByte, char *zErrMsg);
+ void (*(*xDlSym)(sqlite3_vfs *, void *, const char *zSymbol))(void);
+ void (*xDlClose)(sqlite3_vfs *, void *);
+ int (*xRandomness)(sqlite3_vfs *, int nByte, char *zOut);
+ int (*xSleep)(sqlite3_vfs *, int microseconds);
+ int (*xCurrentTime)(sqlite3_vfs *, double *);
+ int (*xGetLastError)(sqlite3_vfs *, int, char *);
+ /*
+ ** The methods above are in version 1 of the sqlite_vfs object
+ ** definition. Those that follow are added in version 2 or later
+ */
+ int (*xCurrentTimeInt64)(sqlite3_vfs *, sqlite3_int64 *);
+ /*
+ ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
+ ** Those below are for version 3 and greater.
+ */
+ int (*xSetSystemCall)(sqlite3_vfs *, const char *zName, sqlite3_syscall_ptr);
+ sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs *, const char *zName);
+ const char *(*xNextSystemCall)(sqlite3_vfs *, const char *zName);
+ /*
+ ** 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.
+ */
};
/*
** </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.
**
** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if
** the call is considered successful.
*/
-SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
+SQLITE_API int sqlite3_db_config(sqlite3 *, int op, ...);
/*
** CAPI3REF: Memory Allocation Routines
** 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,
** call to xShutdown().
*/
typedef struct sqlite3_mem_methods sqlite3_mem_methods;
-struct sqlite3_mem_methods {
- void *(*xMalloc)(int); /* Memory allocation function */
- void (*xFree)(void*); /* Free a prior allocation */
- void *(*xRealloc)(void*,int); /* Resize an allocation */
- int (*xSize)(void*); /* Return the size of an allocation */
- int (*xRoundup)(int); /* Round up request size to allocation size */
- int (*xInit)(void*); /* Initialize the memory allocator */
- void (*xShutdown)(void*); /* Deinitialize the memory allocator */
- void *pAppData; /* Argument to xInit() and xShutdown() */
+struct sqlite3_mem_methods
+{
+ void *(*xMalloc)(int); /* Memory allocation function */
+ void (*xFree)(void *); /* Free a prior allocation */
+ void *(*xRealloc)(void *, int); /* Resize an allocation */
+ int (*xSize)(void *); /* Return the size of an allocation */
+ int (*xRoundup)(int); /* Round up request size to allocation size */
+ int (*xInit)(void *); /* Initialize the memory allocator */
+ void (*xShutdown)(void *); /* Deinitialize the memory allocator */
+ void *pAppData; /* Argument to xInit() and xShutdown() */
};
/*
** 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>
** [extended result codes] feature of SQLite. ^The extended result
** codes are disabled by default for historical compatibility.
*/
-SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
+SQLITE_API int sqlite3_extended_result_codes(sqlite3 *, int onoff);
/*
** CAPI3REF: Last Insert Rowid
** ^(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.)^
**
** unpredictable and might not equal either the old or the new
** last insert [rowid].
*/
-SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
+SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3 *);
/*
** CAPI3REF: Count The Number Of Rows Modified
** 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
** while [sqlite3_changes()] is running then the value returned
** is unpredictable and not meaningful.
*/
-SQLITE_API int sqlite3_changes(sqlite3*);
+SQLITE_API int sqlite3_changes(sqlite3 *);
/*
** CAPI3REF: Total Number Of Rows Modified
** 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
** while [sqlite3_total_changes()] is running then the value
** returned is unpredictable and not meaningful.
*/
-SQLITE_API int sqlite3_total_changes(sqlite3*);
+SQLITE_API int sqlite3_total_changes(sqlite3 *);
/*
** CAPI3REF: Interrupt A Long-Running Query
**
** ^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
** If the database connection closes while [sqlite3_interrupt()]
** is running then bad things will likely happen.
*/
-SQLITE_API void sqlite3_interrupt(sqlite3*);
+SQLITE_API void sqlite3_interrupt(sqlite3 *);
/*
** CAPI3REF: Determine If An SQL Statement Is Complete
** ^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.
*/
-SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
+SQLITE_API int sqlite3_busy_handler(sqlite3 *, int(*)(void *, int), void *);
/*
** CAPI3REF: Set A Busy Timeout
** was defined (using [sqlite3_busy_handler()]) prior to calling
** this routine, that other busy handler is cleared.)^
*/
-SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
+SQLITE_API int sqlite3_busy_timeout(sqlite3 *, int ms);
/*
** CAPI3REF: Convenience Routines For Running Queries
** [sqlite3_errmsg()].
*/
SQLITE_API int sqlite3_get_table(
- sqlite3 *db, /* An open database */
- const char *zSql, /* SQL to be evaluated */
- char ***pazResult, /* Results of the query */
- int *pnRow, /* Number of result rows written here */
- int *pnColumn, /* Number of result columns written here */
- char **pzErrmsg /* Error msg written here */
+ sqlite3 *db, /* An open database */
+ const char *zSql, /* SQL to be evaluated */
+ char ***pazResult, /* Results of the query */
+ int *pnRow, /* Number of result rows written here */
+ int *pnColumn, /* Number of result columns written here */
+ char **pzErrmsg /* Error msg written here */
);
SQLITE_API void sqlite3_free_table(char **result);
** addition that after the string has been read and copied into
** the result, [sqlite3_free()] is called on the input string.)^
*/
-SQLITE_API char *sqlite3_mprintf(const char*,...);
-SQLITE_API char *sqlite3_vmprintf(const char*, va_list);
-SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...);
-SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
+SQLITE_API char *sqlite3_mprintf(const char *, ...);
+SQLITE_API char *sqlite3_vmprintf(const char *, va_list);
+SQLITE_API char *sqlite3_snprintf(int, char *, const char *, ...);
+SQLITE_API char *sqlite3_vsnprintf(int, char *, const char *, va_list);
/*
** CAPI3REF: Memory Allocation Subsystem
** [sqlite3_free()] or [sqlite3_realloc()].
*/
SQLITE_API void *sqlite3_malloc(int);
-SQLITE_API void *sqlite3_realloc(void*, int);
-SQLITE_API void sqlite3_free(void*);
+SQLITE_API void *sqlite3_realloc(void *, int);
+SQLITE_API void sqlite3_free(void *);
/*
** CAPI3REF: Memory Allocator Statistics
** 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()].
**
** sqlite3_prepare_v2() to reprepare a statement after a schema change.
*/
SQLITE_API int sqlite3_set_authorizer(
- sqlite3*,
- int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
- void *pUserData
+ sqlite3 *,
+ int (*xAuth)(void *, int, const char *, const char *, const char *, const char *),
+ void *pUserData
);
/*
** sqlite3_profile() function is considered experimental and is
** subject to change in future versions of SQLite.
*/
-SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
-SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
- void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
+SQLITE_API void *sqlite3_trace(sqlite3 *, void(*xTrace)(void *, const char *), void *);
+SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3 *,
+ void(*xProfile)(void *, const char *, sqlite3_uint64), void *);
/*
** CAPI3REF: Query Progress Callbacks
** 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.
**
** database connections for the meaning of "modify" in this paragraph.
**
*/
-SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
+SQLITE_API void sqlite3_progress_handler(sqlite3 *, int, int(*)(void *), void *);
/*
** 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.
** See also: [sqlite3_temp_directory]
*/
SQLITE_API int sqlite3_open(
- const char *filename, /* Database filename (UTF-8) */
- sqlite3 **ppDb /* OUT: SQLite db handle */
+ const char *filename, /* Database filename (UTF-8) */
+ sqlite3 **ppDb /* OUT: SQLite db handle */
);
SQLITE_API int sqlite3_open16(
- const void *filename, /* Database filename (UTF-16) */
- sqlite3 **ppDb /* OUT: SQLite db handle */
+ const void *filename, /* Database filename (UTF-16) */
+ sqlite3 **ppDb /* OUT: SQLite db handle */
);
SQLITE_API int sqlite3_open_v2(
- const char *filename, /* Database filename (UTF-8) */
- sqlite3 **ppDb, /* OUT: SQLite db handle */
- int flags, /* Flags */
- const char *zVfs /* Name of VFS module to use */
+ const char *filename, /* Database filename (UTF-8) */
+ sqlite3 **ppDb, /* OUT: SQLite db handle */
+ int flags, /* Flags */
+ const char *zVfs /* Name of VFS module to use */
);
/*
** 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
*/
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
-SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
+SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char *, const char *, sqlite3_int64);
/*
** 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.
**
*/
SQLITE_API int sqlite3_errcode(sqlite3 *db);
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
-SQLITE_API const char *sqlite3_errmsg(sqlite3*);
-SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
+SQLITE_API const char *sqlite3_errmsg(sqlite3 *);
+SQLITE_API const void *sqlite3_errmsg16(sqlite3 *);
SQLITE_API const char *sqlite3_errstr(int);
/*
** 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.
**
** New run-time limit categories may be added in future releases.
*/
-SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
+SQLITE_API int sqlite3_limit(sqlite3 *, int id, int newVal);
/*
** CAPI3REF: Run-Time Limit Categories
** </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>
*/
SQLITE_API int sqlite3_prepare(
- sqlite3 *db, /* Database handle */
- const char *zSql, /* SQL statement, UTF-8 encoded */
- int nByte, /* Maximum length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- const char **pzTail /* OUT: Pointer to unused portion of zSql */
+ sqlite3 *db, /* Database handle */
+ const char *zSql, /* SQL statement, UTF-8 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
SQLITE_API int sqlite3_prepare_v2(
- sqlite3 *db, /* Database handle */
- const char *zSql, /* SQL statement, UTF-8 encoded */
- int nByte, /* Maximum length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- const char **pzTail /* OUT: Pointer to unused portion of zSql */
+ sqlite3 *db, /* Database handle */
+ const char *zSql, /* SQL statement, UTF-8 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
SQLITE_API int sqlite3_prepare16(
- sqlite3 *db, /* Database handle */
- const void *zSql, /* SQL statement, UTF-16 encoded */
- int nByte, /* Maximum length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- const void **pzTail /* OUT: Pointer to unused portion of zSql */
+ sqlite3 *db, /* Database handle */
+ const void *zSql, /* SQL statement, UTF-16 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const void **pzTail /* OUT: Pointer to unused portion of zSql */
);
SQLITE_API int sqlite3_prepare16_v2(
- sqlite3 *db, /* Database handle */
- const void *zSql, /* SQL statement, UTF-16 encoded */
- int nByte, /* Maximum length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- const void **pzTail /* OUT: Pointer to unused portion of zSql */
+ sqlite3 *db, /* Database handle */
+ const void *zSql, /* SQL statement, UTF-16 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const void **pzTail /* OUT: Pointer to unused portion of zSql */
);
/*
** 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*);
+SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *);
/*
** CAPI3REF: Dynamically Typed Value Object
** 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.
** See also: [sqlite3_bind_parameter_count()],
** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
*/
-SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
-SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
-SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
-SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
-SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
-SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
-SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
-SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
-SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
+SQLITE_API int sqlite3_bind_blob(sqlite3_stmt *, int, const void *, int n, void(*)(void *));
+SQLITE_API int sqlite3_bind_double(sqlite3_stmt *, int, double);
+SQLITE_API int sqlite3_bind_int(sqlite3_stmt *, int, int);
+SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *, int, sqlite3_int64);
+SQLITE_API int sqlite3_bind_null(sqlite3_stmt *, int);
+SQLITE_API int sqlite3_bind_text(sqlite3_stmt *, int, const char *, int n, void(*)(void *));
+SQLITE_API int sqlite3_bind_text16(sqlite3_stmt *, int, const void *, int, void(*)(void *));
+SQLITE_API int sqlite3_bind_value(sqlite3_stmt *, int, const sqlite3_value *);
+SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *, int, int n);
/*
** CAPI3REF: Number Of SQL Parameters
** [sqlite3_bind_parameter_name()], and
** [sqlite3_bind_parameter_index()].
*/
-SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
+SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *);
/*
** CAPI3REF: Name Of A Host Parameter
** [sqlite3_bind_parameter_count()], and
** [sqlite3_bind_parameter_index()].
*/
-SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
+SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *, int);
/*
** CAPI3REF: Index Of A Parameter With A Given Name
** [sqlite3_bind_parameter_count()], and
** [sqlite3_bind_parameter_index()].
*/
-SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
+SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *, const char *zName);
/*
** CAPI3REF: Reset All Bindings On A Prepared Statement
** the [sqlite3_bind_blob | bindings] on a [prepared statement].
** ^Use this routine to reset all host parameters to NULL.
*/
-SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*);
+SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *);
/*
** CAPI3REF: Number Of Columns In A Result Set
** then the name of the column is unspecified and may change from
** one release of SQLite to the next.
*/
-SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N);
-SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
+SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *, int N);
+SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *, int N);
/*
** CAPI3REF: Source Of Data In A Query Result
** for the same [prepared statement] and result column
** at the same time then the results are undefined.
*/
-SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int);
-SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int);
-SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
+SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *, int);
+SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *, int);
+SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *, int);
+SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *, int);
+SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *, int);
+SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *, int);
/*
** CAPI3REF: Declared Datatype Of A Query Result
** is associated with individual values, not with the containers
** used to hold those values.
*/
-SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
+SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *, int);
+SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *, int);
/*
** CAPI3REF: Evaluate An SQL Statement
** 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
** then the more specific [error codes] are returned directly
** by sqlite3_step(). The use of the "v2" interface is recommended.
*/
-SQLITE_API int sqlite3_step(sqlite3_stmt*);
+SQLITE_API int sqlite3_step(sqlite3_stmt *);
/*
** CAPI3REF: Number of columns in a result set
** 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
** pointer. Subsequent calls to [sqlite3_errcode()] will return
** [SQLITE_NOMEM].)^
*/
-SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
-SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol);
-SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
-SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
-SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
-SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
+SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *, int iCol);
+SQLITE_API int sqlite3_column_bytes(sqlite3_stmt *, int iCol);
+SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt *, int iCol);
+SQLITE_API double sqlite3_column_double(sqlite3_stmt *, int iCol);
+SQLITE_API int sqlite3_column_int(sqlite3_stmt *, int iCol);
+SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt *, int iCol);
+SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt *, int iCol);
+SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt *, int iCol);
+SQLITE_API int sqlite3_column_type(sqlite3_stmt *, int iCol);
+SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *, int iCol);
/*
** CAPI3REF: Destroy A Prepared Statement Object
** ^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.
** statement in which the function is running.
*/
SQLITE_API int sqlite3_create_function(
- sqlite3 *db,
- const char *zFunctionName,
- int nArg,
- int eTextRep,
- void *pApp,
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
- void (*xStep)(sqlite3_context*,int,sqlite3_value**),
- void (*xFinal)(sqlite3_context*)
+ sqlite3 *db,
+ const char *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xFunc)(sqlite3_context *, int, sqlite3_value **),
+ void (*xStep)(sqlite3_context *, int, sqlite3_value **),
+ void (*xFinal)(sqlite3_context *)
);
SQLITE_API int sqlite3_create_function16(
- sqlite3 *db,
- const void *zFunctionName,
- int nArg,
- int eTextRep,
- void *pApp,
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
- void (*xStep)(sqlite3_context*,int,sqlite3_value**),
- void (*xFinal)(sqlite3_context*)
+ sqlite3 *db,
+ const void *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xFunc)(sqlite3_context *, int, sqlite3_value **),
+ void (*xStep)(sqlite3_context *, int, sqlite3_value **),
+ void (*xFinal)(sqlite3_context *)
);
SQLITE_API int sqlite3_create_function_v2(
- sqlite3 *db,
- const char *zFunctionName,
- int nArg,
- int eTextRep,
- void *pApp,
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
- void (*xStep)(sqlite3_context*,int,sqlite3_value**),
- void (*xFinal)(sqlite3_context*),
- void(*xDestroy)(void*)
+ sqlite3 *db,
+ const char *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xFunc)(sqlite3_context *, int, sqlite3_value **),
+ void (*xStep)(sqlite3_context *, int, sqlite3_value **),
+ void (*xFinal)(sqlite3_context *),
+ void(*xDestroy)(void *)
);
/*
** 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.
*/
#ifndef SQLITE_OMIT_DEPRECATED
-SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context *);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt *);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt *, sqlite3_stmt *);
SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
- void*,sqlite3_int64);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void *, sqlite3_int64, int),
+ void *, sqlite3_int64);
#endif
/*
** These routines must be called from the same thread as
** the SQL function that supplied the [sqlite3_value*] parameters.
*/
-SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
-SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
-SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
-SQLITE_API double sqlite3_value_double(sqlite3_value*);
-SQLITE_API int sqlite3_value_int(sqlite3_value*);
-SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
-SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*);
-SQLITE_API const void *sqlite3_value_text16(sqlite3_value*);
-SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*);
-SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*);
-SQLITE_API int sqlite3_value_type(sqlite3_value*);
-SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
+SQLITE_API const void *sqlite3_value_blob(sqlite3_value *);
+SQLITE_API int sqlite3_value_bytes(sqlite3_value *);
+SQLITE_API int sqlite3_value_bytes16(sqlite3_value *);
+SQLITE_API double sqlite3_value_double(sqlite3_value *);
+SQLITE_API int sqlite3_value_int(sqlite3_value *);
+SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value *);
+SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *);
+SQLITE_API const void *sqlite3_value_text16(sqlite3_value *);
+SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *);
+SQLITE_API const void *sqlite3_value_text16be(sqlite3_value *);
+SQLITE_API int sqlite3_value_type(sqlite3_value *);
+SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *);
/*
** CAPI3REF: Obtain Aggregate Function Context
** 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
** This routine must be called from the same thread in which
** the aggregate SQL function is running.
*/
-SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
+SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *, int nBytes);
/*
** CAPI3REF: User Data For Functions
** This routine must be called from the same thread in which
** the application-defined function is running.
*/
-SQLITE_API void *sqlite3_user_data(sqlite3_context*);
+SQLITE_API void *sqlite3_user_data(sqlite3_context *);
/*
** CAPI3REF: Database Connection For Functions
** and [sqlite3_create_function16()] routines that originally
** registered the application defined function.
*/
-SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
+SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *);
/*
** CAPI3REF: Function Auxiliary Data
** These routines must be called from the same thread in which
** the SQL function is running.
*/
-SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
-SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
+SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *, int N);
+SQLITE_API void sqlite3_set_auxdata(sqlite3_context *, int N, void *, void (*)(void *));
/*
** The typedef is necessary to work around problems in certain
** C++ compilers.
*/
-typedef void (*sqlite3_destructor_type)(void*);
+typedef void (*sqlite3_destructor_type)(void *);
#define SQLITE_STATIC ((sqlite3_destructor_type)0)
#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1)
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
*/
-SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
-SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
-SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
-SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*);
-SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*);
-SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
-SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
-SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
-SQLITE_API void sqlite3_result_null(sqlite3_context*);
-SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
-SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
-SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
-SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
+SQLITE_API void sqlite3_result_blob(sqlite3_context *, const void *, int, void(*)(void *));
+SQLITE_API void sqlite3_result_double(sqlite3_context *, double);
+SQLITE_API void sqlite3_result_error(sqlite3_context *, const char *, int);
+SQLITE_API void sqlite3_result_error16(sqlite3_context *, const void *, int);
+SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *);
+SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *);
+SQLITE_API void sqlite3_result_error_code(sqlite3_context *, int);
+SQLITE_API void sqlite3_result_int(sqlite3_context *, int);
+SQLITE_API void sqlite3_result_int64(sqlite3_context *, sqlite3_int64);
+SQLITE_API void sqlite3_result_null(sqlite3_context *);
+SQLITE_API void sqlite3_result_text(sqlite3_context *, const char *, int, void(*)(void *));
+SQLITE_API void sqlite3_result_text16(sqlite3_context *, const void *, int, void(*)(void *));
+SQLITE_API void sqlite3_result_text16le(sqlite3_context *, const void *, int, void(*)(void *));
+SQLITE_API void sqlite3_result_text16be(sqlite3_context *, const void *, int, void(*)(void *));
+SQLITE_API void sqlite3_result_value(sqlite3_context *, sqlite3_value *);
+SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *, int n);
/*
** CAPI3REF: Define New Collating Sequences
** 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,
- void *pArg,
- int(*xCompare)(void*,int,const void*,int,const void*)
+ 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,
- void *pArg,
- int(*xCompare)(void*,int,const void*,int,const void*),
- void(*xDestroy)(void*)
+ 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*,
- const void *zName,
- int eTextRep,
- void *pArg,
- int(*xCompare)(void*,int,const void*,int,const void*)
+ sqlite3 *,
+ const void *zName,
+ 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*,
- void(*)(void*,sqlite3*,int eTextRep,const char*)
+ sqlite3 *,
+ void *,
+ void(*)(void *, sqlite3 *, int eTextRep, const char *)
);
SQLITE_API int sqlite3_collation_needed16(
- sqlite3*,
- void*,
- void(*)(void*,sqlite3*,int eTextRep,const void*)
+ sqlite3 *,
+ void *,
+ void(*)(void *, sqlite3 *, int eTextRep, const void *)
);
#ifdef SQLITE_HAS_CODEC
** of SQLite.
*/
SQLITE_API int sqlite3_key(
- sqlite3 *db, /* Database to be rekeyed */
- const void *pKey, int nKey /* The key */
+ sqlite3 *db, /* Database to be rekeyed */
+ const void *pKey, int nKey /* The key */
);
/*
** of SQLite.
*/
SQLITE_API int sqlite3_rekey(
- sqlite3 *db, /* Database to be rekeyed */
- const void *pKey, int nKey /* The new key */
+ sqlite3 *db, /* Database to be rekeyed */
+ const void *pKey, int nKey /* The new key */
);
/*
-** 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(
- const char *zPassPhrase /* Activation phrase */
+ const char *zPassPhrase /* Activation phrase */
);
#endif
#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(
- const char *zPassPhrase /* Activation phrase */
+ const char *zPassPhrase /* Activation phrase */
);
#endif
** ^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
** connection while this routine is running, then the return value
** is undefined.
*/
-SQLITE_API int sqlite3_get_autocommit(sqlite3*);
+SQLITE_API int sqlite3_get_autocommit(sqlite3 *);
/*
** CAPI3REF: Find The Database Handle Of A Prepared Statement
** to the [sqlite3_prepare_v2()] call (or its variants) that was used to
** create the statement in the first place.
*/
-SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
+SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *);
/*
** CAPI3REF: Return The Filename For A Database Connection
**
** See also the [sqlite3_update_hook()] interface.
*/
-SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
-SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
+SQLITE_API void *sqlite3_commit_hook(sqlite3 *, int(*)(void *), void *);
+SQLITE_API void *sqlite3_rollback_hook(sqlite3 *, void(*)(void *), void *);
/*
** CAPI3REF: Data Change Notification Callbacks
** interfaces.
*/
SQLITE_API void *sqlite3_update_hook(
- sqlite3*,
- void(*)(void *,int ,char const *,char const *,sqlite3_int64),
- void*
+ sqlite3 *,
+ void(*)(void *, int , char const *, char const *, sqlite3_int64),
+ void *
);
/*
**
** See also: [sqlite3_release_memory()]
*/
-SQLITE_API int sqlite3_db_release_memory(sqlite3*);
+SQLITE_API int sqlite3_db_release_memory(sqlite3 *);
/*
** CAPI3REF: Impose A Limit On Heap Size
** 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
** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined.
*/
SQLITE_API int sqlite3_table_column_metadata(
- sqlite3 *db, /* Connection handle */
- const char *zDbName, /* Database name or NULL */
- const char *zTableName, /* Table name */
- const char *zColumnName, /* Column name */
- char const **pzDataType, /* OUTPUT: Declared data type */
- char const **pzCollSeq, /* OUTPUT: Collation sequence name */
- int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */
- int *pPrimaryKey, /* OUTPUT: True if column part of PK */
- int *pAutoinc /* OUTPUT: True if column is auto-increment */
+ sqlite3 *db, /* Connection handle */
+ const char *zDbName, /* Database name or NULL */
+ const char *zTableName, /* Table name */
+ const char *zColumnName, /* Column name */
+ char const **pzDataType, /* OUTPUT: Declared data type */
+ char const **pzCollSeq, /* OUTPUT: Collation sequence name */
+ int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */
+ int *pPrimaryKey, /* OUTPUT: True if column part of PK */
+ int *pAutoinc /* OUTPUT: True if column is auto-increment */
);
/*
** See also the [load_extension() SQL function].
*/
SQLITE_API int sqlite3_load_extension(
- sqlite3 *db, /* Load the extension into this database connection */
- const char *zFile, /* Name of the shared library containing extension */
- const char *zProc, /* Entry point. Derived from zFile if 0 */
- char **pzErrMsg /* Put error message here if not 0 */
+ sqlite3 *db, /* Load the extension into this database connection */
+ const char *zFile, /* Name of the shared library containing extension */
+ const char *zProc, /* Entry point. Derived from zFile if 0 */
+ char **pzErrMsg /* Put error message here if not 0 */
);
/*
** 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
** of this structure must not change while it is registered with
** any database connection.
*/
-struct sqlite3_module {
- int iVersion;
- int (*xCreate)(sqlite3*, void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVTab, char**);
- int (*xConnect)(sqlite3*, void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVTab, char**);
- int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
- int (*xDisconnect)(sqlite3_vtab *pVTab);
- int (*xDestroy)(sqlite3_vtab *pVTab);
- int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
- int (*xClose)(sqlite3_vtab_cursor*);
- int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv);
- int (*xNext)(sqlite3_vtab_cursor*);
- int (*xEof)(sqlite3_vtab_cursor*);
- int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
- int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid);
- int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
- int (*xBegin)(sqlite3_vtab *pVTab);
- int (*xSync)(sqlite3_vtab *pVTab);
- int (*xCommit)(sqlite3_vtab *pVTab);
- int (*xRollback)(sqlite3_vtab *pVTab);
- int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
- 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
- ** below are for version 2 and greater. */
- int (*xSavepoint)(sqlite3_vtab *pVTab, int);
- int (*xRelease)(sqlite3_vtab *pVTab, int);
- int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
+struct sqlite3_module
+{
+ int iVersion;
+ int (*xCreate)(sqlite3 *, void *pAux,
+ int argc, const char *const *argv,
+ sqlite3_vtab **ppVTab, char **);
+ int (*xConnect)(sqlite3 *, void *pAux,
+ int argc, const char *const *argv,
+ sqlite3_vtab **ppVTab, char **);
+ int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info *);
+ int (*xDisconnect)(sqlite3_vtab *pVTab);
+ int (*xDestroy)(sqlite3_vtab *pVTab);
+ int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
+ int (*xClose)(sqlite3_vtab_cursor *);
+ int (*xFilter)(sqlite3_vtab_cursor *, int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv);
+ int (*xNext)(sqlite3_vtab_cursor *);
+ int (*xEof)(sqlite3_vtab_cursor *);
+ int (*xColumn)(sqlite3_vtab_cursor *, sqlite3_context *, int);
+ int (*xRowid)(sqlite3_vtab_cursor *, sqlite3_int64 *pRowid);
+ int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
+ int (*xBegin)(sqlite3_vtab *pVTab);
+ int (*xSync)(sqlite3_vtab *pVTab);
+ int (*xCommit)(sqlite3_vtab *pVTab);
+ int (*xRollback)(sqlite3_vtab *pVTab);
+ int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
+ 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
+ ** below are for version 2 and greater. */
+ int (*xSavepoint)(sqlite3_vtab *pVTab, int);
+ int (*xRelease)(sqlite3_vtab *pVTab, int);
+ int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
};
/*
** a cost of N. A binary search of a table of N entries should have a
** cost of approximately log(N).
*/
-struct sqlite3_index_info {
- /* Inputs */
- int nConstraint; /* Number of entries in aConstraint */
- struct sqlite3_index_constraint {
- int iColumn; /* Column on left-hand side of constraint */
- unsigned char op; /* Constraint operator */
- unsigned char usable; /* True if this constraint is usable */
- int iTermOffset; /* Used internally - xBestIndex should ignore */
- } *aConstraint; /* Table of WHERE clause constraints */
- int nOrderBy; /* Number of terms in the ORDER BY clause */
- struct sqlite3_index_orderby {
- int iColumn; /* Column number */
- unsigned char desc; /* True for DESC. False for ASC. */
- } *aOrderBy; /* The ORDER BY clause */
- /* Outputs */
- struct sqlite3_index_constraint_usage {
- int argvIndex; /* if >0, constraint is part of argv to xFilter */
- unsigned char omit; /* Do not code a test for this constraint */
- } *aConstraintUsage;
- int idxNum; /* Number used to identify the index */
- char *idxStr; /* String, possibly obtained from sqlite3_malloc */
- int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
- int orderByConsumed; /* True if output is already ordered */
- double estimatedCost; /* Estimated cost of using this index */
+struct sqlite3_index_info
+{
+ /* Inputs */
+ int nConstraint; /* Number of entries in aConstraint */
+ struct sqlite3_index_constraint
+ {
+ int iColumn; /* Column on left-hand side of constraint */
+ unsigned char op; /* Constraint operator */
+ unsigned char usable; /* True if this constraint is usable */
+ int iTermOffset; /* Used internally - xBestIndex should ignore */
+ } *aConstraint; /* Table of WHERE clause constraints */
+ int nOrderBy; /* Number of terms in the ORDER BY clause */
+ struct sqlite3_index_orderby
+ {
+ int iColumn; /* Column number */
+ unsigned char desc; /* True for DESC. False for ASC. */
+ } *aOrderBy; /* The ORDER BY clause */
+ /* Outputs */
+ struct sqlite3_index_constraint_usage
+ {
+ int argvIndex; /* if >0, constraint is part of argv to xFilter */
+ unsigned char omit; /* Do not code a test for this constraint */
+ } *aConstraintUsage;
+ int idxNum; /* Number used to identify the index */
+ char *idxStr; /* String, possibly obtained from sqlite3_malloc */
+ int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
+ int orderByConsumed; /* True if output is already ordered */
+ double estimatedCost; /* Estimated cost of using this index */
};
/*
** 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
** destructor.
*/
SQLITE_API int sqlite3_create_module(
- sqlite3 *db, /* SQLite connection to register module with */
- const char *zName, /* Name of the module */
- const sqlite3_module *p, /* Methods for the module */
- void *pClientData /* Client data for xCreate/xConnect */
+ sqlite3 *db, /* SQLite connection to register module with */
+ const char *zName, /* Name of the module */
+ const sqlite3_module *p, /* Methods for the module */
+ void *pClientData /* Client data for xCreate/xConnect */
);
SQLITE_API int sqlite3_create_module_v2(
- sqlite3 *db, /* SQLite connection to register module with */
- const char *zName, /* Name of the module */
- const sqlite3_module *p, /* Methods for the module */
- void *pClientData, /* Client data for xCreate/xConnect */
- void(*xDestroy)(void*) /* Module destructor function */
+ sqlite3 *db, /* SQLite connection to register module with */
+ const char *zName, /* Name of the module */
+ const sqlite3_module *p, /* Methods for the module */
+ void *pClientData, /* Client data for xCreate/xConnect */
+ void(*xDestroy)(void *) /* Module destructor function */
);
/*
** is delivered up to the client application, the string will be automatically
** freed by sqlite3_free() and the zErrMsg field will be zeroed.
*/
-struct sqlite3_vtab {
- const sqlite3_module *pModule; /* The module for this virtual table */
- int nRef; /* NO LONGER USED */
- char *zErrMsg; /* Error message from sqlite3_mprintf() */
- /* Virtual table implementations will typically add additional fields */
+struct sqlite3_vtab
+{
+ const sqlite3_module *pModule; /* The module for this virtual table */
+ int nRef; /* NO LONGER USED */
+ char *zErrMsg; /* Error message from sqlite3_mprintf() */
+ /* Virtual table implementations will typically add additional fields */
};
/*
** This superclass exists in order to define fields of the cursor that
** are common to all implementations.
*/
-struct sqlite3_vtab_cursor {
- sqlite3_vtab *pVtab; /* Virtual table of this cursor */
- /* Virtual table implementations will typically add additional fields */
+struct sqlite3_vtab_cursor
+{
+ sqlite3_vtab *pVtab; /* Virtual table of this cursor */
+ /* Virtual table implementations will typically add additional fields */
};
/*
** to declare the format (the names and datatypes of the columns) of
** the virtual tables they implement.
*/
-SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
+SQLITE_API int sqlite3_declare_vtab(sqlite3 *, const char *zSQL);
/*
** 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.)^
**
** purpose is to be a placeholder function that can be overloaded
** by a [virtual table].
*/
-SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+SQLITE_API int sqlite3_overload_function(sqlite3 *, const char *zFuncName, int nArg);
/*
** The interface to the virtual-table mechanism defined above (back up
**
** ^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
** be released by a call to [sqlite3_blob_close()].
*/
SQLITE_API int sqlite3_blob_open(
- sqlite3*,
- const char *zDb,
- const char *zTable,
- const char *zColumn,
- sqlite3_int64 iRow,
- int flags,
- sqlite3_blob **ppBlob
+ sqlite3 *,
+ const char *zDb,
+ const char *zTable,
+ const char *zColumn,
+ sqlite3_int64 iRow,
+ int flags,
+ sqlite3_blob **ppBlob
);
/*
/*
** 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.
** the default. The choice for the new VFS is arbitrary.)^
*/
SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
-SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
-SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
+SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *, int makeDflt);
+SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *);
/*
** CAPI3REF: Mutexes
** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
*/
SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int);
-SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*);
-SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*);
-SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*);
-SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
+SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *);
+SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *);
+SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *);
+SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *);
/*
** CAPI3REF: Mutex Methods Object
** prior to returning.
*/
typedef struct sqlite3_mutex_methods sqlite3_mutex_methods;
-struct sqlite3_mutex_methods {
- int (*xMutexInit)(void);
- int (*xMutexEnd)(void);
- sqlite3_mutex *(*xMutexAlloc)(int);
- void (*xMutexFree)(sqlite3_mutex *);
- void (*xMutexEnter)(sqlite3_mutex *);
- int (*xMutexTry)(sqlite3_mutex *);
- void (*xMutexLeave)(sqlite3_mutex *);
- int (*xMutexHeld)(sqlite3_mutex *);
- int (*xMutexNotheld)(sqlite3_mutex *);
+struct sqlite3_mutex_methods
+{
+ int (*xMutexInit)(void);
+ int (*xMutexEnd)(void);
+ sqlite3_mutex *(*xMutexAlloc)(int);
+ void (*xMutexFree)(sqlite3_mutex *);
+ void (*xMutexEnter)(sqlite3_mutex *);
+ int (*xMutexTry)(sqlite3_mutex *);
+ void (*xMutexLeave)(sqlite3_mutex *);
+ int (*xMutexHeld)(sqlite3_mutex *);
+ int (*xMutexNotheld)(sqlite3_mutex *);
};
/*
** interface should also return 1 when given a NULL pointer.
*/
#ifndef NDEBUG
-SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
-SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
+SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *);
+SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *);
#endif
/*
/*
** 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
** routine returns a NULL pointer.
*/
-SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
+SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *);
/*
** CAPI3REF: Low-Level Control Of Database Files
**
** See also: [SQLITE_FCNTL_LOCKSTATE]
*/
-SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
+SQLITE_API int sqlite3_file_control(sqlite3 *, const char *zDbName, int op, void *);
/*
** CAPI3REF: Testing Interface
** <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.
**
**
** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
*/
-SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+SQLITE_API int sqlite3_db_status(sqlite3 *, int op, int *pCur, int *pHiwtr, int resetFlg);
/*
** CAPI3REF: Status Parameters for database connections
** 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
**
** See also: [sqlite3_status()] and [sqlite3_db_status()].
*/
-SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
+SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *, int op, int resetFlg);
/*
** CAPI3REF: Status Parameters for prepared statements
** [[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>
** See [sqlite3_pcache_methods2] for additional information.
*/
typedef struct sqlite3_pcache_page sqlite3_pcache_page;
-struct sqlite3_pcache_page {
- void *pBuf; /* The content of the page */
- void *pExtra; /* Extra information associated with the page */
+struct sqlite3_pcache_page
+{
+ void *pBuf; /* The content of the page */
+ void *pExtra; /* Extra information associated with the page */
};
/*
** 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]]
** do their best.
*/
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
-struct sqlite3_pcache_methods2 {
- int iVersion;
- void *pArg;
- int (*xInit)(void*);
- void (*xShutdown)(void*);
- sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
- void (*xCachesize)(sqlite3_pcache*, int nCachesize);
- 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*,
- unsigned oldKey, unsigned newKey);
- void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
- void (*xDestroy)(sqlite3_pcache*);
- void (*xShrink)(sqlite3_pcache*);
+struct sqlite3_pcache_methods2
+{
+ int iVersion;
+ void *pArg;
+ int (*xInit)(void *);
+ void (*xShutdown)(void *);
+ sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
+ void (*xCachesize)(sqlite3_pcache *, int nCachesize);
+ 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 *,
+ unsigned oldKey, unsigned newKey);
+ void (*xTruncate)(sqlite3_pcache *, unsigned iLimit);
+ void (*xDestroy)(sqlite3_pcache *);
+ void (*xShrink)(sqlite3_pcache *);
};
/*
** retained in the header file for backwards compatibility only.
*/
typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
-struct sqlite3_pcache_methods {
- void *pArg;
- int (*xInit)(void*);
- void (*xShutdown)(void*);
- sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable);
- void (*xCachesize)(sqlite3_pcache*, int nCachesize);
- int (*xPagecount)(sqlite3_pcache*);
- void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
- void (*xUnpin)(sqlite3_pcache*, void*, int discard);
- void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey);
- void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
- void (*xDestroy)(sqlite3_pcache*);
+struct sqlite3_pcache_methods
+{
+ void *pArg;
+ int (*xInit)(void *);
+ void (*xShutdown)(void *);
+ sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable);
+ void (*xCachesize)(sqlite3_pcache *, int nCachesize);
+ int (*xPagecount)(sqlite3_pcache *);
+ void *(*xFetch)(sqlite3_pcache *, unsigned key, int createFlag);
+ void (*xUnpin)(sqlite3_pcache *, void *, int discard);
+ void (*xRekey)(sqlite3_pcache *, void *, 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
** possible that they return invalid values.
*/
SQLITE_API sqlite3_backup *sqlite3_backup_init(
- sqlite3 *pDest, /* Destination database handle */
- const char *zDestName, /* Destination database name */
- sqlite3 *pSource, /* Source database handle */
- const char *zSourceName /* Source database name */
+ sqlite3 *pDest, /* Destination database handle */
+ const char *zDestName, /* Destination database name */
+ sqlite3 *pSource, /* Source database handle */
+ const char *zSourceName /* Source database name */
);
SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage);
SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p);
** ^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(
- sqlite3 *pBlocked, /* Waiting connection */
- void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */
- void *pNotifyArg /* Argument to pass to xNotify */
+ sqlite3 *pBlocked, /* Waiting connection */
+ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */
+ void *pNotifyArg /* Argument to pass to xNotify */
);
** ^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*,
- int(*)(void *,sqlite3*,const char*,int),
- void*
+ 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
** attached database, SQLITE_ERROR is returned to the caller.
*/
SQLITE_API int sqlite3_wal_checkpoint_v2(
- sqlite3 *db, /* Database handle */
- const char *zDb, /* Name of attached database (or NULL) */
- int eMode, /* SQLITE_CHECKPOINT_* value */
- int *pnLog, /* OUT: Size of WAL log in frames */
- int *pnCkpt /* OUT: Total number of frames checkpointed */
+ sqlite3 *db, /* Database handle */
+ const char *zDb, /* Name of attached database (or NULL) */
+ int eMode, /* SQLITE_CHECKPOINT_* value */
+ int *pnLog, /* OUT: Size of WAL log in frames */
+ int *pnCkpt /* OUT: Total number of frames checkpointed */
);
/*
** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
** may be added in the future.
*/
-SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
+SQLITE_API int sqlite3_vtab_config(sqlite3 *, int op, ...);
/*
** CAPI3REF: Virtual Table Configuration Options
** 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>
*/
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...)
*/
SQLITE_API int sqlite3_rtree_geometry_callback(
- sqlite3 *db,
- const char *zGeom,
+ sqlite3 *db,
+ const char *zGeom,
#ifdef SQLITE_RTREE_INT_ONLY
- int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes),
+ int (*xGeom)(sqlite3_rtree_geometry *, int n, sqlite3_int64 *a, int *pRes),
#else
- int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes),
+ int (*xGeom)(sqlite3_rtree_geometry *, int n, double *a, int *pRes),
#endif
- void *pContext
+ void *pContext
);
** A pointer to a structure of the following type is passed as the first
** argument to callbacks registered using rtree_geometry_callback().
*/
-struct sqlite3_rtree_geometry {
- void *pContext; /* Copy of pContext passed to s_r_g_c() */
- int nParam; /* Size of array aParam[] */
- double *aParam; /* Parameters passed to SQL geom function */
- void *pUser; /* Callback implementation user data */
- void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */
+struct sqlite3_rtree_geometry
+{
+ void *pContext; /* Copy of pContext passed to s_r_g_c() */
+ int nParam; /* Size of array aParam[] */
+ double *aParam; /* Parameters passed to SQL geom function */
+ void *pUser; /* Callback implementation user data */
+ void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */
};
SSM_CLEANUP_ASSERT(m_pContextRepository->registerResourceFinderEvent(this));
- SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IResponseReactor, (IBase **)&m_pResponseReactor));
+ SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ISensingEngine, (IBase **)&m_pSensingEngine));
SSM_CLEANUP_ASSERT(initializeEngine());
std::vector<ISSMResource *> contextModelList;
std::stringstream sstream;
- m_pResponseReactor->getList(&contextModelList);
+ m_pSensingEngine->getList(&contextModelList);
for (std::vector<ISSMResource *>::iterator itor = contextModelList.begin();
itor != contextModelList.end(); ++itor)
{
return res;
}
-SSMRESULT CPropagationEngine::installResponseReactor(IN IResponseReactor *pResponseReactor)
+SSMRESULT CPropagationEngine::installCurrentSensors()
{
SSMRESULT res = SSM_E_FAIL;
std::vector<ISSMResource *> contextModelList;
- pResponseReactor->getList(&contextModelList);
+ m_pSensingEngine->getList(&contextModelList);
for (std::vector<ISSMResource *>::iterator itor = contextModelList.begin();
itor != contextModelList.end(); ++itor)
SSM_CLEANUP_ASSERT(updateDeviceInfo(&ssmResource, NULL));
- SSM_CLEANUP_ASSERT(installResponseReactor(m_pResponseReactor));
+ SSM_CLEANUP_ASSERT(installCurrentSensors());
CLEANUP:
SAFE_RELEASE(pRootModel);
{
case IContextModel::STATUS_ACTIVATE:
pModel->addRef();
- m_pResponseReactor->registerContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
+ m_pSensingEngine->registerContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
break;
case IContextModel::STATUS_DEACTIVATE:
- m_pResponseReactor->unregisterContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
+ m_pSensingEngine->unregisterContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
//pModel->CleanUpModelData();
pModel->release();
break;
case IContextModel::STATUS_START_READ_VALUE:
//Model must be released from OnEvent callType
pModel->addRef();
- m_pResponseReactor->registerContext(SSM_ONCE, pSSMResource, (CContextModel *)pModel);
+ m_pSensingEngine->registerContext(SSM_ONCE, pSSMResource, (CContextModel *)pModel);
break;
case IContextModel::STATUS_STOP_READ_VALUE:
CSimpleMutex m_mtxContextModelList;
CSimpleMutex m_mtxLookUpList;
- CObjectPtr<IResponseReactor> m_pResponseReactor;
+ CObjectPtr<ISensingEngine> m_pSensingEngine;
CObjectPtr<IContextModel> m_pDeviceModel;
SSMRESULT addResourceFromGetList();
//TODO: Install Context model from SSMResource
- SSMRESULT installContextModelFromISSMResource(IN ISSMResource *pSSMResource);
+ SSMRESULT installCurrentSensors();
- SSMRESULT installResponseReactor(IN IResponseReactor *pResponseReactor);
+ SSMRESULT installContextModelFromISSMResource(IN ISSMResource *pSSMResource);
SSMRESULT installContextModel(IN IContextModel *pParentModel,
IN IContextModel::ConstructionType constructionType,
#ifndef _SSMCore_H_
#define _SSMCore_H_
-#include <string>
-#include <vector>
-
+#include "SSMInterface.h"
#include "SSMModelDefinition.h"
#define IN
*/
#define INTERFACE_DECLSPEC
-enum SSMRESULT
-{
- SSM_S_OK
- , SSM_S_FALSE
- , SSM_E_POINTER
- , SSM_E_OUTOFMEMORY
- , SSM_E_FAIL
- , SSM_E_NOINTERFACE
- , SSM_E_NOTIMPL
-};
-
-/**
-* @class IModelData
-* @brief IModelData Interface
-* This class represents context model data package
-*
-* @see
-*/
-class IModelData
-{
- public:
- /**
- * @fn getDataId
- * @brief Get affected DataId. ContextModel has plenty of data so \n
- * returned data is matched from given condition
- *
- * @param None
- *
- * @return int
- * @warning
- * @exception
- * @see
- */
- virtual int getDataId() = 0;
-
- /**
- * @fn GetPropertyCount
- * @brief ContextModel has at least one property that contains data \n
- * property is described from its specification.
- *
- * @param None
- *
- * @return int
- * @warning
- * @exception
- * @see
- */
- virtual int getPropertyCount() = 0;
-
- /**
- * @fn getPropertyName
- * @brief Retrieve propertyName
- *
- * @param [in] int propertyIndex - index of property to read
- *
- * @return std::string
- * @warning
- * @exception
- * @see
- */
- virtual std::string getPropertyName(IN int propertyIndex) = 0;
-
- /**
- * @fn getPropertyValue
- * @brief Retrieve propertyValue
- *
- * @param [in] int propertyIndex - index of property to read
- *
- * @return std::string
- * @warning
- * @exception
- * @see
- */
- virtual std::string getPropertyValue(IN int propertyIndex) = 0;
-
- /**
- * @fn getPropertyValueByName
- * @brief Retrieve propertyValue using given name
- *
- * @param [in] std::string propertyName - property name looking for
- *
- * @return std::string
- * @warning
- * @exception
- * @see
- */
- virtual std::string getPropertyValueByName(IN std::string propertyName) = 0;
- protected:
- virtual ~IModelData() {};
-};
-
-/**
-* @class IDataReader
-* @brief IDataReader Interface
-* This class represents context model data package's reader
-*
-* @see
-*/
-class IDataReader
-{
- public:
- /**
- * @fn getAffectedModels
- * @brief Get affected ContextModels. The CQL can specify multiple ContextModels for retrieving data.
- *
- * @param [out] std::vector<std::string> *pAffectedModels - affected ContextModel list
- *
- * @return SSMRESULT
- * @warning
- * @exception
- * @see
- */
- virtual SSMRESULT getAffectedModels(OUT std::vector<std::string> *pAffectedModels) = 0;
-
- /**
- * @fn getModelDataCount
- * @brief Get affected data count. There are multiple data can exist from given condition.
- *
- * @param [in] std::string modelName - affected ContextModel name
- *
- * @param [out] int *pDataCount - affected dataId count
- *
- * @return SSMRESULT
- * @warning
- * @exception
- * @see
- */
- virtual SSMRESULT getModelDataCount(IN std::string modelName, OUT int *pDataCount) = 0;
-
- /**
- * @fn getModelData
- * @brief Get actual Context Model data
- *
- * @param [in] std::string modelName - affected ContextModel name
- *
- *
- * @param [in] int dataIndex - affected dataId index
- *
- *
- * @param [out] IModelData **ppModelData - affected ContextModel data reader
- *
- * @return SSMRESULT
- * @warning
- * @exception
- * @see
- */
- virtual SSMRESULT getModelData(IN std::string modelName, IN int dataIndex,
- OUT IModelData **ppModelData) = 0;
- protected:
- virtual ~IDataReader() {};
-};
-
-/**
-* @class IQueryEngineEvent
-* @brief IQueryEngineEvent Interface
-* This class represents Query Engine's event that contains results
-*
-* @see
-*/
-class IQueryEngineEvent
-{
- public:
- /**
- * @fn onQueryEngineEvent
- * @brief Transmit result of SSMCore to Application layer
- *
- * @param [in] int cqid - entered ContextQuery ID
- *
- * @param [in] IDataReader *pResult - result of SSMCore
- *
- * @return SSMRESULT
- * @warning
- * @exception
- * @see
- */
- virtual SSMRESULT onQueryEngineEvent(IN int cqid, IN IDataReader *pResult) = 0;
- protected:
- virtual ~IQueryEngineEvent() {};
-};
-
/**
* @class IQueryEngine
* @brief IQueryEngine Interface
* limitations under the License.
*
******************************************************************/
+#include "SSMCore.h"
#include "SSMInterface/SSMCore_JNI.h"
#include "Common/PlatformLayer.h"
#define _SSMCore_JNI_H_
#include <jni.h>
-#include "SSMCore.h"
#ifdef __cplusplus
extern "C" {
#include "Common/InternalInterface.h"
using namespace OC;
-static std::vector< OC::AttributeMap > g_vecQueryEventResults;
+static std::vector< std::map<std::string, std::string> > g_vecQueryEventResults;
class CQueryEngineEvent: public IQueryEngineEvent
{
IModelData *pModelData = NULL;
std::vector < std::string > affectedModels;
- AttributeMap queryEventResult;
+ std::map<std::string, std::string> queryEventResult;
std::stringstream sstream;
// QueryEngine Id
- queryEventResult["queryEngineId"].push_back(m_queryEngineId);
+ queryEventResult["queryEngineId"] = m_queryEngineId;
// CQID
sstream << cqid;
- queryEventResult["CQID"].push_back(sstream.str());
+ queryEventResult["CQID"] = sstream.str();
sstream.str("");
pResult->getAffectedModels(&affectedModels);
// Affected Model Count
sstream << affectedModels.size();
- queryEventResult["modelCount"].push_back(sstream.str());
+ queryEventResult["modelCount"] = sstream.str();
sstream.str("");
//TODO: we assume that contains only one model at time
{
// Model Name
sstream << (*itor);
- queryEventResult["modelName"].push_back(sstream.str());
+ queryEventResult["modelName"] = sstream.str();
sstream.str("");
pResult->getModelDataCount(*itor, &dataCount);
// Data Count
sstream << dataCount;
- queryEventResult["dataCount"].push_back(sstream.str());
+ queryEventResult["dataCount"] = sstream.str();
sstream.str("");
//FixME: we have to support multiple data count
// Data Id
sstream << pModelData->getDataId();
- queryEventResult["dataId"].push_back(sstream.str());
+ queryEventResult["dataId"] = sstream.str();
sstream.str("");
// Property Count
sstream << pModelData->getPropertyCount();
- queryEventResult["propertyCount"].push_back(sstream.str());
+ queryEventResult["propertyCount"] = sstream.str();
sstream.str("");
for (int j = 0; j < pModelData->getPropertyCount(); j++)
{
// Property Name & Value
sstream << pModelData->getPropertyValue(j).c_str();
- queryEventResult[pModelData->getPropertyName(j).c_str()].push_back(sstream.str());
+ queryEventResult[pModelData->getPropertyName(j).c_str()] = sstream.str();
sstream.str("");
}
}
}
g_vecQueryEventResults.push_back(queryEventResult);
- OCPlatform::notifyObservers(m_hSSMResource);
+
+ //TODO: need to modify for notifying proper clients
+ OCPlatform::notifyAllObservers(m_hSSMResource);
return SSM_S_OK;
}
SSMResourceServer::SSMResourceServer()
{
- m_pPlatform = NULL;
m_hSSMResource = NULL;
}
int SSMResourceServer::initializeManager(std::string &xmlDescription)
{
SSMRESULT res = SSM_E_FAIL;
- CObjectPtr < IResourceConnectivity > pResourceConnectivity;
SSM_CLEANUP_ASSERT(InitializeSSMCore(xmlDescription));
SSM_CLEANUP_ASSERT(StartSSMCore());
- SSM_CLEANUP_ASSERT(
- CreateGlobalInstance(OID_IResourceConnectivity, (IBase **) &pResourceConnectivity));
-
- m_pPlatform = (OC::OCPlatform *) pResourceConnectivity->getPlatform();
-
if (createResource() != 0)
{
SSM_CLEANUP_ASSERT (SSM_E_FAIL);
int SSMResourceServer::createResource()
{
std::string resourceURI = "/service/SoftSensorManager"; // URI of the resource
- std::string resourceTypeName =
- "core.SoftSensorManager"; // resource type name. In this case, it is light
+ std::string resourceTypeName = "core.SoftSensorManager"; // resource type name.
std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
// This will internally create and register the resource.
- OCStackResult result = m_pPlatform->registerResource(m_hSSMResource, resourceURI,
+ OCStackResult result = OCPlatform::registerResource(m_hSSMResource, resourceURI,
resourceTypeName, resourceInterface,
- std::bind(&SSMResourceServer::entityHandler, this, std::placeholders::_1,
- std::placeholders::_2), resourceProperty);
+ std::bind(&SSMResourceServer::entityHandler, this, std::placeholders::_1
+ ), resourceProperty);
if (OC_STACK_OK != result)
{
return 0;
}
-void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > request,
- std::shared_ptr< OCResourceResponse > response)
+OCEntityHandlerResult SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > request)
{
SSMRESULT res = SSM_E_FAIL;
+ auto response = std::make_shared<OC::OCResourceResponse>();
+
if (request)
{
// Get the request type and request flag
std::string requestType = request->getRequestType();
- RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+ int requestFlag = request->getRequestHandlerFlag();
- if (requestFlag == RequestHandlerFlag::InitFlag)
+ response->setRequestHandle(request->getRequestHandle());
+ response->setResourceHandle(request->getResourceHandle());
+
+ if (requestFlag & RequestHandlerFlag::InitFlag)
{
// entity handler to perform resource initialization operations
}
- else if (requestFlag == RequestHandlerFlag::RequestFlag)
+
+ if (requestFlag & RequestHandlerFlag::RequestFlag)
{
+ cout << "\t\trequestFlag : Request\n";
+
// If the request type is GET
if (requestType == "GET")
{
- AttributeMap responseAttributeMap;
+ std::map<std::string, std::string> responseAttributeMap;
OCRepresentation rep = request->getResourceRepresentation();
if (response)
{
- rep.setAttributeMap(responseAttributeMap);
+ for (std::map<std::string, std::string>::iterator itor =
+ responseAttributeMap.begin(); itor != responseAttributeMap.end();
+ ++itor)
+ {
+ rep.setValue(itor->first, itor->second);
+ }
response->setErrorCode(200);
response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
{
OCRepresentation rep = request->getResourceRepresentation();
- AttributeMap requestAttributeMap = rep.getAttributeMap();
-
IQueryEngine *pQueryEngine = NULL;
std::stringstream sstream;
- AttributeMap responseAttributeMap;
-
// Process query params and do required operations ..
- if (requestAttributeMap["command"].back() == "CreateQueryEngine")
+ if (rep.getValue<std::string>("command") == "CreateQueryEngine")
{
CQueryEngineEvent *queryEngineEvent = NULL;
if (res != SSM_S_OK)
{
- responseAttributeMap["error"].push_back("CreateQueryEngine failed");
+ rep.setValue("error", "CreateQueryEngine failed");
goto CLEANUP;
}
if (queryEngineEvent == NULL)
{
- responseAttributeMap["error"].push_back(
- "QueryEngineEvent create failed");
+ rep.setValue("error", "QueryEngineEvent create failed");
goto CLEANUP;
}
if (res != SSM_S_OK)
{
- responseAttributeMap["error"].push_back("RegisterQueryEvent failed");
+ rep.setValue("error", "RegisterQueryEvent failed");
goto CLEANUP;
}
- responseAttributeMap["queryEngineId"].push_back(sstream.str());
+ rep.setValue("queryEngineId", sstream.str());
}
- else if (requestAttributeMap["command"].back() == "ReleaseQueryEngine")
+ else if (rep.getValue<std::string>("command") == "ReleaseQueryEngine")
{
- pQueryEngine = (IQueryEngine *) stoi(
- requestAttributeMap["queryEngineId"].back());
+ pQueryEngine = (IQueryEngine *) std::stoi(
+ rep.getValue<std::string>("queryEngineId"));
ReleaseQueryEngine(pQueryEngine);
}
- else if (requestAttributeMap["command"].back() == "ExecuteContextQuery")
+ else if (rep.getValue<std::string>("command") == "ExecuteContextQuery")
{
int CQID = 0;
- pQueryEngine = (IQueryEngine *) stoi(
- requestAttributeMap["queryEngineId"].back());
+ pQueryEngine = (IQueryEngine *) std::stoi(
+ rep.getValue<std::string>("queryEngineId"));
res = pQueryEngine->executeContextQuery(
- requestAttributeMap["contextQuery"].back(), &CQID);
+ rep.getValue<std::string>("contextQuery"), &CQID);
if (res != SSM_S_OK)
{
- responseAttributeMap["error"].push_back("ExecuteContextQuery failed");
+ rep.setValue("error", "ExecuteContextQuery failed");
goto CLEANUP;
}
sstream << CQID;
- responseAttributeMap["CQID"].push_back(sstream.str());
+ rep.setValue("CQID", sstream.str());
}
- else if (requestAttributeMap["command"].back() == "KillContextQuery")
+ else if (rep.getValue<std::string>("command") == "KillContextQuery")
{
- pQueryEngine = (IQueryEngine *) stoi(
- requestAttributeMap["queryEngineId"].back());
+ pQueryEngine = (IQueryEngine *) std::stoi(
+ rep.getValue<std::string>("queryEngineId"));
- res = pQueryEngine->killContextQuery(stoi(requestAttributeMap["CQID"].back()));
+ res = pQueryEngine->killContextQuery(std::stoi(rep.getValue<std::string>("CQID")));
if (res != SSM_S_OK)
{
- responseAttributeMap["error"].push_back("KillContextQuery failed");
+ rep.setValue("error", "KillContextQuery failed");
goto CLEANUP;
}
}
CLEANUP:
if (response)
{
- rep.setAttributeMap(responseAttributeMap);
-
response->setErrorCode(200);
response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
}
// DELETE request operations
}
}
- else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+
+ if (requestFlag & RequestHandlerFlag::ObserverFlag)
{
// perform observe related operations on the resource.
}
}
- else
- {
- }
+
+ return OCPlatform::sendResponse(response) == OC_STACK_OK ? OC_EH_OK : OC_EH_ERROR;
}
int initializeManager(std::string &xmlDescription);
int terminateManager();
- void entityHandler(std::shared_ptr< OC::OCResourceRequest > request,
- std::shared_ptr< OC::OCResourceResponse > response);
+ OCEntityHandlerResult entityHandler(std::shared_ptr< OC::OCResourceRequest > request);
private:
- OC::OCPlatform *m_pPlatform;
OCResourceHandle m_hSSMResource;
int createResource();
};
#include "QueryProcessor/ConditionedModel.h"
#include "QueryProcessor/EvaluationEngine.h"
#include "QueryProcessor/PropagationEngine.h"
-#include "SensorProcessor/ResponseReactor.h"
+#include "SensorProcessor/SensingEngine.h"
#include "SensorProcessor/ContextExecutor.h"
#include "SensorProcessor/ContextDataReader.h"
#include "SensorProcessor/ResourceFinder.h"
-#include "SensorProcessor/ResourceConnectivity.h"
inline bool operator<( const OID &lhs, const OID &rhs )
{
}
SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IContextRepository, (IBase **)&m_pContextRepository));
- SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IResponseReactor, (IBase **)&m_pResponseReactor));
- m_pContextRepository->setCurrentDeviceInfo(name, type, pathSoftSensors, pathDescription);
+ SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ISensingEngine, (IBase **)&m_pSensingEngine));
+ SSM_CLEANUP_ASSERT(m_pContextRepository->initRepository(name, type, pathSoftSensors,
+ pathDescription));
SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IPropagationEngine, (IBase **)&m_pPropagationEngine));
SSMRESULT CSoftSensorManager::getInstalledModelList(OUT std::vector<ISSMResource *> *pList)
{
- m_pResponseReactor->getList(pList);
+ m_pSensingEngine->getList(pList);
return SSM_S_OK;
}
SSM_CLEANUP_ASSERT(CreateInstance(OID_IContextDataReader, ppvObject));
}
}
- else if (IsEqualOID(OID_IResponseReactor, objectID))
+ else if (IsEqualOID(OID_ISensingEngine, objectID))
{
- if (g_globalInstance->find(OID_IResponseReactor) == g_globalInstance->end())
+ if (g_globalInstance->find(OID_ISensingEngine) == g_globalInstance->end())
{
- SSM_CLEANUP_ASSERT(CreateInstance(OID_IResponseReactor, ppvObject));
- }
- }
- else if (IsEqualOID(OID_IResourceConnectivity, objectID))
- {
- if (g_globalInstance->find(OID_IResourceConnectivity) == g_globalInstance->end())
- {
- SSM_CLEANUP_ASSERT(CreateInstance(OID_IResourceConnectivity, ppvObject));
+ SSM_CLEANUP_ASSERT(CreateInstance(OID_ISensingEngine, ppvObject));
}
}
else
{
SSM_CLEANUP_ASSERT(CreateNewObject<CContextRepository>(objectID, ppObject));
}
- else if (IsEqualOID(OID_IResponseReactor, objectID))
+ else if (IsEqualOID(OID_ISensingEngine, objectID))
{
- SSM_CLEANUP_ASSERT(CreateNewObject<CResponseReactor>(objectID, ppObject));
+ SSM_CLEANUP_ASSERT(CreateNewObject<CSensingEngine>(objectID, ppObject));
}
else if (IsEqualOID(OID_IContextExecutor, objectID))
{
{
SSM_CLEANUP_ASSERT(CreateNewObject<CContextDataReader>(objectID, ppObject));
}
- else if (IsEqualOID(OID_IResourceConnectivity, objectID))
- {
- SSM_CLEANUP_ASSERT(CreateNewObject<CResourceConnectivity>(objectID, ppObject));
- }
CLEANUP:
return res;
private:
CObjectPtr<IContextRepository> m_pContextRepository;
CObjectPtr<IPropagationEngine> m_pPropagationEngine;
- CObjectPtr<IResponseReactor> m_pResponseReactor;
+ CObjectPtr<ISensingEngine> m_pSensingEngine;
public:
SSMRESULT finalConstruct();
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2014 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************/
-
-/*
- * SSMResourceServerLauncher.cpp
- */
-#include "SSMResourceServer.h"
-
-string xmlDescription = "<SSMCore>"
- "<Device>"
- "<UDN>abcde123-31f8-11b4-a222-08002b34c003</UDN>"
- "<Name>MyPC</Name>"
- "<Type>PC</Type>"
- "</Device>"
- "</SSMCore>";
-
-using namespace std;
-
-int main(int argc, char *argv[])
-{
- int inputKey = 0;
-
- try
- {
- SSMResourceServer ssmResourceServer;
-
- cout << "Initializing Resource Server" << endl;
-
- if (ssmResourceServer.initializeManager(xmlDescription) != 0)
- {
- cout << "SSM Resource Server init failed" << endl;
- return -1;
- }
-
- cout << "SSM Resource Server is working, press anykey to terminate" << endl;
-
- cin >> inputKey;
-
- cout << "SSM Resource Server is terminating" << endl;
-
- if (ssmResourceServer.terminateManager() != 0)
- {
- cout << "SSM Resource Server terminate failed" << endl;
- }
- }
- catch (std::exception e)
- {
- cout << e.what() << endl;
- }
-
- cout << "bye bye" << endl;
-}
m_pContextDataReader->getContextData(modelName, startIndex, count, data, pLastIndex);
}
-std::string CContextExecutor::checkError(std::vector<ContextData> data)
-{
- std::string errorMsg = "OK";
-
- for (unsigned int i = 0 ; i < data.size() ; ++i)
- {
- if (data[i].outputProperty[0].find("error") != data[i].outputProperty[0].end())
- {
- errorMsg = data[i].outputProperty[0].find("error")->second ;
- break;
- }
- }
-
- return errorMsg;
-}
-
void CContextExecutor::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
IEvent *pEvent)
{
std::string primitiveSensor)
{
//check m_relatedSoftSensor / apply timestamp
- std::map<std::string, std::vector<ContextData> > returnData;
SSMRESULT ret = SSM_E_FAIL;
+ std::map<std::string, std::vector<ContextData> > returnData;
+ std::vector<ContextData> contextDataList;
+
for (unsigned int i = 0; i < m_relatedSoftSensor[primitiveSensor].size(); ++i)
{
std::string softSensorName = m_relatedSoftSensor[primitiveSensor][i];
{
ret = SSM_S_OK;
std::vector<std::string> inputList = m_registeredResources[softSensorName]->inputList;
- std::vector<ContextData> contextDataList;
for (unsigned int j = 0; j < inputList.size(); j++) //check all "inputlist" arrived or not
{
if (m_storedPrimitiveSensorData.find(inputList[j]) == m_storedPrimitiveSensorData.end())
{
+ //Still we have partial data
ret = SSM_E_FAIL;
break;
}
else
{
- std::vector<ContextData> primitiveSensorData = m_storedPrimitiveSensorData[inputList[j]];
- for (unsigned k = 0; k < primitiveSensorData.size(); k++)
+ //Copy all properties of current primitiveSensor data to outputs
+ for (std::vector<ContextData>::iterator itor = m_storedPrimitiveSensorData[inputList[j]].begin();
+ itor != m_storedPrimitiveSensorData[inputList[j]].end(); ++itor)
{
- contextDataList.push_back(primitiveSensorData[k]);
+ contextDataList.push_back(*itor);
}
}
}
+ //We have all inputs
if (ret == SSM_S_OK)
{
returnData.insert(std::make_pair(softSensorName, contextDataList));
//find soft sensor
std::map<std::string, std::vector<ContextData> > readyContextList = getPreparedContextList(type);
- if (readyContextList.size() > 0)
+ //Run SoftSensor! readyContextList has all data for run
+ std::map<std::string, std::vector<ContextData> >::iterator iter;
+ for (iter = readyContextList.begin(); iter != readyContextList.end(); ++iter)
{
- //Run SoftSensor! readyContextList has all data for run
- std::map<std::string, std::vector<ContextData> >::iterator iter = readyContextList.begin();
- for (; iter != readyContextList.end(); ++iter)
- {
- std::string softSensorName = iter->first;
- std::vector<ContextData> inputData = iter->second;
- std::string errorMsg = checkError(inputData);
+ std::string softSensorName = iter->first;
+ std::vector<ContextData> inputData = iter->second;
- if (!errorMsg.compare("OK"))
- {
- runLogic(inputData, softSensorName);
- }
- else
- {
- inputData.clear();
- inputData.push_back(makeErrorContextData(softSensorName, errorMsg));
- addOutput(inputData);
- }
- }
+ runLogic(inputData, softSensorName);
}
}
else //This data is primitive
m_ctxEventList[softSensor]->onCtxEvent(SPF_START, inputData);
}
m_mtxLibraryIO.unlock();
-}
-
-ContextData CContextExecutor::makeErrorContextData(std::string rootName, std::string errMsg)
-{
- std::map<std::string, std::string> errorMap;
- ContextData errorContextData;
-
- errorMap.insert(std::make_pair("error", errMsg));
- errorMap.insert(std::make_pair("available", "false"));
- errorContextData.rootName = rootName;
- errorContextData.outputPropertyCount = 2;
- errorContextData.outputProperty.push_back(errorMap);
-
- return errorContextData;
}
\ No newline at end of file
std::map<std::string, std::vector<ContextData> > getPreparedContextList(
IN std::string primitiveSensor);
void runLogic(IN std::vector<ContextData> inputData, IN std::string softSensor);
- ContextData makeErrorContextData(IN std::string rootName, IN std::string errMsg);
- std::string checkError(IN std::vector<ContextData> data);
-
};
#endif
{
}
-void CContextRepository::setCurrentDeviceInfo(IN std::string name, IN std::string type,
+SSMRESULT CContextRepository::initRepository(IN std::string name, IN std::string type,
IN std::string pathSoftSensors, IN std::string pathDescription)
{
- //TODO: Someone need to provides a way to generate permanent uuid function
- /*
- m_currentDeviceInfo.friendlyName = name;
- //m_currentDeviceInfo.ID="2fac1234-31f8-11b4-a222-08002b34c003";
- m_currentDeviceInfo.ID = udn;
- m_currentDeviceInfo.IPAddress = "127.0.0.1";
- m_currentDeviceInfo.tp = tp;
- //m_currentDeviceInfo.type = SSM_DEVICE_MOBILE;
- m_currentDeviceInfo.type = td;
- */
+ SSMRESULT res = SSM_E_FAIL;
+
+ std::vector<DictionaryData> dict;
+
m_name = name;
m_type = type;
- m_pathSoftSensors = pathSoftSensors;
- m_pathSoftSensorsDescription = pathDescription;
+
+ if (pathSoftSensors.length() == 0)
+ {
+ SSM_CLEANUP_ASSERT(GetCurrentPath(&m_pathSoftSensors));
+ m_pathSoftSensors.append("/");
+ }
+ else
+ {
+ m_pathSoftSensors = pathSoftSensors;
+ }
+
+ if (pathDescription.length() == 0)
+ {
+ SSM_CLEANUP_ASSERT(GetCurrentPath(&m_pathSoftSensorsDescription));
+ m_pathSoftSensorsDescription.append("/");
+ m_pathSoftSensorsDescription.append(DEFAULT_PATH_SOFT_SENSORS);
+ }
+ else
+ {
+ m_pathSoftSensorsDescription = pathDescription;
+ }
+
+
+ SSM_CLEANUP_ASSERT(loadXMLFromFile(m_pathSoftSensorsDescription.c_str(), &dict));
+ SSM_CLEANUP_ASSERT(makeSSMResourceListForDictionaryData(dict, &m_lstSoftSensor));
+
+CLEANUP:
+ return res;
}
SSMRESULT CContextRepository::loadXMLFromString(char *xmlData,
keyStr = subItem->name(); // key
valueStr = subItem->value(); // value
- if (!keyStr.compare("root_name"))
+ if (!keyStr.compare("name"))
{
dictionaryData.rootName = trim_both(valueStr);
}
keyStr = subItem2->name(); // key
valueStr = subItem2->value(); // value
- if (!keyStr.compare("attribute_property_count"))
- {
- dictionaryData.attributePropertyCount = trim_both(valueStr);
- }
- else if (!keyStr.compare("output_property_count"))
- {
- dictionaryData.outputPropertyCount = trim_both(valueStr);
- }
- if (!keyStr.compare("inputs_count"))
- {
- dictionaryData.inputCount = trim_both(valueStr);
- }
- else if (!keyStr.compare("app_inputs_count"))
- {
- dictionaryData.appInputCount = trim_both(valueStr);
- }
- else if (!keyStr.compare("app_input"))
- {
- dictionaryData.appInputs.push_back(trim_both(valueStr));
- }
- else if (!keyStr.compare("input"))
+ if (!keyStr.compare("input"))
{
dictionaryData.inputs.push_back(trim_both(valueStr));
}
////std::cout<<name << " :: " << subItem2->value() <<std::endl<<std::endl;
for (subItem3 = subItem2->first_node(); subItem3 ; subItem3 = subItem3->next_sibling())
{
-
std::string newKeyStr = subItem3->name(); // key
valueStr = subItem3->value(); // value
- if (!keyStr.compare("attribute_property") || !keyStr.compare("output_property") )
- {
- propertyMap.insert(std::make_pair(trim_both(newKeyStr), trim_both(valueStr))) ;
- }
- else if (!keyStr.compare("enter_condition"))
+ if (!keyStr.compare("attribute") || !keyStr.compare("output") )
{
- enterconditionVector.push_back(trim_both(valueStr));
+ propertyMap.insert(std::make_pair(trim_both(newKeyStr), trim_both(valueStr)));
}
}
- if (!keyStr.compare("attribute_property"))
+ if (!keyStr.compare("attribute"))
{
dictionaryData.attributeProperty.push_back(propertyMap);
}
- else if (!keyStr.compare("output_property"))
+ else if (!keyStr.compare("output"))
{
dictionaryData.outputProperty.push_back(propertyMap);
}
- else if (!keyStr.compare("enter_condition"))
- {
- dictionaryData.enterConditions.push_back(enterconditionVector);
- }
}
}
//for accurate data.
SSMRESULT res = SSM_E_FAIL;
std::basic_ifstream< char > xmlFile(descriptionFilePath.c_str());
- if (descriptionFilePath.length() > 0 && xmlFile.fail())
- {
- //error while opening given path, return error
- SSM_CLEANUP_ASSERT(SSM_E_FAIL);
- }
-
- if (descriptionFilePath.length() == 0)
- {
- //No given path, try to open local Path
- std::string path;
- SSM_CLEANUP_ASSERT(GetCurrentPath(&path));
- path.append("/");
- path.append(DEFAULT_PATH_SOFT_SENSORS);
- xmlFile.open(path);
- }
-
//path loaded
if (!xmlFile.fail())
{
SSMRESULT CContextRepository::getSoftSensorList(OUT std::vector<ISSMResource *> *pSoftSensorList)
{
- SSMRESULT res = SSM_E_FAIL;
- std::vector<DictionaryData> dict;
-
- SSM_CLEANUP_ASSERT(loadXMLFromFile(m_pathSoftSensorsDescription.c_str(), &dict));
-
- SSM_CLEANUP_ASSERT(makeSSMResourceListForDictionaryData(dict, pSoftSensorList));
+ for (size_t i = 0; i < m_lstSoftSensor.size(); i++)
+ {
+ pSoftSensorList->push_back(m_lstSoftSensor.at(i));
+ }
-CLEANUP:
- return res;
+ return SSM_S_OK;
}
SSMRESULT CContextRepository::getPrimitiveSensorList(OUT std::vector<ISSMResource *>
*pPrimitiveSensorList)
{
- for (size_t i = 0; i < m_lstSensor.size(); i++)
+ for (size_t i = 0; i < m_lstPrimitiveSensor.size(); i++)
{
- pPrimitiveSensorList->push_back(m_lstSensor.at(i));
+ pPrimitiveSensorList->push_back(m_lstPrimitiveSensor.at(i));
}
return SSM_S_OK;
SSMRESULT CContextRepository::onResourceFound(IN ISSMResource *pSensor)
{
- m_lstSensor.push_back(pSensor);
+ m_lstPrimitiveSensor.push_back(pSensor);
for (size_t i = 0; i < m_resourceEvents.size(); i++)
{
SSMRESULT CContextRepository::onResourceLost(IN ISSMResource *pSensor)
{
std::vector<ISSMResource *>::iterator itor;
- itor = std::find(m_lstSensor.begin(), m_lstSensor.end(), pSensor);
+ itor = std::find(m_lstPrimitiveSensor.begin(), m_lstPrimitiveSensor.end(), pSensor);
- if (itor != m_lstSensor.end())
+ if (itor != m_lstPrimitiveSensor.end())
{
- m_lstSensor.erase(itor);
+ m_lstPrimitiveSensor.erase(itor);
return SSM_S_OK;
}
typedef void(*InitContext)(IN ICtxDelegate *);
InitContext InitializeContextFunction = NULL;
- if (m_pathSoftSensors.length() == 0)
- {
- SSM_CLEANUP_ASSERT(GetCurrentPath(&m_pathSoftSensors));
- }
-
- m_pathSoftSensors.append("/");
-
// load dll(so)
res = SSM_E_FAIL;
for (unsigned int i = 1; i <= SSM_MODEL_RETRY; ++i)
#endif
if (hModule == NULL)
{
- InitializeContextFunction = NULL;
- continue;
+ //load library failed. raise error
+ SSM_CLEANUP_ASSERT(SSM_E_FAIL);
+ //InitializeContextFunction = NULL;
+ //continue;
}
if (InitializeContextFunction != NULL)
{
private:
CSimpleMutex m_mtxFileIO;
- std::vector<ISSMResource *> m_lstSensor;
+ std::vector<ISSMResource *> m_lstPrimitiveSensor;
+ std::vector<ISSMResource *> m_lstSoftSensor;
CObjectPtr<IResourceFinder> m_resourceFinder;
std::string m_name;
std::string m_type;
/**
- * @fn setCurrentDeviceInfo
- * @brief set device information
+ * @fn initRepository
+ * @brief initialize repository using given info
*
* @param [in] std::string name - Device name
* @param [in] std::string type - Device Type
* @param [in] std::string pathSoftSensors - SoftSensors Repository path
* @param [in] std::string pathDescription - SoftSensors Description path
- * @return void
+ * @return SSMRESULT
*
* @warning
* @exception
* @see
*/
- void setCurrentDeviceInfo(IN std::string name, IN std::string type, IN std::string pathSoftSensors,
- IN std::string pathDescription);
+ SSMRESULT initRepository(IN std::string name, IN std::string type, IN std::string pathSoftSensors,
+ IN std::string pathDescription);
/**
* @fn getSoftSensorList
+++ /dev/null
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************/
-#include "ResourceConnectivity.h"
-
-SSMRESULT CResourceConnectivity::finalConstruct()
-{
- SSMRESULT res = SSM_E_FAIL;
- OC::PlatformConfig cfg(OC::ServiceType::InProc, OC::ModeType::Both,
- "134.134.161.33", 56831, OC::QualityOfService::NonConfirmable);
-
- m_pPlatform = new OC::OCPlatform(cfg);
-
- SSM_CLEANUP_NULL_ASSERT(m_pPlatform);
-
- res = SSM_S_OK;
-
-CLEANUP:
- return res;
-}
-
-void CResourceConnectivity::finalRelease()
-{
- SAFE_DELETE(m_pPlatform);
-}
-
-void *CResourceConnectivity::getPlatform()
-{
- return m_pPlatform;
-}
+++ /dev/null
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************/
-#ifndef _ResourceConnectivity_H_
-#define _ResourceConnectivity_H_
-
-#include "SSMInterface/SSMCore.h"
-#include "Common/PlatformLayer.h"
-#include "Common/InternalInterface.h"
-#include "OCPlatform.h"
-
-class CResourceConnectivity :
- public CObjectRoot<CObjectMultiThreadModel>
- , public IResourceConnectivity
-{
- public:
- SSMRESULT queryInterface(const OID &objectID, IBase **ppObject)
- {
- if (ppObject == NULL)
- return SSM_E_POINTER;
-
- if (IsEqualOID(objectID, OID_IResourceConnectivity))
- {
- IBase *pBase = (IResourceConnectivity *)this;
- pBase->addRef();
- *ppObject = pBase;
- return SSM_S_OK;
- }
-
- return SSM_E_NOINTERFACE;
- }
-
- SSMRESULT finalConstruct();
- void finalRelease();
-
- void *getPlatform();
-
- private:
- OC::OCPlatform *m_pPlatform;
-};
-
-#endif
{
SSMRESULT res = SSM_E_FAIL;
+ OC::PlatformConfig cfg(OC::ServiceType::InProc, OC::ModeType::Both,
+ "0.0.0.0", 0, OC::QualityOfService::LowQos);
+
SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ITasker, (IBase **)&m_pTasker));
- SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IResourceConnectivity,
- (IBase **)&m_pResourceConnectivity));
+
+ OC::OCPlatform::Configure(cfg);
m_pResourceFinderEvent = NULL;
- m_pPlatform = (OC::OCPlatform *)m_pResourceConnectivity->getPlatform();
CLEANUP:
return res;
SSMRESULT CResourceFinder::startResourceFinder()
{
- //m_pPlatform->findResource("", "oc/core/service/SoftSensorManager/SoftSensor",
- m_pPlatform->findResource("", "coap://224.0.1.187/oc/core?rt=SoftSensorManager.Sensor",
- std::bind(&CResourceFinder::onResourceFound, this, std::placeholders::_1));
+ OCStackResult res = OC_STACK_ERROR;
+
+ res = OC::OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=SoftSensorManager.Sensor",
+ std::bind(&CResourceFinder::onResourceFound, this, std::placeholders::_1));
+
+ if (res != OC_STACK_OK)
+ return SSM_E_FAIL;
return SSM_S_OK;
}
SSM_CLEANUP_ASSERT(pResourceHandler->initHandler(*pResource, this));
m_mapResourceHandler[pResource->get()->host() + pResource->get()->uri()] = pResourceHandler;
pResource->get()->get(queryParams, std::bind(&OICResourceHandler::onGetResourceProfile,
- pResourceHandler, std::placeholders::_1, std::placeholders::_2));
+ pResourceHandler, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
break;
case RESOURCE_DISCOVER_SETUP_RESOURCE:
#include "Common/PlatformLayer.h"
#include "Common/InternalInterface.h"
#include "OCPlatform.h"
+#include "OCApi.h"
class CResourceFinder :
public CObjectRoot<CObjectMultiThreadModel>
m_pResource.get()->observe(OC::ObserveType::Observe, queryParams,
std::bind(&OICResourceHandler::onResourceDataReceived,
- this, std::placeholders::_1, std::placeholders::_2));
+ this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
return SSM_S_OK;
}
return SSM_S_OK;
}
- void onResourceDataReceived(const OC::OCRepresentation &representation, const int &eCode)
+ void onResourceDataReceived(const OC::HeaderOptions headerOptions,
+ const OC::OCRepresentation &representation,
+ const int &eCode, const int &sequenceNumber)
{
if (eCode == 0)
{
std::vector<ContextData> lstCtxData;
ContextData ctxData;
std::map<std::string, std::string> outputProperty;
- OC::AttributeMap attributeMap = representation.getAttributeMap();
//Bind data
ctxData.rootName = m_pResource->uri().substr(1);
//TODO: Temporally used for json parsing limitation
- ctxData.outputPropertyCount = attributeMap.size() / 3;
+ ctxData.outputPropertyCount = representation.numberOfAttributes() / 3;
if (ctxData.outputPropertyCount > 0)
{
- for (size_t i = 0; i < attributeMap.size() / 3; i++)
+ for (int i = 0; i < ctxData.outputPropertyCount; i++)
{
- outputProperty["name"] = attributeMap.find(std::to_string(i * 3))->second.front();
- outputProperty["type"] = attributeMap.find(std::to_string(i * 3 + 1))->second.front();
- outputProperty["value"] = attributeMap.find(std::to_string(i * 3 + 2))->second.front();
+ outputProperty["name"] = representation.getValue<std::string>(toString(i * 3));
+ outputProperty["type"] = representation.getValue<std::string>(toString(i * 3 + 1));
+ outputProperty["value"] = representation.getValue<std::string>(toString(i * 3 + 2));
ctxData.outputProperty.push_back(outputProperty);
}
}
}
- void onGetResourceProfile(const OC::OCRepresentation &representation, const int &eCode)
+ void onGetResourceProfile(const OC::HeaderOptions &headerOptions,
+ const OC::OCRepresentation &representation, const int &eCode)
{
//unpack attributeMap
//Create SSMResource using OCResource attributeMap
std::map<std::string, std::string> outputProperty;
- OC::AttributeMap attributeMap = representation.getAttributeMap();
ISSMResource *pSSMResource = new ISSMResource();
pSSMResource->location = SENSOR_LOCATION_REMOTE;
pSSMResource->name = m_pResource->host() + m_pResource->uri();
//bind default primitive sensor property, value to resource class for schema creating
//TODO: Temporally used for json parsing limitation
- for (size_t i = 0; i < attributeMap.size() / 3; i++)
+ for (int i = 0; i < representation.numberOfAttributes() / 3; i++)
{
- outputProperty["name"] = attributeMap.find(std::to_string(i * 3))->second.front();
- outputProperty["type"] = attributeMap.find(std::to_string(i * 3 + 1))->second.front();
- outputProperty["value"] = attributeMap.find(std::to_string(i * 3 + 2))->second.front();
+ outputProperty["name"] = representation.getValue<std::string>(toString(i * 3));
+ outputProperty["type"] = representation.getValue<std::string>(toString(i * 3 + 1));
+ outputProperty["value"] = representation.getValue<std::string>(toString(i * 3 + 2));
pSSMResource->outputProperty.push_back(outputProperty);
}
/////////////////////////////////////////////////////
std::shared_ptr<OC::OCResource> m_pResource;
IThreadClient *m_pResourceFinderClient;
IEvent *m_pEvent;
+
+ std::string toString(int t)
+ {
+ std::ostringstream os;
+ os << t;
+ return os.str();
+ }
};
enum RESOURCE_DISCOVER_STATE {RESOURCE_DISCOVER_REQUESTPROFILE, RESOURCE_DISCOVER_SETUP_RESOURCE};
- OC::OCPlatform *m_pPlatform;
- CObjectPtr<IResourceConnectivity> m_pResourceConnectivity;
IResourceFinderEvent *m_pResourceFinderEvent;
CObjectPtr<ITasker> m_pTasker;
std::map<std::string , OICResourceHandler *> m_mapResourceHandler;
* limitations under the License.
*
******************************************************************/
-#include "ResponseReactor.h"
+#include "SensingEngine.h"
-SSMRESULT CResponseReactor::finalConstruct()
+SSMRESULT CSensingEngine::finalConstruct()
{
SSMRESULT res = SSM_S_OK;
return res;
}
-void CResponseReactor::finalRelease()
+void CSensingEngine::finalRelease()
{
}
-void CResponseReactor::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
- IEvent *pEvent)
+SSMRESULT CSensingEngine::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
+ IEvent *pEvent)
{
m_mtxRequestedContextData.lock();
// if already exists
m_pContextExecutor->registerContext(callType, pSSMResource, this);
m_mtxRequestedContextData.unlock();
+
+ return SSM_S_OK;
}
-void CResponseReactor::unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
+SSMRESULT CSensingEngine::unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
IEvent *pEvent)
{
m_mtxUnregisterContext.lock();
}
m_mtxUnregisterContext.unlock();
+
+ return SSM_S_OK;
}
-void CResponseReactor::getList(std::vector<ISSMResource *> *pList)
+SSMRESULT CSensingEngine::getList(std::vector<ISSMResource *> *pList)
{
pList->clear();
m_pContextRepository->getSoftSensorList(pList);
m_pContextRepository->getPrimitiveSensorList(pList);
+
+ return SSM_S_OK;
}
//Dispatch to upper layer
-int CResponseReactor::onEvent(std::string type, TypeofEvent callType,
- std::vector<ContextData> ctxData)
+int CSensingEngine::onEvent(std::string type, TypeofEvent callType,
+ std::vector<ContextData> ctxData)
{
std::map<std::string, CallbackData >::iterator itor;
#include "SSMInterface/SSMCore.h"
#include "Common/PlatformLayer.h"
-
-//temp include
-#include "ContextRepository.h"
-#include "ContextExecutor.h"
+#include "Common/InternalInterface.h"
/**
- * @class CResponseReactor
- * @brief Class for implement of reactor pattern
- * Delegate requested context to context executor layer.
+ * @class CSensingEngine
+ * @brief Class for implementing main abstration of SensorProcessor
*
*
* @see
*/
-class CResponseReactor :
+class CSensingEngine :
public CObjectRoot<CObjectMultiThreadModel>
- , public IResponseReactor
+ , public ISensingEngine
{
private:
CObjectPtr<IContextRepository> m_pContextRepository;
CSimpleMutex m_mtxUnregisterContext;
public:
-
SSMRESULT finalConstruct();
void finalRelease();
if (ppObject == NULL)
return SSM_E_POINTER;
- if (IsEqualOID(objectID, OID_IResponseReactor))
+ if (IsEqualOID(objectID, OID_ISensingEngine))
{
IBase *pBase = this;
pBase->addRef();
* @param [in] ISSMResource *pSSMResource - Requested context model resource.
* @param [in] IEvent *pEvent - IEvent class for callback.
*
- * @return void
+ * @return SSMRESULT
*
* @warning
* @exception
* @see
*/
- void registerContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource, IN IEvent *pEvent);
+ SSMRESULT registerContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource,
+ IN IEvent *pEvent);
/**
* @fn unregisterContext
* @param [in] ISSMResource *pSSMResource - Requested context model resource.
* @param [in] IEvent *pEvent - IEvent class for callback.
*
- * @return void
+ * @return SSMRESULT
*
* @warning
* @exception
* @see
*/
- void unregisterContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource, IN IEvent *pEvent);
+ SSMRESULT unregisterContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource,
+ IN IEvent *pEvent);
/**
* @fn getList
*
* @param [out] std::vector<ISSMResource> *pList - ISSMResource vector of low level context models or high level context models.
*
- * @return void
+ * @return SSMRESULT
*
* @warning
* @exception
* @see
*/
- virtual void getList(OUT std::vector<ISSMResource *> *pList);
+ SSMRESULT getList(OUT std::vector<ISSMResource *> *pList);
/**
* @fn onEvent
*/
int onEvent(IN std::string name, IN TypeofEvent callType, IN std::vector<ContextData> ctxData);
};
-
-
-#endif
+#endif
\ No newline at end of file
--- /dev/null
+##
+# sampleapp build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+sample_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+
+######################################################################
+# Build flags
+######################################################################
+
+######################################################################
+# Source files and Targets
+######################################################################
+if target_os == 'linux' :
+ # Build linux sample app
+ SConscript('linux/SSMTesterApp/SConscript')
+ SConscript('linux/THSensorApp/SConscript')
+ SConscript('linux/THSensorApp1/SConscript')
+# //******************************************************************
+# //
+# // Copyright 2014 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 ../../../../build/arduino/environment.mk
-
ARDUINO_DIR = /usr/share/arduino
-SRC_PATH=../src
+BUILD := release
+PLATFORM := arduinomega
+ARDUINO_PORT := ttyACM0
+
+SRC_PATH=../src
# override with `make PLATFORM=arduinomega ARDUINOWIFI=1` to enable Arduino WiFi shield
ARDUINOWIFI := 0
APP_NAME := thserver
-BUILD := release
-#BUILD := debug
-PLATFORM := arduinomega
-ARDUINO_PORT := /dev/ttyACM0
-
-OBJ_DIR := ./bin
-
-TB_DIR = ${IOT_BASE}/csdk
-BUILD_DIR = $(TB_DIR)/build/arduino
+TB_DIR = ../../../../../../resource/csdk
LOGGER_DIR = $(TB_DIR)/logger
+OC_LOG_DIR = $(TB_DIR)/../oc_logger
TBSTACK_DIR = $(TB_DIR)/stack
TBSOCKET_DIR = $(TB_DIR)/ocsocket
OCSOCK_DIR = $(TB_DIR)/ocsocket
LOGGER_DIR = $(TB_DIR)/logger
STACK_DIR = $(TB_DIR)/stack
-INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include -I$(STACK_DIR)/include
+INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(OC_LOG_DIR)/include -I$(LOGGER_DIR)/include -I$(STACK_DIR)/include
+
+CC_FLAGS.debug := -O1 -g3 -Wall -c -fmessage-length=0 -pedantic -fpic
+CC_FLAGS.release := -Os -Wall -c -fmessage-length=0 -fpic
-CFLAGS := -Os -Wall -c -DTB_LOG
+CFLAGS := $(CC_FLAGS.$(BUILD)) -DTB_LOG
ifeq ($(ARDUINOWIFI),1)
CFLAGS += -DARDUINOWIFI
+ ARDUINO_SHIELD_TYPE := "/wifi_shield"
+ TRANSPORT_OBJS = $(WIFI_COBJ)
+else
+ ARDUINO_SHIELD_TYPE := "/ethernet_shield"
+ TRANSPORT_OBJS = $(ETH_CPPOBJ) $(ETH_UTIL_CPPOBJ)
endif
-#all: prep_dirs core.a $(APP_NAME).o $(APP_NAME).elf $(APP_NAME).hex
-all: preclean prebuild precopy prep_dirs core.a $(APP_NAME).o $(APP_NAME).elf $(APP_NAME).hex
+OUT_DIR := $(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD)
-precopy:
-# @cd $(TB_DIR) && mkdir -p ${BUILD} && cp -Rdp release/liboctbstack.a ${BUILD}/
+OBJ_DIR := $(OUT_DIR)/bin
-preclean:
- @cd $(BUILD_DIR) && make deepclean
-
-prebuild:
- @cd $(BUILD_DIR) && make PLATFORM=arduinomega ARDUINOWIFI=0
+all: prep_dirs core.a $(APP_NAME).o $(APP_NAME).elf $(APP_NAME).hex
core.a: $(PLATFORM_OBJS)
- @cd $(OBJ_DIR) && $(AR) -x $(TB_DIR)/build/arduino/$(BUILD)/liboctbstack.a
- $(AR) rcs $@ $^ $(OBJ_DIR)/*.o
- $(RANLIB) $@
+ @cd $(OBJ_DIR) && $(AR) -x ../../../../$(TB_DIR)/$(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD)/liboctbstack.a
+ $(AR) rcs $(OBJ_DIR)/$@ $(foreach obj, $^, $(OBJ_DIR)/$(obj)) $(OBJ_DIR)/*.o
+ @cd $(OBJ_DIR) && $(RANLIB) $@
prep_dirs:
+ -mkdir $(PLATFORM)
+ -mkdir $(PLATFORM)/$(ARDUINO_SHIELD_TYPE)
+ -mkdir $(OUT_DIR)
-mkdir $(OBJ_DIR)
%.o: %.c
- $(CC) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $@
-
+ $(CC) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $(OBJ_DIR)/$@
%.o: %.cpp
- $(CCPLUS) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $@
-
+ $(CXX) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $(OBJ_DIR)/$@
%.o: ${SRC_PATH}/%.cpp
- $(CCPLUS) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $@
+ $(CXX) $(CFLAGS) $(CFLAGS_PLATFORM) $(INC_DIRS) $(INC_DIR_PLATFORM) $< -o $(OBJ_DIR)/$@
$(APP_NAME).elf: $(APP_NAME).o core.a
- $(CC) -Os -Wl,--gc-sections,--relax $(CFLAGS_PLATFORM) $^ -lm -o $@
+ifeq ($(PLATFORM),arduinomega)
+ $(CC) -Os -Wl,--gc-sections,--relax $(CFLAGS_PLATFORM) $(foreach obj, $^, $(OBJ_DIR)/$(obj)) -lm -o $(OBJ_DIR)/$@
+else ifeq ($(PLATFORM),arduinodue)
+ $(CXX) -Os -Wl,--gc-sections -mcpu=cortex-m3 -T/$(SDIR_ARD_CORE_3)/linker_scripts/gcc/flash.ld -Wl,-Map,$(APP_NAME).map -o $(OBJ_DIR)/$@ -lm -lgcc -mthumb -Wl,--cref -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 $(foreach obj, $(APP_NAME).o $(SYSCALLS_SAM3_OBJ) $(SPI_OBJ) $(TRANSPORT_OBJS) $(VARIANT_OBJ) core.a, $(OBJ_DIR)/$(obj)) $(SDIR_ARD_CORE_3)/libsam_sam3x8e_gcc_rel.a -Wl,--end-group
+else
+ $(error Wrong value for PLATFORM !!)
+endif
$(APP_NAME).hex: $(APP_NAME).elf
- $(AVR_OBJCOPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $< $(APP_NAME).eep
- $(AVR_OBJCOPY) -O ihex -R .eeprom $< $@
+ifeq ($(PLATFORM),arduinomega)
+ $(AVR_OBJCOPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $(OBJ_DIR)/$< $(OBJ_DIR)/$(APP_NAME).eep
+ $(AVR_OBJCOPY) -O ihex -R .eeprom $(OBJ_DIR)/$< $(OUT_DIR)/$@
+else ifeq ($(PLATFORM),arduinodue)
+ $(ARDUINO_TOOLS_DIR)/arm-none-eabi-objcopy -O binary $(OBJ_DIR)/$< $(OUT_DIR)/$@
+else
+ $(error Wrong value for PLATFORM !!)
+endif
install: all
- $(AVR_PROGRAMMER) -C$(ARDUINO_DIR)/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P$(ARDUINO_PORT) -b115200 -D -Uflash:w:$(APP_NAME).hex:i
+ifeq ($(PLATFORM),arduinomega)
+ $(AVR_PROGRAMMER) -C$(ARDUINO_DIR)/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P/dev/$(ARDUINO_PORT) -b115200 -D -Uflash:w:$(OUT_DIR)/$(APP_NAME).hex:i
+else ifeq ($(PLATFORM),arduinodue)
+ stty -F /dev/$(ARDUINO_PORT) speed 1200 cs8 -cstopb -parenb
+ $(ARDUINO_DIR)/hardware/tools/bossac -i -d --port=$(ARDUINO_PORT) -U false -e -w -v -b $(OUT_DIR)/$(APP_NAME).hex -R
+else
+ $(error Wrong value for PLATFORM !!)
+endif
.PHONY: clean
-clean:
- @rm -f *.o *.d *.elf *.eep *.a *.hex *.bin *.map *-
- @rm -rf $(OBJ_DIR)
+clean: legacy_clean
+ rm -rf arduinomega
+ rm -rf arduinodue
+legacy_clean:
+ @rm -rf bin
+ @rm -f *.o *.d *.elf *.eep *.a *.hex *.bin *.map *-
static THResource TH;
-String g_responsePayloadPut =
- "{\"href\":\"\",\"rep\":{\"0\":\"temperature\",\"1\":\"int\",\"2\":\"0\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\"0\"}}";
-String g_responsePayloadGet =
- "{\"href\":\"\",\"rep\":{\"0\":\"temperature\",\"1\":\"int\",\"2\":\"0\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\"0\"}}";
+//char* g_responsePayloadPut = "{\"href\":\"\",\"rep\":{\"0\":\"temperature\",\"1\":\"int\",\"2\":\"0\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\"0\"}}";
+//char* g_responsePayloadGet = "{\"href\":\"\",\"rep\":{\"0\":\"temperature\",\"1\":\"int\",\"2\":\"0\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\"0\"}}";
/// This is the port which Arduino Server will use for all unicast communication with it's peers
static uint16_t OC_WELL_KNOWN_PORT = 5683;
+#define JSON_BASE00 "{\"href\":\"\",\"rep\":{"
+#define JSON_BASE01 "\"0\":\"temperature\",\"1\":\"int\",\"2\":\""
+#define JSON_BASE02 "\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\""
+#define JSON_BASE03 "\"}}"
+
+char temp[100];
+
+#define LENGTH_VAR 100
+static int base_length = 0;
+
+bool JsonGenerator( THResource &th, char *jsonBuf, uint16_t buf_length )
+{
+ if ( (buf_length - base_length) < LENGTH_VAR )
+ {
+ OC_LOG_V(ERROR, TAG, "Error : length is very long.");
+ return false;
+ }
+
+ sprintf(jsonBuf, JSON_BASE00 JSON_BASE01"%d", th.m_temp);
+ sprintf(jsonBuf + strlen(jsonBuf), JSON_BASE02"%d"JSON_BASE03, th.m_humid);
+
+ Serial.println(jsonBuf);
+
+ return true;
+}
+
byte read_dht11_dat()
{
byte i = 0;
char ssid[] = "SoftSensor_AP";
char pass[] = "1234567890";
+//char ssid[] = "Iotivity-1";
+//char pass[] = "1234567890";
+
int ConnectToNetwork()
{
char *fwVersion;
OC_LOG_V(ERROR, TAG, "error is: %d", error);
return -1;
}
- OC_LOG_V(INFO, TAG, "IPAddress : %s", Serial.print(Ethernet.localIP()));
+ IPAddress ip = Ethernet.localIP();
+ OC_LOG_V(INFO, TAG, "IP Address: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
return 0;
}
#endif //ARDUINOWIFI
extern char *__brkval;
//address of tmp gives us the current stack boundry
int tmp;
+ OC_LOG_V(INFO, TAG, "Stack: %u Heap: %u", (unsigned int)&tmp, (unsigned int)__brkval);
OC_LOG_V(INFO, TAG, "Unallocated Memory between heap and stack: %u",
((unsigned int)&tmp - (unsigned int)__brkval));
#endif
}
+
// This is the entity handler for the registered resource.
// This is invoked by OCStack whenever it recevies a request for this resource.
OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag,
OCEntityHandlerRequest *entityHandlerRequest )
{
OCEntityHandlerResult ehRet = OC_EH_OK;
- const char *typeOfMessage;
- switch (flag)
- {
- case OC_INIT_FLAG:
- typeOfMessage = "OC_INIT_FLAG";
- break;
- case OC_REQUEST_FLAG:
- typeOfMessage = "OC_REQUEST_FLAG";
- break;
- case OC_OBSERVE_FLAG:
- typeOfMessage = "OC_OBSERVE_FLAG";
- break;
- default:
- typeOfMessage = "UNKNOWN";
- }
- OC_LOG_V(INFO, TAG, "Receiving message type: %s", typeOfMessage);
-
- if (entityHandlerRequest && flag == OC_REQUEST_FLAG)
+ if (entityHandlerRequest && (flag & OC_REQUEST_FLAG))
{
+ OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
if (OC_REST_GET == entityHandlerRequest->method)
{
- int str_len = g_responsePayloadGet.length() + 1;
- char charBuf[str_len + 1];
-
- g_responsePayloadGet.toCharArray(charBuf, str_len);
-
- if (strlen(charBuf) < entityHandlerRequest->resJSONPayloadLen)
+ if (JsonGenerator( TH, (char *)entityHandlerRequest->resJSONPayload, \
+ entityHandlerRequest->resJSONPayloadLen))
{
- strncpy((char *)entityHandlerRequest->resJSONPayload, charBuf,
- entityHandlerRequest->resJSONPayloadLen);
}
else
+ {
ehRet = OC_EH_ERROR;
+ }
}
if (OC_REST_PUT == entityHandlerRequest->method)
{
-
- int str_len1 = g_responsePayloadPut.length() + 1;
- char charBuf1[str_len1];
-
- g_responsePayloadPut.toCharArray(charBuf1, str_len1);
-
- if (strlen(charBuf1) < entityHandlerRequest->resJSONPayloadLen)
+ //Do something with the 'put' payload
+ if (JsonGenerator( TH, (char *)entityHandlerRequest->resJSONPayload, \
+ entityHandlerRequest->resJSONPayloadLen))
{
- strncpy((char *)entityHandlerRequest->resJSONPayload, charBuf1,
- entityHandlerRequest->resJSONPayloadLen);
}
else
+ {
ehRet = OC_EH_ERROR;
+ }
}
}
- else if (entityHandlerRequest && flag == OC_OBSERVE_FLAG)
+ if (entityHandlerRequest && (flag & OC_OBSERVE_FLAG))
{
- g_THUnderObservation = 1;
+ if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo->action)
+ {
+ OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
+ g_THUnderObservation = 1;
+ }
+ else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo->action)
+ {
+ OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_DEREGISTER from client"));
+ }
}
return ehRet;
}
-/* Json Generator */
-String JsonGenerator(THResource TH)
-{
- String a = "{\"href\":\"\",\"rep\":{\"0\":\"temperature\",\"1\":\"int\",\"2\":\"";
- String b = "\",\"3\":\"humidity\",\"4\":\"int\",\"5\":\"";
- String c = "\"}}";
-
- String ss;
-
- ss = a + TH.m_temp + b + TH.m_humid + c;
- return ss;
-}
-
// This method is used to display 'Observe' functionality of OC Stack.
static uint8_t modCounter = 0;
void *ChangeTHRepresentation (void *param)
Serial.print(dht11_dat[2], DEC);
Serial.println("C ");
-// delay(2000); //fresh time
TH.m_humid = dht11_dat[0];
TH.m_temp = dht11_dat[2];
- g_responsePayloadGet = JsonGenerator(TH);
-
if (g_THUnderObservation)
{
OC_LOG_V(INFO, TAG, " =====> Notifying stack of new humid level %d\n", TH.m_humid);
OC_LOG_V(INFO, TAG, " =====> Notifying stack of new temp level %d\n", TH.m_temp);
- result = OCNotifyObservers (TH.m_handle);
+ result = OCNotifyAllObservers (TH.m_handle, OC_NA_QOS);
if (OC_STACK_NO_OBSERVERS == result)
{
-
+-include ../../build/linux/root_path.inc
-include ../../build/linux/environment.mk
MAKE=make
--- /dev/null
+##
+# linux sample app build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+linux_sample_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+linux_sample_env.AppendUnique(CPPPATH = ['include'])
+linux_sample_env.AppendUnique(CPPPATH = ['../../../SSMCore/include'])
+linux_sample_env.AppendUnique(CPPPATH = ['../../../SSMCore/src'])
+linux_sample_env.AppendUnique(CPPPATH = ['../../../SDK/include'])
+linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+linux_sample_env.AppendUnique(CPPDEFINES = ['LINUX'])
+linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+linux_sample_env.AppendUnique(LIBS = ['libSSMSDK'])
+linux_sample_env.AppendUnique(LIBS = ['libSSMCORE'])
+linux_sample_env.AppendUnique(LIBS = ['oc'])
+linux_sample_env.AppendUnique(LIBS = ['octbstack'])
+linux_sample_env.AppendUnique(LIBS = ['libcoap'])
+linux_sample_env.AppendUnique(LIBS = ['liboc_logger'])
+linux_sample_env.AppendUnique(LIBS = ['dl'])
+linux_sample_env.AppendUnique(LIBS = ['pthread'])
+
+######################################################################
+#build sampleapp
+######################################################################
+ssmtesterapp = linux_sample_env.Program('SSMTesterApp', 'src/SSMTestApp.cpp')
+Alias("SSMTesterApp", ssmtesterapp)
+env.AppendTarget('SSMTesterApp')
-
+-include ../../../../build/linux/root_path.inc
-include ../../../../build/linux/environment.mk
BOOST=${BOOST_BASE}
RST_NAME=release
# Insert your project name.
-TARGET=ClientApp
+TARGET=SSMTesterApp
CXX=g++
CXX_FLAGS=-std=c++0x -Wall -DLINUX
-CXX_INC=-I${SRC_PATH}/ -I${INC_PATH}/ -I${OUTPUTS_DIR} -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I${SRC_PATH}/ -I${INC_PATH}/ -I${OUTPUTS_DIR} -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+
+CXX_LIB+=${OUTPUTS_DIR}/${SSM_LIB}
+CXX_LIB+=${OUTPUTS_DIR}/${SSMCORE_LIB}
CXX_LIB+=${IOT_RELEASE}/${IOT_LIB}
CXX_LIB+=${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB}
-CXX_LIB+=-lpthread
+CXX_LIB+=${IOT_LOG_DIR}/lib/${IOT_LOG_LIB}
+CXX_LIB+=-lpthread -ldl
SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
OBJPATH=${SRCLIST:.cpp=.o}
pre_job:
@echo " "
- @echo "--------- ClientApp Build Begin. -----------"
+ @echo "--------- ${TARGET} Build Begin. -----------"
@mkdir -p ${RST_NAME}
@echo " "
-${TARGET}: ${OBJLIST} ${OUTPUTS_DIR}/SSMClient.o
+${TARGET}: ${OBJLIST}
$(CXX) $(CXX_FLAGS) -o ./${RST_NAME}/$@ $^ ${CXX_LIB}
@echo " "
post_job:
@echo " "
cp -Rdp ./${RST_NAME}/${TARGET} ${OUTPUTS_DIR}/
- @echo "----------- ClientApp Build Successful. ------------"
+ @echo "----------- ${TARGET} Build Successful. ------------"
@echo "Enter to ${RST_NAME} folder."
@echo " "
#include "OCResource.h"
#include "OCPlatform.h"
+#include "SSMInterface.h"
#include "SSMClient.h"
#include "ISSMClientListener.h"
} DIResult;
class SSMTestApp: public ISSMClientListener
+ , public IQueryEngineEvent
{
private:
- SSMClient m_SSMClient;
+ //SSMClient m_SSMClient;
+ SSMInterface m_SSMClient;
public:
void unregisterQuery();
/* operations from listener interface */
- void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eCode);
-
+ void onRegisterQuery(const std::string &jsonData, SSMReturn &eCode);
+ SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult);
};
#endif /* SSMTESTAPP_H_ */
#include <iostream>
#include "SSMTestApp.h"
-#include "SSMClient.h"
SSMTestApp::SSMTestApp()
{
/* Register Query.*/
void SSMTestApp::registerQuery(std::string queryString)
{
- std::string qid;
- SSMReturn rtn = SSM_ERROR;
+ int qid;
+ SSMRESULT rtn = SSM_E_FAIL;
if (queryString.size() == 0)
{
rtn = m_SSMClient.registerQuery(queryString, this, qid);
- if (rtn == SSM_SUCCESS)
+ if (rtn == SSM_S_OK)
{
printf("The query has been registered!\n");
- printf("QID : %s\n", qid.c_str());
+ printf("QID : %d\n", qid);
}
else
printf("Error occured(%d)", rtn);
void SSMTestApp::unregisterQuery(void)
{
std::string qid;
- SSMReturn rtn = SSM_ERROR;
+ SSMRESULT rtn = SSM_E_FAIL;
printf(" Please Enter query string: ");
cin.ignore();
getline(cin, qid);
- rtn = m_SSMClient.unregisterQuery(qid);
+ rtn = m_SSMClient.unregisterQuery(atoi(qid.c_str()));
- if (rtn == SSM_SUCCESS)
+ if (rtn == SSM_S_OK)
printf("The query has been unregistered!\n");
else
printf("Error occured(%d)\n", (int) rtn);
}
/* APP. Level Callback Function for Observer of client. */
-void SSMTestApp::onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eCode)
+void SSMTestApp::onRegisterQuery(const std::string &jsonData, SSMReturn &eCode)
{
if (eCode == SSM_SUCCESS)
{
- printf("onListener!!!!\n");
- printf("\n");
- printf("T : dry bult temperature. (℃)\n");
- printf("H : relative humidity. (%%)\n");
- printf("Discomport level = 9/5 * T + 32 - 0.55*(1 - H/100)*(9/5 * T - 26) \n");
- printf("\n");
- printf("**************************************\n");
- printf("* All Discomport level : 80 over. *\n");
- printf("* Half Discomport level : 75 over. *\n");
- printf("* Little Discomport level : 68 over. *\n");
- printf("* All Comport level : 67 under.*\n");
- printf("**************************************\n");
- printf("\n");
-
- for (AttributeMap::const_iterator itor = attributeMap.begin(); itor != attributeMap.end();
- ++itor)
- {
- if (strcmp(itor->first.c_str(), "temperature") == 0)
- {
- std::cout << "* Temperature : " << itor->second.front().c_str() << "℃" << std::endl;
- }
- else if (strcmp(itor->first.c_str(), "humidity") == 0)
- {
- std::cout << "* Humidity : " << itor->second.front().c_str() << "%" << std::endl;
- }
- else if (strcmp(itor->first.c_str(), "discomfortIndex") == 0)
- {
- int DI = std::stoi(itor->second.front().c_str());
-
- std::cout << "* DiscomfortIndex : " << DI << "%" << std::endl;
-
- switch (DI)
- {
- case ALL_DISCOMPORT:
- std::cout << "* [Result] All person Discomfort." << std::endl;
- break;
- case HALF_DISCOMPORT:
- std::cout << "* [Result] Half person Discomfort." << std::endl;
- break;
- case LITTLE_DISCOMPORT:
- std::cout << "* [Result] Little person Discomfort." << std::endl;
- break;
- case ALL_COMPORT:
- std::cout << "* [Result] All person Comfort." << std::endl;
- break;
- }
- }
- }
+ std::cout << jsonData << std::endl;
}
else
{
}
}
+SSMRESULT SSMTestApp::onQueryEngineEvent(int cqid, IDataReader *pResult)
+{
+ int dataCount = 0;
+ IModelData *pModelData = NULL;
+ std::vector<std::string> affectedModels;
+
+ cout << "Event received! cqid = " << cqid << endl;
+
+ pResult->getAffectedModels(&affectedModels);
+
+ for (std::vector<std::string>::iterator itor = affectedModels.begin();
+ itor != affectedModels.end(); ++itor)
+ {
+ cout << "Printing " << *itor << " model" << endl;
+ pResult->getModelDataCount(*itor, &dataCount);
+ for (int i = 0; i < dataCount; i++)
+ {
+ pResult->getModelData(*itor, i, &pModelData);
+ cout << "dataId: " << pModelData->getDataId() << endl;
+ for (int j = 0; j < pModelData->getPropertyCount(); j++)
+ {
+ cout << "Type: " << pModelData->getPropertyName(j) << " Value: " << pModelData->getPropertyValue(
+ j) << endl;
+ }
+ }
+ }
+
+ return SSM_S_OK;
+}
+
/**
* APP. Main Function.
*/
--- /dev/null
+##
+# linux sample app build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+linux_sample_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+linux_sample_env.AppendUnique(CPPPATH = ['include'])
+linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+linux_sample_env.AppendUnique(CPPDEFINES = ['LINUX'])
+linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+linux_sample_env.AppendUnique(LIBS = ['oc'])
+linux_sample_env.AppendUnique(LIBS = ['octbstack'])
+linux_sample_env.AppendUnique(LIBS = ['libcoap'])
+linux_sample_env.AppendUnique(LIBS = ['liboc_logger'])
+linux_sample_env.AppendUnique(LIBS = ['pthread'])
+
+######################################################################
+#build sampleapp
+######################################################################
+thsensorapp = linux_sample_env.Program('THSensorApp', 'src/ThingResourceServer.cpp')
+Alias("thsensorapp_sample", thsensorapp)
+env.AppendTarget('thsensorapp_sample')
-
+-include ../../../../build/linux/root_path.inc
-include ../../../../build/linux/environment.mk
BOOST=${BOOST_BASE}
CXX=g++
CXX_FLAGS=-std=c++0x -Wall -DLINUX
-CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
CXX_LIB+=${IOT_RELEASE}/${IOT_LIB}
CXX_LIB+=${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB}
+CXX_LIB+=${IOT_LOG_DIR}/lib/${IOT_LOG_LIB}
CXX_LIB+=-lpthread
SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
pre_job:
@echo " "
- @echo "---------- THSensorApp Build Begin. ------------"
+ @echo "---------- ${TARGET} Build Begin. ------------"
@mkdir -p ${RST_NAME}
@echo " "
post_job:
@echo " "
cp -Rdp ./${RST_NAME}/* ${OUTPUTS_DIR}/
- @echo "----------- THSensorApp Build Successful. -------------"
+ @echo "----------- ${TARGET} Build Successful. -------------"
@echo "Enter to ${RST_NAME} folder."
@echo " "
#include <string>
#include <cstdlib>
-#define COAP_IP "134.134.161.33"
-#define COAP_PORT 56830
+#define COAP_IP "0.0.0.0"
+#define COAP_PORT 0
#define COAP_MODE ModeType::Server
#define COAP_SRVTYPE ServiceType::InProc
/// Access this property from a TB client
int m_humid;
int m_temp;
- string m_resourceUri;
+ std::string m_resourceUri;
+ std::vector<std::string> m_resourceTypes;
+ std::vector<std::string> m_resourceInterfaces;
OCResourceHandle m_resourceHandle;
+ OCRepresentation m_resourceRep;
+ ObservationIds m_interestedObservers;
public:
/// Constructor
TemphumidResource() :
- m_humid(0), m_temp(0), m_resourceUri("/Thing_TempHumSensor"), m_resourceHandle(NULL)
+ m_humid(0), m_temp(0)
{
+ m_resourceUri = "/Thing_TempHumSensor";
+ m_resourceTypes.push_back(COAP_TYPE_NAME);
+ m_resourceInterfaces.push_back(DEFAULT_INTERFACE);
+
+ printf("Running thing as %s\n", m_resourceUri.c_str());
+ m_resourceRep.setUri(m_resourceUri);
+ m_resourceRep.setResourceTypes(m_resourceTypes);
+ m_resourceRep.setResourceInterfaces(m_resourceInterfaces);
}
~TemphumidResource()
{
}
- void registerResource(OC::OCPlatform &platform);
+ void registerResource();
OCResourceHandle getHandle();
- void setRepresentation(AttributeMap &attributeMap);
+ void setResourceRepresentation(OCRepresentation &rep);
- void getRepresentation(AttributeMap &attributeMap);
+ OCRepresentation getResourceRepresentation();
};
#endif /* THINGRESOURCESERVER_H_ */
int g_Observation = 0;
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
- std::shared_ptr< OCResourceResponse > response);
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request);
/*
* TempResourceFunctions
*/
-void TemphumidResource::registerResource(OC::OCPlatform &platform)
+void TemphumidResource::registerResource()
{
- string resourceURI = m_resourceUri; // URI of the resource
- string resourceTypeName = COAP_TYPE_NAME; // resource type name.
- string resourceInterface = DEFAULT_INTERFACE; // resource interface.
-
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
// This will internally create and register the resource.
- OCStackResult result = platform.registerResource(m_resourceHandle, resourceURI,
- resourceTypeName, resourceInterface, &entityHandler, resourceProperty);
+ OCStackResult result = OC::OCPlatform::registerResource(m_resourceHandle, m_resourceUri,
+ m_resourceTypes[0], m_resourceInterfaces[0], &entityHandler, resourceProperty);
if (OC_STACK_OK != result)
{
return m_resourceHandle;
}
-void TemphumidResource::setRepresentation(AttributeMap &attributeMap)
+void TemphumidResource::setResourceRepresentation(OCRepresentation &rep)
{
- cout << "\t\t\t" << "Received representation: " << endl;
- cout << "\t\t\t\t" << "temp: " << attributeMap["temp"][0] << endl;
- cout << "\t\t\t\t" << "humid: " << attributeMap["humid"][0] << endl;
+ int tempHumid;
+ int tempTemp;
+
+ rep.getValue("2", tempTemp);
+ rep.getValue("5", tempHumid);
+
+ m_humid = tempHumid;
+ m_temp = tempTemp;
- m_temp = std::stoi(attributeMap["temp"][0]);
- m_humid = std::stoi(attributeMap["humid"][0]);
+ cout << "\t\t\t" << "Received representation: " << endl;
+ cout << "\t\t\t\t" << "temp: " << m_humid << endl;
+ cout << "\t\t\t\t" << "humid: " << m_temp << endl;
}
-void TemphumidResource::getRepresentation(AttributeMap &attributeMap)
+OCRepresentation TemphumidResource::getResourceRepresentation()
{
- attributeMap["0"].push_back("temperature");
- attributeMap["1"].push_back("int");
-
- attributeMap["2"].push_back(to_string(m_temp));
- attributeMap["3"].push_back("humidity");
- attributeMap["4"].push_back("int");
+ // This representation is temporaily for soft-sensor-management - name, type, vale
+ m_resourceRep.setValue("0", std::string("temperature"));
+ m_resourceRep.setValue("1", std::string("int"));
+ m_resourceRep.setValue("2", std::to_string(m_temp));
+ m_resourceRep.setValue("3", std::string("humidity"));
+ m_resourceRep.setValue("4", std::string("int"));
+ m_resourceRep.setValue("5", std::to_string(m_humid));
- attributeMap["5"].push_back(to_string(m_humid));
+ return m_resourceRep;
}
+// Create the instance of the TemphumidResource class
TemphumidResource g_myResource;
void *TestSensorVal(void *param)
cout << "Notifying observers with resource handle: " << g_myResource.getHandle()
<< endl;
- OCStackResult result = OCPlatform::notifyObservers(g_myResource.getHandle());
+ OCStackResult result = OCPlatform::notifyAllObservers(g_myResource.getHandle());
if (OC_STACK_NO_OBSERVERS == result)
{
return NULL;
}
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
- std::shared_ptr< OCResourceResponse > response)
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request)
{
cout << "\tIn Server CPP entity handler:\n";
+ auto response = std::make_shared<OC::OCResourceResponse>();
+
if (request)
{
// Get the request type and request flag
std::string requestType = request->getRequestType();
- RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+ int requestFlag = request->getRequestHandlerFlag();
- if (requestFlag == RequestHandlerFlag::InitFlag)
+ response->setRequestHandle(request->getRequestHandle());
+ response->setResourceHandle(request->getResourceHandle());
+
+ if (requestFlag & RequestHandlerFlag::InitFlag)
{
cout << "\t\trequestFlag : Init\n";
// entity handler to perform resource initialization operations
}
- else if (requestFlag == RequestHandlerFlag::RequestFlag)
+
+ if (requestFlag & RequestHandlerFlag::RequestFlag)
{
cout << "\t\trequestFlag : Request\n";
cout << "\t\t\trequestType : GET\n";
// Check for query params (if any)
- QueryParamsMap queryParamsMap = request->getQueryParameters();
-
// Process query params and do required operations ..
// Get the representation of this resource at this point and send it as response
- OCRepresentation rep = request->getResourceRepresentation();
- AttributeMap attributeMap;
-
- g_myResource.getRepresentation(attributeMap);
+ OCRepresentation rep = g_myResource.getResourceRepresentation();
if (response)
{
// TODO Error Code
- rep.setAttributeMap(attributeMap);
response->setErrorCode(200);
response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
}
// DELETE request operations
}
}
- else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+
+ if (requestFlag & RequestHandlerFlag::ObserverFlag)
{
pthread_t threadId;
{
std::cout << "Request invalid" << std::endl;
}
+
+ return OCPlatform::sendResponse(response) == OC_STACK_OK ? OC_EH_OK : OC_EH_ERROR;
}
int main()
{
// Create PlatformConfig object
- PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::NonConfirmable);
+ PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, OC::QualityOfService::LowQos);
try
{
- OCPlatform platform(cfg);
+ OC::OCPlatform::Configure(cfg);
- g_myResource.registerResource(platform);
+ g_myResource.registerResource();
int input = 0;
cout << "Type any key to terminate" << endl;
--- /dev/null
+##
+# linux sample app build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+linux_sample_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+linux_sample_env.AppendUnique(CPPPATH = ['include'])
+linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+linux_sample_env.AppendUnique(CPPDEFINES = ['LINUX'])
+linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+linux_sample_env.AppendUnique(LIBS = ['oc'])
+linux_sample_env.AppendUnique(LIBS = ['octbstack'])
+linux_sample_env.AppendUnique(LIBS = ['libcoap'])
+linux_sample_env.AppendUnique(LIBS = ['liboc_logger'])
+linux_sample_env.AppendUnique(LIBS = ['pthread'])
+
+######################################################################
+#build sampleapp
+######################################################################
+thsensorapp1 = linux_sample_env.Program('THSensorApp', 'src/ThingResourceServer1.cpp')
+Alias("thsensorapp1_sample", thsensorapp1)
+env.AppendTarget('thsensorapp1_sample')
-
+-include ../../../../build/linux/root_path.inc
-include ../../../../build/linux/environment.mk
BOOST=${BOOST_BASE}
CXX=g++
CXX_FLAGS=-std=c++0x -Wall -DLINUX
-CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
CXX_LIB+=${IOT_RELEASE}/${IOT_LIB}
CXX_LIB+=${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB}
+CXX_LIB+=${IOT_LOG_DIR}/lib/${IOT_LOG_LIB}
CXX_LIB+=-lpthread
SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
pre_job:
@echo " "
- @echo "---------- THSensorApp Build Begin. ------------"
+ @echo "---------- ${TARGET} Build Begin. ------------"
@mkdir -p ${RST_NAME}
@echo " "
post_job:
@echo " "
cp -Rdp ./${RST_NAME}/* ${OUTPUTS_DIR}/
- @echo "----------- THSensorApp Build Successful. -------------"
+ @echo "----------- ${TARGET} Build Successful. -------------"
@echo "Enter to ${RST_NAME} folder."
@echo " "
#include <string>
#include <cstdlib>
-#define COAP_IP "134.134.161.33"
-#define COAP_PORT 56838
+#define COAP_IP "0.0.0.0"
+#define COAP_PORT 0
#define COAP_MODE ModeType::Server
#define COAP_SRVTYPE ServiceType::InProc
/// Access this property from a TB client
int m_humid;
int m_temp;
- string m_resourceUri;
+ std::string m_resourceUri;
+ std::vector<std::string> m_resourceTypes;
+ std::vector<std::string> m_resourceInterfaces;
OCResourceHandle m_resourceHandle;
+ OCRepresentation m_resourceRep;
+ ObservationIds m_interestedObservers;
public:
/// Constructor
TemphumidResource() :
- m_humid(0), m_temp(0), m_resourceUri("/Thing_TempHumSensor1"), m_resourceHandle(NULL)
+ m_humid(0), m_temp(0)
{
+ m_resourceUri = "/Thing_TempHumSensor1";
+ m_resourceTypes.push_back(COAP_TYPE_NAME);
+ m_resourceInterfaces.push_back(DEFAULT_INTERFACE);
+
+ printf("Running thing as %s\n", m_resourceUri.c_str());
+ m_resourceRep.setUri(m_resourceUri);
+ m_resourceRep.setResourceTypes(m_resourceTypes);
+ m_resourceRep.setResourceInterfaces(m_resourceInterfaces);
}
~TemphumidResource()
{
}
- void registerResource(OC::OCPlatform &platform);
+ void registerResource();
OCResourceHandle getHandle();
- void setRepresentation(AttributeMap &attributeMap);
+ void setResourceRepresentation(OCRepresentation &rep);
- void getRepresentation(AttributeMap &attributeMap);
+ OCRepresentation getResourceRepresentation();
};
#endif /* THINGRESOURCESERVER_H_ */
int g_Observation = 0;
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
- std::shared_ptr< OCResourceResponse > response);
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request);
/*
- * TempResourceFunctions
- */
+* TempResourceFunctions
+*/
-void TemphumidResource::registerResource(OC::OCPlatform &platform)
+void TemphumidResource::registerResource()
{
- string resourceURI = m_resourceUri; // URI of the resource
- string resourceTypeName = COAP_TYPE_NAME; // resource type name.
- string resourceInterface = DEFAULT_INTERFACE; // resource interface.
-
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
// This will internally create and register the resource.
- OCStackResult result = platform.registerResource(m_resourceHandle, resourceURI,
- resourceTypeName, resourceInterface, &entityHandler, resourceProperty);
+ OCStackResult result = OC::OCPlatform::registerResource(m_resourceHandle, m_resourceUri,
+ m_resourceTypes[0], m_resourceInterfaces[0], &entityHandler, resourceProperty);
if (OC_STACK_OK != result)
{
return m_resourceHandle;
}
-void TemphumidResource::setRepresentation(AttributeMap &attributeMap)
+void TemphumidResource::setResourceRepresentation(OCRepresentation &rep)
{
- cout << "\t\t\t" << "Received representation: " << endl;
- cout << "\t\t\t\t" << "temp: " << attributeMap["temp"][0] << endl;
- cout << "\t\t\t\t" << "humid: " << attributeMap["humid"][0] << endl;
+ int tempHumid;
+ int tempTemp;
+
+ rep.getValue("2", tempTemp);
+ rep.getValue("5", tempHumid);
+
+ m_humid = tempHumid;
+ m_temp = tempTemp;
- m_temp = std::stoi(attributeMap["temp"][0]);
- m_humid = std::stoi(attributeMap["humid"][0]);
+ cout << "\t\t\t" << "Received representation: " << endl;
+ cout << "\t\t\t\t" << "temp: " << m_humid << endl;
+ cout << "\t\t\t\t" << "humid: " << m_temp << endl;
}
-void TemphumidResource::getRepresentation(AttributeMap &attributeMap)
+OCRepresentation TemphumidResource::getResourceRepresentation()
{
- attributeMap["0"].push_back("temperature");
- attributeMap["1"].push_back("int");
-
- attributeMap["2"].push_back(to_string(m_temp));
- attributeMap["3"].push_back("humidity");
- attributeMap["4"].push_back("int");
+ // This representation is temporaily for soft-sensor-management - name, type, vale
+ m_resourceRep.setValue("0", std::string("temperature"));
+ m_resourceRep.setValue("1", std::string("int"));
+ m_resourceRep.setValue("2", std::to_string(m_temp));
+ m_resourceRep.setValue("3", std::string("humidity"));
+ m_resourceRep.setValue("4", std::string("int"));
+ m_resourceRep.setValue("5", std::to_string(m_humid));
- attributeMap["5"].push_back(to_string(m_humid));
+ return m_resourceRep;
}
+// Create the instance of the TemphumidResource class
TemphumidResource g_myResource;
void *TestSensorVal(void *param)
cout << "Notifying observers with resource handle: " << g_myResource.getHandle()
<< endl;
- OCStackResult result = OCPlatform::notifyObservers(g_myResource.getHandle());
+ OCStackResult result = OCPlatform::notifyAllObservers(g_myResource.getHandle());
if (OC_STACK_NO_OBSERVERS == result)
{
return NULL;
}
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
- std::shared_ptr< OCResourceResponse > response)
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request)
{
cout << "\tIn Server CPP entity handler:\n";
+ auto response = std::make_shared<OC::OCResourceResponse>();
+
if (request)
{
// Get the request type and request flag
std::string requestType = request->getRequestType();
- RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+ int requestFlag = request->getRequestHandlerFlag();
- if (requestFlag == RequestHandlerFlag::InitFlag)
+ response->setRequestHandle(request->getRequestHandle());
+ response->setResourceHandle(request->getResourceHandle());
+
+ if (requestFlag & RequestHandlerFlag::InitFlag)
{
cout << "\t\trequestFlag : Init\n";
// entity handler to perform resource initialization operations
}
- else if (requestFlag == RequestHandlerFlag::RequestFlag)
+
+ if (requestFlag & RequestHandlerFlag::RequestFlag)
{
cout << "\t\trequestFlag : Request\n";
cout << "\t\t\trequestType : GET\n";
// Check for query params (if any)
- QueryParamsMap queryParamsMap = request->getQueryParameters();
-
// Process query params and do required operations ..
// Get the representation of this resource at this point and send it as response
- OCRepresentation rep = request->getResourceRepresentation();
- AttributeMap attributeMap;
-
- g_myResource.getRepresentation(attributeMap);
+ OCRepresentation rep = g_myResource.getResourceRepresentation();
if (response)
{
// TODO Error Code
- rep.setAttributeMap(attributeMap);
response->setErrorCode(200);
response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
}
// DELETE request operations
}
}
- else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+
+ if (requestFlag & RequestHandlerFlag::ObserverFlag)
{
pthread_t threadId;
if (!startedThread)
{
- pthread_create(&threadId, NULL, TestSensorVal, (void *) NULL);
+ pthread_create(&threadId, NULL, TestSensorVal, (void *)NULL);
startedThread = 1;
}
}
{
std::cout << "Request invalid" << std::endl;
}
+
+ return OCPlatform::sendResponse(response) == OC_STACK_OK ? OC_EH_OK : OC_EH_ERROR;
}
int main()
{
// Create PlatformConfig object
-
- PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::NonConfirmable);
+ PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, OC::QualityOfService::LowQos);
try
{
- OCPlatform platform(cfg);
+ OC::OCPlatform::Configure(cfg);
- g_myResource.registerResource(platform);
+ g_myResource.registerResource();
int input = 0;
cout << "Type any key to terminate" << endl;
+++ /dev/null
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT(oic)
-
-SET(CMAKE_SHARED_LINKER_FLAGS " -Wl,--as-needed")
-SET(CMAKE_EXE_LINKER_FLAGS " -Wl,--as-needed -Wl,--hash-style=both")
-SET(EX_SERVER "simpleserver")
-SET(EX_CLIENT "simpleclient")
-SET(EX_CLIENTSERVER "simpleclientserver")
-SET(OCTBSTACK "octbstack")
-
-INCLUDE_DIRECTORIES(include)
-INCLUDE_DIRECTORIES(csdk/stack/include)
-INCLUDE_DIRECTORIES(csdk/ocsocket/include)
-INCLUDE_DIRECTORIES(csdk/ocrandom/include)
-INCLUDE_DIRECTORIES(csdk/logger/include)
-INCLUDE_DIRECTORIES(csdk/libcoap-4.1.1)
-INCLUDE_DIRECTORIES(${INCLUDE_INSTALL_DIR}/boost)
-LINK_DIRECTORIES(${CMAKE_BINARY_DIR})
-
-#SET(EXTRA_CXXFLAGS "-std=c++11")
-SET(EXTRA_CXXFLAGS "-g3 -std=c++0x")
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}")
-
-SET(SRCS
- OCLib/OCReflect.cpp
- OCLib/OCPlatform.cpp
- OCLib/OCResource.cpp
- OCLib/OCUtilities.cpp
- OCLib/InProcServerWrapper.cpp
- OCLib/InProcClientWrapper.cpp)
-ADD_LIBRARY(${PROJECT_NAME} STATIC ${SRCS})
-
-ADD_EXECUTABLE(${EX_SERVER} examples/simpleserver.cpp)
-TARGET_LINK_LIBRARIES(${EX_SERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
-INSTALL(TARGETS ${EX_SERVER} DESTINATION ${BIN_INSTALL_DIR})
-
-ADD_EXECUTABLE(${EX_CLIENT} examples/simpleclient.cpp)
-TARGET_LINK_LIBRARIES(${EX_CLIENT} ${PROJECT_NAME} ${OCTBSTACK} pthread)
-INSTALL(TARGETS ${EX_CLIENT} DESTINATION ${BIN_INSTALL_DIR})
-
-ADD_EXECUTABLE(${EX_CLIENTSERVER} examples/simpleclientserver.cpp)
-TARGET_LINK_LIBRARIES(${EX_CLIENTSERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
-INSTALL(TARGETS ${EX_CLIENTSERVER} DESTINATION ${BIN_INSTALL_DIR})
-
-ADD_SUBDIRECTORY(csdk)
-#ADD_SUBDIRECTORY(examples)
-ADD_SUBDIRECTORY(oic-sample)
+++ /dev/null
-#!/bin/bash
-
-# Prevent Support Tool(Defect analysis and commit) Execution Batch File!!
-
-# variables
-SDBPATH=/home/iotivity/tizen-sdk/tools/sdb
-GBSRPMPATH=/home/iotivity/GBS-ROOT/rsa/local/repos/rsa/armv7l/RPMS
-PACKAGE=oic-0.0.1-0.armv7l.rpm
-
-gbs build -A armv7l --include-all --ccache
-
-$SDBPATH root on
-
-$SDBPATH push $GBSRPMPATH/$PACKAGE /root/
-
-$SDBPATH shell rpm -Uvh --force /root/oic-0.0.1-0.armv7l.rpm
-
-$SDBPATH shell /usr/apps/com.samsung.oicapp-test/bin/oicapp-test
+++ /dev/null
-com.samsung.oicapp-test system::use_internet r
-
-system::use_internet com.samsung.oicapp-test r
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns="http://tizen.org/ns/packages" package="com.samsung.oicapp-test" version="0.1.0" install-location="internal-only">
- <label>OIC tset</label>
- <author email="email@samsung.com" href="www.samsung.com">Name</author>
- <description>OIC test Application</description>
- <ui-application appid="com.samsung.oicapp-test" exec="/usr/apps/com.samsung.oicapp-test/bin/oicapp-test" nodisplay="false" multiple="false" type="capp" taskmanage="true" mainapp="true">
- <icon>com.samsung.oicapp-test.png</icon>
- <label>OIC test</label>
- </ui-application>
-</manifest>
+++ /dev/null
-/******************************************************************
- *
- * Copyright 2014 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************/
-
-/**
- * @file ISSMClientListener.h
- * @brief This file contains client listener interfaces.
- */
-
-#ifndef ISSMCLIENTLISTENER_H_
-#define ISSMCLIENTLISTENER_H_
-#include <string>
-#include "OCPlatform.h"
-
-/**
- * @brief This enum defines Soft Sensor return types
- */
-typedef enum
-{
- SSM_SUCCESS, SSM_ERROR, SSM_ERROR_QUERY_PARSING, SSM_ERROR_NO_QUERY, SSM_ERROR_NETWORK
-} SSMReturn;
-
-using namespace OC;
-/**
- * @brief ISSMClientListener is a listener interface from which application is derived to get callback from SoftSensorManager service
- */
-class ISSMClientListener
-{
- public:
- /**
- * @brief onRegisterQuery is a pure virtual operation which should be implemented in applications to get callback messages.
- * @param [in] attributeMap - A data map in which SoftSensorManager service sends sensor data with cqid.
- * @param [in] eCode - The address of listener class. When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
- * SSMClient can callback message to the appication.
- * @param [out] cqid - A query id generated from SoftSensorManager service for the queryString request.
- * @return SSMReturn
-
- */
- virtual void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eCode) = 0;
- virtual ~ISSMClientListener()
- {
- }
-};
-
-#endif /* ISSMCLIENTLISTENER_H_ */
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-#include <iostream>
-#include <string>
-
-#include "SSMClient.h"
-#include "OCPlatform.h"
-#include "OCApi.h"
-
-const char *SSM_RESOURCE_URI = "/service/SoftSensorManager";
-
-#define SSM_RESOURCE_TYPE = "core.SoftSensorManager"
-
-#define COAP_IP "134.134.161.33"
-#define COAP_PORT 5683
-#define COAP_MODE ModeType::Client
-#define COAP_SRVTYPE ServiceType::InProc
-
-#define COAP_SERVER_ADDR "coap://224.0.1.187/oc/core?rt=core.SoftSensorManager"
-
-SSMClient::SSMClient()
-{
- m_sem.create(100000);
- m_pPlatform = NULL;
- m_appListener = NULL;
- m_retResponse = SSM_ERROR;
- _findResource();
- _createQueryEngine();
-}
-
-SSMClient::~SSMClient()
-{
- _releaseQueryEngine(m_queryEngineId);
- if (m_pPlatform)
- {
- delete m_pPlatform;
- m_pPlatform = NULL;
- }
-}
-
-void SSMClient::_findResource()
-{
- // Create PlatformConfig object
- PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::Confirmable);
-
- // Create a OCPlatform instance.
- // Note: Platform creation is synchronous call.
- try
- {
- m_pPlatform = new OCPlatform(cfg);
-
- // Find all resources
- OCStackResult result;
- if ((result = m_pPlatform->findResource("", COAP_SERVER_ADDR,
- std::bind(&SSMClient::onFoundResource, this, std::placeholders::_1)))
- != OC_STACK_OK)
- {
- delete m_pPlatform;
- m_pPlatform = NULL;
- return;
- }
-
- m_sem.wait();
-
- }
- catch (OCException e)
- {
- //log(e.what());
- }
-}
-
-void SSMClient::_createQueryEngine(void)
-{
- OCRepresentation rep;
-
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
-
- QueryParamsMap queryParamsMap;
-
- commandValue.push_back("CreateQueryEngine");
-
- requestAttributeMap["command"] = commandValue;
-
- rep.setAttributeMap(requestAttributeMap);
-
- if (m_SSMResource->put(rep, queryParamsMap,
- std::bind(&SSMClient::onCreateQueryEngine, this, std::placeholders::_1,
- std::placeholders::_2)) != OC_STACK_OK)
- {
- return;
- }
-
- m_sem.wait();
-}
-
-void SSMClient::_releaseQueryEngine(std::string queryEngineId)
-{
- OCRepresentation rep;
-
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
- AttributeValues queryEngineIdValue;
-
- QueryParamsMap queryParamsMap;
-
- commandValue.push_back("ReleaseQueryEngine");
-
- requestAttributeMap["command"] = commandValue;
-
- queryEngineIdValue.push_back(queryEngineId);
-
- requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
- rep.setAttributeMap(requestAttributeMap);
-
- m_SSMResource->put(rep, queryParamsMap,
- std::bind(&SSMClient::onReleaseQueryEngine, this, std::placeholders::_1,
- std::placeholders::_2));
-
- m_sem.wait();
-}
-
-SSMReturn SSMClient::registerQuery(std::string queryString, ISSMClientListener *listener,
- std::string &cqid)
-{
- OCRepresentation rep;
-
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
- AttributeValues queryEngineIdValue;
- AttributeValues contextQueryValue;
-
- QueryParamsMap queryParamsMap;
-
- commandValue.push_back("ExecuteContextQuery");
-
- requestAttributeMap["command"] = commandValue;
-
- queryEngineIdValue.push_back(m_queryEngineId);
-
- requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
- contextQueryValue.push_back(queryString);
-
- requestAttributeMap["contextQuery"] = contextQueryValue;
-
- m_appListener = listener;
-
- rep.setAttributeMap(requestAttributeMap);
-
- if (m_SSMResource->put(rep, queryParamsMap,
- std::bind(&SSMClient::onRegisterQuery, this, std::placeholders::_1,
- std::placeholders::_2)) != OC_STACK_OK)
- return SSM_ERROR_NETWORK;
-
- m_sem.wait();
-
- if (m_retResponse == SSM_SUCCESS)
- {
- cqid = m_responseAttributeMap["CQID"].back();
- }
-
- return m_retResponse;
-}
-
-SSMReturn SSMClient::unregisterQuery(std::string cqid)
-{
- OCRepresentation rep;
-
- AttributeMap requestAttributeMap;
- AttributeValues commandValue;
- AttributeValues queryEngineIdValue;
- AttributeValues cqidValue;
-
- QueryParamsMap queryParamsMap;
-
- commandValue.push_back("KillContextQuery");
-
- requestAttributeMap["command"] = commandValue;
-
- queryEngineIdValue.push_back(m_queryEngineId);
-
- requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
- cqidValue.push_back(cqid);
-
- requestAttributeMap["CQID"] = cqidValue;
-
- rep.setAttributeMap(requestAttributeMap);
-
- if (m_SSMResource->put(rep, queryParamsMap,
- std::bind(&SSMClient::onUnregisterQuery, this, std::placeholders::_1,
- std::placeholders::_2)) != OC_STACK_OK)
- return SSM_ERROR_NETWORK;
-
- m_sem.wait();
-
- return m_retResponse;
-}
-
-/**
- * Callback Function List.
- */
-// Callback to found resources
-void SSMClient::onFoundResource(std::shared_ptr< OCResource > resource)
-{
- std::string resourceURI;
- try
- {
- // Do some operations with resource object.
- if (resource)
- {
- // Get the resource URI
- resourceURI = resource->uri();
-
- if (resourceURI.compare(SSM_RESOURCE_URI) == 0)
- {
- m_SSMResource = resource;
- }
- }
- }
- catch (std::exception &e)
- {
- //log(e.what());
- }
-
- m_sem.release();
-}
-
-void SSMClient::onCreateQueryEngine(const OCRepresentation &rep, const int eCode)
-{
- if (eCode != 0)
- {
- m_retResponse = SSM_ERROR_NETWORK;
- goto CLEANUP;
- }
-
- m_responseAttributeMap = rep.getAttributeMap();
- m_queryEngineId = m_responseAttributeMap["queryEngineId"].back();
- m_responseAttributeMap["queryEngineId"].pop_back();
- m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onRegisterQuery(const OCRepresentation &rep, const int eCode)
-{
- QueryParamsMap queryParamsMap;
-
- if (eCode != 0)
- {
- m_retResponse = SSM_ERROR_NETWORK;
- goto CLEANUP;
- }
-
- m_responseAttributeMap = rep.getAttributeMap();
-
- if (m_responseAttributeMap.find("error") != m_responseAttributeMap.end())
- {
- m_retResponse = SSM_ERROR_QUERY_PARSING;
- goto CLEANUP;
- }
-
- m_SSMResource->observe(ObserveType::Observe, queryParamsMap,
- std::bind(&SSMClient::onObserve, this, std::placeholders::_1, std::placeholders::_2));
-
- m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onUnregisterQuery(const OCRepresentation &rep, const int eCode)
-{
- if (eCode != 0)
- {
- m_retResponse = SSM_ERROR_NETWORK;
- goto CLEANUP;
- }
-
- m_responseAttributeMap = rep.getAttributeMap();
-
- if (m_responseAttributeMap.find("error") != m_responseAttributeMap.end())
- {
- m_retResponse = SSM_ERROR_NO_QUERY;
- goto CLEANUP;
- }
-
- m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onReleaseQueryEngine(const OCRepresentation &rep, const int eCode)
-{
- if (eCode != 0)
- {
- m_retResponse = SSM_ERROR_NETWORK;
- goto CLEANUP;
- }
-
- m_responseAttributeMap = rep.getAttributeMap();
-
- m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onObserve(const OCRepresentation &rep, const int &eCode)
-{
- SSMReturn ret = SSM_SUCCESS;
-
- if (eCode != 0)
- {
- ret = SSM_ERROR_NETWORK;
- }
-
- m_appListener->onRegisterQuery(rep.getAttributeMap(), ret);
-}
+++ /dev/null
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/**
- * @file SSMClient.h
- * @brief This file contains the declaration of classes and its members related to SSMClient.
- */
-
-#ifndef RESOURCECLIENT_H_
-#define RESOURCECLIENT_H_
-
-#include <string>
-
-#include "OCResource.h"
-#include "OCPlatform.h"
-#include "ISSMClientListener.h"
-
-using namespace OC;
-
-#if defined(WIN32)
-class CSemaphore
-{
- private:
- HANDLE hSemaphore;
- int m_MaxTimeOut;
-
- public:
- /**
- * This is CSemaphore constructor.
- */
- CSemaphore()
- {
- m_MaxTimeOut = 0;
- }
- /**
- *This is CSemaphore destructor.
- */
- ~CSemaphore()
- {
- }
-
- /**
- * This is a function to creat a semaphore
- * This is syncronus call.
- * @param maximumRequestTimeOut
- * [IN] Request Time out.
- *
- * @return None
- *
- */
- void create(int maximumRequestTimeOut)
- {
- hSemaphore = CreateSemaphore(NULL, 1, 1, NULL);
- m_MaxTimeOut = maximumRequestTimeOut;
- }
-
- /**
- * This is a function to wait for semaphore
- *
- * @return None
- *
- */
- void wait()
- {
- WaitForSingleObject(hSemaphore, m_MaxTimeOut);
- }
-
- /**
- * This is a function to release semaphore
- *
- * @return None
- *
- */
- void release()
- {
- ReleaseSemaphore(hSemaphore, 1, NULL);
- }
-
-};
-
-#elif defined(LINUX)
-#include <semaphore.h>
-
-#define SEM_SUCCESS 0
-
-class CSemaphore
-{
- private:
- sem_t hSemaphore;
- timespec m_MaxTimeOut;
-
- public:
- /**
- * This is CSemaphore constructor.
- */
- CSemaphore()
- {
- m_MaxTimeOut.tv_sec = 0;
- m_MaxTimeOut.tv_nsec = 0;
- }
- /**
- *This is CSemaphore destructor.
- */
- ~CSemaphore()
- {
- }
- /**
- * This is a function to creat a semaphore
- * This is syncronus call.
- * @param maximumRequestTimeOut
- * [IN] Request Time out.
- *
- * @return None
- *
- */
- void create(int maximumRequestTimeOut)
- {
- if ( sem_init(&hSemaphore, 1, 0) < SEM_SUCCESS )
- {
- perror("Error : sem_init.");
- exit(0);
- }
- m_MaxTimeOut.tv_sec = maximumRequestTimeOut;
- }
-
- void wait()
- {
- sem_wait( &hSemaphore );
- }
-
- /**
- * This is a function to release semaphore
- *
- * @return None
- *
- */
- void release()
- {
- sem_post(&hSemaphore);
- }
-
-};
-#endif
-
-/**
- * @brief SSMClient is a wrapper class to provide SoftSensorManager functionality to Application.
- * Basically, SoftSensorManager is developed in Resource model (i.e. messaging with basic functions of put, get, and post).
- * SSMClient abstracts the resource based operations from client applications and provides c++ style functions.
- */
-class SSMClient
-{
- private:
- SSMReturn m_retResponse;
- OCPlatform *m_pPlatform;
- CSemaphore m_sem;
- /**
- * @brief SoftSensorManager Resource.
- */
- std::shared_ptr< OCResource > m_SSMResource;
- /**
- * @brief attribute map .
- */
- AttributeMap m_responseAttributeMap;
- /**
- * @brief query engine.
- */
- std::string m_queryEngineId;
- /**
- * @brief app listener
- */
- ISSMClientListener *m_appListener;
-
- /**
- * @brief internal find resource function
- */
- void _findResource(void);
-
- /**
- * @brief internal Query engine function
- */
- void _createQueryEngine(void);
-
- /**
- * @brief internal release query function
- */
- void _releaseQueryEngine(std::string queryEngineId);
-
- public:
- /**
- * Constructor for SSMClient.
- */
- SSMClient();
- ~SSMClient();
-
- /**
- * This API sends query strings of applications to SoftSensorManager on Iotivity Base messaging.
- *
- * @param [in] queryString - A conditions query statement where the caller application specifies sensors for required data and conditions when the caller wants to get the data.
- * @param [in] listener - The address of listener class. When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
- * SSMClient can callback message to the application.
- * @param [out] cqid - A query id generated from SoftSensorManager service for the queryString request.
- * @return SSMReturn
-
- */
- SSMReturn registerQuery(std::string queryString, ISSMClientListener *listener,
- std::string &cqid);
- /**
- * This API is to cancel the registered sends query strings of applications to SoftSensorManager on Iotivity Base messaging.
- *
- * @param [in] listener - The address of listener class. When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
- * SSMClient can callback message to the application.
- * @param [in] cqid - A query id generated from SoftSensorManager service for the queryString request.
- * @return SSMReturn
- */
- SSMReturn unregisterQuery(std::string cqid);
-
- // friend option. for callback from SSMResource
- void onFoundResource(std::shared_ptr< OCResource > resource);
- void onCreateQueryEngine(const OCRepresentation &rep, const int eCode);
- void onReleaseQueryEngine(const OCRepresentation &rep, const int eCode);
- void onRegisterQuery(const OCRepresentation &rep, const int eCode);
- void onUnregisterQuery(const OCRepresentation &rep, const int eCode);
- void onObserve(const OCRepresentation &rep, const int &eCode);
-};
-
-#endif /* RESOURCECLIENT_H_ */
+++ /dev/null
-[Unit]
-Description=OIC
-After=deviced.service
-
-[Service]
-Type=simple
-ExecStart=/usr/bin/simpleserver
-TimeoutStopSec=1s
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(ssm)
+
+SET(CMAKE_SHARED_LINKER_FLAGS " -Wl,--as-needed")
+SET(CMAKE_EXE_LINKER_FLAGS " -Wl,--as-needed -Wl,--hash-style=both")
+#SET(EX_SERVER "simpleserver")
+#SET(EX_CLIENT "simpleclient")
+#SET(EX_CLIENTSERVER "simpleclientserver")
+#SET(OCTBSTACK "octbstack")
+
+#INCLUDE_DIRECTORIES(include)
+#INCLUDE_DIRECTORIES(csdk/stack/include)
+#INCLUDE_DIRECTORIES(csdk/ocsocket/include)
+#INCLUDE_DIRECTORIES(csdk/ocrandom/include)
+#INCLUDE_DIRECTORIES(csdk/logger/include)
+#INCLUDE_DIRECTORIES(${INCLUDE_INSTALL_DIR}/boost)
+#LINK_DIRECTORIES(${CMAKE_BINARY_DIR})
+
+#SET(EXTRA_CXXFLAGS "-std=c++11")
+#SET(EXTRA_CXXFLAGS "-g3 -std=c++0x")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}")
+
+#SET(SRCS
+# OCLib/OCReflect.cpp
+# OCLib/OCPlatform.cpp
+# OCLib/OCResource.cpp
+# OCLib/InProcServerWrapper.cpp
+# OCLib/InProcClientWrapper.cpp)
+#ADD_LIBRARY(${PROJECT_NAME} STATIC ${SRCS})
+
+#ADD_EXECUTABLE(${EX_SERVER} examples/simpleserver.cpp)
+#TARGET_LINK_LIBRARIES(${EX_SERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+#INSTALL(TARGETS ${EX_SERVER} DESTINATION ${BIN_INSTALL_DIR})
+
+#ADD_EXECUTABLE(${EX_CLIENT} examples/simpleclient.cpp)
+#TARGET_LINK_LIBRARIES(${EX_CLIENT} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+#INSTALL(TARGETS ${EX_CLIENT} DESTINATION ${BIN_INSTALL_DIR})
+
+#ADD_EXECUTABLE(${EX_CLIENTSERVER} examples/simpleclientserver.cpp)
+#TARGET_LINK_LIBRARIES(${EX_CLIENTSERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+#INSTALL(TARGETS ${EX_CLIENTSERVER} DESTINATION ${BIN_INSTALL_DIR})
+
+#ADD_SUBDIRECTORY(csdk)
+#ADD_SUBDIRECTORY(examples)
+ADD_SUBDIRECTORY(oic-sample)
-SET(TESTAPP "oicapp-test")
+SET(TESTAPP "ssmtester")
FILE(GLOB SRCS src/*.c src/*.cpp)
SET(VENDOR "samsung")
SET(PACKAGE ${TESTAPP})
SET(PKGNAME "com.${VENDOR}.${PACKAGE}")
-SET(PREFIX "/usr/apps/com.samsung.oicapp-test")
+SET(PREFIX "/usr/apps/com.samsung.ssmtester")
SET(BINDIR "${PREFIX}/bin")
SET(RESDIR "${PREFIX}/res")
SET(DATADIR "${PREFIX}/data")
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
+LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/lib)
+
ADD_EXECUTABLE(${TESTAPP} ${SRCS})
-TARGET_LINK_LIBRARIES(${TESTAPP} ${pkgs_LDFLAGS} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+TARGET_LINK_LIBRARIES(${TESTAPP} ${pkgs_LDFLAGS} ssmcore oc octbstack oc_logger pthread dl)
INSTALL(TARGETS ${TESTAPP} DESTINATION ${BINDIR})
--- /dev/null
+com.samsung.ssmtester system::use_internet r
+
+system::use_internet com.samsung.ssmtester r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" package="com.samsung.ssmtester" version="0.1.0" install-location="internal-only">
+ <label>OIC test</label>
+ <author email="email@samsung.com" href="www.samsung.com">Name</author>
+ <description>SSM test Application</description>
+ <ui-application appid="com.samsung.ssmtester" exec="/usr/apps/com.samsung.ssmtester/bin/ssmtester" nodisplay="false" multiple="false" type="capp" taskmanage="true" mainapp="true">
+ <icon>com.samsung.oicapp-test.png</icon>
+ <label>SSM test</label>
+ </ui-application>
+</manifest>
#include <efl_assist.h>
#include <string>
+#include <sstream>
#include "oicapp-test.h"
#include "oicapp-utils.h"
-#include "OCResource.h"
-#include "OCPlatform.h"
-#include "SSMClient.h"
-#include "ISSMClientListener.h"
+#include "SSMInterface.h"
static oicapp_data *g_ad = NULL;
-class CSSMClientListener: public ISSMClientListener
+int g_CQID = 9999;
+
+class CQueryEngineEvent : public IQueryEngineEvent
{
public:
- void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn::SSMReturn &eCode)
- {
- //EFL UI printing
- char *queryResult = "";
+ SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult)
+ {
std::stringstream sstream;
- for (AttributeMap::const_iterator itor = attributeMap.begin(); itor != attributeMap.end(); itor++)
+ int dataCount = 0;
+ IModelData *pModelData = NULL;
+ std::vector<std::string> affectedModels;
+
+ pResult->getAffectedModels(&affectedModels);
+
+ for (std::vector<std::string>::iterator itor = affectedModels.begin();
+ itor != affectedModels.end(); ++itor)
{
- //if (itor->first == "queryEngineId")
- //{
- // sstream << itor->first.c_str() << " : " << std::hex << stoi(itor->second.front().c_str()) << "\n";
- //}
- //else
- //{
- sstream << itor->first.c_str() << " : " << itor->second.front().c_str() << "\n";
- //}
+ printf("Printing %s\n", itor->c_str());
+ pResult->getModelDataCount(*itor, &dataCount);
+ for (int i = 0; i < dataCount; i++)
+ {
+ pResult->getModelData(*itor, i, &pModelData);
+ printf("dataId: %d\n", pModelData->getDataId());
+ for (int j = 0; j < pModelData->getPropertyCount(); j++)
+ {
+ sstream << "Type: " << pModelData->getPropertyName(j).c_str() <<
+ " Value: " << pModelData->getPropertyValue(j).c_str() << "<br>";
+ }
+ }
}
-// queryResult = const_cast<char *>(sstream .str().c_str());
- oicapp_util_put_msg (g_ad, g_ad->input_msg);
+ sstream << std::ends;
+ oicapp_util_put_msg(g_ad, sstream.str().c_str());
+ return SSM_S_OK;
}
};
-CSSMClientListener *g_SSMClientListener = new CSSMClientListener();
-SSMClient *g_SSMClient = NULL;
+CQueryEngineEvent *g_SSMClientListener = new CQueryEngineEvent();
+SSMInterface *g_SSMClient = new SSMInterface();
static Elm_Object_Item *oicapp_append_separator(Evas_Object *genlist,
oicapp_data *ad)
item = elm_genlist_item_append(genlist, &ad->itc_seperator, NULL, NULL,
ELM_GENLIST_ITEM_NONE, NULL, NULL);
- elm_genlist_item_select_mode_set(item, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
+ //elm_genlist_item_select_mode_set(item, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
return item;
}
static void oicapp_append_contents(oicapp_data *ad)
{
Elm_Object_Item *item;
-
+ /*
oicapp_append_separator(ad->genlist, ad);
_gl_append_item(ad, &ad->itc_edit);
ad->item_multiline = item;
oicapp_append_separator(ad->genlist, ad);
+ */
+ oicapp_append_separator(ad->genlist, ad);
+
+ elm_genlist_item_append(ad->genlist, &ad->itc_edit, ad, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+
+ oicapp_append_separator(ad->genlist, ad);
+
+ elm_genlist_item_append(ad->genlist, &ad->itc_btn, ad, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+
+ oicapp_append_separator(ad->genlist, ad);
+
+ oicapp_append_separator(ad->genlist, ad);
+
+ oicapp_append_separator(ad->genlist, ad);
+
+ item = _gl_append_item(ad, &ad->itc_multiline);
+
+ ad->item_multiline = item;
+
+ oicapp_append_separator(ad->genlist, ad);
}
static Evas_Object *oicapp_create_conform(Evas_Object *win)
{
oicapp_data *ad = (oicapp_data *)data;
- std::string cqid;
+ std::string str = std::string(ad->input_msg);
+
+ std::string strGT = ">";
+
+ std::string strLT = "<";
+
+ std::size_t foundGT = str.find(strGT);
- g_SSMClient->registerQuery(std::string(ad->input_msg), g_SSMClientListener, cqid);
+ std::size_t foundLT = str.find(strLT);
+
+ std::stringstream sstream;
+
+ if (foundGT != std::string::npos)
+ {
+ str.replace(foundGT, strGT.length(), ">");
+ }
+
+ if (foundLT != std::string::npos)
+ {
+ str.replace(foundLT, strLT.length(), "<");
+ }
+
+ g_SSMClient->registerQuery(str, g_SSMClientListener, g_CQID);
+
+ sstream << "Query executed! cqid = " << g_CQID << std::ends;
+
+ oicapp_util_put_msg(ad, sstream.str().c_str());
ERR("button clicked(%s)", ad->input_msg);
}
ad->input_msg = strdup(elm_entry_entry_get(obj));
-// oicapp_util_put_msg(ad, ad->input_msg);
-
DBG("Clicked : %s", ad->input_msg);
}
return entry;
}
+static char *_item_Text_get(void *data, Evas_Object *obj, const char *part)
+{
+ char *buf =
+ "subscribe Device.DiscomfortIndexSensor if Device.DiscomfortIndexSensor.discomfortIndex > 0";
+
+ return strdup(buf);
+}
+
static inline void oicapp_init_itcs(oicapp_data *ad)
{
ad->itc_seperator.item_style = "dialogue/separator";
ad->itc_seperator.func.del = NULL;
ad->itc_edit.item_style = "dialogue/editfield";
- ad->itc_edit.func.text_get = NULL;
+ ad->itc_edit.func.text_get = _item_Text_get;
ad->itc_edit.func.content_get = _gl_edit_content_get;
ad->itc_edit.func.state_get = NULL;
ad->itc_edit.func.del = NULL;
ad->itc_multiline.item_style = "multiline/1text";
ad->itc_multiline.func.text_get = _gl_multiline_text_get;
- //ad->itc_multiline.func.text_get = NULL;
ad->itc_multiline.func.content_get = NULL;
ad->itc_multiline.func.state_get = NULL;
ad->itc_multiline.func.del = NULL;
ad->genlist = oicapp_create_genlist(ad->navi);
- it = elm_naviframe_item_push(ad->navi, "OIC Tester", NULL, NULL, ad->genlist, NULL);
+ it = elm_naviframe_item_push(ad->navi, "SSM Tester", NULL, NULL, ad->genlist, NULL);
elm_naviframe_item_pop_cb_set(it, _back_cb, ad);
ad->ip_addr = oicapp_util_wifi();
oicapp_append_contents(ad);
- g_SSMClient = new SSMClient();
-
return 0;
}
{
oicapp_data *ad = (oicapp_data *)data;
+ if (g_CQID != 9999)
+ g_SSMClient->unregisterQuery(g_CQID);
+
if (ad->win)
evas_object_del(ad->win);
DBG("Output msg : %s", ad->output_msg);
elm_genlist_item_update(ad->item_multiline);
+ elm_genlist_item_item_class_update(ad->item_multiline, &(ad->itc_multiline));
}
char* oicapp_util_wifi()
-Name: oic
+Name: ssm
Summary: Open Interconnect Consortium
Version: 0.0.1
Release: 0
Group: Network & Connectivity/Service
License: Apache-2.0
Source0: %{name}-%{version}.tar.gz
-Source1: %{name}.service
+Source1: libDiscomfortIndexSensor.so
+Source2: SoftSensorDescription.xml
Source1001: %{name}.manifest
BuildRequires: cmake
-BuildRequires: boost-devel
+#BuildRequires: boost-devel
#BuildRequires: pkgconfig(glib-2.0)
-Buildrequires: gettext-tools
+#Buildrequires: gettext-tools
BuildRequires: pkgconfig(appcore-efl)
BuildRequires: pkgconfig(ecore-x)
BuildRequires: pkgconfig(elementary)
%install
-rm -rf %{buildroot}/BUILD/oic*
+rm -rf %{buildroot}/BUILD/ssm*
#%make_install
+cp -af %{SOURCE1} %{buildroot}/usr/apps/com.samsung.ssmtester/bin/
+cp -af %{SOURCE2} %{buildroot}/usr/apps/com.samsung.ssmtester/bin/
%post
%files
%manifest %{name}.manifest
%defattr(-,root,root,-)
-%{_bindir}/simple*
-/usr/apps/com.samsung.oicapp-test/*
+/usr/apps/com.samsung.ssmtester/*
/usr/share/*
-/etc/smack/accesses2.d/com.samsung.oicapp-test.rule
+/etc/smack/accesses2.d/com.samsung.ssmtester.rule
#%%license LICENSE.APLv2
--- /dev/null
+<softsensors>
+
+ <softsensor>
+ <name>DiscomfortIndexSensor</name>
+ <attributes>
+ <attribute>
+ <name>version</name>
+ <type>string</type>
+ <value>1.0</value>
+ </attribute>
+ <attribute>
+ <name>lifetime</name>
+ <type>int</type>
+ <value>60</value>
+ </attribute>
+ </attributes>
+ <outputs>
+ <output>
+ <name>timestamp</name>
+ <type>string</type>
+ </output>
+ <output>
+ <name>temperature</name>
+ <type>string</type>
+ </output>
+ <output>
+ <name>humidity</name>
+ <type>string</type>
+ </output>
+ <output>
+ <name>discomfortIndex</name>
+ <type>int</type>
+ </output>
+ </outputs>
+ <inputs>
+ <input>Thing_TempHumSensor</input>
+ <input>Thing_TempHumSensor1</input>
+ </inputs>
+ </softsensor>
+
+</softsensors>
+++ /dev/null
-<high_context_dictionary>
-
- <high_context>
- <root_name>DiscomfortIndexSensor</root_name>
- <attributes>
- <attribute_property_count>2</attribute_property_count>
- <attribute_property>
- <name>version</name>
- <type>string</type>
- <value>1.0</value>
- </attribute_property>
- <attribute_property>
- <name>lifetime</name>
- <type>int</type>
- <value>60</value>
- </attribute_property>
- </attributes>
- <outputs>
- <output_property_count>4</output_property_count>
- <output_property>
- <name>timestamp</name>
- <type>string</type>
- <value>""</value>
- </output_property>
- <output_property>
- <name>temperature</name>
- <type>int</type>
- <value>0</value>
- </output_property>
- <output_property>
- <name>humidity</name>
- <type>int</type>
- <value>0</value>
- </output_property>
- <output_property>
- <name>discomfortIndex</name>
- <type>int</type>
- <value>0</value>
- </output_property>
- </outputs>
- <app_inputs>
- <app_input_count>0</app_input_count>
- </app_inputs>
- <inputs>
- <input_count>2</input_count>
- <input>Thing_TempHumSensor</input>
- <input>Thing_TempHumSensor1</input>
- </inputs>
- <enter_conditions>
- <enter_condition>
- <name>Thing_TempHumSensor</name>
- <name>Thing_TempHumSensor1</name>
- </enter_condition>
- </enter_conditions>
- </high_context>
-
-</high_context_dictionary>
-
+-include ../../../../build/linux/root_path.inc
-include ../../../../build/linux/environment.mk
SRC_PATH=../../src
pre_job:
@echo " "
- @echo "---------- SoftSensor Build Begin. ------------"
+ @echo "---------- ${TARGET} Build Begin. ------------"
@mkdir -p ${RST_NAME}
@echo " "
post_job:
@echo " "
cp -Rdp ./${RST_NAME}/lib${TARGET}.so ${OUTPUTS_DIR}/
- cp -Rdp ./HighContextDictionary.xml ${OUTPUTS_DIR}/
- @echo "-------------- SoftSensor Build Successful. -------------"
+ cp -Rdp ../../${SSXML_NAME} ${OUTPUTS_DIR}/
+ @echo "-------------- ${TARGET} Build Successful. -------------"
@echo "Enter to ${RST_NAME} folder."
@echo " "
int discomfortIndex = (int) ERROR;
double sumDI = 0.0;
+ m_result.m_temperature = "";
+ m_result.m_humidity = "";
+
for (int i = 0; i < PHYSICAL_EA; i++)
{
if (i != 0)
output_property.clear();
output_property.insert(std::make_pair("name", "temperature"));
- output_property.insert(std::make_pair("type", "int"));
+ output_property.insert(std::make_pair("type", "string"));
output_property.insert(std::make_pair("value", m_result.m_temperature));
out.outputProperty.push_back(output_property);
output_property.clear();
output_property.insert(std::make_pair("name", "humidity"));
- output_property.insert(std::make_pair("type", "int"));
+ output_property.insert(std::make_pair("type", "string"));
output_property.insert(std::make_pair("value", m_result.m_humidity));
out.outputProperty.push_back(output_property);
+IOTIVITY_DIR=${shell cd ../../../../ && pwd}
+${shell echo "ROOT_DIR=${IOTIVITY_DIR}" > ./root_path.inc}
+-include ./root_path.inc
-include ./environment.mk
MAKE=make
@echo "*********************************************************"
@mkdir -p ${RST_NAME}
@echo " "
-# @cd ${IOT_BASE} && ${MAKE};
-# @cd ${CUR_DIR};
+
build:
@for subdir in ${MAKE_LIST} ; do \
echo ">>>>>>>>>>>> $${subdir}/Makefile run <<<<<<<<<<<<<" ; \
- ${MAKE} -C $${subdir} ; \
+ cd $${subdir} && ${MAKE} ${OPTION} ; \
echo " " ; \
done
@echo " "
@echo " "
clean:
-
-# @cd ${CUR_DIR}/../../../resource/ && make clean
-# @cd ${CUR_DIR}/../../../resource/csdk && make deepclean
-# @cd ${CUR_DIR}/9_Arduino_THSensorApp && make clean
-# @cd ${CUR_DIR}
+
rm -rf ./${RST_NAME}
@for subdir in ${MAKE_LIST} ; do \
echo ">>>>>>>>>>>> $${subdir}/Makefile clean run <<<<<<<<<<<<<<" ; \
-# root path of each PC.
-ROOT_DIR=/home/choi/tmp/test/upload/Iotivity-Candidate
-# service folder path.
-FD_SSM=${ROOT_DIR}/service/SoftSensorManager
+# ioc-resource folder path.
+IOT_BASE=${ROOT_DIR}/resource
+IOT_MAKE_PATH=${IOT_BASE}
+IOT_RELEASE=${IOT_BASE}/release/obj
+IOT_CSDK_LINUX_RELEASE=${IOT_BASE}/csdk/linux/release
+IOT_CSDK_ARDUINOMEGA_RELEASE=${IOT_BASE}/csdk/arduinomega/release
+
+# oic-service folder path.
+FD_SSM=${ROOT_DIR}/service/soft-sensor-manager
FD_SAMPLEAPP=${FD_SSM}/SampleApp
FD_BUILD=${FD_SSM}/build
# outputs directory path.
OUTPUTS_DIR=${FD_BUILD}/arduino/release
-# ioc-resource folder path.
-# IOT_BASE=${FD_SAMPLEAPP}/arduino/resource_a
-IOT_BASE=${ROOT_DIR}/resource
-IOT_MAKE_PATH=${IOT_BASE}
-IOT_RELEASE=${IOT_BASE}/release/obj
-IOT_CSDK_RELEASE=${IOT_BASE}/csdk/release
-
+#OPTION=PLATFORM=arduinomega ARDUINOWIFI=1
# SoftSensorManager makefile path
+MAKE_00=${FD_SAMPLEAPP}/arduino
MAKE_01=${FD_SAMPLEAPP}/arduino/THSensorApp/build
+MAKE_03=${FD_SAMPLEAPP}/arduino/Trackee_Thing/build
+MAKE_04=${FD_SAMPLEAPP}/arduino/Reference_Thing/build
-MAKE_LIST=${MAKE_01}
+MAKE_LIST=${MAKE_01} ${MAKE_03} ${MAKE_04}
-#ARDUINO_DIR = /home/choi/devel/arduino-1.0.5
-ARDUINO_DIR = /home/choi/tmp/test/Arduino
+ARDUINO_DIR = /usr/share/arduino
#ARDUINO_TOOLS_DIR = $(ARDUINO_DIR)/hardware/tools/avr/bin
CC=avr-g++
CCPLUS=avr-g++
+IOTIVITY_DIR=${shell cd ../../../../ && pwd}
+${shell echo "ROOT_DIR=${IOTIVITY_DIR}" > ./root_path.inc}
+-include ./root_path.inc
-include ./environment.mk
MAKE=make
@echo "* *"
@echo "* It's build script for SoftSensorManagement system. *"
@echo "* Before build, Open the environment.mk file. *"
- @echo "* And, Modify ROOT_DIR path, which depend on your PC. *"
@echo "* And, Modify BOOST_BASE path, which depend on your PC. *"
@echo "* *"
@echo "*********************************************************"
clean:
-# @cd ${CUR_DIR}/../../../resource/ && make clean
-# @cd ${CUR_DIR}/../../../resource/csdk && make deepclean
-# @cd ${CUR_DIR}/9_Arduino_THSensorApp && make clean
-# @cd ${CUR_DIR}
rm -rf ./${RST_NAME}
@for subdir in ${MAKE_LIST} ; do \
echo ">>>>>>>>>>>> $${subdir}/Makefile clean run <<<<<<<<<<<<<<" ; \
${MAKE} clean -C $${subdir} ; \
echo " " ; \
done
+ rm -rf ./root_path.inc
-# root path of each PC.
-ROOT_DIR=${PWD}/../../../..
-
# boost folder path.
-BOOST_BASE=/home/iotivity/Desktop/boost_1_56_0
+BOOST_BASE=/usr/include
# ioc-resource folder path.
IOT_BASE=${ROOT_DIR}/resource
IOT_MAKE_PATH=${IOT_BASE}
IOT_RELEASE=${IOT_MAKE_PATH}/release/obj
-IOT_CSDK_RELEASE=${IOT_BASE}/csdk/release
+IOT_CSDK_RELEASE=${IOT_BASE}/csdk/linux/release
+IOT_LOG_DIR=${IOT_BASE}/oc_logger
IOT_LIB=liboc.a
IOT_CSDK_LIB=liboctbstack.a
+IOT_LOG_LIB=liboc_logger.a
# service folder path.
FD_SSM=${ROOT_DIR}/service/soft-sensor-manager
# outputs directory path.
OUTPUTS_DIR=${FD_BUILD}/linux/release
EXEC_DIR=${OUTPUTS_DIR}
-MODEL_DIR="\"${EXEC_DIR}/\""
-HIGH_LOCATION="\"${EXEC_DIR}/HighContextDictionary.xml\""
+SSXML_NAME="SoftSensorDescription.xml"
+SSM_LIB = libSSM.a
+SSMCORE_LIB=libSSMCore.a
# SoftSensorManager makefile path
-MAKE_01=${FD_SDK}/build/linux
-MAKE_02=${FD_SSMCORE}/build/linux
+MAKE_01=${FD_SSMCORE}/build/linux
+MAKE_02=${FD_SDK}/build/linux
MAKE_03=${FD_SAMPLEAPP}/linux
MAKE_04=${FD_SAMPLEAPP}/arduino
MAKE_05=${FD_SOFTSENSOR}/DiscomfortIndexSensor/build/linux
+MAKE_06=${FD_SOFTSENSOR}/IndoorTrajectorySensor/build/linux
-MAKE_LIST=${MAKE_01} ${MAKE_02} ${MAKE_05} ${MAKE_03}
+MAKE_LIST=${MAKE_01} ${MAKE_02} ${MAKE_03} ${MAKE_05} ${MAKE_06}
\ No newline at end of file
--- /dev/null
+##
+# things_manager project build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', exports = 'lib_env')
+
+things_manager_env = lib_env.Clone()
+target_os = env.get('TARGET_OS')
+######################################################################
+# Build flags
+######################################################################
+things_manager_env.AppendUnique(CPPPATH = ['tgm/inc'])
+things_manager_env.AppendUnique(CPPPATH = ['sdk/inc'])
+
+if target_os not in ['windows', 'winrt']:
+ things_manager_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall'])
+ if target_os != 'android':
+ things_manager_env.AppendUnique(CXXFLAGS = ['-pthread'])
+
+if target_os == 'android':
+ things_manager_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+ things_manager_env.AppendUnique(CPPDEFINES = ['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+tgmsdk = things_manager_env.StaticLibrary('TGMSDKLibrary', 'sdk/src/TGMClient.cpp')
+
+things_manager_env.InstallTarget(tgmsdk, 'libTGMSDK')
+
+#Go to build sample apps
+SConscript('sampleapp/SConscript')
\ No newline at end of file
--- /dev/null
+##
+# sampleapp build script
+##
+
+Import('env')
+
+if env.get('TARGET_OS') == 'linux':
+ # Build linux sample app
+ SConscript('linux/tgmclient/SConscript')
--- /dev/null
+##
+# linux sample app build script
+##
+
+Import('env')
+
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/service/third_party_libs.scons', 'lib_env')
+
+linux_sample_env = lib_env.Clone()
+######################################################################
+# Build flags
+######################################################################
+linux_sample_env.AppendUnique(CPPPATH = ['../../../sdk/inc'])
+linux_sample_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+linux_sample_env.AppendUnique(LIBS = ['oc', 'octbstack', 'coap', 'oc_logger', 'TGMSDKLibrary'])
+
+if env.get('TARGET_OS') not in ['windows', 'winrt']:
+ linux_sample_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+tgmclient = linux_sample_env.Program('tgmclient', 'tgmsdkclient.cpp')
+
+Alias("tgmclient_sample", tgmclient)
+env.AppendTarget('tgmclient_sample')
\ No newline at end of file
--- /dev/null
+######################################################################
+# This script manages third party libraries
+#
+#Note: The paths must keep consistent with oic-resource
+######################################################################
+import os
+import platform
+
+Import('env', 'lib_env')
+
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+src_dir = env.get('SRC_DIR')
+
+if target_os not in ['linux', 'darwin']:
+ utils_path = env.get('OIC_UTILS')
+
+resource_path = src_dir + '/resource'
+
+######################################################################
+# Check dependent packages (Linux only)
+######################################################################
+if target_os == 'linux':
+ if not env.GetOption('help'):
+ if not target_arch == platform.machine():
+ print '''
+*********************************** Warning ***********************************
+* You are trying cross build, please make sure (%s) version libraries are
+* installed! *
+*******************************************************************************
+''' % target_arch
+
+ conf = Configure(lib_env)
+
+ if not conf.CheckLib('boost_thread'):
+ print 'Did not find boost_thread, exiting!'
+ Exit(1)
+
+ if not conf.CheckLib('boost_system'):
+ print 'Did not find boost_system, exiting!'
+ Exit(1)
+
+ conf.Finish()
+
+######################################################################
+# The 'include' path of external libraries
+######################################################################
+lib_env.AppendUnique(CPPPATH = [
+ resource_path ,
+ resource_path + '/include' ,
+ resource_path + '/oc_logger/include',
+ resource_path + '/csdk/stack/include',
+ resource_path + '/csdk/ocsocket/include',
+ resource_path + '/csdk/ocrandom/include',
+ resource_path + '/csdk/logger/include'
+ ])
+
+######################################################################
+# The 'include' path of third party libraries
+######################################################################
+if target_os == 'android':
+ lib_env.AppendUnique(CPPPATH = [
+ utils_path + '/android/boost/include',
+ utils_path + '/android/expat/include/expat/',
+ utils_path + '/android/openssl/include',
+ ])
+
+######################################################################
+# The path of third party libraries binary
+######################################################################
+if target_os == 'android':
+ if target_arch == 'armeabi-v7a-hard':
+ target_arch = 'armeabi-v7a'
+
+ if target_arch not in ['x86', 'armeabi', 'armeabi-v7a']:
+ if not env.GetOption('help') and not env.GetOption('clean'):
+ print '''
+*********************************** Warning ***********************************
+* current only x86, armeabi, armeabi-v7a libraries are provided! *
+*******************************************************************************
+'''
+ else:
+ lib_env.AppendUnique(LIBPATH = [
+ utils_path + '/android/boost/libs/' + target_arch,
+ utils_path + '/android/expat/lib/' + target_arch,
+ utils_path + '/android/openssl/lib/' + target_arch,
+ ])
+ # Too much boost warning, suppress the warning
+ lib_env.AppendUnique(CCFLAGS = ['-w'])
+
+elif target_os == 'ios':
+ lib_env.AppendUnique(FRAMEWORKPATH = [utils_path + '/ios/frameworks/'])
+ lib_env.AppendUnique(FRAMEWORKS = ['boost', 'expat', 'openssl'])
+elif target_os == 'darwin':
+ lib_env.AppendUnique(CPPPATH = ['/usr/local/include'])
+ lib_env.AppendUnique(LIBPATH = ['/usr/local/lib'])
+
+Import('env')
+lib_env.AppendUnique(LIBPATH = env.get('BUILD_DIR'))