Added OCF secure apps in examples/OCFSecure 97/25097/2
authorRami Alshafi <ralshafi@vprime.com>
Fri, 15 Sep 2017 18:12:05 +0000 (11:12 -0700)
committerMats Wichmann <mats@linux.com>
Tue, 15 May 2018 17:38:31 +0000 (17:38 +0000)
Added OCF secure server sample application in C++.
Added OCF secure client sample application in C.
Added supporting json and dat files putting the applications in RFNOP state.
Added README file descriping how to use the sample applications.
Added utilities file containing utility functions used by the server
and client applications.
Added SConscript to build the secure samples and modified the SConscipt in
the root directory to include the new SConscript.

Change-Id: I9e1cd4647b55b3e95d1455d7939f13bf3451fd1b
Signed-off-by: Rami Alshafi <ralshafi@vprime.com>
(cherry picked from commit 3974e003fb14a6269ab93d3c2c865e7cb65ce11a)

17 files changed:
SConstruct
examples/OCFSecure/PICS_server_OCF10_vprime.json [new file with mode: 0644]
examples/OCFSecure/README.md [new file with mode: 0644]
examples/OCFSecure/SConscript [new file with mode: 0644]
examples/OCFSecure/client.c [new file with mode: 0644]
examples/OCFSecure/device_properties.dat [new file with mode: 0644]
examples/OCFSecure/ocf_svr_db_client.dat [new file with mode: 0644]
examples/OCFSecure/ocf_svr_db_client.json [new file with mode: 0644]
examples/OCFSecure/ocf_svr_db_server.dat [new file with mode: 0644]
examples/OCFSecure/ocf_svr_db_server_RFNOP.dat [new file with mode: 0644]
examples/OCFSecure/ocf_svr_db_server_RFNOP.json [new file with mode: 0644]
examples/OCFSecure/ocf_svr_db_server_RFOTM.dat [new file with mode: 0644]
examples/OCFSecure/ocf_svr_db_server_RFOTM.json [new file with mode: 0644]
examples/OCFSecure/server.cpp [new file with mode: 0644]
examples/OCFSecure/switch_introspection.dat [new file with mode: 0644]
examples/OCFSecure/switch_introspection.json [new file with mode: 0644]
examples/OCFSecure/utilities.c [new file with mode: 0644]

index 39f859d..127bd09 100644 (file)
@@ -67,6 +67,8 @@ SConscript(build_dir + 'resource/SConscript')
 
 if target_os not in ['darwin','ios', 'android', 'msys_nt', 'windows']:
     SConscript(build_dir + 'examples/OICMiddle/SConscript')
+    if env.get('SECURED') == '1':
+        SConscript(build_dir + 'examples/OCFSecure/SConscript')
 
 java_build = None
 if (env.get('BUILD_JAVA') and env.get('JAVA_HOME')) or target_os == 'android':
diff --git a/examples/OCFSecure/PICS_server_OCF10_vprime.json b/examples/OCFSecure/PICS_server_OCF10_vprime.json
new file mode 100644 (file)
index 0000000..f2b9d98
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    "role": "Server",
+    "supportedVerticalProfile": ["Smart Home"],
+    "supportedDeviceTypes": ["oic.d.switch"],
+    "icv": "ocf.1.0.0",
+    "dmv": "ocf.res.1.0.0, ocf.sh.1.0.0",
+    "resources": ["oic.r.switch.binary", "oic.r.csr", "oic.r.crl", "oic.r.roles"],
+    "jurisdictionSwitch": false,
+    "OTM":["oic.sec.doxm.jw"],
+    "contentFormatVersion": ["1.0.0"],
+    "acceptVersion": ["1.0.0"],
+    "observableOICRES": false,
+    "sct": 9,
+    "persistentDeviceuuid": false,
+    "RDPublishCapability": false,
+    "SSIDSoftAP": "",
+    "PasswordSoftAP": "",
+    "canTurnOnSoftApManually": true,
+    "minNotifyPeriod": [0,10],
+    "maxNotifyPeriod": [0,10],
+    "threshold": [0,5],
+    "threshold_recommended_value": 2,
+    "company": "Vprime",
+    "device": "OCF Developer kit",
+    "multiValueQuerySupport": true
+}
\ No newline at end of file
diff --git a/examples/OCFSecure/README.md b/examples/OCFSecure/README.md
new file mode 100644 (file)
index 0000000..2cda314
--- /dev/null
@@ -0,0 +1,363 @@
+# Introduction
+This is a sample secure application using the "justworks" security model
+There are 2 applications; server and client, which need to be running from 2
+different terminals regardless whether those 2 terminals are running within
+the same machine or not as long as they can discover each other.
+These 2 applications are verified on
+* a regular Ubuntu machine
+* Ubuntu running on Intel Joule
+* Raspbian running on Raspberry Pi 3 and Raspberry Pi Zero W
+
+These applications can be used to verify the build environment is setup
+properly. They can serve as a baseline and a reference for new developers to
+learn how to write simple server and client applications and implement OCF
+security and pass the OCF certification test tool.
+
+# Building the applications
+
+To build the applications, type the following scons command from the root
+directory of IoTivity
+
+```
+$ scons examples/OCFSecure TARGET_TRANSPORT=IP
+```
+
+To speed up the build procerss and utilize more than a single core, you can
+add the -j option followed by the number of cores to utilize for building
+the applications
+
+To build the applications in the debug mode, you can add the following option
+to the scons command RELEASE=0
+
+# Running the applications
+
+To run the applications on a regular machine with Ubuntu, change the directory
+to out/linux/x86_64/release/examples/OCFSecure with the following command
+```
+$ cd out/linux/x86_64/release/examples/OCFSecure/
+```
+Next, run the server application with the following command
+```
+$ ./server
+```
+open up another terminal window within the same directory
+(shortcut:Ctrl+Shift+n) and run the client application with the following
+command.
+```
+$ ./client
+```
+Since there is no physical led attached to a regular machine with Ubuntu, the
+led resource will be simulated. Otherwise, if you are running these
+applications on a Raspberry Pi or Intel Joule board then you would need to
+run the server application with the sudo command so the server application
+can have access to the hardware of the board.
+
+If successful, you should be able to see the list of discovered resources
+in the client terminal as shown below.
+```
+Discovered Resources:
+    #0: /oic/res    @224.0.1.187:5683    resource type: nil
+    #1: /oic/sec/doxm    @fe80::3749:e171:d50f:966d%enp0s3:42825    resource type
+    #2: /oic/sec/pstat    @fe80::3749:e171:d50f:966d%enp0s3:0    resource type
+    #3: /oic/sec/acl2    @10.0.2.15:47132    resource type: oic.r.acl2
+    #4: /oic/sec/cred    @10.0.2.15:47132    resource type: oic.r.cred
+    #5: /oic/sec/crl    @10.0.2.15:47132    resource type: oic.r.crl
+    #6: /oic/sec/csr    @10.0.2.15:47132    resource type: oic.r.csr
+    #7: /oic/sec/roles    @10.0.2.15:47132    resource type: oic.r.roles
+    #8: /oic/d    @10.0.2.15:47132    resource type: oic.wk.d
+    #9: /oic/p    @10.0.2.15:0    resource type: oic.wk.p
+    #10: /introspection    @10.0.2.15:0    resource type: oic.wk.introspection
+
+Request Methods:    1: GET    4: POST
+Usage:\<resource number> \<request method> :
+```
+Usually, you might need to press enter a couple of times to refresh the stdout
+to finally see the complete list like so.
+```
+Discovered Resources:
+    #0: /oic/res    @224.0.1.187:5683    resource type: nil
+    #1: /oic/sec/doxm    @fe80::3749:e171:d50f:966d%enp0s3:42825    resource type
+    #2: /oic/sec/pstat    @fe80::3749:e171:d50f:966d%enp0s3:0    resource type
+    #3: /oic/sec/acl2    @10.0.2.15:47132    resource type: oic.r.acl2
+    #4: /oic/sec/cred    @10.0.2.15:47132    resource type: oic.r.cred
+    #5: /oic/sec/crl    @10.0.2.15:47132    resource type: oic.r.crl
+    #6: /oic/sec/csr    @10.0.2.15:47132    resource type: oic.r.csr
+    #7: /oic/sec/roles    @10.0.2.15:47132    resource type: oic.r.roles
+    #8: /oic/d    @10.0.2.15:47132    resource type: oic.wk.d
+    #9: /oic/p    @10.0.2.15:0    resource type: oic.wk.p
+    #10: /introspection    @10.0.2.15:0    resource type: oic.wk.introspection
+    #11: /oic/sec/doxm    @fe80::5c79:f160:691d:40bd%enp0s8:42825    resource type
+    #12: /oic/sec/pstat    @fe80::5c79:f160:691d:40bd%enp0s8:0    resource type
+    #13: /oic/sec/acl2    @192.168.56.101:47132    resource type: oic.r.acl2
+    #14: /oic/sec/cred    @192.168.56.101:47132    resource type: oic.r.cred
+    #15: /oic/sec/crl    @192.168.56.101:47132    resource type: oic.r.crl
+    #16: /oic/sec/csr    @192.168.56.101:47132    resource type: oic.r.csr
+    #17: /oic/sec/roles    @192.168.56.101:47132    resource type: oic.r.roles
+    #18: /oic/d    @192.168.56.101:47132    resource type: oic.wk.d
+    #19: /oic/p    @192.168.56.101:0    resource type: oic.wk.p
+    #20: /introspection    @192.168.56.101:0    resource type: oic.wk.introspection
+    #21: /oic/sec/doxm    @fe80::3749:e171:d50f:966d%enp0s3:59488    resource type
+    #22: /oic/sec/pstat    @fe80::3749:e171:d50f:966d%enp0s3:0    resource type
+    #23: /oic/sec/acl2    @10.0.2.15:50400    resource type: oic.r.acl2
+    #24: /oic/sec/cred    @10.0.2.15:50400    resource type: oic.r.cred
+    #25: /oic/sec/crl    @10.0.2.15:50400    resource type: oic.r.crl
+    #26: /oic/sec/csr    @10.0.2.15:50400    resource type: oic.r.csr
+    #27: /oic/sec/roles    @10.0.2.15:50400    resource type: oic.r.roles
+    #28: /oic/d    @10.0.2.15:50400    resource type: oic.wk.d
+    #29: /oic/p    @10.0.2.15:0    resource type: oic.wk.p
+    #30: /introspection    @10.0.2.15:0    resource type: oic.wk.introspection
+    #31: /switch    @10.0.2.15:50400    resource type: oic.r.switch.binary
+    #32: /oic/sec/doxm    @fe80::5c79:f160:691d:40bd%enp0s8:59488    resource type
+    #33: /oic/sec/pstat    @fe80::5c79:f160:691d:40bd%enp0s8:0    resource type
+    #34: /oic/sec/acl2    @192.168.56.101:50400    resource type: oic.r.acl2
+    #35: /oic/sec/cred    @192.168.56.101:50400    resource type: oic.r.cred
+    #36: /oic/sec/crl    @192.168.56.101:50400    resource type: oic.r.crl
+    #37: /oic/sec/csr    @192.168.56.101:50400    resource type: oic.r.csr
+    #38: /oic/sec/roles    @192.168.56.101:50400    resource type: oic.r.roles
+    #39: /oic/d    @192.168.56.101:50400    resource type: oic.wk.d
+    #40: /oic/p    @192.168.56.101:0    resource type: oic.wk.p
+    #41: /introspection    @192.168.56.101:0    resource type: oic.wk.introspection
+    #42: /switch    @192.168.56.101:50400    resource type: oic.r.switch.binary
+
+Request Methods:    1: GET    4: POST
+Usage:\<resource number> \<request method> :
+```
+Notice the "/switch" uri on resources #31 and #42. This is a known issue will
+be fixed at the soonest chance. be aware, the "/switch" uri might occure more
+than twice and not all of them are going to work. However, one of them will
+work.
+
+As instructed in the client application. you can enter the number of the
+discovered resource you want to interact with (which is either 31 or 42 in this
+case) followed by 1 for issuing a GET request or 4 for a POST request.
+If you decided to issue a GET request, you should see the following GET
+response if everything went OK.
+
+```
+=========================================================
+Result: (0) - OC_STACK_OK
+07:12.062 INFO: PayloadLog: Payload Type: Representation
+07:12.062 INFO: PayloadLog:     Resource #1
+07:12.062 INFO: PayloadLog:     Resource Types:
+07:12.062 INFO: PayloadLog:         oic.r.switch.binary
+07:12.062 INFO: PayloadLog:     Interfaces:
+07:12.062 INFO: PayloadLog:         oic.if.baseline
+07:12.062 INFO: PayloadLog:         oic.if.a
+07:12.062 INFO: PayloadLog:     Values:
+07:12.062 INFO: PayloadLog:         value(bool):false
+==========================================================
+```
+If you decided to issue a POST request, you will be prompted to create a custom
+payload to be attached to the POST request. As of right now, the only supported
+feature is turning the led on and off. As a result, type 0 to select the
+boolean data type then follow it with the name of the property (the key) which
+is "value" (without quotes as it is writing in the GET response above)
+and then follow that with (the value) either 1 to turn the led on
+or 0 to turn the led off. Next press ENTER twice; once to end the first
+key-value pair entry and once again for completing the custom payload creation.
+
+Below is a copy of an example usage.
+```
+    #42: /switch    @192.168.56.101:50400    resource type: oic.r.switch.binary
+
+Request Methods:    1: GET    4: POST
+Usage:<resource number> <request method> :42 4
+
+Need to create a custom POST payload
+Enter key value pairs as:    <type(int)> <key> <value>
+Type: 0:bool      1:int      2:double      3:string
+press ENTER to finish :0 value 1
+press ENTER to finish :
+```
+
+If successful, you should see the following POST response
+```
+==========================================================
+Result: (4) - OC_STACK_RESOURCE_CHANGED
+08:24.366 INFO: PayloadLog: Payload Type: Representation
+08:24.366 INFO: PayloadLog:     Resource #1
+08:24.366 INFO: PayloadLog:     Resource Types:
+08:24.366 INFO: PayloadLog:         oic.r.switch.binary
+08:24.366 INFO: PayloadLog:     Interfaces:
+08:24.366 INFO: PayloadLog:         oic.if.baseline
+08:24.366 INFO: PayloadLog:         oic.if.a
+08:24.366 INFO: PayloadLog:     Values:
+08:24.366 INFO: PayloadLog:         value(bool):true
+==========================================================
+```
+If for whatever reason you noticed the following response instead, then there
+is a security issue. Hopefully, you will not see this!
+```
+==========================================================
+Result: (46) - OC_STACK_UNAUTHORIZED_REQ
+10:16.370 INFO: PayloadLog: NULL Payload
+==========================================================
+```
+To run the applications on either the Intel Joule or the Raspberry Pi, the mraa
+library must be installed! this is the library that is used to control the
+physical hardware. Without it, you will still get the simulated led but it is
+not as fun as the real led turning on and off in the physical world that you
+can control with your own software! Install it, it is worth it ;)
+
+Installing mraa on the intel joule. From the home directory, type commands
+* $sudo add-apt-repository ppa:mraa/mraa
+* $sudo apt-get update
+* $sudo apt-get install libmraa1 libmraa-dev mraa-tools python-mraa python3-mraa
+
+Installing mraa on the raspberry pi, from the parent directory of IoTivity's
+root directory, type the following commands.
+* $ git clone https://github.com/intel-iot-devkit/mraa.git
+* $ cd mraa && mkdir build && cd build && cmake .. && make
+* $ sudo make install
+
+To run the applications on Intel Joule running ubuntu then the built-in
+led on gpio 100 will be connected to the server and you would be able to
+control it with the client application. It is important to remember to run the
+server applications in sudo mode as hardware access is a super user privilege!
+```
+$ sudo ./server
+```
+Otherwise, you would get an error with unknown gpio or sometimes you will not
+get any errors but the built-in led will not respond to your control. It is the
+same usage as running the applications on a regular machine with Ubuntu which
+should be described above.
+
+To run the applications on Raspberry Pi with Raspian then make sure to connect
+an LED on hardware pin 4 which is gpio 7! The pin mapping of raspberry pi is
+just messed up like that! Google raspberry pi pinout
+This pin has all the following names
+* BCM pin 4
+* Physical pin 7
+* Wiring Pi pin 7
+
+Anyways, have a jumper wire from GPIO 7 to the positive terminal of the led.
+Then connect a resistor from the negative terminal of the led to ground.
+
+Also, it is important to remember to run the server application in sudo mode as
+hardware access is a super user privilege. Otherwise, you might get an error of
+unknown gpio or the app might run but will not control the led and you might
+think you connected the led on the wrong pin which may not be the case.
+
+You can also connect the Enviro pHat sensor board if you have it. Its LED is
+already connected to gpio 7.
+
+# Testing the server app against CTT
+You need to install the OCF Certification Test Tool 2.0 on a Windows machine
+and start it and if the windows machine on the same network as the server and
+the server app is running then the CTT should discover the server. If not,
+please check the correct network interface from the options menu and then
+press the Select IUT button or from the File menu. A pop-up window will
+show the discovered devices and you should be able to see the server device
+as 12345678-1234-1234-1234-123456789012 and in the details section, you
+should be able to see the /switch uri. click on Next. Now, browse to select
+the PICS file which should be included in this example named
+PICS_server_OCF10_vprime.json then click on Next. From the Testing Profiles
+uncheck everything and check OCF 1.0 Server. Next, click on
+Run All Test Cases button. Most likely, you will get a prompt saying
+"Please initiate device to revert to "ready for OTM" state" and there are
+2 options to click on; OK and Cancel because this sample is shipped in the
+"Ready for Normal Operation" state. In this case, kill the server with
+Ctrl+C and from the output directory where the server is running, copy the
+ocf_svr_db_server_RFOTM.dat from the project directory to the project output
+directory and name it as ocf_svr_db_server.dat as shown in the following
+command then re-run the server app then press OK on the prompt once the
+server is running again.
+```
+cp ~/iot/iotivity/examples/OCFSecure/ocf_svr_db_server_RFOTM.dat ocf_svr_db_server.dat
+```
+You might get this prompt again since the CTT does not un-onboard the device
+but now you know what to do!
+Also, you will be prompt to power cycle the device. In this case, you can
+either kill the server app and restart it again or literally power cycle
+your device and re-run the server app once your device is back up and
+connected to the same network.
+Please note, you might see tests passing with warnings and CT1.7.8.11 test
+Case failing but that is OK.
+
+# Known issues
+
+1. Sometimes, the applications will not run because of not finding some library.
+In this case, you would need to export the LD_LIBRARY_PATH to the environment.
+    ```
+    export LD_LIBRARY_PATH=<output dir orwherever the library is>
+    ```
+    Also, since you would need to run the server application in sudo mode, you
+would need to type this command
+    ```
+    $sudo ldconfig
+    ```
+and you might also need to type
+    ```
+    $sudo env LD_LIBRARY_PATH=<output dir or wherever the library is>
+    ```
+Hopefully, you will not run into any library issues but if you run into any
+issue with this application, please send me an e-mail at ralshafi@vprime.com
+and file a bug in JIRA and assign it to me (username: alshafi).
+
+2. Multiple endpoints get discovered and they need to be filtered out
+eventually. In the meantime, there will be multiple /switch links and only one
+of them works and the user will need to issues GET requests to all of them
+until the good one is found. The wrong /switch links will result in
+Result: (255) - OC_STACK_ERROR.
+The correct /a/led link will result in Result: (0) - OC_STACK_OK
+
+# Example Directory
+
+There are 16 files in the example directory.
+* client.c
+    * This is the client program
+* device_properties.dat
+    * This is a file storing the device properties in cbor format which is
+generated automatically by the server application
+* ocf_svr_db_client.dat
+    * This is the cbor format of the secure virtual resource database, defined
+by the human-readable version ocf_svr_db_client.json file, and it is used by
+the client application
+* ocf_svr_db_client.json
+    * This is the human-readable version of ocf_svr_db_client.dat
+* ocf_svr_db_server.dat
+    * This is the cbor format of the secure virtual resource database and it is
+an exact copy from the ocf_svr_db_server_RFNOP.dat which is the cbor version of
+the human-readable version ocf_svr_db_server_RFNOP.json file. This is the case
+because the client application does not support the onboarding and provisioning
+process currently and we need to set the state in the "Ready For Normal
+Operation" manually.
+We also need to set the state in the "Ready For Ownership Method Transfer"
+when testing the application with the OCF Certification Test Tool (CTT).
+In this case, you would need to copy ocf_svr_db_server_RFOTM.dat into
+ocf_svr_db_server.dat since that is the file that will be read by the server.
+* ocf_svr_db_server_RFNOP.dat
+    * This is the cbor format of the secure virtual resource database, defined
+by the human-readable version ocf_svr_db_server_RFNOP.json file and it is *NOT*
+used by the server application. Rename it without the _RFNOP suffix to be read
+by the server
+* ocf_svr_db_server_RFNOP.json
+    * This is the human-readable version of ocf_svr_db_server_RFNOP.dat
+* ocf_svr_db_server_RFOTM.dat
+    * This is the cbor format of the secure virtual resource database, defined
+by the human-readable version ocf_svr_db_server_RFOTM.json file and it is *NOT*
+used by the server application. Rename it without the _RFOTM suffix to be read
+by the server
+* ocf_svr_db_server_RFOTM.json
+    * This is the human-readable version of ocf_svr_db_server_RFOTM.dat
+* PICS_server_OCF10_vprime.json
+    * This is the file that was used as the input to the OCF Certification
+Test Tool.
+* README.md
+    * This is this file :)
+* SConscript
+    * This is the script that is being used by the scons tool to know how
+to build the sample applications and what needs to be copied to the output
+directory.
+* server.cpp
+    * This is the server program.
+* switch_introspection.dat
+    * This is the cbor format of the introspection file (also known as
+Introspection Device Data IDD) the server needs to read to implement
+the introspection feature.
+* switch_introspection.json
+    * This is the human-readable version of switch_introspection.dat file
+which is also know as the "swagger" file.
+* utilities.c
+    * this is a supplementary program containing custom utility c functions
+that help with reporting log messages mainly as of current.
diff --git a/examples/OCFSecure/SConscript b/examples/OCFSecure/SConscript
new file mode 100644 (file)
index 0000000..97ab880
--- /dev/null
@@ -0,0 +1,117 @@
+# /******************************************************************
+# *
+# * Copyright 2017 Vprime All Rights Reserved.
+# *
+# *
+# *
+# * Licensed under the Apache License, Version 2.0 (the "License");
+# * you may not use this file except in compliance with the License.
+# * You may obtain a copy of the License at
+# *
+# *      http://www.apache.org/licenses/LICENSE-2.0
+# *
+# * Unless required by applicable law or agreed to in writing, software
+# * distributed under the License is distributed on an "AS IS" BASIS,
+# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# * See the License for the specific language governing permissions and
+# * limitations under the License.
+# *
+# *****************************************************************
+# \author    Rami Alshafi <ralshafi@vprime.com>
+# */
+
+Import('env')
+import os
+import os.path
+import platform as p
+target_os = env.get('TARGET_OS')
+target_arch = env.get('TARGET_ARCH')
+samples_env = env.Clone()
+src_dir = env.get('SRC_DIR')
+build_dir = env.get('BUILD_DIR')
+
+######################################################################
+# Build flags
+######################################################################
+samples_env.PrependUnique(CPPPATH=[
+    '#/resource/include/',
+    '#/resource/csdk/include',
+    '#/resource/csdk/stack/include',
+    '#/resource/csdk/stack/include/experimental',
+    '#/resource/csdk/security/include',
+    '#/resource/csdk/connectivity/api',
+    '#/resource/oc_logger/include',
+    '#/resource/csdk/logger/include/experimental'
+])
+cpp_defines = ['__WITH_DTLS__', 'TB_LOG']
+libraries = ['octbstack', 'oc']
+# identify which hardware the samples will be running on.
+platform_info = p.platform()
+joule = 'Linux' in platform_info and 'joule' in platform_info and \
+'Ubuntu' in platform_info
+raspberry_pi = 'Linux' in platform_info and \
+('armv7l' in platform_info or 'armv6l' in platform_info) and \
+'debian' in platform_info
+if joule or raspberry_pi:
+    conf = Configure(env)
+    if not conf.CheckCXXHeader('mraa.hpp'):
+        print("required library mraa not installed! ")
+        if joule and not raspberry_pi:
+            print(" To install mraa\n\
+                $sudo add-apt-repository ppa:mraa/mraa\n\
+                $sudo apt-get update\n\
+                $sudo apt-get install libmraa1 libmraa-dev\
+                 mraa-tools python-mraa python3-mraa\n")
+        elif not joule and raspberry_pi:
+            print("to install mraa\n\
+                $git clone https://github.com/intel-iot-devkit/\
+                mraa.git ../mraa\n\
+                $mkdir ../mraa/build && cd ../mraa/build && cmake .. && make\n\
+                $sudo make install")
+        else:
+            print("please install mraa")
+    else:
+        cpp_defines.append('WITH_MRAA')
+        libraries.append('mraa')
+        if joule and not raspberry_pi:
+            cpp_defines.append('JOULE')
+        elif not joule and raspberry_pi:
+            cpp_defines.append('RASPBERRY')
+        else:
+            print "ERROR: unknown board"
+    conf.Finish()
+samples_env.AppendUnique(RPATH=[build_dir])
+samples_env.AppendUnique(CPPDEFINES=cpp_defines)
+samples_env.AppendUnique(CFLAGS=['-std=c99'])
+samples_env.AppendUnique(CXXFLAGS=['-std=c++0x', '-Wall', '-Wextra', '-Werror',
+                                   '-pthread', '-fpermissive'])
+samples_env.PrependUnique(LIBS=libraries)
+if target_arch in ['x86_64', 'arm64']:
+    samples_env.AppendUnique(CPPFLAGS=['-Llib64'])
+else:
+    samples_env.AppendUnique(CPPFLAGS=['-Llib'])
+if env.get('SECURED') == '1':
+    samples_env.AppendUnique(LIBS=['mbedtls', 'mbedx509', 'mbedcrypto'])
+if target_os in ['linux']:
+    samples_env.ParseConfig('pkg-config --cflags --libs sqlite3')
+
+######################################################################
+# Source files and Targets
+######################################################################
+client = samples_env.Program('client', ['client.c'])
+server = samples_env.Program('server', ['server.cpp'])
+examples_dir = '/examples/OCFSecure/'
+client_dat = samples_env.Install(
+    build_dir + examples_dir, src_dir + examples_dir + 'ocf_svr_db_client.dat')
+client_dev = samples_env.Install(
+    build_dir + examples_dir, src_dir + examples_dir + 'device_properties.dat')
+server_dat = samples_env.Install(
+    build_dir + examples_dir, src_dir + examples_dir + 'ocf_svr_db_server.dat')
+introspection_dat = samples_env.Install(
+    build_dir + examples_dir, src_dir + examples_dir + 'switch_introspection.dat')
+
+list_of_samples = [client, client_dat, client_dev, server, server_dat]
+
+Alias("secureExamples", list_of_samples)
+
+env.AppendTarget('secureExamples')
diff --git a/examples/OCFSecure/client.c b/examples/OCFSecure/client.c
new file mode 100644 (file)
index 0000000..d161b3b
--- /dev/null
@@ -0,0 +1,585 @@
+/******************************************************************
+*
+* Copyright 2018 Vprime All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*****************************************************************
+\author    Rami Alshafi <ralshafi@vprime.com>
+*/
+///////////////////////////////////////////////////////////////////////
+//NOTE :  This sample server is generated based on IotivityandZigbeeClient.c
+///////////////////////////////////////////////////////////////////////
+
+
+#include <signal.h>
+#include <unistd.h>
+#include "payload_logging.h"
+#include "utilities.c"
+#include "ocstackconfig.h"
+
+#define DEFAULT_CONTEXT_VALUE       (0x99)
+#define MAX_RESOURCE_TYPE_SIZE      (32)
+#define MAX_RESOURCES_REMEMBERED    (100)
+#define MAX_USER_INPUT              (100)
+#define TAG "CLIENT_APP"
+
+static uint32_t DISC_RES_COUNTER = 0;
+static bool PROMPT_USER = false;
+static char SVR_DB[] = "./ocf_svr_db_client.dat";
+static char DEV_PROP[] = "./device_properties.dat";
+
+static bool STOP = false;
+typedef struct
+{
+    char uri[MAX_URI_LENGTH];
+    char resourceType[MAX_RESOURCE_TYPE_SIZE];
+    OCDevAddr address;
+
+} DiscoveredResourceInfo;
+
+static DiscoveredResourceInfo DISC_RES[MAX_RESOURCES_REMEMBERED];
+
+
+/**
+* Utility method to print the list of discovered resources to the stdout
+*/
+static void
+PrintDiscoveredResources(void)
+{
+    printf("=============================================================\n");
+    printf("Discovered Resources:\n");
+    for(uint32_t i = 0; i < DISC_RES_COUNTER; ++i)
+    {
+        DiscoveredResourceInfo currentResource = DISC_RES[i];
+
+        printf("\t#%u: uri:%s\taddr:%s\tport: %u\tresource type: %s\n",
+               i,
+               currentResource.uri,
+               currentResource.address.addr,
+               currentResource.address.port,
+               currentResource.resourceType);
+    }
+}
+
+
+/**
+* Utility method to format and print the response result to the stdout.
+*
+* @param[in] clientResponse contains the content to be printed.
+*/
+void
+PrintFormattedResult(OCClientResponse *clientResponse)
+{
+    OCStackResult clientResult = clientResponse->result;
+    printf("==========================================================\n");
+    printf("Result: (%d) - %s\n", clientResult,
+            decode_oc_stack_result(clientResult));
+    OIC_LOG_PAYLOAD(INFO, clientResponse->payload);
+    printf("==========================================================\n");
+}
+
+
+/**
+* Method to register the discovered resources.
+*
+* @param[in] clientResponse containing info about discovered resources.
+*/
+void
+RegisterDiscoveredResources(OCClientResponse *clientResponse)
+{
+    if (!(OCDiscoveryPayload*)clientResponse->payload)
+    {
+        OIC_LOG_V(INFO, TAG,
+            "[%s] Could not discover any resources.", __func__);
+        return;
+    }
+    OCResourcePayload* discoveredResource =
+    ((OCDiscoveryPayload*)(clientResponse->payload))->resources;
+    while (discoveredResource && discoveredResource != discoveredResource->next)
+    {
+        if (DISC_RES_COUNTER == MAX_RESOURCES_REMEMBERED)
+        {
+            OIC_LOG_V(WARNING, TAG,
+                "[%s] Max of %u resources reached. Ignoring the rest.",
+                __func__, MAX_RESOURCES_REMEMBERED);
+            break;
+        }
+        // 'oic/res' must be 1st resource to test out queries and its responses.
+        if (DISC_RES_COUNTER == 0)
+        {
+            strncpy(DISC_RES[DISC_RES_COUNTER].uri,
+                    clientResponse->resourceUri, MAX_URI_LENGTH - 1);
+            strncpy(DISC_RES[DISC_RES_COUNTER].resourceType,
+                    OC_RSRVD_RESOURCE_TYPE_RES, MAX_RESOURCE_TYPE_SIZE - 1);
+            DISC_RES[DISC_RES_COUNTER].address = clientResponse->devAddr;
+            ++DISC_RES_COUNTER;
+        }
+
+        strncpy(DISC_RES[DISC_RES_COUNTER].uri,
+            discoveredResource->uri, MAX_URI_LENGTH - 1);
+
+        strncpy(DISC_RES[DISC_RES_COUNTER].resourceType,
+            discoveredResource->types->value, MAX_RESOURCE_TYPE_SIZE - 1);
+        DISC_RES[DISC_RES_COUNTER].address = clientResponse->devAddr;
+        // secure the endpoint of the discovered secure resource.
+        if (discoveredResource->eps->family & OC_FLAG_SECURE)
+        {
+            if (0 == strcmp(discoveredResource->eps->tps, "coaps"))
+            {
+                strncpy(clientResponse->devAddr.addr,
+                        discoveredResource->eps->addr,
+                        sizeof(clientResponse->devAddr.addr));
+                clientResponse->devAddr.port = discoveredResource->eps->port;
+                clientResponse->devAddr.flags =
+                (OCTransportFlags)(discoveredResource->eps->family | OC_SECURE);
+                OIC_LOG_V(INFO, TAG, "[%s] DTLS port: %d",
+                          __func__,
+                          clientResponse->devAddr.port);
+            }
+        }
+        ++DISC_RES_COUNTER;
+        discoveredResource = discoveredResource->next;
+    }
+
+}
+
+
+/**
+* Internal method to invoke the OCDoRequest API
+*
+* @param[in] requestUri resource URI used to invoke the request.
+* @param[in] payload payload used to invoke the request
+* @param[in] method the desired method to be used to invoke the request
+* @param[in] cb the call back handler to be used to invoke the request
+* @param[in] address the address to be used to invoke the request
+*
+* @return stack result
+*/
+OCStackResult
+InvokeOCDoRequest(const char *requestUri,
+                  OCPayload *payload,
+                  OCMethod method,
+                  OCClientResponseHandler cb,
+                  OCDevAddr *address)
+{
+    OCCallbackData cbData = {
+                                .context = (void*)DEFAULT_CONTEXT_VALUE,
+                                .cb = cb
+                            };
+
+    OCConnectivityType connType = CT_ADAPTER_IP;
+    OCQualityOfService qos = OC_LOW_QOS;
+    OCDoHandle handle = NULL;
+    uint8_t numOptions = 0;
+
+    OCStackResult ret = OCDoRequest(&handle,
+                                    method,
+                                    requestUri,
+                                    address,
+                                    payload,
+                                    connType,
+                                    qos,
+                                    &cbData,
+                                    NULL,
+                                    numOptions);
+    if (ret != OC_STACK_OK)
+    {
+        PROMPT_USER = true;
+        OIC_LOG_V(ERROR, TAG,
+                  "[%s] OCDoRequest with method %s returns error (%d): %s",
+                  __func__,
+                  decode_oc_method(method),
+                  ret,
+                  decode_oc_stack_result(ret));
+    }
+    return ret;
+}
+
+
+/**
+* The response call back method which prints the response to the stdout
+* @param[in] ctx unused
+* @param[in] handle unused
+* @param[in] clientResponse the response that need to be printed
+*
+* @return stack application result
+*/
+OCStackApplicationResult
+ResponseCallbacks(void* ctx,
+                  OCDoHandle handle,
+                  OCClientResponse * clientResponse)
+{
+    OC_UNUSED(handle);
+    OC_UNUSED(ctx);
+    if (clientResponse == NULL)
+    {
+        OIC_LOG_V(INFO, TAG, "[%s] Client request response is NULL", __func__);
+        return   OC_STACK_DELETE_TRANSACTION;
+    }
+    PrintFormattedResult(clientResponse);
+    PROMPT_USER = true;
+    return OC_STACK_KEEP_TRANSACTION;
+}
+
+
+/**
+* Call back method for discovery request that logs the response payload
+* and registers the discovered resources.
+*
+* @param[in] ctx unused.
+* @param[in] handle unused.
+* @param[in] clientResponse discovery response with discovered resources info.
+*
+* @return stack application result
+*/
+OCStackApplicationResult
+DiscoveryRequestCallBack(void* ctx,
+                         OCDoHandle handle,
+                         OCClientResponse * clientResponse)
+{
+    OC_UNUSED(handle);
+    OC_UNUSED(ctx);
+    if (!clientResponse)
+    {
+        OIC_LOG_V(INFO, TAG, "[%s] Client discovery response is NULL",
+                  __func__);
+        return OC_STACK_KEEP_TRANSACTION;
+    }
+    OIC_LOG_V(INFO, TAG, "[%s] Discovered addr:%s\tport:%d",
+          __func__,
+          clientResponse->devAddr.addr,
+          clientResponse->devAddr.port);
+    PrintFormattedResult(clientResponse);
+    RegisterDiscoveredResources(clientResponse);
+
+    PROMPT_USER = true;
+
+    return OC_STACK_KEEP_TRANSACTION;
+}
+
+
+/**
+* allows the user to create their own custom payload with however many
+* key value pairs.
+*
+* @return payload
+*/
+OCPayload*
+GetCustomPostPayload(void)
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if (!payload)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed to create payload object", __func__);
+        exit(1);
+    }
+
+    char key[MAX_USER_INPUT] = {0};
+    char input[MAX_USER_INPUT] = {0};
+    char valueString[MAX_USER_INPUT] = {0};
+    int value = 0;
+    double valueDouble = 0.0;
+    int type = -1;
+    printf("\nNeed to create a custom POST payload");
+    printf("\nEnter key value pairs as:\t<type(int)> <key> <value>");
+    printf("\nType: 0:bool \t 1:int \t 2:double \t 3:string\n");
+    while (true)
+    {
+        printf("press ENTER to finish :");
+        char *ret = fgets(input, sizeof(input), stdin);
+        (void) ret;
+        int inCount = sscanf(input, "%d %s %s", &type, key, valueString);
+
+        if (inCount <= 0)
+        {
+            break;
+        }
+        if (inCount != 3)
+        {
+            printf("Invalid input\n");
+            OCRepPayloadDestroy(payload);
+            PROMPT_USER = true;
+            return NULL;
+        }
+
+        if (type == 0)  //bool
+        {
+            if (sscanf(valueString, "%d", &value) == 1)
+            {
+                OCRepPayloadSetPropBool(payload, key, value);
+            }
+        }
+        else if (type == 1)  //int
+        {
+            if (sscanf(valueString, "%d", &value) == 1)
+            {
+                OCRepPayloadSetPropInt(payload, key, value);
+            }
+        }
+        else if (type == 2)  //double
+        {
+            if (sscanf(valueString, "%lf", &valueDouble) == 1)
+            {
+                OCRepPayloadSetPropDouble(payload, key, valueDouble);
+            }
+        }
+        else if (type == 3)  //string
+        {
+            OCRepPayloadSetPropString(payload, key, valueString);
+        }
+        else
+        {
+            OIC_LOG_V(ERROR, TAG,
+                      "[%s] Invalid entry. stopping accepting key-values",
+                      __func__);
+            OCRepPayloadDestroy(payload);
+            PROMPT_USER = true;
+            return NULL;
+        }
+        memset(input, 0, sizeof (input));
+        memset(key, 0, sizeof (key));
+        memset(valueString, 0, sizeof (valueString));
+    }
+
+    if (payload->values)
+    {
+        return (OCPayload *) payload;
+    }
+    else
+    {
+        OCRepPayloadDestroy(payload);
+        return NULL;
+    }
+}
+
+
+/**
+* Processes the user input to figure out which request to initialize.
+*
+* @param[in] resourceNo the number of discovered resource.
+* @param[in] clientMethod the method the user wants to initiate.
+*/
+void
+ProcessUserInput(int resourceNo, int clientMethod)
+{
+    const char *resourceUri = DISC_RES[resourceNo].uri;
+    OCDevAddr resourceAddr = DISC_RES[resourceNo].address;
+    switch (clientMethod)
+    {
+        case OC_REST_GET:
+            OIC_LOG_V(INFO, TAG,
+                      "[%s] Initializing GET request for resource: %s",
+                      __func__,
+                      resourceUri);
+            InvokeOCDoRequest(resourceUri,
+                              NULL,
+                              OC_REST_GET,
+                              ResponseCallbacks,
+                              &resourceAddr);
+            break;
+
+        case OC_REST_POST:
+        {
+            OIC_LOG_V(INFO, TAG,
+                      "[%s] Initializing POST request for resource: %s",
+                      __func__,
+                      resourceUri);
+            OCPayload *payload = GetCustomPostPayload();
+            if (payload)
+            {
+                InvokeOCDoRequest(resourceUri,
+                                  payload,
+                                  OC_REST_POST,
+                                  ResponseCallbacks,
+                                  &resourceAddr);
+            }
+            else
+            {
+                OIC_LOG_V(ERROR, TAG,
+                          "[%s] Error creating POST payload. Aborting",
+                          __func__);
+                PROMPT_USER = true;
+            }
+            break;
+        }
+
+        default:
+            PROMPT_USER = true;
+            OIC_LOG_V(INFO, TAG, "[%s] Invalid client request method (%d) %s",
+                      __func__,
+                      clientMethod,
+                      decode_oc_method(clientMethod));
+    }
+}
+
+
+/**
+* Utility method to capture the user input.
+*/
+void
+GetUserInput(void)
+{
+    PrintDiscoveredResources();
+    printf("\nRequest Methods:\t%d: GET\t%d: POST", OC_REST_GET, OC_REST_POST);
+    printf("\nUsage:<resource number> <request method> :");
+
+    char input[10] = {0};
+    uint32_t resourceNo = 0;
+    int requestMethod = 0;
+
+    char * ret = fgets(input, sizeof(input), stdin);
+    (void) ret;
+    int inCount = sscanf(input, "%d %d", &resourceNo, &requestMethod);
+
+    if (inCount != 2)
+    {
+        printf("Invalid input\n");
+        PROMPT_USER = true;
+        return;
+    }
+    if (resourceNo >= DISC_RES_COUNTER)
+    {
+        printf("Invalid resource\n");
+        PROMPT_USER = true;
+        return;
+    }
+    ProcessUserInput(resourceNo, requestMethod);
+}
+
+
+/**
+* SIGINT handler call back method to update the STOP flag to exit the main loop.
+*
+* @param[in] signalNumber
+*/
+void
+SIGINTHandlerCallBack(int signalNumber)
+{
+    OIC_LOG_V(INFO, TAG, "[%s] Received SIGINT", __func__);
+    if (signalNumber == SIGINT)
+    {
+        STOP = true;
+    }
+}
+
+
+/**
+* Custom fopen method to open the secure virtual resource database and
+* the device properties.
+*
+* @param[in] file file name to be opened
+* @param[in] mode the mode in which the file will be opened
+*
+* @return opened file
+*/
+FILE*
+ClientFOpen(const char *file, const char *mode)
+{
+    if (0 == strcmp(file, DEV_PROP))
+    {
+        return fopen(DEV_PROP, mode);
+    }
+    else if (0 == strcmp(file, OC_SECURITY_DB_DAT_FILE_NAME))
+    {
+        return fopen(SVR_DB, mode);
+    }
+    else
+    {
+        return fopen(file, mode);
+    }
+}
+
+
+/**
+* main function
+*/
+int
+main(void)
+{
+
+    OCStackResult stack_res;
+    OIC_LOG_V(DEBUG, TAG,
+              "[%s] Initializing and registering persistent storage",
+              __func__);
+    OCPersistentStorage ps = {ClientFOpen, fread, fwrite, fclose, unlink};
+    OCRegisterPersistentStorageHandler(&ps);
+    OIC_LOG_V(DEBUG, TAG,
+              "[%s] Initializing IoTivity stack for client_server",
+              __func__);
+    stack_res = OCInit(NULL, 0, OC_CLIENT_SERVER);
+    // notice you need client_server, not client in order to enable security.
+    if (stack_res != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG,
+                  "[%s] Failed to initialize IoTivity stack (%d): %s",
+                  __func__,
+                  stack_res,
+                  decode_oc_stack_result(stack_res));
+        return -1;
+    }
+    // initiate discovery request
+    stack_res = InvokeOCDoRequest(OC_RSRVD_WELL_KNOWN_URI,
+                                  0,
+                                  OC_REST_DISCOVER,
+                                  DiscoveryRequestCallBack,
+                                  0);
+    if (stack_res != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG,
+                  "[%s] Failed to initiate discovery request (%d): %s",
+                  __func__,
+                  stack_res,
+                  decode_oc_stack_result(stack_res));
+        return -1;
+    }
+    OIC_LOG_V(INFO, TAG,
+              "[%s] Client is running, press ctrl+c to STOP...",
+              __func__);
+    signal(SIGINT, SIGINTHandlerCallBack);
+    while (!STOP)
+    {
+        stack_res = OCProcess();
+        if (stack_res != OC_STACK_OK)
+        {
+            OIC_LOG_V(ERROR, TAG,
+                      "[%s] IoTivity stack process failure (%d): %s",
+                      __func__,
+                      stack_res,
+                      decode_oc_stack_result(stack_res));
+            return -1;
+        }
+
+        if (PROMPT_USER)
+        {
+            PROMPT_USER = false;
+            GetUserInput();
+        }
+    }
+
+    OIC_LOG_V(INFO, TAG, "[%s] stopping IoTivity client...", __func__);
+    stack_res = OCStop();
+    if (stack_res != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG,
+                  "[%s] Failed to STOP IoTivity client (%d): %s",
+                  __func__,
+                  stack_res,
+                  decode_oc_stack_result(stack_res));
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/examples/OCFSecure/device_properties.dat b/examples/OCFSecure/device_properties.dat
new file mode 100644 (file)
index 0000000..06431f5
--- /dev/null
@@ -0,0 +1 @@
+¿pDevicePropertiesX-¿dpiidx$b90c0019-3cd9-926a-6161-9772cdab36b2ÿÿ
\ No newline at end of file
diff --git a/examples/OCFSecure/ocf_svr_db_client.dat b/examples/OCFSecure/ocf_svr_db_client.dat
new file mode 100644 (file)
index 0000000..9cabf63
Binary files /dev/null and b/examples/OCFSecure/ocf_svr_db_client.dat differ
diff --git a/examples/OCFSecure/ocf_svr_db_client.json b/examples/OCFSecure/ocf_svr_db_client.json
new file mode 100644 (file)
index 0000000..0b6a907
--- /dev/null
@@ -0,0 +1,60 @@
+{\r
+    "acl": {\r
+        "aclist2": [\r
+            {\r
+                "aceid": 1,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p"},\r
+                    { "href": "/oic/sec/doxm"}\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 2,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p"},\r
+                    { "href": "oic/sec/doxm"}\r
+                ],\r
+                "permission": 2\r
+            }\r
+        ],\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232"\r
+    },\r
+    "pstat": {\r
+        "dos": { "s": 3, "p": false },\r
+        "isop": true,\r
+        "cm": 0,\r
+        "tm": 0,\r
+        "om": 4,\r
+        "sm": 4,\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232"\r
+    },\r
+    "doxm": {\r
+        "oxms": [0],\r
+        "oxmsel": 0,\r
+        "sct": 1,\r
+        "owned": true,\r
+        "deviceuuid": "32323232-3232-3232-3232-323232323232",\r
+        "devowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232"\r
+    },\r
+    "cred":{\r
+        "creds": [\r
+            {\r
+                "credid": 1,\r
+                "subjectuuid": "12345678-1234-1234-1234-123456789012",\r
+                "credtype": 1,\r
+                "privatedata":{\r
+                    "data":"AAAAAAAAAAAAAAAA",\r
+                    "encoding": "oic.sec.encoding.raw"\r
+                }\r
+            }],\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232"\r
+    }\r
+}\r
diff --git a/examples/OCFSecure/ocf_svr_db_server.dat b/examples/OCFSecure/ocf_svr_db_server.dat
new file mode 100644 (file)
index 0000000..ab78ab9
Binary files /dev/null and b/examples/OCFSecure/ocf_svr_db_server.dat differ
diff --git a/examples/OCFSecure/ocf_svr_db_server_RFNOP.dat b/examples/OCFSecure/ocf_svr_db_server_RFNOP.dat
new file mode 100644 (file)
index 0000000..ab78ab9
Binary files /dev/null and b/examples/OCFSecure/ocf_svr_db_server_RFNOP.dat differ
diff --git a/examples/OCFSecure/ocf_svr_db_server_RFNOP.json b/examples/OCFSecure/ocf_svr_db_server_RFNOP.json
new file mode 100644 (file)
index 0000000..34bc431
--- /dev/null
@@ -0,0 +1,78 @@
+{\r
+    "acl": {\r
+        "aclist2": [\r
+            {\r
+                "aceid": 1,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 2,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 5,\r
+                "subject": {"uuid": "32323232-3232-3232-3232-323232323232"},\r
+                "resources":[\r
+                    { "href":"/switch",\r
+                      "rt" : ["oic.r.switch.binary"],\r
+                      "if" : ["oic.if.baseline", "oic.if.a"]}\r
+                ],\r
+                "permission": 7\r
+            }\r
+        ],\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "rt": ["oic.r.acl"],\r
+        "if": ["oic.if.baseline"]\r
+    },\r
+    "pstat": {\r
+        "dos": { "s": 3, "p": false },\r
+        "isop": true,\r
+        "cm": 0,\r
+        "tm": 0,\r
+        "om": 4,\r
+        "sm": 4,\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "rt": ["oic.r.pstat"],\r
+        "if": ["oic.if.baseline"]\r
+    },\r
+    "doxm": {\r
+        "oxms": [0],\r
+        "oxmsel": 0,\r
+        "sct": 9,\r
+        "owned": true,\r
+        "deviceuuid": "12345678-1234-1234-1234-123456789012",\r
+        "devowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "rt": ["oic.r.doxm"],\r
+        "if": ["oic.if.baseline"]\r
+    },\r
+    "cred":{\r
+        "creds": [\r
+            {\r
+                "credid": 1,\r
+                "subjectuuid": "32323232-3232-3232-3232-323232323232",\r
+                "credtype": 1,\r
+                "privatedata":{\r
+                    "data":"AAAAAAAAAAAAAAAA",\r
+                    "encoding": "oic.sec.encoding.raw"\r
+                }\r
+            }],\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "rt": ["oic.r.cred"],\r
+        "if": ["oic.if.baseline"]\r
+    }\r
+}\r
diff --git a/examples/OCFSecure/ocf_svr_db_server_RFOTM.dat b/examples/OCFSecure/ocf_svr_db_server_RFOTM.dat
new file mode 100644 (file)
index 0000000..f95379b
Binary files /dev/null and b/examples/OCFSecure/ocf_svr_db_server_RFOTM.dat differ
diff --git a/examples/OCFSecure/ocf_svr_db_server_RFOTM.json b/examples/OCFSecure/ocf_svr_db_server_RFOTM.json
new file mode 100644 (file)
index 0000000..d6a11f6
--- /dev/null
@@ -0,0 +1,63 @@
+{\r
+    "acl": {\r
+        "aclist2": [\r
+            {\r
+                "aceid": 1,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 2,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 5,\r
+                "subject": {"conntype": "auth-crypt" },\r
+                "resources":[\r
+                    { "href":"/switch",\r
+                      "rt" : ["oic.r.switch.binary"],\r
+                      "if" : ["oic.if.baseline", "oic.if.a"]}\r
+                ],\r
+                "permission": 7\r
+            }\r
+        ],\r
+        "rowneruuid": "00000000-0000-0000-0000-000000000000",\r
+        "rt": ["oic.r.acl"],\r
+        "if": ["oic.if.baseline"]\r
+    },\r
+    "pstat": {\r
+        "dos": { "s": 1, "p": false },\r
+        "isop": false,\r
+        "cm": 2,\r
+        "tm": 0,\r
+        "om": 4,\r
+        "sm": 4,\r
+        "rowneruuid": "00000000-0000-0000-0000-000000000000",\r
+        "rt": ["oic.r.pstat"],\r
+        "if": ["oic.if.baseline"]\r
+    },\r
+    "doxm": {\r
+        "oxms": [0],\r
+        "oxmsel": 0,\r
+        "sct": 9,\r
+        "owned": false,\r
+        "deviceuuid": "12345678-1234-1234-1234-123456789012",\r
+        "devowneruuid": "00000000-0000-0000-0000-000000000000",\r
+        "rowneruuid": "00000000-0000-0000-0000-000000000000",\r
+        "rt": ["oic.r.doxm"],\r
+        "if": ["oic.if.baseline"]\r
+    }\r
+}\r
diff --git a/examples/OCFSecure/server.cpp b/examples/OCFSecure/server.cpp
new file mode 100644 (file)
index 0000000..18dda17
--- /dev/null
@@ -0,0 +1,574 @@
+/******************************************************************
+*
+* Copyright 2018 Vprime All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*****************************************************************
+\author    Rami Alshafi <ralshafi@vprime.com>
+*/
+///////////////////////////////////////////////////////////////////////
+// NOTE :  This sample server is generated based on ocserverbasicops.cpp
+///////////////////////////////////////////////////////////////////////
+
+
+#include "iotivity_config.h"
+#ifdef WITH_MRAA
+#include "mraa.hpp"
+#endif
+#include <signal.h>
+#include "ocstack.h"
+#include "ocpayload.h"
+#include "logger.h"
+#include "utilities.c"
+#include <unistd.h>
+#include <time.h>
+#define TAG "SERVER_APP"
+
+static bool STOP = false;
+static char SVR_DB[] = "ocf_svr_db_server.dat";
+static char INTROSPECTION_FILE[] = "switch_introspection.dat";
+#ifdef JOULE
+int LED_PIN = 100; // built-in led on the intel joule board
+#endif
+#ifdef RASPBERRY
+int LED_PIN = 7;
+#endif
+#ifdef WITH_MRAA
+mraa::Gpio *GPIO;
+#endif
+
+typedef struct
+{
+    OCResourceHandle handle;
+    const char* type = "oic.r.switch.binary";
+    const char * interface = OC_RSRVD_INTERFACE_ACTUATOR;
+    const char* uri = "/switch";
+    uint8_t properties = OC_DISCOVERABLE | OC_SECURE;
+    bool value = false;
+
+} BinarySwitch;
+
+static BinarySwitch SWITCH;
+
+static const char* PLATFORM_ID = "12345678-1234-1234-1234-123456789012";
+static const char* MANUFACTURER_NAME = "Vprime";
+// Set of strings for each of device info fields
+static const char*  DEVICE_NAME = "OCF Developer kit";
+static const char*  SPEC_VERSION = "ocf.1.0.0";
+static const char*  DATA_MODEL_VERSION = "ocf.res.1.0.0,ocf.sh.1.0.0";
+static const char*  PROTO_INDEP_ID = "b0ed9259-ec95-4ac6-8f62-241d0da02683";
+static const char*  DEVICE_TYPE = "oic.d.switch";
+
+
+/**
+* utility function to set the platform information
+*
+* @return stack result
+*/
+OCStackResult SetPlatformInfo()
+{
+    OCStackResult result = OC_STACK_ERROR;
+    OCResourceHandle rHandle = OCGetResourceHandleAtUri(OC_RSRVD_PLATFORM_URI);
+    if (rHandle == NULL)
+    {
+        OIC_LOG_V(ERROR, TAG,
+                  "[%s] Platform Resource does not exist", __func__);
+        return result;
+    }
+    result = OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM,
+                                OC_RSRVD_PLATFORM_ID,
+                                PLATFORM_ID);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed to set platform ID", __func__);
+        return result;
+    }
+    else
+    {
+        char * pin = NULL;
+        OCGetPropertyValue(PAYLOAD_TYPE_PLATFORM,
+                           OC_RSRVD_PLATFORM_ID,
+                           (void **) &pin);
+        OIC_LOG_V(INFO, TAG, "[%s] Set platform ID successfully to %s",
+            __func__,
+            pin);
+    }
+    result = OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM,
+                                OC_RSRVD_MFG_NAME,
+                                MANUFACTURER_NAME);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed to set platform name",
+                  __func__);
+        return result;
+    }
+    else
+    {
+        char * mn = NULL;
+        OCGetPropertyValue(PAYLOAD_TYPE_PLATFORM,
+                           OC_RSRVD_MFG_NAME,
+                           (void **) &mn);
+        OIC_LOG_V(INFO, TAG, "[%s] Set manufacture name successfully to %s",
+            __func__,
+            mn);
+    }
+
+    return OC_STACK_OK;
+}
+
+
+/**
+* utility function to set the device information
+*
+* @return stack result
+*/
+OCStackResult SetDeviceInfo(void)
+{
+    OCStackResult result = OC_STACK_ERROR;
+
+    OCResourceHandle handle = OCGetResourceHandleAtUri(OC_RSRVD_DEVICE_URI);
+    if (handle == NULL)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed to find device resource %s",
+                  __func__,
+                  OC_RSRVD_DEVICE_URI);
+        return result;
+    }
+
+    result = OCBindResourceTypeToResource(handle, DEVICE_TYPE);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed to add device type", __func__);
+        return result;
+    }
+
+    result = OCSetPropertyValue(PAYLOAD_TYPE_DEVICE,
+                                OC_RSRVD_DEVICE_NAME,
+                                DEVICE_NAME);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed to set device name", __func__);
+        return result;
+    }
+
+    result = OCSetPropertyValue(PAYLOAD_TYPE_DEVICE,
+                                OC_RSRVD_DATA_MODEL_VERSION,
+                                DATA_MODEL_VERSION);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed to set data model versions",
+                  __func__);
+        return result;
+    }
+
+    result = OCSetPropertyValue(PAYLOAD_TYPE_DEVICE,
+                                OC_RSRVD_SPEC_VERSION,
+                                SPEC_VERSION);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed to set spec version", __func__);
+        return result;
+    }
+
+    result = OCSetPropertyValue(PAYLOAD_TYPE_DEVICE,
+                                OC_RSRVD_PROTOCOL_INDEPENDENT_ID,
+                                PROTO_INDEP_ID);
+    if (result != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed to set proptocol independent id",
+                  __func__);
+        return result;
+    }
+
+    return OC_STACK_OK;
+}
+
+
+/**
+* Internal method to create the response payload and updates it with the
+* resource properties.
+*
+* @param[in] resource the resource used to created the response payload
+*
+* @return response payload
+*/
+OCRepPayload*
+CreateResponsePayload(BinarySwitch resource)
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if (!payload)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed to create response payload",
+                  __func__);
+        return NULL;
+    }
+    OIC_LOG_V(DEBUG, TAG, "[%s] Created response payload successfully."
+              "Setting up properties...",
+              __func__);
+    OCRepPayloadAddInterface(payload, OC_RSRVD_INTERFACE_DEFAULT);
+    OCRepPayloadAddInterface(payload, resource.interface);
+    OCRepPayloadAddResourceType(payload, resource.type);
+    OCRepPayloadSetPropBool(payload, "value", resource.value);
+
+    return payload;
+}
+
+
+/**
+* Internal method to process the GET request.
+*
+* @param[out] payload pointer to the payload that needs to be updated
+*
+* @return Entity handler result
+*/
+OCEntityHandlerResult
+ProcessGetRequest(OCRepPayload **payload)
+{
+    OCEntityHandlerResult eh_res = OC_EH_ERROR;
+    OIC_LOG_V(DEBUG, TAG, "[%s] Processing GET request", __func__);
+    OCRepPayload *ResponsePayload = CreateResponsePayload(SWITCH);
+
+    if (ResponsePayload)
+    {
+        *payload = ResponsePayload;
+        eh_res = OC_EH_OK;
+    }
+
+    return eh_res;
+}
+
+
+/**
+* Internal method to process the POST request.
+*
+* @param[in] ehRequest a pointer to the entity handler request
+* @param[out] payload a pointer to the pointer to the payload that needs to be
+* updated
+*
+* @return Entity handler result
+*/
+OCEntityHandlerResult
+ProcessPostRequest(OCEntityHandlerRequest *ehRequest,
+                   OCRepPayload **payload)
+{
+    OCEntityHandlerResult eh_res = OC_EH_ERROR;
+    OIC_LOG_V(DEBUG, TAG, "[%s] Processing POST request", __func__);
+    // casting the request payload into a OCRepPayload data type to
+    // read the value property
+    const OCRepPayload* requestPayload = (OCRepPayload*)(ehRequest->payload);
+    bool value;
+    if (OCRepPayloadGetPropBool(requestPayload, "value", &value))
+    {
+        SWITCH.value = value;
+        #if defined(JOULE) || defined(RASPBERRY)
+        GPIO->write(value);
+        #endif
+    }
+    else
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed updating the value property",
+                  __func__);
+        return eh_res;
+    }
+
+    OCRepPayload *ResponsePayload = CreateResponsePayload(SWITCH);
+
+    if (ResponsePayload)
+    {
+        *payload = ResponsePayload;
+        eh_res = OC_EH_OK;
+    }
+
+    return eh_res;
+}
+
+
+/**
+* The entity handler call back method for the SWITCH resource to handle the GET
+* and POST requests.
+*
+* @param[in] flag entity handler flag which could be request or observer
+* @param[in] ehRequest a pointer to the entity handler request
+* @param[in] callbackParam unused
+*
+* @return Entity handler result
+*/
+OCEntityHandlerResult
+OCEntityHandlerCallBack(OCEntityHandlerFlag flag,
+                        OCEntityHandlerRequest *ehRequest,
+                        void* callbackParam)
+{
+    OC_UNUSED(callbackParam);
+    if (!ehRequest)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Invalid request pointer", __func__);
+        return OC_EH_ERROR;
+    }
+    if (ehRequest->payload &&
+        ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] payload type must be representation",
+                  __func__);
+        return OC_EH_ERROR;
+    }
+    OIC_LOG_V(INFO, TAG, "[%s] Flags: 0x%x: %s",
+               __func__,
+               flag,
+               decode_oc_eh_flag(flag));
+
+
+    OCEntityHandlerResult eh_res = OC_EH_ERROR;
+    OCStackResult stackResult = OC_STACK_ERROR;
+
+    OCEntityHandlerResponse ehResponse;
+    memset(&ehResponse, 0, sizeof(ehResponse));
+    OCMethod requestMethod = ehRequest->method;
+
+
+    OCRepPayload* payload = NULL;
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OIC_LOG_V(INFO, TAG, "[%s] OC_REQUEST_FLAG is detected", __func__);
+        if (ehRequest)
+        {
+            if (OC_REST_GET == requestMethod)
+            {
+                OIC_LOG_V(INFO, TAG, "[%s] Processing GET request", __func__);
+                eh_res = ProcessGetRequest(&payload);
+            }
+            else if (OC_REST_POST == requestMethod)
+            {
+                OIC_LOG_V(INFO, TAG, "[%s] Processing POST request",
+                           __func__);
+                eh_res = ProcessPostRequest(ehRequest, &payload);
+            }
+            else
+            {
+                OIC_LOG_V(INFO, TAG, "[%s] Received unsupported method (%d):"
+                           " %s",
+                           __func__,
+                           ehRequest->method,
+                           decode_oc_method(ehRequest->method));
+                eh_res = OC_EH_ERROR;
+            }
+
+            if (eh_res == OC_EH_OK)
+            {
+                ehResponse.requestHandle = ehRequest->requestHandle;
+                ehResponse.resourceHandle = ehRequest->resource;
+                ehResponse.ehResult = eh_res;
+                ehResponse.payload = (OCPayload*)(payload);
+                ehResponse.numSendVendorSpecificHeaderOptions = 0;
+                memset(ehResponse.sendVendorSpecificHeaderOptions, 0,
+                       sizeof(ehResponse.sendVendorSpecificHeaderOptions));
+                memset(ehResponse.resourceUri,
+                       0,
+                       sizeof(ehResponse.resourceUri));
+                ehResponse.persistentBufferFlag = 0;
+
+                // Send the ehResponse
+                stackResult = OCDoResponse(&ehResponse);
+                if (stackResult != OC_STACK_OK)
+                {
+                    OIC_LOG_V(ERROR, TAG, "[%s] Failed to send a ehResponse "
+                              "(%d): %s",
+                              __func__,
+                              stackResult,
+                              decode_oc_stack_result(stackResult));
+                    eh_res = OC_EH_ERROR;
+                }
+            }
+            else
+            {
+                OIC_LOG_V(ERROR, TAG, "[%s] Entity handler failure (%d): %s",
+                          __func__,
+                          eh_res,
+                          decode_oc_eh_result(eh_res));
+            }
+        }
+    }
+
+    OCPayloadDestroy(ehResponse.payload);
+    return eh_res;
+}
+
+
+/**
+* SIGINT call back handler to update the STOP flag to exit the main loop.
+*
+* @param[in] signalNumber
+*/
+void
+SIGINTHandlerCallBack(int signalNumber)
+{
+    OIC_LOG_V(INFO, TAG, "[%s] Received SIGINT", __func__);
+    if (signalNumber == SIGINT)
+    {
+        STOP = true;
+    }
+}
+
+
+/**
+* Custom fopen method to open the secure virtual resource database correctly.
+*
+* @param[in] path file name to be opened
+* @param[in] mode the mode in which the file will be opened in
+*
+* @return opened file
+*/
+FILE*
+ServerFOpen(const char *path,
+            const char *mode)
+{
+    if (0 == strcmp(path, OC_SECURITY_DB_DAT_FILE_NAME))
+    {
+        OIC_LOG_V(DEBUG, TAG, "[%s] reading file: %s with mode: %s",
+                  __func__,
+                  SVR_DB,
+                  mode);
+        return fopen(SVR_DB, mode);
+    }
+    else if(0 == strcmp(path, OC_INTROSPECTION_FILE_NAME))
+    {
+        OIC_LOG_V(DEBUG, TAG, "[%s] reading file: %s with mode: %s",
+                  __func__,
+                  INTROSPECTION_FILE,
+                  mode);
+      return fopen(INTROSPECTION_FILE, mode);
+    }
+    else
+    {
+        OIC_LOG_V(DEBUG, TAG, "[%s] reading file: %s with mode: %s",
+                  __func__,
+                  path,
+                  mode);
+        return fopen(path, mode);
+    }
+}
+
+
+/**
+* main function
+*/
+int
+main(void)
+{
+    OCStackResult stack_res = OC_STACK_ERROR;
+    // enabling GPIO if running on the Intel Joule or the raspberry pi
+    #if (defined(JOULE) || defined(RASPBERRY)) && defined(WITH_MRAA)
+    GPIO = new mraa::Gpio(LED_PIN);
+    if (!GPIO)
+    {
+      OIC_LOG_V(ERROR, TAG, "Error instantiating gpio %d", LED_PIN);
+    }
+    GPIO->dir(mraa::DIR_OUT);
+    #endif
+
+    OIC_LOG_V(DEBUG, TAG, "[%s] Initializing and registering persistent"
+              "storage",
+              __func__);
+    OCPersistentStorage ps = {ServerFOpen, fread, fwrite, fclose, unlink};
+    OCRegisterPersistentStorageHandler(&ps);
+
+    OIC_LOG_V(DEBUG, TAG, "[%s] Initializing IoTivity stack for server",
+              __func__);
+    stack_res = OCInit(NULL, 0, OC_SERVER);
+    if (stack_res != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed to initialize IoTivity stack (%d): "
+                  "%s",
+                  __func__, stack_res, decode_oc_stack_result(stack_res));
+        return stack_res;
+    }
+
+    stack_res = SetPlatformInfo();
+
+    if (stack_res != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Platform Registration failed\n", __func__);
+        return stack_res;
+    }
+    else
+    {
+        OIC_LOG_V(INFO, TAG, "[%s] Platform set successfully", __func__);
+    }
+
+    stack_res = SetDeviceInfo();
+    if (stack_res != OC_STACK_OK)
+    {
+      OIC_LOG_V(ERROR, TAG, "[%s] Device Registration failed\n", __func__);
+      return stack_res;
+    }
+    else
+    {
+        OIC_LOG_V(INFO, TAG, "[%s] Device set successfully", __func__);
+    }
+
+    stack_res = OCCreateResource(&(SWITCH.handle),
+                                 SWITCH.type,
+                                 SWITCH.interface,
+                                 SWITCH.uri,
+                                 OCEntityHandlerCallBack,
+                                 NULL,
+                                 SWITCH.properties);
+    if (stack_res != OC_STACK_OK)
+    {
+      OIC_LOG_V(ERROR, TAG, "[%s] Failed to create resource\n", __func__);
+      return stack_res;
+    }
+    else
+    {
+        OIC_LOG_V(INFO, TAG, "[%s] Created resource successfully", __func__);
+    }
+
+    struct timespec timeout;
+    timeout.tv_sec  = 0;
+    timeout.tv_nsec = 100000000L;
+
+    OIC_LOG_V(INFO, TAG, "[%s] Server is running, press ctrl+c to stop...",
+              __func__);
+
+    signal(SIGINT, SIGINTHandlerCallBack);
+
+    while (!STOP)
+    {
+        stack_res = OCProcess();
+        if (stack_res != OC_STACK_OK)
+        {
+            OIC_LOG_V(ERROR, TAG, "[%s] IoTivity stack process failure (%d): "
+                      "%s",
+                      __func__, stack_res, decode_oc_stack_result(stack_res));
+            return stack_res;
+        }
+        nanosleep(&timeout, NULL);
+    }
+
+    OIC_LOG_V(INFO, TAG, "[%s] Stopping IoTivity server...", __func__);
+
+    stack_res = OCStop();
+    if (stack_res != OC_STACK_OK)
+    {
+        OIC_LOG_V(ERROR, TAG, "[%s] Failed to stop IoTivity server (%d): %s",
+                  __func__,
+                  stack_res,
+                  decode_oc_stack_result(stack_res));
+        return stack_res;
+    }
+
+    return 0;
+}
diff --git a/examples/OCFSecure/switch_introspection.dat b/examples/OCFSecure/switch_introspection.dat
new file mode 100644 (file)
index 0000000..3293652
--- /dev/null
@@ -0,0 +1 @@
+¿gswaggerc2.0dinfo¿etitleqmy_example_devicegversionqmy device versionÿgschemes\9fdhttpÿhconsumes\9fpapplication/jsonÿhproduces\9fpapplication/jsonÿepaths¿g/switch¿cget¿jparameters\9f¿dnamebifbinequerykdescription`denum\9fhoic.if.aooic.if.baselineÿdtypefstringÿÿiresponses¿c200¿kdescription`fschema¿d$refx\1a#/definitions/BinarySwitchÿÿÿÿdpost¿jparameters\9f¿dnamebifbinequerykdescription`denum\9fhoic.if.aooic.if.baselineÿdtypefstringÿ¿dnamedbodybindbodyhrequiredôfschema¿d$refx\1a#/definitions/BinarySwitchÿÿÿiresponses¿c200¿kdescription`fschema¿d$refx\1a#/definitions/BinarySwitchÿÿÿÿÿÿkdefinitions¿lBinarySwitch¿dtypefobjecthrequired\9fevalueÿjproperties¿evalue¿dtypegbooleankdescriptiontStatus of the switchÿbrt¿dtypeearrayeitems\9f¿dtypefstringimaxLength\18@ÿÿhminItems\ 1kdescriptionmResource TypehreadOnlyõgdefault\9fsoic.r.switch.binaryÿÿbif¿dtypeearraykdescriptionx,The interface set supported by this resourcehreadOnlyõeitems¿dtypefstringdenum\9fooic.if.baselinehoic.if.aÿÿÿan¿dtypefstringimaxLength\18@kdescriptionx\1dFriendly name of the resourcehreadOnlyõÿbid¿dtypefstringkdescriptionx%Instance ID of this specific resourcehreadOnlyõÿerange¿dtypeearraykdescriptionx&The valid range for the value PropertyhreadOnlyõhminItems\ 2hmaxItems\ 2eitems¿dtypefnumberÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/examples/OCFSecure/switch_introspection.json b/examples/OCFSecure/switch_introspection.json
new file mode 100644 (file)
index 0000000..6e02a21
--- /dev/null
@@ -0,0 +1,136 @@
+{\r
+    "swagger": "2.0",\r
+    "info": {\r
+      "title": "OCF Dev Kit",\r
+      "version": "1.0"\r
+    },\r
+    "schemes": [\r
+        "http"\r
+    ],\r
+    "consumes": [\r
+        "application/json"\r
+    ],\r
+    "produces": [\r
+        "application/json"\r
+    ],\r
+    "paths": {\r
+       "/switch": {\r
+          "get": {\r
+            "parameters": [\r
+               {\r
+                 "name": "if",\r
+                 "in": "query",\r
+                 "description": "",\r
+                 "enum": [ "oic.if.a","oic.if.baseline" ],\r
+\r
+                 "type": "string"\r
+                }\r
+            ],\r
+            "responses": {\r
+              "200" : {\r
+                  "description" : "",\r
+                  "schema" :\r
+                  {\r
+                    "$ref": "#/definitions/BinarySwitch"\r
+                  }\r
+               }\r
+            }\r
+\r
+           },\r
+\r
+          "post": {\r
+            "parameters": [\r
+               {\r
+                 "name": "if",\r
+                 "in": "query",\r
+                 "description": "",\r
+                 "enum": [ "oic.if.a","oic.if.baseline" ],\r
+\r
+                 "type": "string"\r
+                },\r
+                {\r
+                  "name": "body",\r
+                  "in": "body",\r
+                  "required": false,\r
+                   "schema" :\r
+                  {\r
+                    "$ref": "#/definitions/BinarySwitch"\r
+                  }\r
+                }\r
+            ],\r
+            "responses": {\r
+              "200" : {\r
+                  "description" : "",\r
+                   "schema" :\r
+                  {\r
+                    "$ref": "#/definitions/BinarySwitch"\r
+                  }\r
+\r
+               }\r
+            }\r
+          }\r
+        }\r
+    },\r
+    "definitions":\r
+    {\r
+        "BinarySwitch": {\r
+           "type": "object",\r
+           "required": [\r
+             "value"\r
+           ],\r
+           "properties":  {\r
+               "value": {\r
+                  "type": "boolean",\r
+                  "description": "Status of the switch"\r
+                },\r
+                "rt": {\r
+                  "type": "array",\r
+                  "items" : [\r
+                    {\r
+                      "type" : "string",\r
+                      "maxLength": 64\r
+                    }\r
+                  ],\r
+                  "minItems" : 1,\r
+                  "description": "Resource Type",\r
+                  "readOnly" : true,\r
+                  "default" : [ "oic.r.switch.binary" ]\r
+                },\r
+                "if": {\r
+                    "type": "array",\r
+                    "description": "The interface set supported by this resource",\r
+                    "readOnly" : true,\r
+                    "items": {\r
+                        "type": "string",\r
+                        "enum": [\r
+                            "oic.if.baseline",\r
+                            "oic.if.a"\r
+                        ]\r
+                    }\r
+                },\r
+                "n": {\r
+                    "type": "string",\r
+                    "maxLength": 64,\r
+                    "description": "Friendly name of the resource",\r
+                    "readOnly" : true\r
+                },\r
+                "id": {\r
+                    "type": "string",\r
+                    "description": "Instance ID of this specific resource",\r
+                    "readOnly" : true\r
+                },\r
+                "range": {\r
+                    "type": "array",\r
+                    "description": "The valid range for the value Property",\r
+                    "readOnly" : true,\r
+                    "minItems": 2,\r
+                    "maxItems": 2,\r
+                    "items": {\r
+                        "type": "number"\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/examples/OCFSecure/utilities.c b/examples/OCFSecure/utilities.c
new file mode 100644 (file)
index 0000000..f63a86c
--- /dev/null
@@ -0,0 +1,202 @@
+
+const char* decode_oc_stack_result (OCStackResult result)
+{
+    switch (result)
+    {
+        case OC_STACK_OK:
+            return "OC_STACK_OK";
+        case OC_STACK_RESOURCE_DELETED:
+            return "OC_STACK_RESOURCE_DELETED";
+        case OC_STACK_CONTINUE:
+            return "OC_STACK_CONTINUE";
+        case OC_STACK_RESOURCE_CREATED:
+            return "OC_STACK_RESOURCE_CREATED";
+        case OC_STACK_RESOURCE_CHANGED:
+            return "OC_STACK_RESOURCE_CHANGED";
+        case OC_STACK_INVALID_URI:
+            return "OC_STACK_INVALID_URI";
+        case OC_STACK_INVALID_QUERY:
+            return "OC_STACK_INVALID_QUERY";
+        case OC_STACK_INVALID_IP:
+            return "OC_STACK_INVALID_IP";
+        case OC_STACK_INVALID_PORT:
+            return "OC_STACK_INVALID_PORT";
+        case OC_STACK_INVALID_CALLBACK:
+            return "OC_STACK_INVALID_CALLBACK";
+        case OC_STACK_INVALID_METHOD:
+            return "OC_STACK_INVALID_METHOD";
+        case OC_STACK_INVALID_PARAM:
+            return "OC_STACK_INVALID_PARAM";
+        case OC_STACK_INVALID_OBSERVE_PARAM:
+            return "OC_STACK_INVALID_OBSERVE_PARAM";
+        case OC_STACK_NO_MEMORY:
+            return "OC_STACK_NO_MEMORY";
+        case OC_STACK_COMM_ERROR:
+            return "OC_STACK_COMM_ERROR";
+        case OC_STACK_TIMEOUT:
+            return "OC_STACK_TIMEOUT";
+        case OC_STACK_ADAPTER_NOT_ENABLED:
+            return "OC_STACK_ADAPTER_NOT_ENABLED";
+        case OC_STACK_NOTIMPL:
+            return "OC_STACK_NOTIMPL";
+        case OC_STACK_NO_RESOURCE:
+            return "OC_STACK_NO_RESOURCE";
+        case OC_STACK_RESOURCE_ERROR:
+            return "OC_STACK_RESOURCE_ERROR";
+        case OC_STACK_SLOW_RESOURCE:
+            return "OC_STACK_SLOW_RESOURCE";
+        case OC_STACK_DUPLICATE_REQUEST:
+            return "OC_STACK_DUPLICATE_REQUEST";
+        case OC_STACK_NO_OBSERVERS:
+            return "OC_STACK_NO_OBSERVERS";
+        case OC_STACK_OBSERVER_NOT_FOUND:
+            return "OC_STACK_OBSERVER_NOT_FOUND";
+        case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+            return "OC_STACK_VIRTUAL_DO_NOT_HANDLE";
+        case OC_STACK_INVALID_OPTION:
+            return "OC_STACK_INVALID_OPTION";
+        case OC_STACK_MALFORMED_RESPONSE:
+            return "OC_STACK_MALFORMED_RESPONSE";
+        case OC_STACK_PERSISTENT_BUFFER_REQUIRED:
+            return "OC_STACK_PERSISTENT_BUFFER_REQUIRED";
+        case OC_STACK_INVALID_REQUEST_HANDLE:
+            return "OC_STACK_INVALID_REQUEST_HANDLE";
+        case OC_STACK_INVALID_DEVICE_INFO:
+            return "OC_STACK_INVALID_DEVICE_INFO";
+        case OC_STACK_INVALID_JSON:
+            return "OC_STACK_INVALID_JSON";
+        case OC_STACK_UNAUTHORIZED_REQ:
+            return "OC_STACK_UNAUTHORIZED_REQ";
+        case OC_STACK_PDM_IS_NOT_INITIALIZED:
+            return "OC_STACK_PDM_IS_NOT_INITIALIZED";
+        case OC_STACK_DUPLICATE_UUID:
+            return "OC_STACK_DUPLICATE_UUID";
+        case OC_STACK_INCONSISTENT_DB:
+            return "OC_STACK_INCONSISTENT_DB";
+        case OC_STACK_AUTHENTICATION_FAILURE:
+            return "OC_STACK_AUTHENTICATION_FAILURE";
+        case OC_STACK_ERROR:
+            return "OC_STACK_ERROR";
+        case OC_STACK_TOO_LARGE_REQ:
+            return "OC_STACK_TOO_LARGE_REQ";
+        case OC_STACK_NOT_ALLOWED_OXM:
+            return "OC_STACK_NOT_ALLOWED_OXM";
+        case OC_STACK_BAD_ENDPOINT:
+            return "OC_STACK_BAD_ENDPOINT";
+        case OC_STACK_USER_DENIED_REQ:
+            return "OC_STACK_USER_DENIED_REQ";
+        case OC_STACK_NOT_ACCEPTABLE:
+            return "OC_STACK_NOT_ACCEPTABLE";
+        case OC_STACK_FORBIDDEN_REQ:
+            return "OC_STACK_FORBIDDEN_REQ";
+        case OC_STACK_INTERNAL_SERVER_ERROR:
+            return "OC_STACK_INTERNAL_SERVER_ERROR";
+        case OC_STACK_GATEWAY_TIMEOUT:
+            return "OC_STACK_GATEWAY_TIMEOUT";
+        case OC_STACK_SERVICE_UNAVAILABLE:
+            return "OC_STACK_SERVICE_UNAVAILABLE";
+    #ifdef WITH_PRESENCE
+        case OC_STACK_PRESENCE_STOPPED:
+            return "OC_STACK_PRESENCE_STOPPED";
+        case OC_STACK_PRESENCE_TIMEOUT:
+            return "OC_STACK_PRESENCE_TIMEOUT";
+        case OC_STACK_PRESENCE_DO_NOT_HANDLE:
+            return "OC_STACK_PRESENCE_DO_NOT_HANDLE";
+    #endif
+        default:
+            return "Unknown result!";
+    }
+}
+
+const char* decode_oc_eh_result (OCEntityHandlerResult result)
+{
+    switch(result)
+    {
+        case OC_EH_OK:
+            return "OC_EH_OK";
+        case OC_EH_ERROR:
+            return "OC_EH_ERROR";
+        case OC_EH_SLOW:
+            return "OC_EH_SLOW";
+        case OC_EH_RESOURCE_CREATED:
+            return "OC_EH_RESOURCE_CREATED";
+        case OC_EH_RESOURCE_DELETED:
+            return "OC_EH_RESOURCE_DELETED";
+        case OC_EH_VALID:
+            return "OC_EH_VALID";
+        case OC_EH_CHANGED:
+            return "OC_EH_CHANGED";
+        case OC_EH_CONTENT:
+            return "OC_EH_CONTENT";
+        case OC_EH_BAD_REQ:
+            return "OC_EH_BAD_REQ";
+        case OC_EH_UNAUTHORIZED_REQ:
+            return "OC_EH_UNAUTHORIZED_REQ";
+        case OC_EH_BAD_OPT:
+            return "OC_EH_BAD_OPT";
+        case OC_EH_FORBIDDEN:
+            return "OC_EH_FORBIDDEN";
+        case OC_EH_RESOURCE_NOT_FOUND:
+            return "OC_EH_RESOURCE_NOT_FOUND";
+        case OC_EH_METHOD_NOT_ALLOWED:
+            return "OC_EH_METHOD_NOT_ALLOWED";
+        case OC_EH_NOT_ACCEPTABLE:
+            return "OC_EH_NOT_ACCEPTABLE";
+        case OC_EH_TOO_LARGE:
+            return "OC_EH_TOO_LARGE";
+        case OC_EH_UNSUPPORTED_MEDIA_TYPE:
+            return "OC_EH_UNSUPPORTED_MEDIA_TYPE";
+        case OC_EH_INTERNAL_SERVER_ERROR:
+            return "OC_EH_INTERNAL_SERVER_ERROR";
+        case OC_EH_BAD_GATEWAY:
+            return "OC_EH_BAD_GATEWAY";
+        case OC_EH_SERVICE_UNAVAILABLE:
+            return "OC_EH_SERVICE_UNAVAILABLE";
+        case OC_EH_RETRANSMIT_TIMEOUT:
+            return "OC_EH_RETRANSMIT_TIMEOUT";
+        default:
+            return "Unknown result!";
+    }
+}
+
+const char* decode_oc_method (OCMethod method)
+{
+    switch(method)
+    {
+        case OC_REST_NOMETHOD:
+            return "OC_REST_NOMETHOD";
+        case OC_REST_GET:
+            return "OC_REST_GET";
+        case OC_REST_PUT:
+            return "OC_REST_PUT";
+        case OC_REST_POST:
+            return "OC_REST_POST";
+        case OC_REST_DELETE:
+            return "OC_REST_DELETE";
+        case OC_REST_OBSERVE:
+            return "OC_REST_OBSERVE";
+        case OC_REST_OBSERVE_ALL:
+            return "OC_REST_OBSERVE_ALL";
+        case OC_REST_DISCOVER:
+            return "OC_REST_DISCOVER";
+    #ifdef WITH_PRESENCE
+        case OC_REST_PRESENCE:
+            return "OC_REST_PRESENCE";
+    #endif
+        default:
+            return "Unknown method";
+    }
+}
+
+const char* decode_oc_eh_flag (OCEntityHandlerFlag flag)
+{
+    switch(flag)
+    {
+        case OC_REQUEST_FLAG:
+            return "OC_REQUEST_FLAG";
+        case OC_OBSERVE_FLAG:
+            return "OC_OBSERVE_FLAG";
+        default:
+            return "Unknown oc eh flag";
+    }
+}