From b2e13cb430aeee5eca38253a454a0665eb6a68b6 Mon Sep 17 00:00:00 2001 From: "hyuna0213.jo" Date: Wed, 19 Aug 2015 12:53:37 +0900 Subject: [PATCH] Merge master to cloud-interface branch merge master branch to use latest master code. Change-Id: I57a2415e334c99755df87da5f97f28deb3ce5d76 Signed-off-by: hyuna0213.jo Reviewed-on: https://gerrit.iotivity.org/gerrit/2238 Reviewed-by: Jaehong Jo Reviewed-by: Jon A. Cruz Tested-by: Jon A. Cruz --- android/BuildInstructionsForAndroidAPI.txt | 5 +- android/android_api/SConscript | 2 +- .../main/java/org/iotivity/base/OcPlatform.java | 2 +- .../java/org/iotivity/ca/CaLeClientInterface.java | 40 +- .../java/org/iotivity/ca/CaLeServerInterface.java | 33 +- auto_build.sh | 13 +- build_common/android/compatibility/c_compat.c | 13 - resource/c_common/platform_features.h | 7 + resource/csdk/connectivity/api/cacommon.h | 62 +- resource/csdk/connectivity/api/cainterface.h | 241 +++--- resource/csdk/connectivity/common/inc/uarraylist.h | 15 +- .../csdk/connectivity/common/src/caremotehandler.c | 206 +---- .../common/src/cathreadpool_pthreads.c | 12 +- resource/csdk/connectivity/common/src/uarraylist.c | 18 +- .../csdk/connectivity/inc/caadapterinterface.h | 2 +- resource/csdk/connectivity/inc/caadapternetdtls.h | 4 +- resource/csdk/connectivity/inc/caipinterface.h | 40 +- resource/csdk/connectivity/inc/camessagehandler.h | 2 - .../sampleService/src/main/jni/ResourceModel.c | 40 +- .../src/adapter_util/caadapternetdtls.c | 71 +- .../src/bt_edr_adapter/android/caedrutils.c | 40 +- .../src/bt_edr_adapter/android/caedrutils.h | 11 - .../src/bt_edr_adapter/tizen/caedrendpoint.c | 1 - .../src/bt_edr_adapter/tizen/caedrnwmonitor.c | 3 +- .../src/bt_le_adapter/android/caleclient.c | 58 +- .../src/bt_le_adapter/android/caleclient.h | 8 - .../src/bt_le_adapter/android/caleserver.c | 33 +- .../src/bt_le_adapter/android/caleserver.h | 7 - .../connectivity/src/bt_le_adapter/caleadapter.c | 376 ++++----- .../src/bt_le_adapter/tizen/cableserver.c | 52 +- .../csdk/connectivity/src/cablockwisetransfer.c | 21 +- .../csdk/connectivity/src/cainterfacecontroller.c | 6 +- resource/csdk/connectivity/src/camessagehandler.c | 134 ++-- .../csdk/connectivity/src/canetworkconfigurator.c | 10 +- resource/csdk/connectivity/src/caprotocolmessage.c | 8 + .../src/ip_adapter/android/caipnwmonitor.c | 350 +++++++- .../src/ip_adapter/arduino/caipnwmonitor_eth.cpp | 14 +- .../src/ip_adapter/arduino/caipnwmonitor_wifi.cpp | 14 +- .../src/ip_adapter/arduino/caipserver_eth.cpp | 10 +- .../src/ip_adapter/arduino/caipserver_wifi.cpp | 11 +- .../csdk/connectivity/src/ip_adapter/caipadapter.c | 15 +- .../csdk/connectivity/src/ip_adapter/caipserver.c | 116 +-- .../src/ip_adapter/linux/caipnwmonitor.c | 24 +- .../src/ip_adapter/tizen/caipnwmonitor.c | 24 +- resource/csdk/doc/CCF Lite GIT Repo Layout.docx | Bin 127908 -> 0 bytes resource/csdk/security/src/secureresourcemanager.c | 2 +- resource/csdk/stack/include/octypes.h | 11 +- .../arduino/SimpleClientServer/ocserver/SConscript | 5 + .../samples/linux/SimpleClientServer/occlient.cpp | 308 +++---- .../linux/SimpleClientServer/occlientbasicops.cpp | 166 ++-- .../linux/SimpleClientServer/occlientbasicops.h | 15 +- .../linux/SimpleClientServer/occlientcoll.cpp | 75 +- .../linux/SimpleClientServer/occlientslow.cpp | 110 ++- .../samples/linux/secure/occlientbasicops.cpp | 151 ++-- resource/csdk/stack/src/ocpayloadconvert.c | 565 ++++++------- resource/csdk/stack/src/ocpayloadparse.c | 2 +- resource/csdk/stack/src/ocstack.c | 38 +- resource/examples/simpleclient.cpp | 2 +- resource/examples/simpleclientHQ.cpp | 2 +- resource/src/OCRepresentation.cpp | 7 - resource/third_party_libs.scons | 4 +- service/SConscript | 2 +- .../NotificationManager/src/ResourceHosting.cpp | 4 +- .../plugins/mqtt-light/lib/cpp/test.txt | 883 --------------------- service/resource-encapsulation/SConscript | 18 +- .../examples/linux/SampleResourceClient.cpp | 8 +- .../include/RCSDiscoveryManager.h | 120 ++- .../include/RCSResourceAttributes.h | 54 +- .../include/RCSResourceObject.h | 15 +- .../resource-encapsulation/src/common/SConscript | 77 +- .../src/RCSResourceAttributes.cpp | 74 +- .../src/common/utils/include/AtomicHelper.h | 306 +++++++ .../src/resourceBroker/include/ResourcePresence.h | 4 +- .../src/resourceBroker/src/ResourcePresence.cpp | 3 +- .../src/resourceClient/RCSDiscoveryManager.cpp | 33 +- .../src/resourceContainer/SConscript | 35 +- .../src/ResourceContainerImpl.cpp | 4 +- .../src/serverBuilder/SConscript | 70 +- .../src/serverBuilder/src/RCSResourceObject.cpp | 39 +- .../unittests/RCSResourceObjectTest.cpp | 3 +- .../unittests/ResourceClientTest.cpp | 9 +- .../java/org/iotivity/service/ssm/DataReader.java | 4 +- .../java/org/iotivity/service/ssm/ModelData.java | 6 +- .../java/org/iotivity/service/ssm/QueryEngine.java | 8 +- .../SSMCore/src/SSMInterface/SSMCore_JNI.cpp | 38 +- .../SSMCore/src/SSMInterface/SSMCore_JNI.h | 22 +- service/third_party_libs.scons | 4 +- 87 files changed, 2442 insertions(+), 3038 deletions(-) mode change 100644 => 100755 resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c delete mode 100644 resource/csdk/doc/CCF Lite GIT Repo Layout.docx delete mode 100644 service/protocol-plugin/plugins/mqtt-light/lib/cpp/test.txt create mode 100644 service/resource-encapsulation/src/common/utils/include/AtomicHelper.h diff --git a/android/BuildInstructionsForAndroidAPI.txt b/android/BuildInstructionsForAndroidAPI.txt index 1b0f239..a30df42 100644 --- a/android/BuildInstructionsForAndroidAPI.txt +++ b/android/BuildInstructionsForAndroidAPI.txt @@ -10,11 +10,10 @@ Build Instructions for Android-API: def ndkBuild = new File(System.env.ANDROID_NDK_HOME, 'ndk-build.cmd') 4.Build scons for android and your targeted architecture (This will also build Android API): - a.scons TARGET_OS=android TARGET_ARCH= TARGET_TRANSPORT=IP RELEASE=1 - where can be armeabi, armeabi-v7a, x86. + a.scons TARGET_OS=android TARGET_ARCH= TARGET_TRANSPORT= RELEASE=1 + where can be armeabi, armeabi-v7a, x86, x86_64. Note: To build in debug mode, use RELEASE=0. Note: The minimum SDK version supported is 21. - Note: Only TARGET_TRANSPORT currently supported is IP b.If the project is setup correctly, you should see a BUILD SUCCESSFUL message on the terminal c.You should see the .aar files generated inside of '/android/android_api/base/build/outputs/aar' directory. The .aar files contain jni directory and also a .jar file diff --git a/android/android_api/SConscript b/android/android_api/SConscript index 11983d7..5fba6e7 100644 --- a/android/android_api/SConscript +++ b/android/android_api/SConscript @@ -43,6 +43,6 @@ if not os.path.exists(android_home + '/platforms/android-21') or not os.path.exi os.system(android_home + '/tools/android') jdk_env = Environment(ENV=os.environ) -jdk_env['BUILDERS']['Gradle'] = Builder(action = env.get('ANDROID_GRADLE') + ' build -b' + os.getcwd()+'/build.gradle -PTARGET_ARCH=%s -PRELEASE=%s' %(ANDROID_TARGET_ARCH, ANDROID_RELEASE)) +jdk_env['BUILDERS']['Gradle'] = Builder(action = env.get('ANDROID_GRADLE') + ' build -b' + os.getcwd()+'/build.gradle -PTARGET_ARCH=%s -PRELEASE=%s --stacktrace' %(ANDROID_TARGET_ARCH, ANDROID_RELEASE)) jdk_env.Gradle(target="base/objs", source="base/src/main/java/org/iotivity/base/OcResource.java") diff --git a/android/android_api/base/src/main/java/org/iotivity/base/OcPlatform.java b/android/android_api/base/src/main/java/org/iotivity/base/OcPlatform.java index d042e9e..fc562be 100644 --- a/android/android_api/base/src/main/java/org/iotivity/base/OcPlatform.java +++ b/android/android_api/base/src/main/java/org/iotivity/base/OcPlatform.java @@ -63,7 +63,7 @@ public final class OcPlatform { */ public static final String GROUP_INTERFACE = "oic.mi.grp"; - public static final String WELL_KNOWN_QUERY = "224.0.1.187:5683/oic/res"; + public static final String WELL_KNOWN_QUERY = "/oic/res"; public static final String MULTICAST_PREFIX = "224.0.1.187:5683"; public static final String MULTICAST_IP = "224.0.1.187"; public static final int MULTICAST_PORT = 5683; diff --git a/android/android_api/base/src/main/java/org/iotivity/ca/CaLeClientInterface.java b/android/android_api/base/src/main/java/org/iotivity/ca/CaLeClientInterface.java index 891cb40..ef20573 100644 --- a/android/android_api/base/src/main/java/org/iotivity/ca/CaLeClientInterface.java +++ b/android/android_api/base/src/main/java/org/iotivity/ca/CaLeClientInterface.java @@ -72,8 +72,7 @@ public class CaLeClientInterface { private native static void caLeRegisterGattCallback(BluetoothGattCallback callback); // BluetoothAdapter.LeScanCallback - private native static void caLeScanCallback(BluetoothDevice device, - int rssi, byte[] scanRecord); + private native static void caLeScanCallback(BluetoothDevice device); // BluetoothGattCallback private native static void caLeGattConnectionStateChangeCallback( @@ -81,24 +80,13 @@ public class CaLeClientInterface { private native static void caLeGattServicesDiscoveredCallback(BluetoothGatt gatt, int status); - private native static void caLeGattCharacteristicReadCallback( - BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, - byte[] data, int status); - private native static void caLeGattCharacteristicWriteCallback( - BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, - byte[] data, int status); + BluetoothGatt gatt, byte[] data, int status); private native static void caLeGattCharacteristicChangedCallback( - BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] data); - - private native static void caLeGattDescriptorReadCallback(BluetoothGatt gatt, - BluetoothGattDescriptor descriptor, - int status); + BluetoothGatt gatt, byte[] data); - private native static void caLeGattDescriptorWriteCallback(BluetoothGatt gatt, - BluetoothGattDescriptor descriptor, - int status); + private native static void caLeGattDescriptorWriteCallback(BluetoothGatt gatt, int status); private native static void caLeGattReliableWriteCompletedCallback(BluetoothGatt gatt, int status); @@ -125,7 +113,7 @@ public class CaLeClientInterface { Log.d(TAG, "UUID : " + uuid.toString()); if(uuid.toString().contains(SERVICE_UUID.toLowerCase())) { Log.d(TAG, "we found that has the Device"); - caLeScanCallback(device, rssi, scanRecord); + caLeScanCallback(device); } } } catch(UnsatisfiedLinkError e) { @@ -202,9 +190,6 @@ public class CaLeClientInterface { public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicRead(gatt, characteristic, status); - - caLeGattCharacteristicReadCallback(gatt, characteristic, - characteristic.getValue(), status); } @Override @@ -212,8 +197,7 @@ public class CaLeClientInterface { BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicWrite(gatt, characteristic, status); - caLeGattCharacteristicWriteCallback(gatt, characteristic, - characteristic.getValue(), status); + caLeGattCharacteristicWriteCallback(gatt, characteristic.getValue(), status); } @Override @@ -221,16 +205,13 @@ public class CaLeClientInterface { BluetoothGattCharacteristic characteristic) { super.onCharacteristicChanged(gatt, characteristic); - caLeGattCharacteristicChangedCallback(gatt, characteristic, - characteristic.getValue()); + caLeGattCharacteristicChangedCallback(gatt, characteristic.getValue()); } @Override public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { super.onDescriptorRead(gatt, descriptor, status); - - caLeGattDescriptorReadCallback(gatt, descriptor, status); } @Override @@ -238,21 +219,17 @@ public class CaLeClientInterface { int status) { super.onDescriptorWrite(gatt, descriptor, status); - caLeGattDescriptorWriteCallback(gatt, descriptor, status); + caLeGattDescriptorWriteCallback(gatt, status); } @Override public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { super.onReliableWriteCompleted(gatt, status); - - caLeGattReliableWriteCompletedCallback(gatt, status); } @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { super.onReadRemoteRssi(gatt, rssi, status); - - caLeGattReadRemoteRssiCallback(gatt, rssi, status); } }; @@ -293,3 +270,4 @@ public class CaLeClientInterface { }; } + diff --git a/android/android_api/base/src/main/java/org/iotivity/ca/CaLeServerInterface.java b/android/android_api/base/src/main/java/org/iotivity/ca/CaLeServerInterface.java index 18ac49f..281beac 100644 --- a/android/android_api/base/src/main/java/org/iotivity/ca/CaLeServerInterface.java +++ b/android/android_api/base/src/main/java/org/iotivity/ca/CaLeServerInterface.java @@ -56,23 +56,10 @@ public class CaLeServerInterface { BluetoothGattService service); private native static void caLeGattServerCharacteristicReadRequestCallback( - BluetoothDevice device, - int requestId, int offset, BluetoothGattCharacteristic characteristic, byte[] data); + BluetoothDevice device, byte[] data); private native static void caLeGattServerCharacteristicWriteRequestCallback( - BluetoothDevice device, int requestId, - BluetoothGattCharacteristic characteristic, byte[] data, boolean preparedWrite, - boolean responseNeeded, int offset, byte[] value); - - private native static void caLeGattServerDescriptorReadRequestCallback( - BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor); - - public native static void caLeGattServerDescriptorWriteRequestCallback( - BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, - boolean preparedWrite, boolean responseNeeded, int offset, byte[] value); - - private native static void caLeGattServerExecuteWriteCallback(BluetoothDevice device, - int requestId, boolean execute); + BluetoothDevice device, byte[] data); private native static void caLeGattServerNotificationSentCallback(BluetoothDevice device, int status); @@ -107,9 +94,7 @@ public class CaLeServerInterface { BluetoothGattCharacteristic characteristic) { super.onCharacteristicReadRequest(device, requestId, offset, characteristic); - caLeGattServerCharacteristicReadRequestCallback(device, requestId, offset, - characteristic, - characteristic.getValue()); + caLeGattServerCharacteristicReadRequestCallback(device, characteristic.getValue()); } @Override @@ -119,9 +104,7 @@ public class CaLeServerInterface { super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value); - caLeGattServerCharacteristicWriteRequestCallback(device, requestId, characteristic, - value, preparedWrite, responseNeeded, - offset, value); + caLeGattServerCharacteristicWriteRequestCallback(device, value); } @Override @@ -129,8 +112,6 @@ public class CaLeServerInterface { BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) { super.onDescriptorReadRequest(device, requestId, offset, descriptor); - - caLeGattServerDescriptorReadRequestCallback(device, requestId, offset, descriptor); } @Override @@ -140,17 +121,11 @@ public class CaLeServerInterface { byte[] value) { super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value); - - caLeGattServerDescriptorWriteRequestCallback(device, requestId, descriptor, - preparedWrite, responseNeeded, offset, - value); } @Override public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) { super.onExecuteWrite(device, requestId, execute); - - caLeGattServerExecuteWriteCallback(device, requestId, execute); } @Override diff --git a/auto_build.sh b/auto_build.sh index 568920e..750f641 100755 --- a/auto_build.sh +++ b/auto_build.sh @@ -69,9 +69,18 @@ function build_android() echo "*********** Build for android x86 *************" scons TARGET_OS=android TARGET_ARCH=x86 RELEASE=$1 TARGET_TRANSPORT=IP $2 + scons TARGET_OS=android TARGET_ARCH=x86 RELEASE=$1 TARGET_TRANSPORT=BT $2 + scons TARGET_OS=android TARGET_ARCH=x86 RELEASE=$1 TARGET_TRANSPORT=BLE $2 + + echo "*********** Build for android x86_64 *************" + scons TARGET_OS=android TARGET_ARCH=x86_64 RELEASE=$1 TARGET_TRANSPORT=IP $2 + scons TARGET_OS=android TARGET_ARCH=x86_64 RELEASE=$1 TARGET_TRANSPORT=BT $2 + scons TARGET_OS=android TARGET_ARCH=x86_64 RELEASE=$1 TARGET_TRANSPORT=BLE $2 echo "*********** Build for android armeabi *************" scons TARGET_OS=android TARGET_ARCH=armeabi RELEASE=$1 TARGET_TRANSPORT=IP $2 + scons TARGET_OS=android TARGET_ARCH=armeabi RELEASE=$1 TARGET_TRANSPORT=BT $2 + scons TARGET_OS=android TARGET_ARCH=armeabi RELEASE=$1 TARGET_TRANSPORT=BLE $2 # enable parallel build export SCONSFLAGS="-Q -j 4" @@ -82,10 +91,12 @@ function build_arduino() echo "*********** Build for arduino avr *************" scons resource TARGET_OS=arduino UPLOAD=false BOARD=mega TARGET_ARCH=avr TARGET_TRANSPORT=IP SHIELD=ETH RELEASE=$1 $2 scons resource TARGET_OS=arduino UPLOAD=false BOARD=mega TARGET_ARCH=avr TARGET_TRANSPORT=IP SHIELD=WIFI RELEASE=$1 $2 + scons resource TARGET_OS=arduino UPLOAD=false BOARD=mega TARGET_ARCH=avr TARGET_TRANSPORT=BLE SHIELD=RBL_NRF8001 RELEASE=$1 $2 echo "*********** Build for arduino arm *************" scons resource TARGET_OS=arduino UPLOAD=false BOARD=arduino_due_x TARGET_ARCH=arm TARGET_TRANSPORT=IP SHIELD=ETH RELEASE=$1 $2 scons resource TARGET_OS=arduino UPLOAD=false BOARD=arduino_due_x TARGET_ARCH=arm TARGET_TRANSPORT=IP SHIELD=WIFI RELEASE=$1 $2 + # BLE support for the Arduino Due is currently unavailable. } function build_tizen() @@ -210,5 +221,3 @@ else fi echo "===================== done =====================" - - diff --git a/build_common/android/compatibility/c_compat.c b/build_common/android/compatibility/c_compat.c index 000428a..b76c739 100644 --- a/build_common/android/compatibility/c_compat.c +++ b/build_common/android/compatibility/c_compat.c @@ -45,16 +45,3 @@ void srandom(unsigned int __s) { srand48(__s); } - -/* from unistd.h */ -int getpagesize(void) -{ - extern unsigned int __page_size; - return __page_size; -} - -int __getpageshift(void) -{ - extern unsigned int __page_shift; - return __page_shift; -} diff --git a/resource/c_common/platform_features.h b/resource/c_common/platform_features.h index 2fdaded..8f39e19 100644 --- a/resource/c_common/platform_features.h +++ b/resource/c_common/platform_features.h @@ -34,4 +34,11 @@ #define SUPPORTS_DEFAULT_CTOR #endif +#if (__STDC_VERSION__ >= 201112L) + #include + #define OC_STATIC_ASSERT(condition, msg) static_assert(condition, msg) +#else + #define OC_STATIC_ASSERT(condition, msg) ((void)sizeof(char[2*!!(condition) - 1])) +#endif + #endif diff --git a/resource/csdk/connectivity/api/cacommon.h b/resource/csdk/connectivity/api/cacommon.h index b5beea1..cc261ce 100644 --- a/resource/csdk/connectivity/api/cacommon.h +++ b/resource/csdk/connectivity/api/cacommon.h @@ -236,13 +236,21 @@ typedef struct { CATransportAdapter_t adapter; // adapter type CATransportFlags_t flags; // transport modifiers + uint16_t port; // for IP char addr[MAX_ADDR_STR_SIZE_CA]; // address for all uint32_t interface; // usually zero for default interface - uint16_t port; // for IP - CARemoteId_t identity; // endpoint identity } CAEndpoint_t; /** + * Endpoint information for secure messages + */ +typedef struct +{ + CAEndpoint_t endpoint; /**< endpoint */ + CARemoteId_t identity; /**< endpoint identity */ +} CASecureEndpoint_t; + +/** * @enum CAResult_t * Enums for CA return values */ @@ -347,6 +355,7 @@ typedef struct CAPayload_t payload; /**< payload of the request */ size_t payloadSize; /**< size in bytes of the payload */ CAURI_t resourceUri; /**< Resource URI information **/ + CARemoteId_t identity; /**< endpoint identity */ } CAInfo_t; /** @@ -406,16 +415,38 @@ typedef struct */ typedef struct { - int fd; - uint16_t port; + int fd; /**< socket fd */ + uint16_t port; /**< socket port */ } CASocket_t; +#define HISTORYSIZE (4) + +typedef struct +{ + CATransportFlags_t flags; + uint16_t messageId; +} CAHistoryItem_t; + +typedef struct +{ + int nextIndex; + CAHistoryItem_t items[HISTORYSIZE]; +} CAHistory_t; + +/** + * Hold interface index for keeping track of comings and goings + */ +typedef struct +{ + int32_t ifIndex; /**< network interface index */ +} CAIfItem_t; + typedef struct { - CATransportFlags_t clientFlags; - CATransportFlags_t serverFlags; - bool client; - bool server; + CATransportFlags_t clientFlags; /**< flag for client */ + CATransportFlags_t serverFlags; /**< flag for server */ + bool client; /**< client mode */ + bool server; /**< server mode */ struct sockets { @@ -432,17 +463,26 @@ typedef struct int shutdownFds[2]; /**< shutdown pipe */ int selectTimeout; /**< in seconds */ int maxfd; /**< highest fd (for select) */ - int numInterfaces; /**< number of active interfaces */ bool started; /**< the IP adapter has started */ bool terminate; /**< the IP adapter needs to stop */ bool ipv6enabled; /**< IPv6 enabled by OCInit flags */ bool ipv4enabled; /**< IPv4 enabled by OCInit flags */ + bool dualstack; /**< IPv6 and IPv4 enabled */ + + struct networkmonitors + { + CAIfItem_t *ifItems; /**< current network interface index list */ + size_t sizeIfItems; /**< size of network interface index array */ + size_t numIfItems; /**< number of valid network interfaces */ + } nm; } ip; struct calayer { - CATransportFlags_t previousRequestFlags; /**< address family filtering */ - uint16_t previousRequestMessageId; /**< address family filtering */ + CAHistory_t requestHistory; /**< filter IP family in requests */ + CAHistory_t responseHistory; /**< filter IP family in responses */ + CATransportFlags_t previousRequestFlags;/**< address family filtering */ + uint16_t previousRequestMessageId; /**< address family filtering */ } ca; } CAGlobals_t; diff --git a/resource/csdk/connectivity/api/cainterface.h b/resource/csdk/connectivity/api/cainterface.h index 27b4ff2..7449b28 100644 --- a/resource/csdk/connectivity/api/cainterface.h +++ b/resource/csdk/connectivity/api/cainterface.h @@ -42,28 +42,25 @@ extern "C" #endif /** - * @brief Callback function type for request delivery. - * @param object [OUT] Endpoint object from which the request is received. It contains - * endpoint address based on the connectivity type. - * @param requestInfo [OUT] Info for resource model to understand about the request. - * @return NONE + * Callback function type for request delivery. + * @param[out] object Endpoint object from which the request is received. + * It contains endpoint address based on the connectivity type. + * @param[out] requestInfo Info for resource model to understand about the request. */ typedef void (*CARequestCallback)(const CAEndpoint_t *object, const CARequestInfo_t *requestInfo); /** - * @brief Callback function type for response delivery. - * @param object [OUT] Endpoint object from which the response is received. - * @param responseInfo [OUT] Identifier which needs to be mapped with response. - * @return NONE + * Callback function type for response delivery. + * @param[out] object Endpoint object from which the response is received. + * @param[out] responseInfo Identifier which needs to be mapped with response. */ typedef void (*CAResponseCallback)(const CAEndpoint_t *object, const CAResponseInfo_t *responseInfo); /** - * @brief Callback function type for error - * @param object [OUT] remote device information - * @param errorInfo [OUT] CA Error information - * @return NONE + * Callback function type for error. + * @param[out] object remote device information. + * @param[out] errorInfo CA Error information. */ typedef void (*CAErrorCallback)(const CAEndpoint_t *object, const CAErrorInfo_t *errorInfo); @@ -76,83 +73,80 @@ typedef void (*CAErrorCallback)(const CAEndpoint_t *object, */ typedef struct { - unsigned char identity[DTLS_PSK_ID_LEN]; /** identity of self */ - uint32_t num; /** number of credentials in this blob */ + unsigned char identity[DTLS_PSK_ID_LEN]; /** identity of self. */ + uint32_t num; /** number of credentials in this blob. */ OCDtlsPskCreds *creds; /** list of credentials. Size of this array is determined by 'num' variable. */ } CADtlsPskCredsBlob_t; /** - * @brief Callback function type for getting DTLS credentials. - * @param credInfo [OUT] DTLS credentials info. Handler has to allocate new memory for - * both credInfo and credInfo->creds which is then freed by CA - * @return NONE + * Callback function type for getting DTLS credentials. + * @param[out] credInfo DTLS credentials info. Handler has to allocate new memory for. + * both credInfo and credInfo->creds which is then freed by CA. */ typedef void (*CAGetDTLSCredentialsHandler)(CADtlsPskCredsBlob_t **credInfo); #endif //__WITH_DTLS__ /** - * @brief Initialize the connectivity abstraction module. - * It will initialize adapters, thread pool and other modules based on the platform - * compilation options. + * Initialize the connectivity abstraction module. + * It will initialize adapters, thread pool and other modules based on the platform + * compilation options. * - * @return #CA_STATUS_OK or #CA_STATUS_FAILED or #CA_MEMORY_ALLOC_FAILED + * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED or ::CA_MEMORY_ALLOC_FAILED */ CAResult_t CAInitialize(); /** - * @brief Terminate the connectivity abstraction module. - * All threads, data structures are destroyed for next initializations. - * @return NONE + * Terminate the connectivity abstraction module. + * All threads, data structures are destroyed for next initializations. */ void CATerminate(); /** - * @brief Starts listening servers. - * This API is used by resource hosting server for listening multicast requests. - * Based on the adapters configurations, different kinds of servers are started. - * @return #CA_STATUS_OK or #CA_STATUS_FAILED + * Starts listening servers. + * This API is used by resource hosting server for listening multicast requests. + * Based on the adapters configurations, different kinds of servers are started. + * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED */ CAResult_t CAStartListeningServer(); /** - * @brief Starts discovery servers. - * This API is used by resource required clients for listening multicast requests. - * Based on the adapters configurations, different kinds of servers are started. - * @return #CA_STATUS_OK or #CA_STATUS_FAILED + * Starts discovery servers. + * This API is used by resource required clients for listening multicast requests. + * Based on the adapters configurations, different kinds of servers are started. + * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED */ CAResult_t CAStartDiscoveryServer(); /** - * @brief Register request callbacks and response callbacks. - * Requests and responses are delivered these callbacks . - * @param ReqHandler [IN] Request callback ( for GET,PUT ..etc) - * @param RespHandler [IN] Response Handler Callback + * Register request callbacks and response callbacks. + * Requests and responses are delivered these callbacks. + * @param[in] ReqHandler Request callback ( for GET,PUT ..etc). + * @param[in] RespHandler Response Handler Callback. * @see CARequestCallback * @see CAResponseCallback * @see CAErrorCallback - * @return NONE */ void CARegisterHandler(CARequestCallback ReqHandler, CAResponseCallback RespHandler, CAErrorCallback ErrorHandler); #ifdef __WITH_DTLS__ /** - * @brief Register callback to get DTLS PSK credentials. - * @param GetDTLSCredentials [IN] GetDTLS Credetials callback - * @return #CA_STATUS_OK + * Register callback to get DTLS PSK credentials. + * @param[in] GetDTLSCredentials GetDTLS Credetials callback. + * @return ::CA_STATUS_OK */ CAResult_t CARegisterDTLSCredentialsHandler(CAGetDTLSCredentialsHandler GetDTLSCredentials); #endif //__WITH_DTLS__ /** - * @brief Create an endpoint description - * @param flags [IN] how the adapter should be used - * @param adapter [IN] which adapter to use - * @param addr [IN] string representation of address - * @param port [IN] port (for IP_ADAPTER) - * @param endpoint [OUT] Endpoint which contains the above - * @return #CA_STATUS_OK or #CA_STATUS_FAILED + * Create an endpoint description. + * @param[in] flags how the adapter should be used. + * @param[in] adapter which adapter to use. + * @param[in] addr string representation of address. + * @param[in] port port (for IP_ADAPTER). + * @param[in] endpoint Endpoint which contains the above. + * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED * @remark The created Remote endpoint can be freed using CADestroyEndpoint(). * @see CADestroyEndpoint */ @@ -163,94 +157,93 @@ CAResult_t CACreateEndpoint(CATransportFlags_t flags, CAEndpoint_t **object); /** - * @brief Destroy the remote endpoint created - * @param object [IN] Remote Endpoint object created with CACreateEndpoint - * @return NONE + * Destroy the remote endpoint created. + * @param[in] object Remote Endpoint object created with CACreateEndpoint. */ void CADestroyEndpoint(CAEndpoint_t *object); /** - * @brief Generating the token for matching the request and response. - * @param token [OUT] Token for the request - * @param tokenLength [IN] length of the token - * @return #CA_STATUS_OK or #CA_STATUS_FAILED or #CA_MEMORY_ALLOC_FAILED - * or #CA_STATUS_NOT_INITIALIZED + * Generating the token for matching the request and response. + * @param[in] token Token for the request. + * @param[in] tokenLength length of the token. + * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED or + * ::CA_MEMORY_ALLOC_FAILED or ::CA_STATUS_NOT_INITIALIZED * @remark Token memory is destroyed by the caller using CADestroyToken(). * @see CADestroyToken */ CAResult_t CAGenerateToken(CAToken_t *token, uint8_t tokenLength); /** - * @brief Destroy the token generated by CAGenerateToken - * @param token [IN] token to be freed - * @return NONE + * Destroy the token generated by CAGenerateToken. + * @param[in] token token to be freed. */ void CADestroyToken(CAToken_t token); /** - * @brief Send control Request on a resource - * @param object [IN] Endpoint where the payload need to be sent. + * Send control Request on a resource. + * @param[in] object Endpoint where the payload need to be sent. * This endpoint is delivered with Request or response callback. - * @param requestInfo [IN] Information for the request. - * @return #CA_STATUS_OK #CA_STATUS_FAILED #CA_MEMORY_ALLOC_FAILED + * @param[in] requestInfo Information for the request. + * @return ::CA_STATUS_OK ::CA_STATUS_FAILED ::CA_MEMORY_ALLOC_FAILED */ CAResult_t CASendRequest(const CAEndpoint_t *object, const CARequestInfo_t *requestInfo); /** - * @brief Send the response - * @param object [IN] Endpoint where the payload need to be sent. - * This endpoint is delivered with Request or response callback - * @param responseInfo [IN] Information for the response - * @return #CA_STATUS_OK or #CA_STATUS_FAILED or #CA_MEMORY_ALLOC_FAILED + * Send the response. + * @param[in] object Endpoint where the payload need to be sent. + * This endpoint is delivered with Request or response callback. + * @param[in] responseInfo Information for the response. + * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED or ::CA_MEMORY_ALLOC_FAILED */ CAResult_t CASendResponse(const CAEndpoint_t *object, const CAResponseInfo_t *responseInfo); /** - * @brief Send notification to the remote object - * @param object [IN] Endpoint where the payload need to be sent. + * Send notification to the remote object. + * @param[in] object Endpoint where the payload need to be sent. * This endpoint is delivered with Request or response callback. - * @param responseInfo [IN] Information for the response. - * @return #CA_STATUS_OK or #CA_STATUS_FAILED or #CA_MEMORY_ALLOC_FAILED + * @param[in] responseInfo Information for the response. + * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED or ::CA_MEMORY_ALLOC_FAILED */ CAResult_t CASendNotification(const CAEndpoint_t *object, const CAResponseInfo_t *responseInfo); /** - * @brief Select network to use - * @param interestedNetwork [IN] Connectivity Type enum - * @return #CA_STATUS_OK or #CA_NOT_SUPPORTED or #CA_STATUS_FAILED or #CA_NOT_SUPPORTED + * Select network to use. + * @param[in] interestedNetwork Connectivity Type enum. + * @return ::CA_STATUS_OK or ::CA_NOT_SUPPORTED or + * ::CA_STATUS_FAILED or ::CA_NOT_SUPPORTED */ CAResult_t CASelectNetwork(CATransportAdapter_t interestedNetwork); /** - * @brief Select network to unuse - * @param nonInterestedNetwork [IN] Connectivity Type enum - * @return #CA_STATUS_OK or #CA_NOT_SUPPORTED or #CA_STATUS_FAILED + * Select network to unuse. + * @param[in] nonInterestedNetwork Connectivity Type enum. + * @return ::CA_STATUS_OK or ::CA_NOT_SUPPORTED or ::CA_STATUS_FAILED */ CAResult_t CAUnSelectNetwork(CATransportAdapter_t nonInterestedNetwork); /** - * @brief Get network information - * It should be destroyed by the caller as it Get Information. - * @param info [OUT] LocalConnectivity objects - * @param size [OUT] No Of Array objects - * @return #CA_STATUS_OK or #CA_STATUS_FAILED or #CA_STATUS_INVALID_PARAM or -* #CA_MEMORY_ALLOC_FAILED + * Get network information. + * It should be destroyed by the caller as it Get Information. + * @param[out] info LocalConnectivity objects + * @param[out] size No Of Array objects + * @return ::CA_STATUS_OK or ::CA_STATUS_FAILED or + * ::CA_STATUS_INVALID_PARAM or ::CA_MEMORY_ALLOC_FAILED */ CAResult_t CAGetNetworkInformation(CAEndpoint_t **info, uint32_t *size); /** - * @brief To Handle the Request or Response - * @return #CA_STATUS_OK + * To Handle the Request or Response. + * @return ::CA_STATUS_OK */ CAResult_t CAHandleRequestResponse(); #ifdef RA_ADAPTER /** - * @brief Set Remote Access information for XMPP Client. - * @param caraInfo [IN] remote access info. + * Set Remote Access information for XMPP Client. + * @param[in] caraInfo remote access info. * - * @return #CA_STATUS_OK + * @return ::CA_STATUS_OK */ CAResult_t CASetRAInfo(const CARAInfo_t *caraInfo); #endif @@ -259,26 +252,26 @@ CAResult_t CASetRAInfo(const CARAInfo_t *caraInfo); #ifdef __WITH_DTLS__ /** - * Select the cipher suite for dtls handshake + * Select the cipher suite for dtls handshake. * - * @param[IN] cipher cipher suite (Note : Make sure endianness) - * 0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA - * 0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8 - * 0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 + * @param[in] cipher cipher suite (Note : Make sure endianness). + * 0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA + * 0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8 + * 0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 * - * @retval CA_STATUS_OK Successful - * @retval CA_STATUS_INVALID_PARAM Invalid input argumets - * @retval CA_STATUS_FAILED Operation failed + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. */ CAResult_t CASelectCipherSuite(const uint16_t cipher); /** - * Enable TLS_ECDH_anon_WITH_AES_128_CBC_SHA cipher suite in dtls + * Enable TLS_ECDH_anon_WITH_AES_128_CBC_SHA cipher suite in dtls. * - * @param[IN] enable TRUE/FALSE enables/disables anonymous cipher suite + * @param[in] enable TRUE/FALSE enables/disables anonymous cipher suite. * - * @retval CA_STATUS_OK Successful - * @retval CA_STATUS_FAILED Operation failed + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_FAILED Operation failed. * * @note anonymous cipher suite should only be enabled for 'JustWorks' provisioning. */ @@ -286,23 +279,23 @@ CAResult_t CAEnableAnonECDHCipherSuite(const bool enable); /** - * Generate ownerPSK using PRF + * Generate ownerPSK using PRF. * OwnerPSK = TLS-PRF('master key' , 'oic.sec.doxm.jw', - * 'ID of new device(Resource Server)', - * 'ID of owner smart-phone(Provisioning Server)') + * 'ID of new device(Resource Server)', + * 'ID of owner smart-phone(Provisioning Server)') * - * @param[IN] endpoint information of network address - * @param[IN] label Ownership transfer method e.g)"oic.sec.doxm.jw" - * @param[IN] labelLen Byte length of label - * @param[IN] rsrcServerDeviceID ID of new device(Resource Server) - * @param[IN] rsrcServerDeviceIDLen Byte length of rsrcServerDeviceID - * @param[IN] provServerDeviceID label of previous owner - * @param[IN] provServerDeviceIDLen byte length of provServerDeviceID - * @param[IN,OUT] ownerPSK Output buffer for owner PSK - * @param[IN] ownerPSKSize Byte length of the ownerPSK to be generated + * @param[in] endpoint information of network address. + * @param[in] label Ownership transfer method e.g)"oic.sec.doxm.jw". + * @param[in] labelLen Byte length of label. + * @param[in] rsrcServerDeviceID ID of new device(Resource Server). + * @param[in] rsrcServerDeviceIDLen Byte length of rsrcServerDeviceID. + * @param[in] provServerDeviceID label of previous owner. + * @param[in] provServerDeviceIDLen byte length of provServerDeviceID. + * @param[in,out] ownerPSK Output buffer for owner PSK. + * @param[in] ownerPSKSize Byte length of the ownerPSK to be generated. * - * @retval CA_STATUS_OK Successful - * @retval CA_STATUS_FAILED Operation failed + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_FAILED Operation failed. */ CAResult_t CAGenerateOwnerPSK(const CAEndpoint_t *endpoint, const uint8_t* label, const size_t labelLen, @@ -313,22 +306,22 @@ CAResult_t CAGenerateOwnerPSK(const CAEndpoint_t *endpoint, uint8_t* ownerPSK, const size_t ownerPSKSize); /** - * Initiate DTLS handshake with selected cipher suite + * Initiate DTLS handshake with selected cipher suite. * - * @param[IN] endpoint information of network address + * @param[in] endpoint information of network address. * - * @retval CA_STATUS_OK Successful - * @retval CA_STATUS_FAILED Operation failed + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_FAILED Operation failed. */ CAResult_t CAInitiateHandshake(const CAEndpoint_t *endpoint); /** - * Close the DTLS session + * Close the DTLS session. * - * @param[IN] endpoint information of network address + * @param[in] endpoint information of network address. * - * @retval CA_STATUS_OK Successful - * @retval CA_STATUS_FAILED Operation failed + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_FAILED Operation failed. */ CAResult_t CACloseDtlsSession(const CAEndpoint_t *endpoint); diff --git a/resource/csdk/connectivity/common/inc/uarraylist.h b/resource/csdk/connectivity/common/inc/uarraylist.h index a055a1b..7e8403a 100644 --- a/resource/csdk/connectivity/common/inc/uarraylist.h +++ b/resource/csdk/connectivity/common/inc/uarraylist.h @@ -22,7 +22,7 @@ #define U_ARRAYLIST_H_ #include -#include "cacommon.h" +#include #ifdef __cplusplus extern "C" @@ -31,6 +31,10 @@ extern "C" /** * array list structure. + * + * @note + * Members should be treated as private and not accessed directly. Instead + * all access should be through the defined u_arraylist_*() functions. */ typedef struct u_arraylist_t { @@ -50,10 +54,8 @@ u_arraylist_t *u_arraylist_create(); * Arraylist elements are deleted. Calling function must take care of free * dynamic memory allocated before freeing the arraylist. * @param[in] list u_arraylist pointer - * @return ::CAResult_t. - * ::CA_STATUS_OK if Success, ::CA_STATUS_INVALID_PARAM if pointer to list is NULL. */ -CAResult_t u_arraylist_free(u_arraylist_t **list); +void u_arraylist_free(u_arraylist_t **list); /** * Returns the data of the index from the array list. @@ -67,10 +69,9 @@ void *u_arraylist_get(const u_arraylist_t *list, uint32_t index); * Add data in the array list. * @param[in] list pointer of array list. * @param[in] data pointer of data. - * @return CAResult_t. - * ::CA_STATUS_OK if Success, ::CA_MEMORY_ALLOC_FAILED if memory allocation fails. + * @return true if success, false otherwise. */ -CAResult_t u_arraylist_add(u_arraylist_t *list, void *data); +bool u_arraylist_add(u_arraylist_t *list, void *data); /** * Remove the data of the index from the array list. diff --git a/resource/csdk/connectivity/common/src/caremotehandler.c b/resource/csdk/connectivity/common/src/caremotehandler.c index 48e5f56..cca8bd8 100644 --- a/resource/csdk/connectivity/common/src/caremotehandler.c +++ b/resource/csdk/connectivity/common/src/caremotehandler.c @@ -63,94 +63,16 @@ CARequestInfo_t *CACloneRequestInfo(const CARequestInfo_t *rep) return NULL; } - *clone = *rep; - - if (rep->info.token) - { - char *temp = NULL; - - // allocate token field - uint8_t len = rep->info.tokenLength; - - if (len) - { - temp = (char *) OICCalloc(len, sizeof(char)); - if (!temp) - { - OIC_LOG(ERROR, TAG, "CACloneRequestInfo Out of memory"); - - CADestroyRequestInfoInternal(clone); - - return NULL; - } - memcpy(temp, rep->info.token, len); - } - - // save the token - clone->info.token = temp; - clone->info.tokenLength = len; - } - - if (NULL != rep->info.options && 0 < rep->info.numOptions) - { - // save the options - clone->info.options = - (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) * rep->info.numOptions); - if (NULL == clone->info.options) - { - OIC_LOG(ERROR, TAG, "CACloneRequestInfo Out of memory"); - OICFree(clone->info.token); - OICFree(clone); - return NULL; - } - memcpy(clone->info.options, rep->info.options, - sizeof(CAHeaderOption_t) * rep->info.numOptions); - } - else - { - clone->info.options = NULL; - clone->info.numOptions = 0; - } - - if (NULL != rep->info.payload && 0 < rep->info.payloadSize) + CAResult_t result = CACloneInfo(&rep->info, &clone->info); + if(CA_STATUS_OK != result) { - // allocate payload field - uint8_t *temp = OICMalloc(rep->info.payloadSize); - if (NULL == temp) - { - OIC_LOG(ERROR, TAG, "CACloneRequestInfo Out of memory"); - - CADestroyRequestInfoInternal(clone); - - return NULL; - } - memcpy(temp, rep->info.payload, rep->info.payloadSize); - - // save the payload - clone->info.payload = temp; - } - else - { - clone->info.payload = NULL; - clone->info.payloadSize = 0; + OIC_LOG(ERROR, TAG, "CACloneRequestInfo error in CACloneInfo"); + CADestroyRequestInfoInternal(clone); + return NULL; } - if (NULL != rep->info.resourceUri) - { - // allocate payload field - char *temp = OICStrdup(rep->info.resourceUri); - if (NULL == temp) - { - OIC_LOG(ERROR, TAG, "CACloneRequestInfo Out of memory"); - - CADestroyRequestInfoInternal(clone); - - return NULL; - } - - // save the resourceUri - clone->info.resourceUri = temp; - } + clone->method = rep->method; + clone->isMulticast = rep->isMulticast; return clone; } @@ -198,96 +120,16 @@ CAResponseInfo_t *CACloneResponseInfo(const CAResponseInfo_t *rep) OIC_LOG(ERROR, TAG, "CACloneResponseInfo Out of memory"); return NULL; } - *clone = *rep; - if (rep->info.token) + CAResult_t result = CACloneInfo(&rep->info, &clone->info); + if(CA_STATUS_OK != result) { - char *temp = NULL; - - // allocate token field - uint8_t len = rep->info.tokenLength; - - if (len) - { - temp = (char *) OICCalloc(len, sizeof(char)); - if (!temp) - { - OIC_LOG(ERROR, TAG, "CACloneResponseInfo Out of memory"); - - CADestroyResponseInfoInternal(clone); - - return NULL; - } - memcpy(temp, rep->info.token, len); - } - // save the token - clone->info.token = temp; - clone->info.tokenLength = len; - } - - if (NULL != rep->info.options && rep->info.numOptions) - { - // save the options - clone->info.options = - (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) * rep->info.numOptions); - - if (NULL == clone->info.options) - { - OIC_LOG(ERROR, TAG, "CACloneResponseInfo Out of memory"); - - OICFree(clone->info.token); - OICFree(clone); - return NULL; - } - memcpy(clone->info.options, rep->info.options, - sizeof(CAHeaderOption_t) * rep->info.numOptions); - } - else - { - clone->info.options = NULL; - clone->info.numOptions = 0; - } - - if (NULL != rep->info.payload && 0 < rep->info.payloadSize) - { - // allocate payload field - uint8_t *temp = (uint8_t *) OICMalloc(rep->info.payloadSize); - if (NULL == temp) - { - OIC_LOG(ERROR, TAG, "CACloneResponseInfo Out of memory"); - - CADestroyResponseInfoInternal(clone); - - return NULL; - } - memcpy(temp, rep->info.payload, rep->info.payloadSize); - - // save the payload - clone->info.payload = temp; - } - else - { - clone->info.payload = NULL; - clone->info.payloadSize = 0; - } - - if (NULL != rep->info.resourceUri) - { - // allocate payload field - char *temp = OICStrdup(rep->info.resourceUri); - if (NULL == temp) - { - OIC_LOG(ERROR, TAG, "CACloneResponseInfo Out of memory"); - - CADestroyResponseInfoInternal(clone); - - return NULL; - } - - // save the resourceUri - clone->info.resourceUri = temp; + OIC_LOG(ERROR, TAG, "CACloneResponseInfo error in CACloneInfo"); + CADestroyResponseInfoInternal(clone); + return NULL; } + clone->result = rep->result; return clone; } @@ -386,6 +228,8 @@ CAResult_t CACloneInfo(const CAInfo_t *info, CAInfo_t *clone) return CA_STATUS_INVALID_PARAM; } + memset(clone, 0 , sizeof(CAInfo_t)); + //Do not free clone. we cannot declare it const, as the content is modified if ((info->token) && (0 < info->tokenLength)) { @@ -397,7 +241,7 @@ CAResult_t CACloneInfo(const CAInfo_t *info, CAInfo_t *clone) temp = (char *) OICMalloc(len * sizeof(char)); if (!temp) { - OIC_LOG(ERROR, TAG, "CAClonePayloadInfo Out of memory"); + OIC_LOG(ERROR, TAG, "CACloneInfo Out of memory"); return CA_MEMORY_ALLOC_FAILED; } @@ -415,20 +259,21 @@ CAResult_t CACloneInfo(const CAInfo_t *info, CAInfo_t *clone) if (!clone->options) { - OIC_LOG(ERROR, TAG, "CAClonePayloadInfo Out of memory"); + OIC_LOG(ERROR, TAG, "CACloneInfo Out of memory"); CADestroyInfoInternal(clone); return CA_MEMORY_ALLOC_FAILED; } memcpy(clone->options, info->options, sizeof(CAHeaderOption_t) * info->numOptions); + clone->numOptions = info->numOptions; } - if (info->payload && 0 < info->payloadSize) + if ((info->payload) && (0 < info->payloadSize)) { // allocate payload field uint8_t *temp = OICMalloc(info->payloadSize); if (!temp) { - OIC_LOG(ERROR, TAG, "CAClonePayloadInfo Out of memory"); + OIC_LOG(ERROR, TAG, "CACloneInfo Out of memory"); CADestroyInfoInternal(clone); return CA_MEMORY_ALLOC_FAILED; } @@ -436,11 +281,7 @@ CAResult_t CACloneInfo(const CAInfo_t *info, CAInfo_t *clone) // save the payload clone->payload = temp; - } - else - { - clone->payload = NULL; - clone->payloadSize = 0; + clone->payloadSize = info->payloadSize; } if (info->resourceUri) @@ -449,7 +290,7 @@ CAResult_t CACloneInfo(const CAInfo_t *info, CAInfo_t *clone) char *temp = OICStrdup(info->resourceUri); if (!temp) { - OIC_LOG(ERROR, TAG, "CAClonePayloadInfo Out of memory"); + OIC_LOG(ERROR, TAG, "CACloneInfo Out of memory"); CADestroyInfoInternal(clone); return CA_MEMORY_ALLOC_FAILED; } @@ -458,6 +299,9 @@ CAResult_t CACloneInfo(const CAInfo_t *info, CAInfo_t *clone) clone->resourceUri = temp; } + clone->messageId = info->messageId; + clone->type = info->type; + return CA_STATUS_OK; } diff --git a/resource/csdk/connectivity/common/src/cathreadpool_pthreads.c b/resource/csdk/connectivity/common/src/cathreadpool_pthreads.c index 744b1a5..751bafc 100644 --- a/resource/csdk/connectivity/common/src/cathreadpool_pthreads.c +++ b/resource/csdk/connectivity/common/src/cathreadpool_pthreads.c @@ -165,13 +165,13 @@ CAResult_t ca_thread_pool_add_task(ca_thread_pool_t thread_pool, ca_thread_func } ca_mutex_lock(thread_pool->details->list_lock); - CAResult_t addResult = u_arraylist_add(thread_pool->details->threads_list, (void*)threadHandle); + bool addResult = u_arraylist_add(thread_pool->details->threads_list, (void*)threadHandle); ca_mutex_unlock(thread_pool->details->list_lock); - if(addResult != CA_STATUS_OK) + if(!addResult) { OIC_LOG_V(ERROR, TAG, "Arraylist Add failed, may not be properly joined: %d", addResult); - return addResult; + return CA_STATUS_FAILED; } OIC_LOG(DEBUG, TAG, "OUT"); @@ -200,11 +200,7 @@ void ca_thread_pool_free(ca_thread_pool_t thread_pool) } } - CAResult_t freeres = u_arraylist_free(&(thread_pool->details->threads_list)); - if(CA_STATUS_OK != freeres) - { - OIC_LOG_V(ERROR, TAG, "Failed to free array list, error was: %d", freeres); - } + u_arraylist_free(&(thread_pool->details->threads_list)); ca_mutex_unlock(thread_pool->details->list_lock); ca_mutex_free(thread_pool->details->list_lock); diff --git a/resource/csdk/connectivity/common/src/uarraylist.c b/resource/csdk/connectivity/common/src/uarraylist.c index be897be..8cc88f4 100644 --- a/resource/csdk/connectivity/common/src/uarraylist.c +++ b/resource/csdk/connectivity/common/src/uarraylist.c @@ -54,19 +54,17 @@ u_arraylist_t *u_arraylist_create() return list; } -CAResult_t u_arraylist_free(u_arraylist_t **list) +void u_arraylist_free(u_arraylist_t **list) { if (!list || !(*list)) { - return CA_STATUS_INVALID_PARAM; + return; } OICFree((*list)->data); OICFree(*list); *list = NULL; - - return CA_STATUS_OK; } void *u_arraylist_get(const u_arraylist_t *list, uint32_t index) @@ -84,20 +82,20 @@ void *u_arraylist_get(const u_arraylist_t *list, uint32_t index) return NULL; } -CAResult_t u_arraylist_add(u_arraylist_t *list, void *data) +bool u_arraylist_add(u_arraylist_t *list, void *data) { if (!list) { - return CA_STATUS_INVALID_PARAM; + return false; } if (list->size <= list->length) { - - uint32_t new_size = list->size + 1; + uint32_t new_size = list->size + 1; if (!(list->data = (void **) realloc(list->data, new_size * sizeof(void *)))) { - return CA_MEMORY_ALLOC_FAILED; + OIC_LOG(ERROR, TAG, "Failed to re-allocation memory"); + return false; } memset(list->data + list->size, 0, (new_size - list->size) * sizeof(void *)); @@ -107,7 +105,7 @@ CAResult_t u_arraylist_add(u_arraylist_t *list, void *data) list->data[list->length] = data; list->length++; - return CA_STATUS_OK; + return true; } void *u_arraylist_remove(u_arraylist_t *list, uint32_t index) diff --git a/resource/csdk/connectivity/inc/caadapterinterface.h b/resource/csdk/connectivity/inc/caadapterinterface.h index f220870..a750291 100644 --- a/resource/csdk/connectivity/inc/caadapterinterface.h +++ b/resource/csdk/connectivity/inc/caadapterinterface.h @@ -168,7 +168,7 @@ typedef void (*CARegisterConnectivityCallback)(CAConnectivityHandler_t handler, * This will be used during the receive of network requests and response. * @see SendUnicastData(), SendMulticastData() */ -typedef void (*CANetworkPacketReceivedCallback)(const CAEndpoint_t *endPoint, +typedef void (*CANetworkPacketReceivedCallback)(const CASecureEndpoint_t *sep, const void *data, uint32_t dataLen); /** diff --git a/resource/csdk/connectivity/inc/caadapternetdtls.h b/resource/csdk/connectivity/inc/caadapternetdtls.h index dc19b9f..e6940d8 100644 --- a/resource/csdk/connectivity/inc/caadapternetdtls.h +++ b/resource/csdk/connectivity/inc/caadapternetdtls.h @@ -38,7 +38,7 @@ */ extern void OCGetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo); -typedef void (*CAPacketReceivedCallback)(const CAEndpoint_t *endpoint, +typedef void (*CAPacketReceivedCallback)(const CASecureEndpoint_t *sep, const void *data, uint32_t dataLength); typedef void (*CAPacketSendCallback)(CAEndpoint_t *endpoint, @@ -249,7 +249,7 @@ CAResult_t CAAdapterNetDtlsEncrypt(const CAEndpoint_t *endpoint, * @retval ::CA_STATUS_FAILED Operation failed. * */ -CAResult_t CAAdapterNetDtlsDecrypt(const CAEndpoint_t *endpoint, +CAResult_t CAAdapterNetDtlsDecrypt(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t dataLen); diff --git a/resource/csdk/connectivity/inc/caipinterface.h b/resource/csdk/connectivity/inc/caipinterface.h index 6a71f28..677b1f9 100644 --- a/resource/csdk/connectivity/inc/caipinterface.h +++ b/resource/csdk/connectivity/inc/caipinterface.h @@ -50,12 +50,12 @@ typedef enum /** * Callback to be notified on reception of any data from remote OIC devices. * - * @param[in] endpoint network endpoint description. + * @param[in] sep network endpoint description. * @param[in] data Data received from remote OIC device. * @param[in] dataLength Length of data in bytes. * @pre Callback must be registered using CAIPSetPacketReceiveCallback(). */ -typedef void (*CAIPPacketReceivedCallback)(const CAEndpoint_t *endpoint, +typedef void (*CAIPPacketReceivedCallback)(const CASecureEndpoint_t *sep, const void *data, uint32_t dataLength); @@ -173,7 +173,41 @@ typedef struct u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex); /** - * Set callback for error handling. + * @brief Find a new network interface. + * + * @return Description of interface (or NULL if no change) + */ +CAInterface_t *CAFindInterfaceChange(); + +/** + * @brief Let the network monitor update the polling interval. + * @param [in] current polling interval + * + * @return desired polling interval + */ +int CAGetPollingInterval(int interval); + +/** + * @brief Tell the IP server an interface has been added. + */ +void CAWakeUpForChange(); + +/** + * @brief Initializes network monitor. + * + * @return ::CA_STATUS_OK or Appropriate error code. + */ +CAResult_t CAIPInitializeNetworkMonitor(); + +/** + * @brief Terminates network monitor. + * + * @return ::CA_STATUS_OK or Appropriate error code. + */ +CAResult_t CAIPTerminateNetworkMonitor(); + +/** + * @brief Set callback for error handling. * * @param[in] ipErrorCallback callback to notify error to the ipadapter. */ diff --git a/resource/csdk/connectivity/inc/camessagehandler.h b/resource/csdk/connectivity/inc/camessagehandler.h index 4ec1cad..45f9f64 100644 --- a/resource/csdk/connectivity/inc/camessagehandler.h +++ b/resource/csdk/connectivity/inc/camessagehandler.h @@ -52,9 +52,7 @@ typedef struct CARequestInfo_t *requestInfo; CAResponseInfo_t *responseInfo; CAErrorInfo_t *errorInfo; - CAHeaderOption_t *options; CADataType_t dataType; - uint8_t numOptions; } CAData_t; #ifdef __cplusplus diff --git a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/ResourceModel.c b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/ResourceModel.c index 705427b..ce5f039 100644 --- a/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/ResourceModel.c +++ b/resource/csdk/connectivity/samples/android/casample/sampleService/src/main/jni/ResourceModel.c @@ -1372,6 +1372,13 @@ void callback(char *subject, char *receivedData) { bool isAttached = false; JNIEnv* env; + + if (!g_responseListenerObject) + { + LOGE("g_responseListenerObject is NULL, cannot have callback"); + return; + } + jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { @@ -1387,6 +1394,12 @@ void callback(char *subject, char *receivedData) } jclass cls = (*env)->GetObjectClass(env, g_responseListenerObject); + if (!cls) + { + LOGE("could not get class"); + goto detach_thread; + } + jmethodID mid = (*env)->GetMethodID(env, cls, "OnResponseReceived", "(Ljava/lang/String;Ljava/lang/String;)V"); if (!mid) @@ -1461,7 +1474,7 @@ void parsing_coap_uri(const char* uri, addressSet_t* address, CATransportFlags_t } // #2. copy uri for parse - int32_t len = strlen(uri) - startIndex; + size_t len = strlen(uri) - startIndex; if (len <= 0) { @@ -1476,19 +1489,26 @@ void parsing_coap_uri(const char* uri, addressSet_t* address, CATransportFlags_t return; } - memcpy(cloneUri, &uri[startIndex], sizeof(char) * len); - cloneUri[len] = '\0'; + OICStrcpy(cloneUri, len+1, &uri[startIndex]); - char *pAddress = cloneUri; - LOGI("pAddress : %s", pAddress); + char *pstr = NULL; + //filter out the resource uri + char *pUrl = strtok_r(cloneUri, "/", &pstr); - int res = get_address_set(pAddress, address); - if (res == -1) + if (pUrl) { - LOGE("address parse error"); + LOGI("pAddress : %s", pUrl); + int res = get_address_set(pUrl, address); + if (res == -1) + { + LOGE("address parse error"); - free(cloneUri); - return; + return; + } + } + else + { + LOGE("strtok_r error, could not get the address"); } return; diff --git a/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c b/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c index 97a72bf..af9ed9a 100644 --- a/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c +++ b/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c @@ -50,7 +50,7 @@ static ca_mutex g_dtlsContextMutex = NULL; */ static CAGetDTLSCredentialsHandler g_getCredentialsCallback = NULL; -static CAEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer) +static CASecureEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer) { uint32_t list_index = 0; uint32_t list_length = 0; @@ -61,18 +61,18 @@ static CAEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer) return NULL; } - CAEndpoint_t *peerInfo; + CASecureEndpoint_t *peerInfo = NULL; list_length = u_arraylist_length(g_caDtlsContext->peerInfoList); for (list_index = 0; list_index < list_length; list_index++) { - peerInfo = (CAEndpoint_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index); + peerInfo = (CASecureEndpoint_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index); if (NULL == peerInfo) { continue; } - if((0 == strncmp(peer->addr, peerInfo->addr, MAX_ADDR_STR_SIZE_CA)) && - (peer->port == peerInfo->port)) + if((0 == strncmp(peer->addr, peerInfo->endpoint.addr, MAX_ADDR_STR_SIZE_CA)) && + (peer->port == peerInfo->endpoint.port)) { return peerInfo; } @@ -80,8 +80,8 @@ static CAEndpoint_t *GetPeerInfo(const CAEndpoint_t *peer) return NULL; } -static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint16_t port, - const unsigned char *id, uint16_t id_length, CATransportFlags_t flag) +static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port, + const unsigned char *id, uint16_t id_length) { if(NULL == peerAddr || NULL == id @@ -93,31 +93,28 @@ static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint16_t port, return CA_STATUS_INVALID_PARAM; } - CAEndpoint_t *peer = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t)); + CASecureEndpoint_t *peer = (CASecureEndpoint_t *)OICCalloc(1, sizeof (CASecureEndpoint_t)); if (NULL == peer) { OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfo malloc failed!"); return CA_MEMORY_ALLOC_FAILED; } - OICStrcpy(peer->addr, sizeof(peer->addr), peerAddr); - peer->port = port; - peer->flags = flag; - peer->flags |= CA_SECURE; - peer->adapter = CA_ADAPTER_IP; + OICStrcpy(peer->endpoint.addr, sizeof(peer->endpoint.addr), peerAddr); + peer->endpoint.port = port; memcpy(peer->identity.id, id, id_length); peer->identity.id_length = id_length; - if(NULL != GetPeerInfo(peer)) + if (NULL != GetPeerInfo(&peer->endpoint)) { OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList peer already exist"); OICFree(peer); return CA_STATUS_FAILED; } - CAResult_t result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peer); - if (CA_STATUS_OK != result) + bool result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peer); + if (!result) { OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!"); OICFree(peer); @@ -301,8 +298,8 @@ static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg) return CA_STATUS_FAILED; } - CAResult_t result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg); - if (CA_STATUS_OK != result) + bool result = u_arraylist_add(g_caDtlsContext->cacheList, (void *)msg); + if (!result) { OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!"); } @@ -385,12 +382,13 @@ static int32_t CAReadDecryptedPayload(dtls_context_t *context, stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session; - CAEndpoint_t endpoint = { 0 }; - CAConvertAddrToName(&(addrInfo->addr.st), endpoint.addr, &endpoint.port); - endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6; - endpoint.flags |= CA_SECURE; - endpoint.adapter = CA_ADAPTER_IP; - int type = 0; + CASecureEndpoint_t sep = + { .endpoint = + { .adapter = CA_ADAPTER_IP, .flags = + ((addrInfo->addr.st.ss_family == AF_INET) ? CA_IPV4 : CA_IPV6) | CA_SECURE, .port = 0 }, + .identity = + { 0 } }; + CAConvertAddrToName(&(addrInfo->addr.st), sep.endpoint.addr, &sep.endpoint.port); if (NULL == g_caDtlsContext) { @@ -398,17 +396,18 @@ static int32_t CAReadDecryptedPayload(dtls_context_t *context, return 0; } + int type = 0; if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) && (NULL != g_caDtlsContext->adapterCallbacks[type].recvCallback)) { // Get identity of the source of packet - CAEndpoint_t *peerInfo = GetPeerInfo(&endpoint); + CASecureEndpoint_t *peerInfo = GetPeerInfo(&sep.endpoint); if (peerInfo) { - endpoint.identity = peerInfo->identity; + sep.identity = peerInfo->identity; } - g_caDtlsContext->adapterCallbacks[type].recvCallback(&endpoint, buf, bufLen); + g_caDtlsContext->adapterCallbacks[type].recvCallback(&sep, buf, bufLen); } else { @@ -483,7 +482,7 @@ static int32_t CAHandleSecureEvent(dtls_context_t *context, OIC_LOG(INFO, NET_DTLS_TAG, "Peer closing connection"); stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session; - char peerAddr[MAX_ADDR_STR_SIZE_CA] = {0}; + char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 }; uint16_t port = 0; CAConvertAddrToName(&(addrInfo->addr.st), peerAddr, &port); CARemovePeerFromPeerInfoList(peerAddr, port); @@ -550,15 +549,11 @@ static int32_t CAGetPskCredentials(dtls_context_t *ctx, // data structure when handshake completes. Therefore, currently this is a // workaround to cache remote end-point identity when tinyDTLS asks for PSK. stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session; - char peerAddress[MAX_ADDR_STR_SIZE_CA] = {0}; + char peerAddr[MAX_ADDR_STR_SIZE_CA] = { 0 }; uint16_t port = 0; - CAConvertAddrToName(&(addrInfo->addr.st), peerAddress, &port); + CAConvertAddrToName(&(addrInfo->addr.st), peerAddr, &port); - CATransportFlags_t flag = - addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6; - - CAResult_t result = CAAddIdToPeerInfoList(peerAddress, - port, desc, descLen, flag); + CAResult_t result = CAAddIdToPeerInfoList(peerAddr, port, desc, descLen); if(CA_STATUS_OK != result ) { OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList"); @@ -954,15 +949,15 @@ CAResult_t CAAdapterNetDtlsEncrypt(const CAEndpoint_t *endpoint, return CA_STATUS_OK; } -CAResult_t CAAdapterNetDtlsDecrypt(const CAEndpoint_t *endpoint, +CAResult_t CAAdapterNetDtlsDecrypt(const CASecureEndpoint_t *sep, uint8_t *data, uint32_t dataLen) { OIC_LOG(DEBUG, NET_DTLS_TAG, "IN"); - VERIFY_NON_NULL_RET(endpoint, NET_DTLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM); + VERIFY_NON_NULL_RET(sep, NET_DTLS_TAG, "endpoint is NULL" , CA_STATUS_INVALID_PARAM); stCADtlsAddrInfo_t addrInfo = { 0 }; - CAConvertNameToAddr(endpoint->addr, endpoint->port, &(addrInfo.addr.st)); + CAConvertNameToAddr(sep->endpoint.addr, sep->endpoint.port, &(addrInfo.addr.st)); addrInfo.ifIndex = 0; addrInfo.size = CASizeOfAddrInfo(&addrInfo); diff --git a/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrutils.c b/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrutils.c index cbd1fb8..5a8a231 100644 --- a/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrutils.c +++ b/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrutils.c @@ -525,7 +525,7 @@ void CAEDRNativeRemoveDevice(const char *remoteAddress) OIC_LOG_V(DEBUG, TAG, "[EDR][Native] remove state : %s", remoteAddress); OICFree(state); - CAEDRReorderingDeviceList(index); + u_arraylist_remove(g_deviceStateList, index); break; } } @@ -569,23 +569,6 @@ CAConnectedState_t CAEDRIsConnectedDevice(const char *remoteAddress) return STATE_DISCONNECTED; } -void CAEDRReorderingDeviceList(uint32_t index) -{ - if (index >= g_deviceStateList->length) - { - return; - } - - if (index < g_deviceStateList->length - 1) - { - memmove(&g_deviceStateList->data[index], &g_deviceStateList->data[index + 1], - (g_deviceStateList->length - index - 1) * sizeof(void *)); - } - - g_deviceStateList->size--; - g_deviceStateList->length--; -} - /** * Device Socket Object List */ @@ -808,7 +791,7 @@ void CAEDRNativeRemoveDeviceSocket(JNIEnv *env, jobject deviceSocket) (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress); - CAEDRReorderingDeviceSocketList(index); + u_arraylist_remove(g_deviceObjectList, index); break; } (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); @@ -856,7 +839,7 @@ void CAEDRNativeRemoveDeviceSocketBaseAddr(JNIEnv *env, jstring address) (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->ReleaseStringUTFChars(env, address, remoteAddress); - CAEDRReorderingDeviceSocketList(index); + u_arraylist_remove(g_deviceObjectList, index); break; } (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); @@ -939,20 +922,3 @@ uint32_t CAEDRGetSocketListLength() return length; } - -void CAEDRReorderingDeviceSocketList(uint32_t index) -{ - if (index >= g_deviceObjectList->length) - { - return; - } - - if (index < g_deviceObjectList->length - 1) - { - memmove(&g_deviceObjectList->data[index], &g_deviceObjectList->data[index + 1], - (g_deviceObjectList->length - index - 1) * sizeof(void *)); - } - - g_deviceObjectList->size--; - g_deviceObjectList->length--; -} diff --git a/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrutils.h b/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrutils.h index 00ddffc..ec12615 100644 --- a/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrutils.h +++ b/resource/csdk/connectivity/src/bt_edr_adapter/android/caedrutils.h @@ -130,12 +130,6 @@ void CAEDRNativeRemoveDevice(const char *remoteAddress); CAConnectedState_t CAEDRIsConnectedDevice(const char *remoteAddress); /** - * Reordering for the list. - * @param[in] index index of device list that want to reordering. - */ -void CAEDRReorderingDeviceList(uint32_t index); - -/** * This function will create the device socket list. */ void CAEDRNativeCreateDeviceSocketList(); @@ -196,11 +190,6 @@ jobject CAEDRNativeGetDeviceSocketBaseAddr(JNIEnv *env, const char* remoteAddres */ uint32_t CAEDRGetSocketListLength(); -/** - * Reordering for the list. - * @param[in] index index of device list that want to reordering. - */ -void CAEDRReorderingDeviceSocketList(uint32_t index); #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/resource/csdk/connectivity/src/bt_edr_adapter/tizen/caedrendpoint.c b/resource/csdk/connectivity/src/bt_edr_adapter/tizen/caedrendpoint.c index 18061e7..c7156e6 100644 --- a/resource/csdk/connectivity/src/bt_edr_adapter/tizen/caedrendpoint.c +++ b/resource/csdk/connectivity/src/bt_edr_adapter/tizen/caedrendpoint.c @@ -34,7 +34,6 @@ CAResult_t CAEDRSendData(int serverFD, const void *data, uint32_t dataLength) OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN"); VERIFY_NON_NULL(data, EDR_ADAPTER_TAG, "Data is null"); - VERIFY_NON_NULL(sentDataLen, EDR_ADAPTER_TAG, "Sent data length holder is null"); if (0 > serverFD) { diff --git a/resource/csdk/connectivity/src/bt_edr_adapter/tizen/caedrnwmonitor.c b/resource/csdk/connectivity/src/bt_edr_adapter/tizen/caedrnwmonitor.c index 20b9962..d9af8e6 100644 --- a/resource/csdk/connectivity/src/bt_edr_adapter/tizen/caedrnwmonitor.c +++ b/resource/csdk/connectivity/src/bt_edr_adapter/tizen/caedrnwmonitor.c @@ -51,10 +51,9 @@ static CAEDRNetworkStatusCallback g_edrNetworkChangeCallback = NULL; static void CAEDRAdapterStateChangeCallback(int result, bt_adapter_state_e adapterState, void *userData); -void *GMainLoopThread (void *param) +void GMainLoopThread (void *param) { g_main_loop_run(g_mainloop); - return NULL; } CAResult_t CAEDRInitializeNetworkMonitor(const ca_thread_pool_t threadPool) diff --git a/resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.c b/resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.c index 38ae49a..075c9bd 100644 --- a/resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.c +++ b/resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.c @@ -2221,7 +2221,12 @@ CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address) (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->ReleaseStringUTFChars(env, address, remoteAddress); - CALEClientReorderingList(index, g_deviceList); + if (NULL == u_arraylist_remove(g_deviceList, index)) + { + OIC_LOG(ERROR, TAG, "List removal failed."); + ca_mutex_unlock(g_deviceListMutex); + return CA_STATUS_FAILED; + } ca_mutex_unlock(g_deviceListMutex); return CA_STATUS_OK; } @@ -2468,8 +2473,15 @@ CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt) (*env)->DeleteGlobalRef(env, jarrayObj); (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress); + + if (NULL == u_arraylist_remove(g_gattObjectList, index)) + { + OIC_LOG(ERROR, TAG, "List removal failed."); + ca_mutex_unlock(g_gattObjectMutex); + return CA_STATUS_FAILED; + } ca_mutex_unlock(g_gattObjectMutex); - return CALEClientReorderingList(index, g_gattObjectList); + return CA_STATUS_OK; } (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress); @@ -2537,8 +2549,14 @@ CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr) (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->ReleaseStringUTFChars(env, addr, remoteAddress); + if (NULL == u_arraylist_remove(g_gattObjectList, index)) + { + OIC_LOG(ERROR, TAG, "List removal failed."); + ca_mutex_unlock(g_gattObjectMutex); + return CA_STATUS_FAILED; + } ca_mutex_unlock(g_gattObjectMutex); - return CALEClientReorderingList(index, g_gattObjectList); + return CA_STATUS_OK; } (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->ReleaseStringUTFChars(env, addr, remoteAddress); @@ -2716,12 +2734,12 @@ CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress) OIC_LOG_V(DEBUG, TAG, "remove state : %s", remoteAddress); OICFree(state); - CAResult_t res = CALEClientReorderingList(index, g_deviceStateList); - if(CA_STATUS_OK != res) + if (NULL == u_arraylist_remove(g_deviceStateList, index)) { - OIC_LOG(ERROR, TAG, "CALEClientReorderingList has failed"); - return res; + OIC_LOG(ERROR, TAG, "List removal failed."); + return CA_STATUS_FAILED; } + return CA_STATUS_OK; } } @@ -2873,32 +2891,6 @@ void CALEClientCreateDeviceList() } } -CAResult_t CALEClientReorderingList(uint32_t index, u_arraylist_t *list) -{ - if (!list) - { - OIC_LOG(ERROR, TAG, "list is null"); - return CA_STATUS_FAILED; - } - - if (index >= list->length) - { - OIC_LOG(ERROR, TAG, "index is not available"); - return CA_STATUS_FAILED; - } - - if (index < list->length - 1) - { - memmove(&list->data[index], &list->data[index + 1], - (list->length - index - 1) * sizeof(void *)); - } - - list->size--; - list->length--; - - return CA_STATUS_OK; -} - /** * Check Sent Count for remove g_sendBuffer */ diff --git a/resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.h b/resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.h index 1b04609..708a1c5 100644 --- a/resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.h +++ b/resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.h @@ -509,14 +509,6 @@ bool CALEClientIsSetCharacteristic(const char* remoteAddress); void CALEClientCreateDeviceList(); /** - * Reordering for device state list. - * @param[in] index index of device list that want to reordering. - * @param[in] list the list to reorder. - * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h). - */ -CAResult_t CALEClientReorderingList(uint32_t index, u_arraylist_t *list); - -/** * update the counter which data is sent to remote device. * @param[in] env JNI interface pointer. */ diff --git a/resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.c b/resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.c index db04fac..8f8ec34 100644 --- a/resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.c +++ b/resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.c @@ -2018,12 +2018,11 @@ CAResult_t CALEServerRemoveDevice(JNIEnv *env, jstring address) (*env)->ReleaseStringUTFChars(env, address, remoteAddress); (*env)->DeleteGlobalRef(env, jarrayObj); - CAResult_t res = CALEServerReorderinglist(index); - if (CA_STATUS_OK != res) + if (NULL == u_arraylist_remove(g_connectedDeviceList, index)) { - OIC_LOG(ERROR, TAG, "CALEServerReorderinglist has failed"); + OIC_LOG(ERROR, TAG, "List removal failed."); ca_mutex_unlock(g_connectedDeviceListMutex); - return res; + return CA_STATUS_FAILED; } ca_mutex_unlock(g_connectedDeviceListMutex); return CA_STATUS_OK; @@ -2041,32 +2040,6 @@ CAResult_t CALEServerRemoveDevice(JNIEnv *env, jstring address) return CA_STATUS_FAILED; } -CAResult_t CALEServerReorderinglist(uint32_t index) -{ - if (!g_connectedDeviceList) - { - OIC_LOG(ERROR, TAG, "g_connectedDeviceList is null"); - return CA_STATUS_FAILED; - } - - if (index >= g_connectedDeviceList->length) - { - OIC_LOG(ERROR, TAG, "index is not available"); - return CA_STATUS_FAILED; - } - - if (index < g_connectedDeviceList->length - 1) - { - memmove(&g_connectedDeviceList->data[index], &g_connectedDeviceList->data[index + 1], - (g_connectedDeviceList->length - index - 1) * sizeof(void *)); - } - - g_connectedDeviceList->size--; - g_connectedDeviceList->length--; - - return CA_STATUS_OK; -} - JNIEXPORT void JNICALL Java_org_iotivity_ca_CaLeServerInterface_caLeRegisterGattServerCallback(JNIEnv *env, jobject obj, jobject callback) diff --git a/resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.h b/resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.h index 1b7a862..48484b5 100644 --- a/resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.h +++ b/resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.h @@ -292,13 +292,6 @@ CAResult_t CALEServerRemoveAllDevices(JNIEnv *env); CAResult_t CALEServerRemoveDevice(JNIEnv *env, jstring address); /** - * Reordering for the list (connected device list). - * @param[in] index index of device list that want to reordering. - * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h). - */ -CAResult_t CALEServerReorderinglist(uint32_t index); - -/** * initialize mutex. * @return ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h). */ diff --git a/resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c b/resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c index 9a46051..2a198db 100644 --- a/resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c +++ b/resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c @@ -257,193 +257,6 @@ static CAQueueingThread_t *g_bleReceiverQueue = NULL; static CAQueueingThread_t *g_bleServerSendQueueHandle = NULL; /** - * Starting LE connectivity adapters. - * - * As its peer to peer it does not require to start any servers. - * - * @return ::CA_STATUS_OK or Appropriate error code. - */ -static CAResult_t CAStartLE(); - -/** - * Start listening server for receiving multicast search requests. - * - * Transport Specific Behavior: - * LE Starts GATT Server with prefixed UUID and Characteristics - * per OIC Specification. - * @return ::CA_STATUS_OK or Appropriate error code. - */ -static CAResult_t CAStartLEListeningServer(); - -/** - * Sarting discovery of servers for receiving multicast - * advertisements. - * - * Transport Specific Behavior: - * LE Starts GATT Server with prefixed UUID and Characteristics - * per OIC Specification. - * - * @return ::CA_STATUS_OK or Appropriate error code - */ -static CAResult_t CAStartLEDiscoveryServer(); - -/** - * Send data to the endpoint using the adapter connectivity. - * - * @param[in] endpoint Remote Endpoint information (like MAC address, - * reference URI and connectivity type) to which - * the unicast data has to be sent. - * @param[in] data Data which required to be sent. - * @param[in] dataLen Size of data to be sent. - * - * @note dataLen must be > 0. - * - * @return The number of bytes sent on the network, or -1 on error. - */ -static int32_t CASendLEUnicastData(const CAEndpoint_t *endpoint, - const void *data, - uint32_t dataLen); - -/** - * Send multicast data to the endpoint using the LE connectivity. - * - * @param[in] endpoint Remote Endpoint information to which the - * multicast data has to be sent. - * @param[in] data Data which required to be sent. - * @param[in] dataLen Size of data to be sent. - * - * @note dataLen must be > 0. - * - * @return The number of bytes sent on the network, or -1 on error. - */ -static int32_t CASendLEMulticastData(const CAEndpoint_t *endpoint, - const void *data, - uint32_t dataLen); - -/** - * Get LE Connectivity network information. - * - * @param[out] info Local connectivity information structures. - * @param[out] size Number of local connectivity structures. - * - * @return ::CA_STATUS_OK or Appropriate error code. - */ -static CAResult_t CAGetLEInterfaceInformation(CAEndpoint_t **info, - uint32_t *size); - -/** - * Read Synchronous API callback. - * - * @return ::CA_STATUS_OK or Appropriate error code. - */ -static CAResult_t CAReadLEData(); - -/** - * Stopping the adapters and close socket connections. - * - * LE Stops all GATT servers and GATT Clients. - * - * @return ::CA_STATUS_OK or Appropriate error code. - */ -static CAResult_t CAStopLE(); - -/** - * Terminate the LE connectivity adapter. - * - * Configuration information will be deleted from further use. - */ -static void CATerminateLE(); - -/** - * Set the NetworkPacket received callback to CA layer from adapter - * layer. - * - * @param[in] callback Callback handle sent from the upper layer. - */ -static void CASetLEReqRespAdapterCallback(CANetworkPacketReceivedCallback callback); - -/** - * Push the data from CA layer to the Sender processor queue. - * - * @param[in] remoteEndpoint Remote endpoint information of the - * server. - * @param[in] data Data to be transmitted from LE. - * @param[in] dataLen Length of the Data being transmitted. - * - * @return ::CA_STATUS_OK or Appropriate error code. - * @retval ::CA_STATUS_OK Successful. - * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. - * @retval ::CA_STATUS_FAILED Operation failed. - */ -static CAResult_t CALEAdapterServerSendData(const CAEndpoint_t *remoteEndpoint, - const uint8_t *data, - uint32_t dataLen); - -/** - * Push the data from CA layer to the Sender processor queue. - * - * @param[in] remoteEndpoint Remote endpoint information of the - * server. - * @param[in] data Data to be transmitted from LE. - * @param[in] dataLen Length of the Data being transmitted. - * - * @return ::CA_STATUS_OK or Appropriate error code. - * @retval ::CA_STATUS_OK Successful. - * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. - * @retval ::CA_STATUS_FAILED Operation failed. - */ -static CAResult_t CALEAdapterClientSendData(const CAEndpoint_t *remoteEndpoint, - const uint8_t *data, - uint32_t dataLen); - -/** - * This function will receive the data from the GattServer and add the - * data to the Server receiver queue. - * - * @param[in] remoteAddress Remote address of the device from where - * data is received. - * @param[in] data Actual data recevied from the remote - * device. - * @param[in] dataLength Length of the data received from the - * remote device. - * @param[in] sentLength Length of the data sent from the remote - * device. - * - * @return ::CA_STATUS_OK or Appropriate error code. - * @retval ::CA_STATUS_OK Successful. - * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. - * @retval ::CA_STATUS_FAILED Operation failed. - * - */ -static CAResult_t CALEAdapterServerReceivedData(const char *remoteAddress, - const uint8_t *data, - uint32_t dataLength, - uint32_t *sentLength); - -/** - * This function will receive the data from the GattClient and add the - * data into the Client receiver queue. - * - * @param[in] remoteAddress Remote address of the device from where - * data is received. - * @param[in] data Actual data recevied from the remote - * device. - * @param[in] dataLength Length of the data received from the - * remote device. - * @param[in] sentLength Length of the data sent from the remote - * device. - * - * @return ::CA_STATUS_OK or Appropriate error code. - * @retval ::CA_STATUS_OK Successful. - * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. - * @retval ::CA_STATUS_FAILED Operation failed. - */ -static CAResult_t CALEAdapterClientReceivedData(const char *remoteAddress, - const uint8_t *data, - uint32_t dataLength, - uint32_t *sentLength); - -/** * This function will be associated with the sender queue for * GattServer. * @@ -1606,6 +1419,193 @@ static void CATerminateLEAdapterMutex() OIC_LOG(DEBUG, CALEADAPTER_TAG, "OUT"); } +/** + * Starting LE connectivity adapters. + * + * As its peer to peer it does not require to start any servers. + * + * @return ::CA_STATUS_OK or Appropriate error code. + */ +static CAResult_t CAStartLE(); + +/** + * Start listening server for receiving multicast search requests. + * + * Transport Specific Behavior: + * LE Starts GATT Server with prefixed UUID and Characteristics + * per OIC Specification. + * @return ::CA_STATUS_OK or Appropriate error code. + */ +static CAResult_t CAStartLEListeningServer(); + +/** + * Sarting discovery of servers for receiving multicast + * advertisements. + * + * Transport Specific Behavior: + * LE Starts GATT Server with prefixed UUID and Characteristics + * per OIC Specification. + * + * @return ::CA_STATUS_OK or Appropriate error code + */ +static CAResult_t CAStartLEDiscoveryServer(); + +/** + * Send data to the endpoint using the adapter connectivity. + * + * @param[in] endpoint Remote Endpoint information (like MAC address, + * reference URI and connectivity type) to which + * the unicast data has to be sent. + * @param[in] data Data which required to be sent. + * @param[in] dataLen Size of data to be sent. + * + * @note dataLen must be > 0. + * + * @return The number of bytes sent on the network, or -1 on error. + */ +static int32_t CASendLEUnicastData(const CAEndpoint_t *endpoint, + const void *data, + uint32_t dataLen); + +/** + * Send multicast data to the endpoint using the LE connectivity. + * + * @param[in] endpoint Remote Endpoint information to which the + * multicast data has to be sent. + * @param[in] data Data which required to be sent. + * @param[in] dataLen Size of data to be sent. + * + * @note dataLen must be > 0. + * + * @return The number of bytes sent on the network, or -1 on error. + */ +static int32_t CASendLEMulticastData(const CAEndpoint_t *endpoint, + const void *data, + uint32_t dataLen); + +/** + * Get LE Connectivity network information. + * + * @param[out] info Local connectivity information structures. + * @param[out] size Number of local connectivity structures. + * + * @return ::CA_STATUS_OK or Appropriate error code. + */ +static CAResult_t CAGetLEInterfaceInformation(CAEndpoint_t **info, + uint32_t *size); + +/** + * Read Synchronous API callback. + * + * @return ::CA_STATUS_OK or Appropriate error code. + */ +static CAResult_t CAReadLEData(); + +/** + * Stopping the adapters and close socket connections. + * + * LE Stops all GATT servers and GATT Clients. + * + * @return ::CA_STATUS_OK or Appropriate error code. + */ +static CAResult_t CAStopLE(); + +/** + * Terminate the LE connectivity adapter. + * + * Configuration information will be deleted from further use. + */ +static void CATerminateLE(); + +/** + * This function will receive the data from the GattServer and add the + * data to the Server receiver queue. + * + * @param[in] remoteAddress Remote address of the device from where + * data is received. + * @param[in] data Actual data recevied from the remote + * device. + * @param[in] dataLength Length of the data received from the + * remote device. + * @param[in] sentLength Length of the data sent from the remote + * device. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + * + */ +static CAResult_t CALEAdapterServerReceivedData(const char *remoteAddress, + const uint8_t *data, + uint32_t dataLength, + uint32_t *sentLength); + +/** + * This function will receive the data from the GattClient and add the + * data into the Client receiver queue. + * + * @param[in] remoteAddress Remote address of the device from where + * data is received. + * @param[in] data Actual data recevied from the remote + * device. + * @param[in] dataLength Length of the data received from the + * remote device. + * @param[in] sentLength Length of the data sent from the remote + * device. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + */ +static CAResult_t CALEAdapterClientReceivedData(const char *remoteAddress, + const uint8_t *data, + uint32_t dataLength, + uint32_t *sentLength); + +/** + * Set the NetworkPacket received callback to CA layer from adapter + * layer. + * + * @param[in] callback Callback handle sent from the upper layer. + */ +static void CASetLEReqRespAdapterCallback(CANetworkPacketReceivedCallback callback); + +/** + * Push the data from CA layer to the Sender processor queue. + * + * @param[in] remoteEndpoint Remote endpoint information of the + * server. + * @param[in] data Data to be transmitted from LE. + * @param[in] dataLen Length of the Data being transmitted. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + */ +static CAResult_t CALEAdapterServerSendData(const CAEndpoint_t *remoteEndpoint, + const uint8_t *data, + uint32_t dataLen); + +/** + * Push the data from CA layer to the Sender processor queue. + * + * @param[in] remoteEndpoint Remote endpoint information of the + * server. + * @param[in] data Data to be transmitted from LE. + * @param[in] dataLen Length of the Data being transmitted. + * + * @return ::CA_STATUS_OK or Appropriate error code. + * @retval ::CA_STATUS_OK Successful. + * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. + * @retval ::CA_STATUS_FAILED Operation failed. + */ +static CAResult_t CALEAdapterClientSendData(const CAEndpoint_t *remoteEndpoint, + const uint8_t *data, + uint32_t dataLen); + CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback, CANetworkPacketReceivedCallback reqRespCallback, CANetworkChangeCallback netCallback, @@ -1670,7 +1670,7 @@ CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback, static CAResult_t CAStartLE() { - OIC_LOG(DEBUG, CALEADAPTER_TAG, __func__); + OIC_LOG(DEBUG, CALEADAPTER_TAG, "CAStartLE"); return CAStartLEAdapter(); } diff --git a/resource/csdk/connectivity/src/bt_le_adapter/tizen/cableserver.c b/resource/csdk/connectivity/src/bt_le_adapter/tizen/cableserver.c index a971465..807f1d9 100644 --- a/resource/csdk/connectivity/src/bt_le_adapter/tizen/cableserver.c +++ b/resource/csdk/connectivity/src/bt_le_adapter/tizen/cableserver.c @@ -219,8 +219,8 @@ void CAStartBleGattServerThread(void *data) return; } - char *charReadUUID = CA_GATT_RESPONSE_CHRC_UUID; - char charReadValue[] = {33, 44, 55, 66}; // These are initial random values + static const char charReadUUID[] = CA_GATT_RESPONSE_CHRC_UUID; + uint8_t charReadValue[] = {33, 44, 55, 66}; // These are initial random values ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charReadUUID, charReadValue, CA_BLE_INITIAL_BUF_SIZE, true); // For Read Characteristics. @@ -232,8 +232,8 @@ void CAStartBleGattServerThread(void *data) return; } - char *charWriteUUID = CA_GATT_REQUEST_CHRC_UUID; - char charWriteValue[] = {33, 44, 55, 66}; // These are initial random values + static const char charWriteUUID[] = CA_GATT_REQUEST_CHRC_UUID; + uint8_t charWriteValue[] = {33, 44, 55, 66}; // These are initial random values ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charWriteUUID, charWriteValue, @@ -592,7 +592,7 @@ void CABleGattRemoteCharacteristicWriteCb(char *charPath, OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, - "charPath = [%s] charValue = [%x] len [%d]", + "charPath = [%s] charValue = [%p] len [%d]", charPath, charValue, charValueLen); @@ -647,12 +647,12 @@ CAResult_t CARegisterBleServicewithGattServer(const char *svcPath) } CAResult_t CAAddNewCharacteristicsToGattServer(const char *svcPath, const char *charUUID, - const char *charValue, int charValueLen, bool read) + const uint8_t *charValue, int charValueLen, bool read) { OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - char *charFlags[1]; + const char *charFlags[1]; if(read) { charFlags[0] = "notify"; @@ -665,8 +665,14 @@ CAResult_t CAAddNewCharacteristicsToGattServer(const char *svcPath, const char * size_t flagLen = sizeof(charFlags) / sizeof(charFlags[0]); char *charPath = NULL; - int ret = bt_gatt_add_characteristic(charUUID, charValue, charValueLen, charFlags, flagLen, - svcPath, &charPath); + int ret = + bt_gatt_add_characteristic(charUUID, + (const char *) charValue, + charValueLen, + charFlags, + flagLen, + svcPath, + &charPath); if (0 != ret || NULL == charPath) { @@ -713,7 +719,7 @@ CAResult_t CARemoveCharacteristicsFromGattServer(const char *charPath) } CAResult_t CAUpdateCharacteristicsToGattClient(const char *address, - const char *charValue, + const uint8_t *charValue, uint32_t charValueLen) { OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); @@ -733,7 +739,7 @@ CAResult_t CAUpdateCharacteristicsToGattClient(const char *address, return CA_STATUS_FAILED; } - char *data = (char *) OICCalloc(sizeof(char), (charValueLen + 1)); + char *data = OICCalloc(charValueLen, 1); if (NULL == data) { OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "malloc failed!"); @@ -741,12 +747,16 @@ CAResult_t CAUpdateCharacteristicsToGattClient(const char *address, return CA_STATUS_FAILED; } - OICStrcpy(data, charValueLen + 1, charValue); + memcpy(data, charValue, charValueLen); // Binary data - OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "updating characteristics char [%s] data [%s] dataLen [%d]", + OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "updating characteristics char [%s] data [%p] dataLen [%u]", (const char *)g_gattReadCharPath, data, charValueLen); - int ret = bt_gatt_update_characteristic(g_gattReadCharPath, data, charValueLen, address); + int ret = + bt_gatt_update_characteristic(g_gattReadCharPath, + data, + charValueLen, + address); if (0 != ret) { OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, @@ -763,7 +773,7 @@ CAResult_t CAUpdateCharacteristicsToGattClient(const char *address, return CA_STATUS_OK; } -CAResult_t CAUpdateCharacteristicsToAllGattClients(const char *charValue, uint32_t charValueLen) +CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *charValue, uint32_t charValueLen) { OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); @@ -778,7 +788,7 @@ CAResult_t CAUpdateCharacteristicsToAllGattClients(const char *charValue, uint32 return CA_STATUS_FAILED; } - char *data = (char *) OICMalloc(sizeof(char) * (charValueLen + 1)); + char *data = OICMalloc(charValueLen); if (NULL == data) { OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "malloc failed!"); @@ -786,12 +796,16 @@ CAResult_t CAUpdateCharacteristicsToAllGattClients(const char *charValue, uint32 return CA_STATUS_FAILED; } - OICStrcpy(data, charValueLen + 1, charValue); + memcpy(data, charValue, charValueLen); // Binary data - OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "updating characteristics char [%s] data [%s] dataLen [%d]", + OIC_LOG_V(DEBUG, TZ_BLE_SERVER_TAG, "updating characteristics char [%s] data [%p] dataLen [%u]", (const char *)g_gattReadCharPath, data, charValueLen); - int ret = bt_gatt_update_characteristic(g_gattReadCharPath, data, charValueLen, NULL); + int ret = + bt_gatt_update_characteristic(g_gattReadCharPath, + data, + charValueLen, + NULL); if (0 != ret) { OIC_LOG_V(ERROR, TZ_BLE_SERVER_TAG, diff --git a/resource/csdk/connectivity/src/cablockwisetransfer.c b/resource/csdk/connectivity/src/cablockwisetransfer.c index c016654..80cd517 100644 --- a/resource/csdk/connectivity/src/cablockwisetransfer.c +++ b/resource/csdk/connectivity/src/cablockwisetransfer.c @@ -2004,22 +2004,6 @@ CAData_t *CACloneCAData(const CAData_t *data) clone->remoteEndpoint = CACloneEndpoint(data->remoteEndpoint); } - if (NULL != data->options && 0 < data->numOptions) - { - // copy data - CAHeaderOption_t *headerOption = (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) - * data->numOptions); - if (NULL == headerOption) - { - OIC_LOG(ERROR, TAG, "Out of memory"); - CADestroyDataSet(clone); - return NULL; - } - memcpy(headerOption, data->options, sizeof(CAHeaderOption_t) * data->numOptions); - - clone->options = headerOption; - } - return clone; } @@ -2475,8 +2459,8 @@ CABlockData_t *CACreateNewBlockData(const CAData_t *sendData) ca_mutex_lock(g_context.blockDataListMutex); - CAResult_t res = u_arraylist_add(g_context.dataList, (void *) data); - if (CA_STATUS_OK != res) + bool res = u_arraylist_add(g_context.dataList, (void *) data); + if (!res) { OIC_LOG(ERROR, TAG, "add has failed"); CADestroyBlockID(data->blockDataId); @@ -2558,7 +2542,6 @@ void CADestroyDataSet(CAData_t* data) CAFreeEndpoint(data->remoteEndpoint); CADestroyRequestInfoInternal(data->requestInfo); CADestroyResponseInfoInternal(data->responseInfo); - OICFree(data->options); OICFree(data); } diff --git a/resource/csdk/connectivity/src/cainterfacecontroller.c b/resource/csdk/connectivity/src/cainterfacecontroller.c index 9df1da3..9b1f8d4 100644 --- a/resource/csdk/connectivity/src/cainterfacecontroller.c +++ b/resource/csdk/connectivity/src/cainterfacecontroller.c @@ -123,14 +123,14 @@ CAResult_t CASetAdapterRAInfo(const CARAInfo_t *caraInfo) } #endif -static void CAReceivedPacketCallback(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLen) +static void CAReceivedPacketCallback(const CASecureEndpoint_t *sep, + const void *data, uint32_t dataLen) { OIC_LOG(DEBUG, TAG, "IN"); - // Call the callback. if (g_networkPacketReceivedCallback != NULL) { - g_networkPacketReceivedCallback(endpoint, data, dataLen); + g_networkPacketReceivedCallback(sep, data, dataLen); } else { diff --git a/resource/csdk/connectivity/src/camessagehandler.c b/resource/csdk/connectivity/src/camessagehandler.c index 38b185d..0742377 100644 --- a/resource/csdk/connectivity/src/camessagehandler.c +++ b/resource/csdk/connectivity/src/camessagehandler.c @@ -71,8 +71,9 @@ static void CAErrorHandler(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLen, CAResult_t result); -static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, const void *data, - CADataType_t dataType); +static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, + const CARemoteId_t *identity, + const void *data, CADataType_t dataType); static void CASendErrorInfo(const CAEndpoint_t *endpoint, const CAInfo_t *info, CAResult_t result); @@ -82,7 +83,7 @@ static void CAProcessReceivedData(CAData_t *data); #endif static void CADestroyData(void *data, uint32_t size); static void CALogPayloadInfo(CAInfo_t *info); -static bool CADropSecondRequest(const CAEndpoint_t *endpoint, uint16_t messageId); +static bool CADropSecondMessage(CAHistory_t *history, const CAEndpoint_t *endpoint, uint16_t id); #ifdef WITH_BWT void CAAddDataToSendThread(CAData_t *data) @@ -111,7 +112,7 @@ void CAAddDataToReceiveThread(CAData_t *data) static bool CAIsSelectedNetworkAvailable() { u_arraylist_t *list = CAGetSelectedNetworkList(); - if (!list || list->length == 0) + if (!list || u_arraylist_length(list) == 0) { OIC_LOG(ERROR, TAG, "No selected network"); return false; @@ -120,7 +121,9 @@ static bool CAIsSelectedNetworkAvailable() return true; } -static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, const void *data, CADataType_t dataType) +static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, + const CARemoteId_t *identity, + const void *data, CADataType_t dataType) { OIC_LOG(DEBUG, TAG, "CAGenerateHandlerData IN"); CAInfo_t *info = NULL; @@ -164,6 +167,10 @@ static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, const void } cadata->responseInfo = resInfo; info = &resInfo->info; + if (identity) + { + info->identity = *identity; + } OIC_LOG(DEBUG, TAG, "Response Info :"); CALogPayloadInfo(info); } @@ -188,7 +195,7 @@ static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, const void return NULL; } - if (CADropSecondRequest(endpoint, reqInfo->info.messageId)) + if (CADropSecondMessage(&caglobals.ca.requestHistory, endpoint, reqInfo->info.messageId)) { OIC_LOG(ERROR, TAG, "Second Request with same Token, Drop it"); CAFreeEndpoint(ep); @@ -199,6 +206,10 @@ static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, const void cadata->requestInfo = reqInfo; info = &reqInfo->info; + if (identity) + { + info->identity = *identity; + } OIC_LOG(DEBUG, TAG, "Request Info :"); CALogPayloadInfo(info); } @@ -225,6 +236,10 @@ static CAData_t* CAGenerateHandlerData(const CAEndpoint_t *endpoint, const void cadata->errorInfo = errorInfo; info = &errorInfo->info; + if (identity) + { + info->identity = *identity; + } OIC_LOG(DEBUG, TAG, "error Info :"); CALogPayloadInfo(info); } @@ -330,7 +345,6 @@ static void CADestroyData(void *data, uint32_t size) CADestroyErrorInfoInternal(cadata->errorInfo); } - OICFree(cadata->options); OICFree(cadata); OIC_LOG(DEBUG, TAG, "CADestroyData OUT"); } @@ -548,47 +562,55 @@ static void CASendThreadProcess(void *threadData) /* * If a second message arrives with the same token and the other address * family, drop it. Typically, IPv6 beats IPv4, so the IPv4 message is dropped. - * This can be made more robust (for instance, another message could arrive - * in between), but it is good enough for now. */ -static bool CADropSecondRequest(const CAEndpoint_t *endpoint, uint16_t messageId) +static bool CADropSecondMessage(CAHistory_t *history, const CAEndpoint_t *ep, uint16_t id) { - if (!endpoint) + if (!ep) { return true; } - if (endpoint->adapter != CA_ADAPTER_IP) + if (ep->adapter != CA_ADAPTER_IP) + { + return false; + } + if (!caglobals.ip.dualstack) { return false; } bool ret = false; - CATransportFlags_t familyFlags = endpoint->flags & CA_IPFAMILY_MASK; + CATransportFlags_t familyFlags = ep->flags & CA_IPFAMILY_MASK; - if (messageId == caglobals.ca.previousRequestMessageId) + for (size_t i = 0; i < sizeof(history->items) / sizeof(history->items[0]); i++) { - if ((familyFlags ^ caglobals.ca.previousRequestFlags) == CA_IPFAMILY_MASK) + CAHistoryItem_t *item = &(history->items[i]); + if (id == item->messageId) { - if (familyFlags & CA_IPV6) - { - OIC_LOG(INFO, TAG, "IPv6 duplicate response ignored"); - } - else + if ((familyFlags ^ item->flags) == CA_IPFAMILY_MASK) { - OIC_LOG(INFO, TAG, "IPv4 duplicate response ignored"); + OIC_LOG_V(INFO, TAG, "IPv%c duplicate message ignored", + familyFlags & CA_IPV6 ? '6' : '4'); + ret = true; + break; } - ret = true; } } - caglobals.ca.previousRequestFlags = familyFlags; - caglobals.ca.previousRequestMessageId = messageId; + + history->items[history->nextIndex].flags = familyFlags; + history->items[history->nextIndex].messageId = id; + if (++history->nextIndex >= HISTORYSIZE) + { + history->nextIndex = 0; + } + return ret; } -static void CAReceivedPacketCallback(const CAEndpoint_t *remoteEndpoint, const void *data, uint32_t dataLen) +static void CAReceivedPacketCallback(const CASecureEndpoint_t *sep, + const void *data, uint32_t dataLen) { OIC_LOG(DEBUG, TAG, "IN"); - VERIFY_NON_NULL_VOID(remoteEndpoint, TAG, "remoteEndpoint"); + VERIFY_NON_NULL_VOID(sep, TAG, "remoteEndpoint"); VERIFY_NON_NULL_VOID(data, TAG, "data"); uint32_t code = CA_NOT_FOUND; @@ -604,7 +626,7 @@ static void CAReceivedPacketCallback(const CAEndpoint_t *remoteEndpoint, const v OIC_LOG_V(DEBUG, TAG, "code = %d", code); if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code) { - cadata = CAGenerateHandlerData(remoteEndpoint, pdu, CA_REQUEST_DATA); + cadata = CAGenerateHandlerData(&(sep->endpoint), &(sep->identity), pdu, CA_REQUEST_DATA); if (!cadata) { OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, CAGenerateHandlerData failed!"); @@ -614,7 +636,7 @@ static void CAReceivedPacketCallback(const CAEndpoint_t *remoteEndpoint, const v } else { - cadata = CAGenerateHandlerData(remoteEndpoint, pdu, CA_RESPONSE_DATA); + cadata = CAGenerateHandlerData(&(sep->endpoint), &(sep->identity), pdu, CA_RESPONSE_DATA); if (!cadata) { OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, CAGenerateHandlerData failed!"); @@ -652,24 +674,24 @@ static void CAReceivedPacketCallback(const CAEndpoint_t *remoteEndpoint, const v CAProcessReceivedData(cadata); #else #ifdef WITH_BWT - if (CA_ADAPTER_GATT_BTLE != remoteEndpoint->adapter) + if (CA_ADAPTER_GATT_BTLE != sep->endpoint.adapter) + { + CAResult_t res = CAReceiveBlockWiseData(pdu, &(sep->endpoint), cadata, dataLen); + if (CA_NOT_SUPPORTED == res) { - CAResult_t res = CAReceiveBlockWiseData(pdu, remoteEndpoint, cadata, dataLen); - if (CA_NOT_SUPPORTED == res) - { - OIC_LOG(ERROR, TAG, "this message does not have block option"); - CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t)); - } - else - { - CADestroyData(cadata, sizeof(CAData_t)); - } + OIC_LOG(ERROR, TAG, "this message does not have block option"); + CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t)); } else -#endif { - CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t)); + CADestroyData(cadata, sizeof(CAData_t)); } + } + else +#endif + { + CAQueueingThreadAddData(&g_receiveThread, cadata, sizeof(CAData_t)); + } #endif coap_delete_pdu(pdu); @@ -746,7 +768,6 @@ static CAData_t* CAPrepareSendData(const CAEndpoint_t *endpoint, const void *sen CADataType_t dataType) { OIC_LOG(DEBUG, TAG, "CAPrepareSendData IN"); - CAInfo_t *info = NULL; CAData_t *cadata = (CAData_t *) OICCalloc(1, sizeof(CAData_t)); if (!cadata) @@ -768,7 +789,6 @@ static CAData_t* CAPrepareSendData(const CAEndpoint_t *endpoint, const void *sen } cadata->type = request->isMulticast ? SEND_TYPE_MULTICAST : SEND_TYPE_UNICAST; - info = &request->info; cadata->requestInfo = request; } else if(CA_RESPONSE_DATA == dataType) @@ -784,7 +804,6 @@ static CAData_t* CAPrepareSendData(const CAEndpoint_t *endpoint, const void *sen } cadata->type = SEND_TYPE_UNICAST; - info = &response->info; cadata->responseInfo = response; } else @@ -794,25 +813,6 @@ static CAData_t* CAPrepareSendData(const CAEndpoint_t *endpoint, const void *sen return NULL; } - if (NULL != info->options && 0 < info->numOptions) - { - uint8_t numOptions = info->numOptions; - // copy data - CAHeaderOption_t *headerOption = (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) - * numOptions); - if(!headerOption) - { - OIC_LOG(ERROR, TAG, "memory allocation failed"); - CADestroyData(cadata, sizeof(CAData_t)); - return NULL; - } - - memcpy(headerOption, info->options, sizeof(CAHeaderOption_t) * numOptions); - - cadata->options = headerOption; - cadata->numOptions = numOptions; - } - CAEndpoint_t* ep = CACloneEndpoint(endpoint); if (!ep) { @@ -1149,7 +1149,7 @@ static void CALogPayloadInfo(CAInfo_t *info) { if(info) { - if (!info->options) + if (info->options) { for (uint32_t i = 0; i < info->numOptions; i++) { @@ -1159,13 +1159,13 @@ static void CALogPayloadInfo(CAInfo_t *info) } } - if (!info->payload) + if (info->payload) { OIC_LOG_V(DEBUG, TAG, "payload: %p(%u)", info->payload, info->payloadSize); } - if (!info->token) + if (info->token) { OIC_LOG(DEBUG, TAG, "token:"); OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *) info->token, @@ -1200,7 +1200,7 @@ void CAErrorHandler(const CAEndpoint_t *endpoint, return; } - CAData_t *cadata = CAGenerateHandlerData(endpoint, pdu, CA_ERROR_DATA); + CAData_t *cadata = CAGenerateHandlerData(endpoint, NULL, pdu, CA_ERROR_DATA); if(!cadata) { OIC_LOG(ERROR, TAG, "CAErrorHandler, CAGenerateHandlerData failed!"); diff --git a/resource/csdk/connectivity/src/canetworkconfigurator.c b/resource/csdk/connectivity/src/canetworkconfigurator.c index 01e9d4d..d36d378 100644 --- a/resource/csdk/connectivity/src/canetworkconfigurator.c +++ b/resource/csdk/connectivity/src/canetworkconfigurator.c @@ -50,7 +50,7 @@ CAResult_t CAAddNetworkType(CATransportAdapter_t transportType) return CA_MEMORY_ALLOC_FAILED; } } - CAResult_t res = CA_STATUS_OK; + bool res = true; switch (transportType) { case CA_ADAPTER_IP: @@ -111,15 +111,15 @@ CAResult_t CAAddNetworkType(CATransportAdapter_t transportType) break; } - if (CA_STATUS_OK != res) + if (!res) { OIC_LOG_V(ERROR, TAG, "Add arraylist failed[Err code: %d]", res); - return res; + return CA_STATUS_FAILED; } // start selected interface adapter - res = CAStartAdapter(transportType); + CAResult_t result = CAStartAdapter(transportType); OIC_LOG(DEBUG, TAG, "OUT"); - return res; + return result; exit: OIC_LOG(DEBUG, TAG, "This adapter is already enabled"); diff --git a/resource/csdk/connectivity/src/caprotocolmessage.c b/resource/csdk/connectivity/src/caprotocolmessage.c index a418a03..b140264 100644 --- a/resource/csdk/connectivity/src/caprotocolmessage.c +++ b/resource/csdk/connectivity/src/caprotocolmessage.c @@ -229,6 +229,14 @@ coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode) return NULL; } + if (outpdu->hdr->version != COAP_DEFAULT_VERSION) + { + OIC_LOG_V(ERROR, TAG, "coap version is not available : %d", + outpdu->hdr->version); + coap_delete_pdu(outpdu); + return NULL; + } + if (outCode) { (*outCode) = (uint32_t) CA_RESPONSE_CODE(outpdu->hdr->code); diff --git a/resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c b/resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c old mode 100644 new mode 100755 index b15502c..7896334 --- a/resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c +++ b/resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c @@ -35,42 +35,135 @@ #include "logger.h" #include "oic_malloc.h" #include "oic_string.h" +#include "org_iotivity_ca_CaIpInterface.h" #define TAG "IP_MONITOR" -char *getHostIPAddress(const char *ifa_name) { - static char address[INET_ADDRSTRLEN] = {}; - memset(&address, 0, INET_ADDRSTRLEN); - struct ifreq ifr; - int sck, status, len = sizeof(ifr.ifr_name) - 1; - char *ip; +static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family, + uint32_t addr, int flags); - if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) { +static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index, + const char *name, int family, uint32_t addr, int flags); + +CAResult_t CAIPJniInit(); + +#define MAX_INTERFACE_INFO_LENGTH 1024 // allows 32 interfaces from SIOCGIFCONF + +CAResult_t CAIPInitializeNetworkMonitor() +{ + return CAIPJniInit(); +} + +CAResult_t CAIPTerminateNetworkMonitor() +{ + return CA_STATUS_OK; +} + +int CAGetPollingInterval(int interval) +{ + return interval; +} + +CAInterface_t *CAFindInterfaceChange() +{ + char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 }; + struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf }; + + int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd; + if (ioctl(s, SIOCGIFCONF, &ifc) < 0) + { + OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno)); return NULL; } - strncpy(ifr.ifr_name, ifa_name, len); - ifr.ifr_name[len] = '\0'; - if ((status = ioctl(sck, SIOCGIFADDR, &ifr)) < 0) { - close(sck); + CAInterface_t *foundNewInterface = NULL; + + struct ifreq* ifr = ifc.ifc_req; + size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]); + size_t ifreqsize = ifc.ifc_len; + + CAIfItem_t *previous = (CAIfItem_t *)OICMalloc(ifreqsize); + if (!previous) + { + OIC_LOG(ERROR, TAG, "OICMalloc failed"); return NULL; } - close(sck); - ip = inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr); - len = sizeof(address) - 1; - strncpy(address, ip, len); - address[len] = '\0'; - return address; -} -u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) -{ - if (desiredIndex < 0) + memcpy(previous, caglobals.ip.nm.ifItems, ifreqsize); + size_t numprevious = caglobals.ip.nm.numIfItems; + + if (ifreqsize > caglobals.ip.nm.sizeIfItems) { - OIC_LOG_V(ERROR, TAG, "invalid index : %d", desiredIndex); - return NULL; + + CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize); + if (!items) + { + OIC_LOG(ERROR, TAG, "OICRealloc failed"); + OICFree(previous); + return NULL; + } + caglobals.ip.nm.ifItems = items; + caglobals.ip.nm.sizeIfItems = ifreqsize; } + caglobals.ip.nm.numIfItems = 0; + for (size_t i = 0; i < interfaces; i++) + { + struct ifreq* item = &ifr[i]; + char *name = item->ifr_name; + struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr; + uint32_t ipv4addr = sa4->sin_addr.s_addr; + + if (ioctl(s, SIOCGIFFLAGS, item) < 0) + { + OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno)); + continue; + } + int16_t flags = item->ifr_flags; + if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING)) + { + continue; + } + if (ioctl(s, SIOCGIFINDEX, item) < 0) + { + OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno)); + continue; + } + + int ifIndex = item->ifr_ifindex; + caglobals.ip.nm.ifItems[i].ifIndex = ifIndex; // refill interface list + caglobals.ip.nm.numIfItems++; + + if (foundNewInterface) + { + continue; // continue updating interface list + } + + // see if this interface didn't previously exist + bool found = false; + for (size_t j = 0; j < numprevious; j++) + { + if (ifIndex == previous[j].ifIndex) + { + found = true; + break; + } + } + if (found) + { + OIC_LOG_V(INFO, TAG, "Interface found: %s", name); + continue; + } + + foundNewInterface = CANewInterfaceItem(ifIndex, name, AF_INET, ipv4addr, flags); + } + + OICFree(previous); + return foundNewInterface; +} + +u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) +{ u_arraylist_t *iflist = u_arraylist_create(); if (!iflist) { @@ -78,34 +171,81 @@ u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) return NULL; } - char* ipAddr = getHostIPAddress("wlan0"); - if (NULL == ipAddr) + char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 }; + struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf }; + + int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd; + if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { - OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno)); + OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno)); u_arraylist_destroy(iflist); return NULL; } - OIC_LOG_V(DEBUG, TAG, "Got ifaddrs:: %s", ipAddr); - struct in_addr inaddr; - inet_pton(AF_INET, ipAddr, &(inaddr)); + struct ifreq* ifr = ifc.ifc_req; + size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]); + size_t ifreqsize = ifc.ifc_len; - CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));; - OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, "wlan0"); - ifitem->index = 0; //if_nametoindex("wlan0"); - ifitem->family = AF_INET; //we support ipv4 only - ifitem->ipv4addr = inaddr.s_addr; - ifitem->flags = IFF_UP|IFF_RUNNING; - - CAResult_t result = u_arraylist_add(iflist, ifitem); - if (CA_STATUS_OK != result) + if (ifreqsize > caglobals.ip.nm.sizeIfItems) { - OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); - goto exit; + CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize); + if (!items) + { + OIC_LOG(ERROR, TAG, "OICRealloc failed"); + goto exit; + } + caglobals.ip.nm.ifItems = items; + caglobals.ip.nm.sizeIfItems = ifreqsize; } - OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family); + caglobals.ip.nm.numIfItems = 0; + for (size_t i = 0; i < interfaces; i++) + { + CAResult_t result = CA_STATUS_OK; + struct ifreq* item = &ifr[i]; + char *name = item->ifr_name; + struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr; + uint32_t ipv4addr = sa4->sin_addr.s_addr; + + if (ioctl(s, SIOCGIFFLAGS, item) < 0) + { + OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno)); + continue; + } + int16_t flags = item->ifr_flags; + if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING)) + { + continue; + } + if (ioctl(s, SIOCGIFINDEX, item) < 0) + { + OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno)); + continue; + } + + int ifindex = item->ifr_ifindex; + caglobals.ip.nm.ifItems[i].ifIndex = ifindex; + caglobals.ip.nm.numIfItems++; + + if (desiredIndex && (ifindex != desiredIndex)) + { + continue; + } + // Add IPv4 interface + result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags); + if (CA_STATUS_OK != result) + { + goto exit; + } + + // Add IPv6 interface + result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags); + if (CA_STATUS_OK != result) + { + goto exit; + } + } return iflist; exit: @@ -113,3 +253,131 @@ exit: return NULL; } +static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index, + const char *name, int family, uint32_t addr, int flags) +{ + CAInterface_t *ifitem = CANewInterfaceItem(index, name, family, addr, flags); + if (!ifitem) + { + return CA_STATUS_FAILED; + } + bool result = u_arraylist_add(iflist, ifitem); + if (!result) + { + OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); + OICFree(ifitem); + return CA_STATUS_FAILED; + } + + return CA_STATUS_OK; +} + +static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family, + uint32_t addr, int flags) +{ + CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t)); + if (!ifitem) + { + OIC_LOG(ERROR, TAG, "Malloc failed"); + return NULL; + } + + OICStrcpy(ifitem->name, sizeof (ifitem->name), name); + ifitem->index = index; + ifitem->family = family; + ifitem->ipv4addr = addr; + ifitem->flags = flags; + + return ifitem; +} + +CAResult_t CAIPJniInit() +{ + OIC_LOG(DEBUG, TAG, "CAIPJniInit_IN"); + + JavaVM *jvm = CANativeJNIGetJavaVM(); + if (!jvm) + { + OIC_LOG(ERROR, TAG, "Could not get JavaVM pointer"); + return CA_STATUS_FAILED; + } + + jobject context = CANativeJNIGetContext(); + if (!context) + { + OIC_LOG(ERROR, TAG, "unable to get application context"); + return CA_STATUS_FAILED; + } + + JNIEnv* env; + if ((*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK) + { + OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer"); + return CA_STATUS_FAILED; + } + + jclass cls_Context = (*env)->FindClass(env, "android/content/Context"); + if (!cls_Context) + { + OIC_LOG(ERROR, TAG, "Could not get context object class"); + return CA_STATUS_FAILED; + } + + jmethodID mid_getApplicationContext = (*env)->GetMethodID(env, cls_Context, + "getApplicationContext", + "()Landroid/content/Context;"); + if (!mid_getApplicationContext) + { + OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method"); + return CA_STATUS_FAILED; + } + + jobject jApplicationContext = (*env)->CallObjectMethod(env, context, + mid_getApplicationContext); + if (!jApplicationContext) + { + OIC_LOG(ERROR, TAG, "Could not get application context"); + return CA_STATUS_FAILED; + } + + jclass cls_CaIpInterface = (*env)->FindClass(env, "org/iotivity/ca/CaIpInterface"); + if (!cls_CaIpInterface) + { + OIC_LOG(ERROR, TAG, "Could not get CaIpInterface class"); + return CA_STATUS_FAILED; + } + + jmethodID mid_CaIpInterface_ctor = (*env)->GetMethodID(env, cls_CaIpInterface, "", + "(Landroid/content/Context;)V"); + if (!mid_CaIpInterface_ctor) + { + OIC_LOG(ERROR, TAG, "Could not get CaIpInterface constructor method"); + return CA_STATUS_FAILED; + } + + (*env)->NewObject(env, cls_CaIpInterface, mid_CaIpInterface_ctor, jApplicationContext); + OIC_LOG(DEBUG, TAG, "Create CaIpInterface instance, success"); + + OIC_LOG(DEBUG, TAG, "CAIPJniInit_OUT"); + return CA_STATUS_OK; +} + +JNIEXPORT void JNICALL +Java_org_iotivity_ca_CaIpInterface_caIpStateEnabled(JNIEnv *env, jclass class) +{ + (void)env; + (void)class; + OIC_LOG(DEBUG, TAG, "caIpStateEnabled"); + + CAWakeUpForChange(); +} + +JNIEXPORT void JNICALL +Java_org_iotivity_ca_CaIpInterface_caIpStateDisabled(JNIEnv *env, jclass class) +{ + (void)env; + (void)class; + OIC_LOG(DEBUG, TAG, "caIpStateDisabled"); + + CAIPGetInterfaceInformation(0); +} diff --git a/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_eth.cpp b/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_eth.cpp index 243f328..06fca45 100644 --- a/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_eth.cpp +++ b/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_eth.cpp @@ -45,6 +45,16 @@ // defined & used (as-is defined in the linux socket headers). #define AF_INET (2) +CAResult_t CAIPInitializeNetworkMonitor() +{ + return CA_STATUS_OK; +} + +CAResult_t CAIPTerminateNetworkMonitor() +{ + return CA_STATUS_OK; +} + /// Retrieves the IP address assigned to Arduino Ethernet shield void CAArduinoGetInterfaceAddress(uint32_t *address) { @@ -64,7 +74,7 @@ void CAArduinoGetInterfaceAddress(uint32_t *address) u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { - CAResult_t result; + bool result = true; u_arraylist_t *iflist = u_arraylist_create(); if (!iflist) @@ -88,7 +98,7 @@ u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) CAArduinoGetInterfaceAddress(&ifitem->ipv4addr); result = u_arraylist_add(iflist, ifitem); - if (CA_STATUS_OK != result) + if (!result) { OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); goto exit; diff --git a/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_wifi.cpp b/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_wifi.cpp index 92acb32..f35de3c 100644 --- a/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_wifi.cpp +++ b/resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_wifi.cpp @@ -46,6 +46,16 @@ // defined & used (as-is defined in the linux socket headers). #define AF_INET (2) +CAResult_t CAIPInitializeNetworkMonitor() +{ + return CA_STATUS_OK; +} + +CAResult_t CAIPTerminateNetworkMonitor() +{ + return CA_STATUS_OK; +} + /// Retrieves the IP address assigned to Arduino WiFi shield void CAArduinoGetInterfaceAddress(uint32_t *address) { @@ -68,7 +78,7 @@ void CAArduinoGetInterfaceAddress(uint32_t *address) u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { - CAResult_t result = CA_STATUS_OK; + bool result = true; u_arraylist_t *iflist = u_arraylist_create(); if (!iflist) @@ -92,7 +102,7 @@ u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) CAArduinoGetInterfaceAddress(&ifitem->ipv4addr); result = u_arraylist_add(iflist, ifitem); - if (CA_STATUS_OK != result) + if (!result) { OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); goto exit; diff --git a/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_eth.cpp b/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_eth.cpp index 099e6d3..74a51f6 100644 --- a/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_eth.cpp +++ b/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_eth.cpp @@ -194,12 +194,10 @@ void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port, OIC_LOG(DEBUG, TAG, "IN"); if (g_packetReceivedCallback) { - CAEndpoint_t ep; - strncpy(ep.addr, ipAddress, MAX_ADDR_STR_SIZE_CA); - ep.port = port; - ep.flags = CA_IPV4; - ep.adapter = CA_ADAPTER_IP; - g_packetReceivedCallback(&ep, data, dataLength); + CASecureEndpoint_t sep = + {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = CA_IPV4, .port = port}}; + OICStrcpy(sep.endpoint.addr, sizeof(sep.endpoint.addr), ipAddress); + g_packetReceivedCallback(&sep, data, dataLength); } OIC_LOG(DEBUG, TAG, "OUT"); } diff --git a/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_wifi.cpp b/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_wifi.cpp index 0086b22..d537adc 100644 --- a/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_wifi.cpp +++ b/resource/csdk/connectivity/src/ip_adapter/arduino/caipserver_wifi.cpp @@ -181,12 +181,11 @@ void CAPacketReceivedCallback(const char *ipAddress, const uint16_t port, OIC_LOG(DEBUG, TAG, "IN"); if (gPacketReceivedCallback) { - CAEndpoint_t ep; - strncpy(ep.addr, ipAddress, MAX_ADDR_STR_SIZE_CA); - ep.port = port; - ep.flags = CA_IPV4; - ep.adapter = CA_ADAPTER_IP; - gPacketReceivedCallback(&ep, data, dataLength); + CASecureEndpoint_t sep = + {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = CA_IPV4, .port = port}}; + + OICStrcpy(sep.endpoint.addr, sizeof(sep.endpoint.addr), ipAddress); + gPacketReceivedCallback(&sep, data, dataLength); OIC_LOG(DEBUG, TAG, "Notified network packet"); } OIC_LOG(DEBUG, TAG, "OUT"); diff --git a/resource/csdk/connectivity/src/ip_adapter/caipadapter.c b/resource/csdk/connectivity/src/ip_adapter/caipadapter.c index 1579c03..f2ba419 100644 --- a/resource/csdk/connectivity/src/ip_adapter/caipadapter.c +++ b/resource/csdk/connectivity/src/ip_adapter/caipadapter.c @@ -75,7 +75,7 @@ static CANetworkChangeCallback g_networkChangeCallback = NULL; */ static CAErrorHandleCallback g_errorCallback = NULL; -static void CAIPPacketReceivedCB(const CAEndpoint_t *endpoint, +static void CAIPPacketReceivedCB(const CASecureEndpoint_t *endpoint, const void *data, uint32_t dataLength); #ifdef __WITH_DTLS__ static void CAIPPacketSendCB(CAEndpoint_t *endpoint, @@ -164,19 +164,20 @@ static void CAIPPacketSendCB(CAEndpoint_t *endpoint, const void *data, uint32_t } #endif -void CAIPPacketReceivedCB(const CAEndpoint_t *endpoint, const void *data, + +void CAIPPacketReceivedCB(const CASecureEndpoint_t *sep, const void *data, uint32_t dataLength) { OIC_LOG(DEBUG, TAG, "IN"); - VERIFY_NON_NULL_VOID(endpoint, TAG, "ipAddress is NULL"); + VERIFY_NON_NULL_VOID(sep, TAG, "sep is NULL"); VERIFY_NON_NULL_VOID(data, TAG, "data is NULL"); - OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", endpoint->addr, endpoint->port); + OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", sep->endpoint.addr, sep->endpoint.port); if (g_networkPacketCallback) { - g_networkPacketCallback(endpoint, data, dataLength); + g_networkPacketCallback(sep, data, dataLength); } OIC_LOG(DEBUG, TAG, "OUT"); } @@ -239,6 +240,7 @@ static void CAInitializeIPGlobals() } caglobals.ip.ipv6enabled = flags & CA_IPV6; caglobals.ip.ipv4enabled = flags & CA_IPV4; + caglobals.ip.dualstack = caglobals.ip.ipv6enabled && caglobals.ip.ipv4enabled; } CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback, @@ -262,6 +264,7 @@ CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback, caglobals.ip.threadpool = handle; CAIPSetPacketReceiveCallback(CAIPPacketReceivedCB); + CAIPInitializeNetworkMonitor(); #ifdef __WITH_DTLS__ CAAdapterNetDtlsInit(); @@ -425,6 +428,8 @@ void CATerminateIP() { OIC_LOG(DEBUG, TAG, "IN"); + CAIPTerminateNetworkMonitor(); + #ifdef __WITH_DTLS__ CADTLSSetAdapterCallbacks(NULL, NULL, 0); #endif diff --git a/resource/csdk/connectivity/src/ip_adapter/caipserver.c b/resource/csdk/connectivity/src/ip_adapter/caipserver.c index 3568b65..6ead6a4 100644 --- a/resource/csdk/connectivity/src/ip_adapter/caipserver.c +++ b/resource/csdk/connectivity/src/ip_adapter/caipserver.c @@ -20,13 +20,6 @@ #include "caipinterface.h" -#ifndef __APPLE__ -#include -#else - #ifndef IPV6_ADD_MEMBERSHIP - #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP - #endif -#endif #include #include #include @@ -106,6 +99,7 @@ static void CAHandleNetlink(); static void CAApplyInterfaces(); static void CAFindReadyMessage(); static void CASelectReturned(fd_set *readFds, int ret); +static void CAProcessNewInterface(CAInterface_t *ifchanged); static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags); #define SET(TYPE, FDS) \ @@ -203,6 +197,11 @@ static void CASelectReturned(fd_set *readFds, int ret) } else { + CAInterface_t *ifchanged = CAFindInterfaceChange(); + if (ifchanged) + { + CAProcessNewInterface(ifchanged); + } break; } @@ -230,20 +229,20 @@ static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags) return CA_STATUS_FAILED; } - CAEndpoint_t ep = { .adapter = CA_ADAPTER_IP, - .flags = flags }; + CASecureEndpoint_t sep = + {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = flags}}; if (flags & CA_IPV6) { - ep.interface = ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id; + sep.endpoint.interface = ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id; ((struct sockaddr_in6 *)&srcAddr)->sin6_scope_id = 0; } - CAConvertAddrToName(&srcAddr, ep.addr, &ep.port); + CAConvertAddrToName(&srcAddr, sep.endpoint.addr, &sep.endpoint.port); if (flags & CA_SECURE) { #ifdef __WITH_DTLS__ - int ret = CAAdapterNetDtlsDecrypt(&ep, (uint8_t *)recvBuffer, recvLen); + int ret = CAAdapterNetDtlsDecrypt(&sep, (uint8_t *)recvBuffer, recvLen); OIC_LOG_V(DEBUG, TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret); #else OIC_LOG(ERROR, TAG, "Encrypted message but no DTLS"); @@ -253,7 +252,7 @@ static CAResult_t CAReceiveMessage(int fd, CATransportFlags_t flags) { if (g_packetReceivedCallback) { - g_packetReceivedCallback(&ep, recvBuffer, recvLen); + g_packetReceivedCallback(&sep, recvBuffer, recvLen); } } @@ -473,6 +472,8 @@ CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool) // create source of network interface change notifications CAInitializeNetlink(); + caglobals.ip.selectTimeout = CAGetPollingInterval(caglobals.ip.selectTimeout); + CAApplyInterfaces(); caglobals.ip.terminate = false; @@ -507,6 +508,14 @@ void CAIPStopServer() OIC_LOG(DEBUG, TAG, "OUT"); } +void CAWakeUpForChange() +{ + if (caglobals.ip.shutdownFds[1] != -1) + { + write(caglobals.ip.shutdownFds[1], "w", 1); + } +} + static void applyMulticastToInterface4(struct in_addr inaddr) { if (!caglobals.ip.ipv4enabled) @@ -537,7 +546,7 @@ static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t interface) struct ipv6_mreq mreq; mreq.ipv6mr_multiaddr = *addr; mreq.ipv6mr_interface = interface; - if (setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof (mreq))) + if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof (mreq))) { if (EADDRINUSE != errno) { @@ -609,74 +618,81 @@ static void CAApplyInterfaces() u_arraylist_destroy(iflist); } +static void CAProcessNewInterface(CAInterface_t *ifitem) +{ + applyMulticastToInterface6(ifitem->index); + struct in_addr inaddr; + inaddr.s_addr = ifitem->ipv4addr; + applyMulticastToInterface4(inaddr); +} + static void CAHandleNetlink() { #ifdef __linux__ char buf[4096]; struct nlmsghdr *nh; struct sockaddr_nl sa; - struct iovec iov = { buf, sizeof(buf) }; - struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 }; + struct iovec iov = { buf, sizeof (buf) }; + struct msghdr msg = { (void *)&sa, sizeof (sa), &iov, 1, NULL, 0, 0 }; size_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0); for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { - if (nh->nlmsg_type == RTM_NEWLINK) + if (nh->nlmsg_type != RTM_NEWLINK) { - struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh); - if ((ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING)) - { - continue; - } + continue; + } + + struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(nh); + if (!ifi || (ifi->ifi_flags & IFF_LOOPBACK) || !(ifi->ifi_flags & IFF_RUNNING)) + { + continue; + } - int newIndex = ifi->ifi_index; + int newIndex = ifi->ifi_index; - u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex); - if (!iflist) + u_arraylist_t *iflist = CAIPGetInterfaceInformation(newIndex); + if (!iflist) + { + OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); + return; + } + + uint32_t listLength = u_arraylist_length(iflist); + for (uint32_t i = 0; i < listLength; i++) + { + CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); + if (!ifitem) { - OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno)); - return; + continue; } - uint32_t listLength = u_arraylist_length(iflist); - for (uint32_t i = 0; i < listLength; i++) + if ((int)ifitem->index != newIndex) { - CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i); - if (!ifitem) - { - continue; - } - - if ((int)ifitem->index != newIndex) - { - continue; - } - - applyMulticastToInterface6(newIndex); - struct in_addr inaddr; - inaddr.s_addr = ifitem->ipv4addr; - applyMulticastToInterface4(inaddr); - break; // we found the one we were looking for + continue; } - u_arraylist_destroy(iflist); + + CAProcessNewInterface(ifitem); + break; // we found the one we were looking for } + u_arraylist_destroy(iflist); } #endif // __linux__ } void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback) { -OIC_LOG(DEBUG, TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); -g_packetReceivedCallback = callback; + g_packetReceivedCallback = callback; -OIC_LOG(DEBUG, TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "OUT"); } void CAIPSetExceptionCallback(CAIPExceptionCallback callback) { -OIC_LOG(DEBUG, TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); g_exceptionCallback = callback; diff --git a/resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c b/resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c index a5fb789..fd889ee 100644 --- a/resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c +++ b/resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c @@ -36,6 +36,26 @@ #define TAG "IP_MONITOR" +CAResult_t CAIPInitializeNetworkMonitor() +{ + return CA_STATUS_OK; +} + +CAResult_t CAIPTerminateNetworkMonitor() +{ + return CA_STATUS_OK; +} + +int CAGetPollingInterval(int interval) +{ + return interval; +} + +CAInterface_t *CAFindInterfaceChange() +{ + return NULL; +} + u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { if (desiredIndex < 0) @@ -111,8 +131,8 @@ u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) ifitem->ipv4addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr; ifitem->flags = ifa->ifa_flags; - CAResult_t result = u_arraylist_add(iflist, ifitem); - if (CA_STATUS_OK != result) + bool result = u_arraylist_add(iflist, ifitem); + if (!result) { OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); goto exit; diff --git a/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c b/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c index 90e200f..b81b357 100644 --- a/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c +++ b/resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c @@ -36,6 +36,26 @@ #define TAG "IP_MONITOR" +CAResult_t CAIPInitializeNetworkMonitor() +{ + return CA_STATUS_OK; +} + +CAResult_t CAIPTerminateNetworkMonitor() +{ + return CA_STATUS_OK; +} + +int CAGetPollingInterval(int interval) +{ + return interval; +} + +CAInterface_t *CAFindInterfaceChange() +{ + return NULL; +} + u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) { u_arraylist_t *iflist = u_arraylist_create(); @@ -92,8 +112,8 @@ u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex) ifitem->ipv4addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr; ifitem->flags = ifa->ifa_flags; - CAResult_t result = u_arraylist_add(iflist, ifitem); - if (CA_STATUS_OK != result) + bool result = u_arraylist_add(iflist, ifitem); + if (!result) { OIC_LOG(ERROR, TAG, "u_arraylist_add failed."); goto exit; diff --git a/resource/csdk/doc/CCF Lite GIT Repo Layout.docx b/resource/csdk/doc/CCF Lite GIT Repo Layout.docx deleted file mode 100644 index 0020cc5c13b3572de951647038f81e9047061c30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 127908 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'=I3%wXZ-m9 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%0A8y8dOSpR=Zo8ntpY>&RjP^DPe7 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%0DDM7#Bf5Y%yebQ|HQbAIGW6kB+i65xaG@y&N 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 W4GSKj;Ef9SPZT`Jr7nMS&;JMRI}B?8 diff --git a/resource/csdk/security/src/secureresourcemanager.c b/resource/csdk/security/src/secureresourcemanager.c index ddccc55..48e7bfc 100644 --- a/resource/csdk/security/src/secureresourcemanager.c +++ b/resource/csdk/security/src/secureresourcemanager.c @@ -73,7 +73,7 @@ void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requ // Copy the subjectID OicUuid_t subjectId = {.id = {0}}; - memcpy(subjectId.id, endPoint->identity.id, sizeof(subjectId.id)); + memcpy(subjectId.id, requestInfo->info.identity.id, sizeof(subjectId.id)); //Check the URI has the query and skip it before checking the permission char *uri = strstr(requestInfo->info.resourceUri, "?"); diff --git a/resource/csdk/stack/include/octypes.h b/resource/csdk/stack/include/octypes.h index 5f602ff..839fd73 100644 --- a/resource/csdk/stack/include/octypes.h +++ b/resource/csdk/stack/include/octypes.h @@ -377,17 +377,15 @@ typedef struct /** transport modifiers.*/ OCTransportFlags flags; + /** for IP.*/ + uint16_t port; + /** address for all adapters.*/ char addr[MAX_ADDR_STR_SIZE]; /** usually zero for default interface.*/ uint32_t interface; - /** for IP.*/ - uint16_t port; - - /** secure node identity.*/ - OCIdentity identity; } OCDevAddr; /** @@ -1029,6 +1027,9 @@ typedef struct /** backward compatibility.*/ OCConnectivityType connType; + /** the security identity of the remote server.*/ + OCIdentity identity; + /** the is the result of our stack, OCStackResult should contain coap/other error codes.*/ OCStackResult result; diff --git a/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript b/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript index bc37c05..5b551bb 100644 --- a/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript +++ b/resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript @@ -20,6 +20,11 @@ Import('env') +transport = env.get('TARGET_TRANSPORT') +if 'BLE' in transport: + # Only supported for ethernet and WiFi. + Return() + arduino_simplecs_env = env.Clone() ###################################################################### # Build flags diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp index 533436a..5faaccd 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp @@ -32,27 +32,21 @@ #include "payload_logging.h" // Tracking user input -static int UNICAST_DISCOVERY = 0; -static int TEST_CASE = 0; -static int CONNECTIVITY = 0; +static int UnicastDiscovery = 0; +static int TestCase = 0; +static int Connectivity = 0; -static const char * UNICAST_DEVICE_DISCOVERY_QUERY = "coap://%s/oic/d"; -static const char * MULTICAST_DEVICE_DISCOVERY_QUERY = "/oic/d"; -static const char * UNICAST_PLATFORM_DISCOVERY_QUERY = "coap://%s/oic/p"; -static const char * MULTICAST_PLATFORM_DISCOVERY_QUERY = "/oic/p"; +static const char *DEVICE_DISCOVERY_QUERY = "%s/oic/d"; +static const char *PLATFORM_DISCOVERY_QUERY = "%s/oic/p"; +static const char *RESOURCE_DISCOVERY_QUERY = "%s/oic/res"; -static const char * UNICAST_RESOURCE_DISCOVERY_QUERY = "coap://%s/oic/res"; -static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oic/res"; //The following variable determines the interface protocol (IPv4, IPv6, etc) -//to be used for sending unicast messages. Default set to IPv4. -static OCConnectivityType OC_CONNTYPE = CT_ADAPTER_IP; -static std::string coapServerIP = "255.255.255.255"; -static std::string coapServerPort = "5683"; +//to be used for sending unicast messages. Default set to IP dual stack. +static OCConnectivityType ConnType = CT_ADAPTER_IP; +static OCDevAddr serverAddr; +static char discoveryAddr[100]; static std::string coapServerResource = "/a/light"; -// Size to hold IPV4_ADDRESS:PORT -static const int IPV4_ADDR_SIZE = 24; -//Use ipv4addr for both InitDiscovery and InitPlatformOrDeviceDiscovery -char ipv4addr[IPV4_ADDR_SIZE]; + void StripNewLineChar(char* str); // The handle for the observe registration @@ -82,7 +76,7 @@ OCPayload* putPayload() { OCRepPayload* payload = OCRepPayloadCreate(); - if(!payload) + if (!payload) { std::cout << "Failed to create put payload object"<result)); OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload); @@ -194,12 +189,12 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle /*handle*/, OCStackApplicationResult postReqCB(void *ctx, OCDoHandle /*handle*/, OCClientResponse *clientResponse) { - if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + if (ctx == (void*)DEFAULT_CONTEXT_VALUE) { OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully"); } - if(clientResponse) + if (clientResponse) { OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload); @@ -216,12 +211,12 @@ OCStackApplicationResult deleteReqCB(void *ctx, OCDoHandle /*handle*/, OCClientResponse *clientResponse) { - if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + if (ctx == (void*)DEFAULT_CONTEXT_VALUE) { OC_LOG(INFO, TAG, "Callback Context for DELETE recvd successfully"); } - if(clientResponse) + if (clientResponse) { OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload); @@ -237,13 +232,13 @@ OCStackApplicationResult deleteReqCB(void *ctx, OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/, OCClientResponse * clientResponse) { - if(clientResponse == NULL) + if (clientResponse == NULL) { OC_LOG(INFO, TAG, "getReqCB received NULL clientResponse"); return OC_STACK_DELETE_TRANSACTION; } - if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + if (ctx == (void*)DEFAULT_CONTEXT_VALUE) { OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully"); } @@ -253,14 +248,14 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/, OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload); OC_LOG(INFO, TAG, PCF("=============> Get Response")); - if(clientResponse->numRcvdVendorSpecificHeaderOptions > 0) + if (clientResponse->numRcvdVendorSpecificHeaderOptions > 0) { OC_LOG (INFO, TAG, "Received vendor specific options"); uint8_t i = 0; OCHeaderOption * rcvdOptions = clientResponse->rcvdVendorSpecificHeaderOptions; for( i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++) { - if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID) + if (((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID) { OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with", ((OCHeaderOption)rcvdOptions[i]).optionID ); @@ -276,12 +271,12 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/, OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle /*handle*/, OCClientResponse * clientResponse) { - if(ctx == (void*)DEFAULT_CONTEXT_VALUE) + if (ctx == (void*)DEFAULT_CONTEXT_VALUE) { OC_LOG(INFO, TAG, "Callback Context for OBS query recvd successfully"); } - if(clientResponse) + if (clientResponse) { OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber); @@ -292,7 +287,7 @@ OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle /*handle*/, gNumObserveNotifies++; if (gNumObserveNotifies == 15) //large number to test observing in DELETE case. { - if(TEST_CASE == TEST_OBS_REQ_NON || TEST_CASE == TEST_OBS_REQ_CON) + if (TestCase == TEST_OBS_REQ_NON || TestCase == TEST_OBS_REQ_CON) { if (OCCancel (gObserveDoHandle, OC_LOW_QOS, NULL, 0) != OC_STACK_OK) { @@ -300,7 +295,7 @@ OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle /*handle*/, } return OC_STACK_DELETE_TRANSACTION; } - else if(TEST_CASE == TEST_OBS_REQ_NON_CANCEL_IMM) + else if (TestCase == TEST_OBS_REQ_NON_CANCEL_IMM) { if (OCCancel (gObserveDoHandle, OC_HIGH_QOS, NULL, 0) != OC_STACK_OK) { @@ -308,16 +303,16 @@ OCStackApplicationResult obsReqCB(void* ctx, OCDoHandle /*handle*/, } } } - if(clientResponse->sequenceNumber == OC_OBSERVE_REGISTER) + if (clientResponse->sequenceNumber == OC_OBSERVE_REGISTER) { OC_LOG(INFO, TAG, "This also serves as a registration confirmation"); } - else if(clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER) + else if (clientResponse->sequenceNumber == OC_OBSERVE_DEREGISTER) { OC_LOG(INFO, TAG, "This also serves as a deregistration confirmation"); return OC_STACK_DELETE_TRANSACTION; } - else if(clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION) + else if (clientResponse->sequenceNumber == OC_OBSERVE_NO_OPTION) { OC_LOG(INFO, TAG, "This also tells you that registration/deregistration failed"); return OC_STACK_DELETE_TRANSACTION; @@ -341,7 +336,6 @@ OCStackApplicationResult presenceCB(void* ctx, OCDoHandle /*handle*/, if (clientResponse) { OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result)); - OC_LOG_V(INFO, TAG, "NONCE NUMBER: %u", clientResponse->sequenceNumber); OC_LOG_V(INFO, TAG, "Callback Context for Presence notification recvd successfully %d", gNumPresenceNotifies); OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload); @@ -366,7 +360,7 @@ OCStackApplicationResult presenceCB(void* ctx, OCDoHandle /*handle*/, // This is a function called back when a device is discovered OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/, - OCClientResponse * clientResponse) + OCClientResponse * clientResponse) { if (ctx == (void*) DEFAULT_CONTEXT_VALUE) { @@ -385,10 +379,11 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/, clientResponse->devAddr.port); OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload); - OC_CONNTYPE = clientResponse->connType; + ConnType = clientResponse->connType; + serverAddr = clientResponse->devAddr; parseClientResponse(clientResponse); - switch(TEST_CASE) + switch(TestCase) { case TEST_GET_REQ_NON: InitGetRequest(OC_LOW_QOS, 0, 0); @@ -453,16 +448,16 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/, return OC_STACK_KEEP_TRANSACTION; } -OCStackApplicationResult PlatformDiscoveryReqCB (void* ctx, - OCDoHandle /*handle*/, - OCClientResponse * clientResponse) +OCStackApplicationResult PlatformDiscoveryReqCB(void* ctx, + OCDoHandle /*handle*/, + OCClientResponse * clientResponse) { if (ctx == (void*) DEFAULT_CONTEXT_VALUE) { OC_LOG(INFO, TAG, "Callback Context for Platform DISCOVER query recvd successfully"); } - if(clientResponse) + if (clientResponse) { OC_LOG(INFO, TAG, PCF("Discovery Response:")); OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload); @@ -472,18 +467,18 @@ OCStackApplicationResult PlatformDiscoveryReqCB (void* ctx, OC_LOG_V(INFO, TAG, "PlatformDiscoveryReqCB received Null clientResponse"); } - return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION; + return (UnicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION; } -OCStackApplicationResult DeviceDiscoveryReqCB (void* ctx, OCDoHandle /*handle*/, - OCClientResponse * clientResponse) +OCStackApplicationResult DeviceDiscoveryReqCB(void* ctx, OCDoHandle /*handle*/, + OCClientResponse * clientResponse) { if (ctx == (void*) DEFAULT_CONTEXT_VALUE) { OC_LOG(INFO, TAG, "Callback Context for Device DISCOVER query recvd successfully"); } - if(clientResponse) + if (clientResponse) { OC_LOG(INFO, TAG, PCF("Discovery Response:")); OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload); @@ -493,7 +488,7 @@ OCStackApplicationResult DeviceDiscoveryReqCB (void* ctx, OCDoHandle /*handle*/, OC_LOG_V(INFO, TAG, "PlatformDiscoveryReqCB received Null clientResponse"); } - return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION; + return (UnicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION; } #ifdef WITH_PRESENCE @@ -503,37 +498,37 @@ int InitPresence() OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); std::ostringstream query; std::ostringstream querySuffix; - query << "coap://" << coapServerIP << ":" << coapServerPort << OC_RSRVD_PRESENCE_URI; - if(TEST_CASE == TEST_OBS_PRESENCE) + query << OC_RSRVD_PRESENCE_URI; + if (TestCase == TEST_OBS_PRESENCE) { - result = InvokeOCDoResource(query, OC_REST_PRESENCE, OC_LOW_QOS, - presenceCB, NULL, 0); + result = InvokeOCDoResource(query, &serverAddr, OC_REST_PRESENCE, + OC_LOW_QOS, presenceCB, NULL, 0); } - if(TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTER || TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTERS) + if (TestCase == TEST_OBS_PRESENCE_WITH_FILTER || TestCase == TEST_OBS_PRESENCE_WITH_FILTERS) { querySuffix.str(""); querySuffix << query.str() << "?rt=core.led"; - result = InvokeOCDoResource(querySuffix, OC_REST_PRESENCE, OC_LOW_QOS, - presenceCB, NULL, 0); + result = InvokeOCDoResource(querySuffix, &serverAddr, OC_REST_PRESENCE, + OC_LOW_QOS, presenceCB, NULL, 0); } - if(TEST_CASE == TEST_OBS_PRESENCE_WITH_FILTERS) + if (TestCase == TEST_OBS_PRESENCE_WITH_FILTERS) { - if(result == OC_STACK_OK) + if (result == OC_STACK_OK) { querySuffix.str(""); querySuffix << query.str() << "?rt=core.fan"; - result = InvokeOCDoResource(querySuffix, OC_REST_PRESENCE, OC_LOW_QOS, + result = InvokeOCDoResource(querySuffix, &serverAddr, OC_REST_PRESENCE, OC_LOW_QOS, presenceCB, NULL, 0); } } - if(TEST_CASE == TEST_OBS_MULTICAST_PRESENCE) + if (TestCase == TEST_OBS_MULTICAST_PRESENCE) { - if(result == OC_STACK_OK) + if (result == OC_STACK_OK) { std::ostringstream multicastPresenceQuery; multicastPresenceQuery.str(""); multicastPresenceQuery << "coap://" << OC_MULTICAST_PREFIX << OC_RSRVD_PRESENCE_URI; - result = InvokeOCDoResource(multicastPresenceQuery, OC_REST_PRESENCE, OC_LOW_QOS, + result = InvokeOCDoResource(multicastPresenceQuery, &serverAddr, OC_REST_PRESENCE, OC_LOW_QOS, presenceCB, NULL, 0); } } @@ -545,8 +540,8 @@ int InitGetRequestToUnavailableResource(OCQualityOfService qos) { OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); std::ostringstream query; - query << "coap://" << coapServerIP << ":" << coapServerPort << "/SomeUnknownResource"; - return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, + query << "/SomeUnknownResource"; + return (InvokeOCDoResource(query, &serverAddr, OC_REST_GET, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0)); } @@ -554,17 +549,17 @@ int InitObserveRequest(OCQualityOfService qos) { OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); std::ostringstream query; - query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; - return (InvokeOCDoResource(query, - OC_REST_OBSERVE, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, obsReqCB, NULL, 0)); + query << coapServerResource; + return (InvokeOCDoResource(query, &serverAddr, OC_REST_OBSERVE, + (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, obsReqCB, NULL, 0)); } int InitPutRequest(OCQualityOfService qos) { OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); std::ostringstream query; - query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; - return (InvokeOCDoResource(query, OC_REST_PUT, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, + query << coapServerResource; + return (InvokeOCDoResource(query, &serverAddr, OC_REST_PUT, (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, putReqCB, NULL, 0)); } @@ -573,10 +568,10 @@ int InitPostRequest(OCQualityOfService qos) OCStackResult result; OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); std::ostringstream query; - query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + query << coapServerResource; // First POST operation (to create an Light instance) - result = InvokeOCDoResource(query, OC_REST_POST, + result = InvokeOCDoResource(query, &serverAddr, OC_REST_POST, ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), postReqCB, NULL, 0); if (OC_STACK_OK != result) @@ -586,7 +581,7 @@ int InitPostRequest(OCQualityOfService qos) } // Second POST operation (to create an Light instance) - result = InvokeOCDoResource(query, OC_REST_POST, + result = InvokeOCDoResource(query, &serverAddr, OC_REST_POST, ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), postReqCB, NULL, 0); if (OC_STACK_OK != result) @@ -595,7 +590,7 @@ int InitPostRequest(OCQualityOfService qos) } // This POST operation will update the original resourced /a/light - return (InvokeOCDoResource(query, OC_REST_POST, + return (InvokeOCDoResource(query, &serverAddr, OC_REST_POST, ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), postReqCB, NULL, 0)); } @@ -604,7 +599,7 @@ void* RequestDeleteDeathResourceTask(void* myqos) { sleep (30);//long enough to give the server time to finish deleting the resource. std::ostringstream query; - query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + query << coapServerResource; OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); @@ -619,7 +614,7 @@ void* RequestDeleteDeathResourceTask(void* myqos) qos = OC_HIGH_QOS; } - OCStackResult result = InvokeOCDoResource(query, OC_REST_DELETE, + OCStackResult result = InvokeOCDoResource(query, &serverAddr, OC_REST_DELETE, qos, deleteReqCB, NULL, 0); @@ -635,12 +630,12 @@ int InitDeleteRequest(OCQualityOfService qos) { OCStackResult result; std::ostringstream query; - query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + query << coapServerResource; OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); // First DELETE operation - result = InvokeOCDoResource(query, OC_REST_DELETE, + result = InvokeOCDoResource(query, &serverAddr, OC_REST_DELETE, qos, deleteReqCB, NULL, 0); if (OC_STACK_OK != result) @@ -666,7 +661,7 @@ int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptio OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); std::ostringstream query; - query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + query << coapServerResource; // ocserver is written to only process "power= MAX_TESTS) || - (CONNECTIVITY < CT_ADAPTER_DEFAULT || CONNECTIVITY >= MAX_CT)) + if ((UnicastDiscovery != 0 && UnicastDiscovery != 1) || + (TestCase < TEST_DISCOVER_REQ || TestCase >= MAX_TESTS) || + (Connectivity < CT_ADAPTER_DEFAULT || Connectivity >= MAX_CT)) { PrintUsage(); return -1; } - /* Initialize OCStack*/ - if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK) + if (OCInit1(OC_CLIENT, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS) != OC_STACK_OK) { OC_LOG(ERROR, TAG, "OCStack init error"); return 0; } - if(CONNECTIVITY == CT_ADAPTER_DEFAULT || CONNECTIVITY == CT_IP) + if (Connectivity == CT_ADAPTER_DEFAULT || Connectivity == CT_IP) { - OC_CONNTYPE = CT_ADAPTER_IP; + ConnType = CT_ADAPTER_IP; } else { @@ -868,28 +815,31 @@ int main(int argc, char* argv[]) PrintUsage(); } - if (UNICAST_DISCOVERY) + discoveryAddr[0] = '\0'; + + if (UnicastDiscovery) { - OC_LOG(INFO, TAG, "Enter IP address with port number of the Server hosting resource"); - OC_LOG(INFO, TAG, "as follows - eg: 192.168.0.15:45454 (IP:Port) \n"); + OC_LOG(INFO, TAG, "Enter IP address of server with optional port number"); + OC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n"); + OC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n"); - if (fgets(ipv4addr, IPV4_ADDR_SIZE, stdin)) + if (fgets(discoveryAddr, sizeof (discoveryAddr), stdin)) { //Strip newline char from ipv4addr - StripNewLineChar(ipv4addr); + StripNewLineChar(discoveryAddr); } else { - OC_LOG(ERROR, TAG, "!! Bad input for IPV4 address. !!"); + OC_LOG(ERROR, TAG, "!! Bad input for IP address. !!"); return OC_STACK_INVALID_PARAM; } } - if(UNICAST_DISCOVERY == 0 && TEST_CASE == TEST_DISCOVER_DEV_REQ) + if (UnicastDiscovery == 0 && TestCase == TEST_DISCOVER_DEV_REQ) { InitDeviceDiscovery(OC_LOW_QOS); } - else if(UNICAST_DISCOVERY == 0 && TEST_CASE == TEST_DISCOVER_PLATFORM_REQ) + else if (UnicastDiscovery == 0 && TestCase == TEST_DISCOVER_PLATFORM_REQ) { InitPlatformDiscovery(OC_LOW_QOS); } @@ -922,35 +872,6 @@ int main(int argc, char* argv[]) return 0; } -std::string getIPAddrTBServer(OCClientResponse * clientResponse) -{ - if (!clientResponse) - { - return ""; - } - if (!clientResponse->addr) - { - return ""; - } - - return std::string(clientResponse->devAddr.addr); -} - -std::string getPortTBServer(OCClientResponse * clientResponse) -{ - if (!clientResponse) - { - return ""; - } - if (!clientResponse->addr) - { - return ""; - } - std::ostringstream ss; - ss << clientResponse->devAddr.port; - return ss.str(); -} - std::string getConnectivityType (OCConnectivityType connType) { switch (connType & CT_MASK_ADAPTER) @@ -977,13 +898,10 @@ std::string getConnectivityType (OCConnectivityType connType) std::string getQueryStrForGetPut(OCClientResponse * /*clientResponse*/) { - return "/a/light"; } void parseClientResponse(OCClientResponse * clientResponse) { - coapServerIP = getIPAddrTBServer(clientResponse); - coapServerPort = getPortTBServer(clientResponse); coapServerResource = getQueryStrForGetPut(clientResponse); } diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp index ce00796..e2a4a69 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp @@ -37,17 +37,14 @@ #define MAX_IP_ADDR_ST_SZ 16 //string size of "155.255.255.255" (15 + 1) #define MAX_PORT_ST_SZ 6 //string size of "65535" (5 + 1) -static int IPV4_ADDR_SIZE = 24; -static int UNICAST_DISCOVERY = 0; -static int TEST_CASE = 0; -static int CONNECTIVITY = 0; - -static const char UNICAST_DISCOVERY_QUERY[] = "coap://%s/oic/res"; +static int UnicastDiscovery = 0; +static int TestCase = 0; +static int Connectivity = 0; //The following variable determines the interface protocol (IP, etc) //to be used for sending unicast messages. Default set to IP. -static OCConnectivityType OC_CONNTYPE = CT_ADAPTER_IP; -static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oic/res"; +static OCConnectivityType ConnType = CT_ADAPTER_IP; +static const char *RESOURCE_DISCOVERY_QUERY = "%s/oic/res"; int gQuitFlag = 0; @@ -100,9 +97,12 @@ const ResourceNode * getResource() return resourceList; } -OCStackResult InvokeOCDoResource(std::ostringstream &query, OCMethod method, - OCConnectivityType connType, OCQualityOfService qos, - OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions) +OCStackResult InvokeOCDoResource(std::ostringstream &query, + OCMethod method, + const OCDevAddr *dest, + OCQualityOfService qos, + OCClientResponseHandler cb, + OCHeaderOption * options, uint8_t numOptions) { OCStackResult ret; OCCallbackData cbData; @@ -111,9 +111,9 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query, OCMethod method, cbData.context = (void*)DEFAULT_CONTEXT_VALUE; cbData.cd = NULL; - ret = OCDoResource(NULL, method, query.str().c_str(), 0, + ret = OCDoResource(NULL, method, query.str().c_str(), dest, (method == OC_REST_PUT || method == OC_REST_POST) ? putPayload() : NULL, - connType, qos, &cbData, options, numOptions); + CT_DEFAULT, qos, &cbData, options, numOptions); if (ret != OC_STACK_OK) { @@ -125,7 +125,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query, OCMethod method, } OCStackApplicationResult putReqCB(void* ctx, OCDoHandle /*handle*/, - OCClientResponse * clientResponse) + OCClientResponse * clientResponse) { if(ctx == (void*)DEFAULT_CONTEXT_VALUE) { @@ -149,7 +149,7 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle /*handle*/, } OCStackApplicationResult postReqCB(void *ctx, OCDoHandle /*handle*/, - OCClientResponse *clientResponse) + OCClientResponse *clientResponse) { if(ctx == (void*)DEFAULT_CONTEXT_VALUE) { @@ -174,7 +174,7 @@ OCStackApplicationResult postReqCB(void *ctx, OCDoHandle /*handle*/, } OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/, - OCClientResponse * clientResponse) + OCClientResponse * clientResponse) { if (ctx == (void*) DEFAULT_CONTEXT_VALUE) { @@ -221,7 +221,7 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/, * This is a function called back when a device is discovered */ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/, - OCClientResponse * clientResponse) + OCClientResponse * clientResponse) { if (ctx == (void*)DEFAULT_CONTEXT_VALUE) { @@ -247,7 +247,7 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/, { OC_LOG(ERROR, TAG, "<====DISCOVERY Callback fail to receive clientResponse====>\n"); } - return (UNICAST_DISCOVERY) ? + return (UnicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ; } @@ -262,10 +262,10 @@ int InitPutRequest(OCQualityOfService qos) OC_LOG_V(ERROR, TAG, "Resource null, can't do PUT request\n"); return -1; } - query << "coap://" << resource->ip << ":" << resource->port << resource->uri ; + query << resource->uri; OC_LOG_V(INFO, TAG,"Executing InitPutRequest, Query: %s", query.str().c_str()); - return (InvokeOCDoResource(query, OC_REST_PUT, resource->connType, + return (InvokeOCDoResource(query, OC_REST_PUT, &resource->endpoint, ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), putReqCB, NULL, 0)); } @@ -275,7 +275,7 @@ int InitPostRequest(OCQualityOfService qos) OCStackResult result; std::ostringstream query; //Get most recently inserted resource - const ResourceNode * resource = getResource(); + const ResourceNode *resource = getResource(); if(!resource) { @@ -283,11 +283,11 @@ int InitPostRequest(OCQualityOfService qos) return -1; } - query << "coap://" << resource->ip << ":" << resource->port << resource->uri ; + query << resource->uri; OC_LOG_V(INFO, TAG,"Executing InitPostRequest, Query: %s", query.str().c_str()); // First POST operation (to create an LED instance) - result = InvokeOCDoResource(query, OC_REST_POST, resource->connType, + result = InvokeOCDoResource(query, OC_REST_POST, &resource->endpoint, ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), postReqCB, NULL, 0); if (OC_STACK_OK != result) @@ -297,7 +297,7 @@ int InitPostRequest(OCQualityOfService qos) } // Second POST operation (to create an LED instance) - result = InvokeOCDoResource(query, OC_REST_POST, resource->connType, + result = InvokeOCDoResource(query, OC_REST_POST, &resource->endpoint, ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), postReqCB, NULL, 0); if (OC_STACK_OK != result) @@ -306,7 +306,7 @@ int InitPostRequest(OCQualityOfService qos) } // This POST operation will update the original resourced /a/led - return (InvokeOCDoResource(query, OC_REST_POST,resource->connType, + return (InvokeOCDoResource(query, OC_REST_POST, &resource->endpoint, ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), postReqCB, NULL, 0)); } @@ -322,10 +322,10 @@ int InitGetRequest(OCQualityOfService qos) OC_LOG_V(ERROR, TAG, "Resource null, can't do GET request\n"); return -1; } - query << "coap://" << resource->ip << ":" << resource->port << resource->uri ; + query << resource->uri; OC_LOG_V(INFO, TAG,"Executing InitGetRequest, Query: %s", query.str().c_str()); - return (InvokeOCDoResource(query, OC_REST_GET, resource->connType, + return (InvokeOCDoResource(query, OC_REST_GET, &resource->endpoint, (qos == OC_HIGH_QOS)?OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0)); } @@ -333,44 +333,34 @@ int InitDiscovery() { OCStackResult ret; OCCallbackData cbData; - /* Start a discovery query*/ - char szQueryUri[64] = {}; - if (UNICAST_DISCOVERY) + char queryUri[200]; + char ipaddr[100] = { '\0' }; + + if (UnicastDiscovery) { - char ipv4addr[IPV4_ADDR_SIZE]; - OC_LOG(INFO, TAG, "Enter IP address with port of the Server hosting resource"\ - "(Ex: 192.168.0.15:1234) "); + OC_LOG(INFO, TAG, "Enter IP address (with optional port) of the Server hosting resource\n"); + OC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n"); + OC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n"); - if (fgets(ipv4addr, IPV4_ADDR_SIZE, stdin)) + if (fgets(ipaddr, sizeof (ipaddr), stdin)) { - //Strip newline char from ipv4addr - StripNewLineChar(ipv4addr); - snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_DISCOVERY_QUERY, ipv4addr); + StripNewLineChar(ipaddr); //Strip newline char from ipaddr } else { - OC_LOG(ERROR, TAG, "!! Bad input for IPV4 address. !!"); + OC_LOG(ERROR, TAG, "!! Bad input for IP address. !!"); return OC_STACK_INVALID_PARAM; } } - else - { - OICStrcpy(szQueryUri, sizeof(szQueryUri), MULTICAST_RESOURCE_DISCOVERY_QUERY); - } + + snprintf(queryUri, sizeof (queryUri), RESOURCE_DISCOVERY_QUERY, ipaddr); + cbData.cb = discoveryReqCB; cbData.context = (void*)DEFAULT_CONTEXT_VALUE; cbData.cd = NULL; - if (UNICAST_DISCOVERY) - { - ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE, - OC_LOW_QOS, &cbData, NULL, 0); - } - else - { - ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, CT_DEFAULT, - OC_LOW_QOS, &cbData, NULL, 0); - } + ret = OCDoResource(NULL, OC_REST_DISCOVER, queryUri, 0, 0, CT_DEFAULT, + OC_LOW_QOS, &cbData, NULL, 0); if (ret != OC_STACK_OK) { OC_LOG(ERROR, TAG, "OCStack resource error"); @@ -378,48 +368,9 @@ int InitDiscovery() return ret; } -const char *getIPAddr(const OCClientResponse *clientResponse) -{ - if (!clientResponse) - { - return ""; - } - - const OCDevAddr *devAddr = &clientResponse->devAddr; - char *ipaddr = (char *) OICCalloc(1, strlen(devAddr->addr) +1); - if (ipaddr) - { - snprintf(ipaddr, MAX_IP_ADDR_ST_SZ, "%s", devAddr->addr); - } - else - { - OC_LOG(ERROR, TAG, "Memory not allocated to ipaddr"); - } - return ipaddr; -} - -const char *getPort(const OCClientResponse *clientResponse) -{ - if(!clientResponse) - { - return ""; - } - - char *port = NULL; - if((port = (char *)OICCalloc(1, MAX_PORT_ST_SZ))) - { - snprintf(port, MAX_PORT_ST_SZ, "%d", clientResponse->devAddr.port); - } - else - { - OC_LOG(ERROR, TAG, "Memory not allocated to port"); - } - return port; -} - void queryResource() { - switch(TEST_CASE) + switch(TestCase) { case TEST_DISCOVER_REQ: break; @@ -507,9 +458,7 @@ int insertResource(const char * sid, char const * uri, { iter->sid = sid_cpy; iter->uri = uri_cpy; - iter->ip = getIPAddr(clientResponse); - iter->port = getPort(clientResponse); - iter->connType = clientResponse->connType; + iter->endpoint = clientResponse->devAddr; iter->next = NULL; } else @@ -543,9 +492,9 @@ void printResourceList() OC_LOG(INFO, TAG, "*****************************************************"); OC_LOG_V(INFO, TAG, "sid = %s",iter->sid); OC_LOG_V(INFO, TAG, "uri = %s", iter->uri); - OC_LOG_V(INFO, TAG, "ip = %s", iter->ip); - OC_LOG_V(INFO, TAG, "port = %s", iter->port); - switch (iter->connType & CT_MASK_ADAPTER) + OC_LOG_V(INFO, TAG, "ip = %s", iter->endpoint.addr); + OC_LOG_V(INFO, TAG, "port = %d", iter->endpoint.port); + switch (iter->endpoint.adapter) { case OC_ADAPTER_IP: OC_LOG(INFO, TAG, "connType = Default (IPv4)"); @@ -576,8 +525,6 @@ void freeResourceList() resourceList = resourceList->next; OICFree((void *)temp->sid); OICFree((void *)temp->uri); - OICFree((void *)temp->ip); - OICFree((void *)temp->port); OICFree(temp); } resourceList = NULL; @@ -592,14 +539,13 @@ int main(int argc, char* argv[]) switch(opt) { case 'u': - UNICAST_DISCOVERY = atoi(optarg); + UnicastDiscovery = atoi(optarg); break; case 't': - TEST_CASE = atoi(optarg); + TestCase = atoi(optarg); break; case 'c': - - CONNECTIVITY = atoi(optarg); + Connectivity = atoi(optarg); break; default: PrintUsage(); @@ -607,24 +553,24 @@ int main(int argc, char* argv[]) } } - if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) || - (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) || - (CONNECTIVITY < CT_ADAPTER_DEFAULT || CONNECTIVITY >= MAX_CT)) + if ((UnicastDiscovery != 0 && UnicastDiscovery != 1) || + (TestCase < TEST_DISCOVER_REQ || TestCase >= MAX_TESTS) || + (Connectivity < CT_ADAPTER_DEFAULT || Connectivity >= MAX_CT)) { PrintUsage(); return -1; } /* Initialize OCStack*/ - if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK) + if (OCInit1(OC_CLIENT, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS) != OC_STACK_OK) { OC_LOG(ERROR, TAG, "OCStack init error"); return 0; } - if(CONNECTIVITY == CT_ADAPTER_DEFAULT || CONNECTIVITY == CT_IP) + if(Connectivity == CT_ADAPTER_DEFAULT || Connectivity == CT_IP) { - OC_CONNTYPE = CT_ADAPTER_IP;//CT_DEFAULT; + ConnType = CT_ADAPTER_IP;//CT_DEFAULT; } else { diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.h b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.h index 012a11a..15c0dfd 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.h +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.h @@ -28,9 +28,6 @@ //----------------------------------------------------------------------------- #define TAG "occlientbasicops" #define DEFAULT_CONTEXT_VALUE 0x99 -#ifndef MAX_LENGTH_IPv4_ADDR -#define MAX_LENGTH_IPv4_ADDR 16 -#endif //----------------------------------------------------------------------------- // Typedefs @@ -63,9 +60,7 @@ struct ResourceNode { const char * sid; const char * uri; - const char * ip; - const char * port; - OCConnectivityType connType; + OCDevAddr endpoint; ResourceNode * next; }; @@ -76,12 +71,6 @@ struct ResourceNode /* call getResult in common.cpp to get the result in string format. */ const char *getResult(OCStackResult result); -/* Get the IP address of the server */ -const char * getIPAddr(const OCClientResponse * clientResponse); - -/* Get the port number the server is listening on */ -const char * getPort(const OCClientResponse * clientResponse); - /* Performs GET/PUT/POST query on most recently discovered resource*/ void queryResource(); @@ -132,7 +121,7 @@ void parseClientResponse(OCClientResponse * clientResponse); * to the lower layers */ OCStackResult InvokeOCDoResource(std::ostringstream &query, - OCMethod method, OCQualityOfService qos, + OCMethod method, OCDevAddr *dest, OCQualityOfService qos, OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions); /* diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp index 23392f9..c023c26 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp @@ -30,8 +30,6 @@ #include "payload_logging.h" #include "logger.h" const char *getResult(OCStackResult result); -std::string getIPAddrTBServer(OCClientResponse * clientResponse); -std::string getPortTBServer(OCClientResponse * clientResponse); std::string getQueryStrForGetPut(); #define TAG PCF("occlient") @@ -63,10 +61,10 @@ typedef enum { CT_ADAPTER_DEFAULT = 0, CT_IP, MAX_CT -} CLIENT_CONNECTIVITY_TYPE; +} CLIENT_ConnectivityType_TYPE; -unsigned static int TEST = TEST_INVALID; -unsigned static int CONNECTIVITY = 0; +unsigned static int TestType = TEST_INVALID; +unsigned static int ConnectivityType = 0; typedef struct { @@ -90,8 +88,8 @@ testToTextMap queryInterface[] = { //The following variable determines the interface protocol (IP, etc) //to be used for sending unicast messages. Default set to IP. -static OCConnectivityType OC_CONNTYPE = CT_ADAPTER_IP; -static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oic/res"; +static OCConnectivityType ConnType = CT_ADAPTER_IP; +static const char * RESOURCE_DISCOVERY_QUERY = "/oic/res"; // The handle for the observe registration OCDoHandle gObserveDoHandle; @@ -202,17 +200,16 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle /*handle*/, } } } - if(TEST == TEST_PUT_DEFAULT || TEST == TEST_PUT_BATCH || TEST == TEST_PUT_LINK_LIST) + if(TestType == TEST_PUT_DEFAULT || TestType == TEST_PUT_BATCH || TestType == TEST_PUT_LINK_LIST) { InitPutRequest(clientResponse); } return OC_STACK_KEEP_TRANSACTION; } - // This is a function called back when a device is discovered OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/, - OCClientResponse * clientResponse) + OCClientResponse * clientResponse) { OC_LOG(INFO, TAG, "Entering discoveryReqCB (Application Layer CB)"); @@ -230,10 +227,10 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle /*handle*/, clientResponse->devAddr.port); OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload); - OC_CONNTYPE = clientResponse->connType; + ConnType = clientResponse->connType; - if(TEST == TEST_UNKNOWN_RESOURCE_GET_DEFAULT || TEST == TEST_UNKNOWN_RESOURCE_GET_BATCH ||\ - TEST == TEST_UNKNOWN_RESOURCE_GET_LINK_LIST) + if(TestType == TEST_UNKNOWN_RESOURCE_GET_DEFAULT || TestType == TEST_UNKNOWN_RESOURCE_GET_BATCH ||\ + TestType == TEST_UNKNOWN_RESOURCE_GET_LINK_LIST) { InitGetRequestToUnavailableResource(clientResponse); } @@ -250,14 +247,14 @@ int InitGetRequestToUnavailableResource(OCClientResponse * clientResponse) OCStackResult ret; OCCallbackData cbData; std::ostringstream getQuery; - getQuery << "coap://" << clientResponse->devAddr.addr << ":" << - clientResponse->devAddr.port << "/SomeUnknownResource"; + getQuery << "/SomeUnknownResource"; cbData.cb = getReqCB; cbData.context = (void*)DEFAULT_CONTEXT_VALUE; cbData.cd = NULL; - ret = OCDoResource(NULL, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_CONNTYPE, OC_LOW_QOS, - &cbData, NULL, 0); + ret = OCDoResource(NULL, OC_REST_GET, getQuery.str().c_str(), + &clientResponse->devAddr, 0, ConnType, OC_LOW_QOS, + &cbData, NULL, 0); if (ret != OC_STACK_OK) { OC_LOG(ERROR, TAG, "OCStack resource error"); @@ -272,9 +269,7 @@ int InitObserveRequest(OCClientResponse * clientResponse) OCCallbackData cbData; OCDoHandle handle; std::ostringstream obsReg; - obsReg << "coap://" << clientResponse->devAddr.addr << ":" << - clientResponse->devAddr.addr << - getQueryStrForGetPut(); + obsReg << getQueryStrForGetPut(); cbData.cb = getReqCB; cbData.context = (void*)DEFAULT_CONTEXT_VALUE; cbData.cd = NULL; @@ -283,8 +278,9 @@ int InitObserveRequest(OCClientResponse * clientResponse) OC_LOG_PAYLOAD(INFO, TAG, payload); OCPayloadDestroy(payload); - ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(), 0, 0, OC_CONNTYPE, - OC_LOW_QOS, &cbData, NULL, 0); + ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(), + &clientResponse->devAddr, 0, ConnType, + OC_LOW_QOS, &cbData, NULL, 0); if (ret != OC_STACK_OK) { OC_LOG(ERROR, TAG, "OCStack resource error"); @@ -305,7 +301,7 @@ int InitPutRequest(OCClientResponse * clientResponse) std::ostringstream getQuery; getQuery << "coap://" << clientResponse->devAddr.addr << ":" << clientResponse->devAddr.port << - "/a/room" << queryInterface[TEST].text; + "/a/room" << queryInterface[TestType].text; cbData.cb = putReqCB; cbData.context = (void*)DEFAULT_CONTEXT_VALUE; cbData.cd = NULL; @@ -314,8 +310,9 @@ int InitPutRequest(OCClientResponse * clientResponse) OC_LOG_PAYLOAD(INFO, TAG, payload); OCPayloadDestroy(payload); - ret = OCDoResource(NULL, OC_REST_PUT, getQuery.str().c_str(), 0, putPayload(), - OC_CONNTYPE, OC_LOW_QOS, &cbData, NULL, 0); + ret = OCDoResource(NULL, OC_REST_PUT, getQuery.str().c_str(), + &clientResponse->devAddr, putPayload(), ConnType, + OC_LOW_QOS, &cbData, NULL, 0); if (ret != OC_STACK_OK) { OC_LOG(ERROR, TAG, "OCStack resource error"); @@ -331,18 +328,16 @@ int InitGetRequest(OCClientResponse * clientResponse) //* Make a GET query*/ std::ostringstream getQuery; - getQuery << "coap://" << clientResponse->devAddr.addr << ":" << - clientResponse->devAddr.port << - "/a/room" << queryInterface[TEST].text; + getQuery << "/a/room" << queryInterface[TestType].text; std::cout << "Get Query: " << getQuery.str() << std::endl; cbData.cb = getReqCB; cbData.context = (void*)DEFAULT_CONTEXT_VALUE; cbData.cd = NULL; - ret = OCDoResource(NULL, OC_REST_GET, - getQuery.str().c_str(), 0, 0, OC_CONNTYPE, OC_LOW_QOS, - &cbData, NULL, 0); + ret = OCDoResource(NULL, OC_REST_GET, getQuery.str().c_str(), + &clientResponse->devAddr, 0, ConnType, OC_LOW_QOS, + &cbData, NULL, 0); if (ret != OC_STACK_OK) { OC_LOG(ERROR, TAG, "OCStack resource error"); @@ -357,12 +352,12 @@ int InitDiscovery() /* Start a discovery query*/ char szQueryUri[64] = { 0 }; - strcpy(szQueryUri, MULTICAST_RESOURCE_DISCOVERY_QUERY); + strcpy(szQueryUri, RESOURCE_DISCOVERY_QUERY); cbData.cb = discoveryReqCB; cbData.context = (void*)DEFAULT_CONTEXT_VALUE; cbData.cd = NULL; - ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, OC_CONNTYPE, + ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, NULL, 0, ConnType, OC_LOW_QOS, &cbData, NULL, 0); if (ret != OC_STACK_OK) @@ -381,18 +376,18 @@ int main(int argc, char* argv[]) switch (opt) { case 't': - TEST = atoi(optarg); + TestType = atoi(optarg); break; case 'c': - CONNECTIVITY = atoi(optarg); + ConnectivityType = atoi(optarg); break; default: PrintUsage(); return -1; } } - if ((TEST <= TEST_INVALID || TEST >= MAX_TESTS) || - CONNECTIVITY >= MAX_CT) + if ((TestType <= TEST_INVALID || TestType >= MAX_TESTS) || + ConnectivityType >= MAX_CT) { PrintUsage(); return -1; @@ -405,14 +400,14 @@ int main(int argc, char* argv[]) return 0; } - if(CONNECTIVITY == CT_ADAPTER_DEFAULT || CONNECTIVITY == CT_IP) + if(ConnectivityType == CT_ADAPTER_DEFAULT || ConnectivityType == CT_IP) { - OC_CONNTYPE = CT_ADAPTER_IP; + ConnType = CT_ADAPTER_IP; } else { OC_LOG(INFO, TAG, "Default Connectivity type selected..."); - OC_CONNTYPE = CT_ADAPTER_IP; + ConnType = CT_ADAPTER_IP; } InitDiscovery(); diff --git a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp index abf0e52..8b98b52 100644 --- a/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp +++ b/resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp @@ -33,20 +33,17 @@ #include "payload_logging.h" // Tracking user input -static int UNICAST_DISCOVERY = 0; -static int TEST_CASE = 0; -static int CONNECTIVITY = 0; +static int UnicastDiscovery = 0; +static int TestCase = 0; +static int ConnectivityType = 0; -static const char * UNICAST_DISCOVERY_QUERY = "coap://%s/oic/res"; -static std::string coapServerIP = "255.255.255.255"; -static uint16_t coapServerPort = 5683; static std::string coapServerResource = "/a/led"; //The following variable determines the interface protocol (IP, etc) //to be used for sending unicast messages. Default set to IP. -static OCConnectivityType OC_CONNTYPE = CT_ADAPTER_IP; -static const char * MULTICAST_RESOURCE_DISCOVERY_QUERY = "/oic/res"; -static int IPV4_ADDR_SIZE = 24; +static OCConnectivityType AdapterType = CT_ADAPTER_IP; +static OCDevAddr endpoint; +static const char *RESOURCE_DISCOVERY_QUERY = "%s/oic/res"; void StripNewLineChar(char* str); int gQuitFlag = 0; @@ -62,7 +59,7 @@ void handleSigInt(int signum) static void PrintUsage() { - OC_LOG(INFO, TAG, "Usage : occlient -c <0|1|2> -u <0|1> -t <1|2|3>"); + OC_LOG(INFO, TAG, "Usage : occlient -c <0|1> -u <0|1> -t <1|2|3>"); OC_LOG(INFO, TAG, "-c 0 : Default auto-selection"); OC_LOG(INFO, TAG, "-c 1 : IP Connectivity Type"); OC_LOG(INFO, TAG, "-u <0|1> : Perform multicast/unicast discovery of resources"); @@ -90,7 +87,7 @@ OCPayload* putPayload() } OCStackResult InvokeOCDoResource(std::ostringstream &query, - OCMethod method, OCQualityOfService qos, + OCMethod method, OCDevAddr *dest, OCQualityOfService qos, OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions) { OCStackResult ret; @@ -100,9 +97,9 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query, cbData.context = (void*)DEFAULT_CONTEXT_VALUE; cbData.cd = NULL; - ret = OCDoResource(NULL, method, query.str().c_str(), 0, + ret = OCDoResource(NULL, method, query.str().c_str(), dest, (method == OC_REST_PUT) ? putPayload() : NULL, - OC_CONNTYPE, qos, &cbData, options, numOptions); + AdapterType, qos, &cbData, options, numOptions); if (ret != OC_STACK_OK) { @@ -167,9 +164,9 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, clientResponse->devAddr.addr, clientResponse->devAddr.port); OC_LOG_PAYLOAD (INFO, TAG, clientResponse->payload); - parseClientResponse(clientResponse); + endpoint = clientResponse->devAddr; - switch(TEST_CASE) + switch(TestCase) { case TEST_NON_CON_OP: InitGetRequest(OC_LOW_QOS); @@ -189,7 +186,7 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, } } - return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ; + return UnicastDiscovery ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ; } @@ -197,62 +194,56 @@ int InitGetRequest(OCQualityOfService qos) { OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); std::ostringstream query; - query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + query << coapServerResource; OC_LOG_V (INFO, TAG, "Performing GET with query : %s", query.str().c_str()); - return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)? - OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0)); + return (InvokeOCDoResource(query, OC_REST_GET, &endpoint, + (qos == OC_HIGH_QOS)? OC_HIGH_QOS : OC_LOW_QOS, + getReqCB, NULL, 0)); } int InitPutRequest(OCQualityOfService qos) { OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); std::ostringstream query; - query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource; + query << coapServerResource; OC_LOG_V (INFO, TAG, "Performing PUT with query : %s", query.str().c_str()); - return (InvokeOCDoResource(query, OC_REST_PUT, (qos == OC_HIGH_QOS)? - OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0)); + return (InvokeOCDoResource(query, OC_REST_PUT, &endpoint, + (qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS, + getReqCB, NULL, 0)); } int InitDiscovery() { OCStackResult ret; OCCallbackData cbData; - /* Start a discovery query*/ - char szQueryUri[64] = { 0 }; - if (UNICAST_DISCOVERY) + char queryUri[200]; + char ipaddr[100] = { '\0' }; + + if (UnicastDiscovery) { - char ipv4addr[IPV4_ADDR_SIZE]; - OC_LOG(INFO, TAG, "Enter IPv4:port of the Server hosting resource"\ - "(Ex: 192.168.0.15:1234)"); - if (fgets(ipv4addr, IPV4_ADDR_SIZE, stdin)) + OC_LOG(INFO, TAG, "Enter IP address (with optional port) of the Server hosting resource\n"); + OC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n"); + OC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n"); + + if (fgets(ipaddr, sizeof (ipaddr), stdin)) { - //Strip newline char from ipv4addr - StripNewLineChar(ipv4addr); - snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_DISCOVERY_QUERY, ipv4addr); + StripNewLineChar(ipaddr); //Strip newline char from ipaddr } else { - OC_LOG(ERROR, TAG, "!! Bad input for IPV4 address. !!"); + OC_LOG(ERROR, TAG, "!! Bad input for IP address. !!"); return OC_STACK_INVALID_PARAM; } } - else - { - OICStrcpy(szQueryUri, sizeof(szQueryUri), MULTICAST_RESOURCE_DISCOVERY_QUERY); - } + + snprintf(queryUri, sizeof (queryUri), RESOURCE_DISCOVERY_QUERY, ipaddr); + cbData.cb = discoveryReqCB; cbData.context = (void*)DEFAULT_CONTEXT_VALUE; cbData.cd = NULL; - if(UNICAST_DISCOVERY) - { - ret = OCDoResource(NULL, OC_REST_GET, szQueryUri, 0, 0, OC_CONNTYPE, - OC_LOW_QOS, &cbData, NULL, 0); - } - else - { - ret = OCDoResource(NULL, OC_REST_DISCOVER, szQueryUri, 0, 0, CT_DEFAULT, - OC_LOW_QOS, &cbData, NULL, 0); - } + + ret = OCDoResource(NULL, OC_REST_DISCOVER, queryUri, 0, 0, CT_DEFAULT, + OC_LOW_QOS, &cbData, NULL, 0); if (ret != OC_STACK_OK) { OC_LOG(ERROR, TAG, "OCStack resource error"); @@ -269,13 +260,13 @@ int main(int argc, char* argv[]) switch(opt) { case 'u': - UNICAST_DISCOVERY = atoi(optarg); + UnicastDiscovery = atoi(optarg); break; case 't': - TEST_CASE = atoi(optarg); + TestCase = atoi(optarg); break; case 'c': - CONNECTIVITY = atoi(optarg); + ConnectivityType = atoi(optarg); break; default: PrintUsage(); @@ -283,9 +274,9 @@ int main(int argc, char* argv[]) } } - if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) || - (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS) || - (CONNECTIVITY < CT_ADAPTER_DEFAULT || CONNECTIVITY >= MAX_CT)) + if ((UnicastDiscovery != 0 && UnicastDiscovery != 1) || + (TestCase < TEST_DISCOVER_REQ || TestCase >= MAX_TESTS) || + (ConnectivityType < CT_ADAPTER_DEFAULT || ConnectivityType >= MAX_CT)) { PrintUsage(); return -1; @@ -298,14 +289,14 @@ int main(int argc, char* argv[]) return 0; } - if(CONNECTIVITY == CT_ADAPTER_DEFAULT || CONNECTIVITY == CT_IP) + if(ConnectivityType == CT_ADAPTER_DEFAULT || ConnectivityType == CT_IP) { - OC_CONNTYPE = CT_ADAPTER_IP; + AdapterType = CT_ADAPTER_IP; } else { OC_LOG(INFO, TAG, "Default Connectivity type selected..."); - OC_CONNTYPE = CT_ADAPTER_IP; + AdapterType = CT_ADAPTER_IP; } InitDiscovery(); @@ -338,10 +329,3 @@ std::string getQueryStrForGetPut(OCClientResponse * clientResponse) return "/a/led"; } -void parseClientResponse(OCClientResponse * clientResponse) -{ - coapServerIP = clientResponse->devAddr.addr; - coapServerPort = clientResponse->devAddr.port; - coapServerResource = getQueryStrForGetPut(clientResponse); -} - diff --git a/resource/csdk/stack/samples/linux/secure/occlientbasicops.cpp b/resource/csdk/stack/samples/linux/secure/occlientbasicops.cpp index b375da1..41a9b66 100644 --- a/resource/csdk/stack/samples/linux/secure/occlientbasicops.cpp +++ b/resource/csdk/stack/samples/linux/secure/occlientbasicops.cpp @@ -34,22 +34,18 @@ #include "common.h" #define TAG "occlientbasicops" -static int UNICAST_DISCOVERY = 0; -static int TEST_CASE = 0; -static int CONN_TYPE = 0; +static int UnicastDiscovery = 0; +static int TestCase = 0; +static int ConnType = 0; -static int IPV4_ADDR_SIZE = 24; -static char UNICAST_DISCOVERY_QUERY[] = "coap://%s/oic/res"; -static char MULTICAST_DISCOVERY_QUERY[] = "/oic/res"; +static char DISCOVERY_QUERY[] = "%s/oic/res"; OCConnectivityType discoveryReqConnType = CT_ADAPTER_IP; +static OCDevAddr endpoint; -static std::string coapServerIP; -static std::string coapServerPort; static std::string coapServerResource; static int coapSecureResource; static OCConnectivityType ocConnType; - //Secure Virtual Resource database for Iotivity Client application //It contains Client's Identity and the PSK credentials //of other devices which the client trusts @@ -92,12 +88,15 @@ static void PrintUsage() " Initiate Nonconfirmable Get/Put/Post Requests"); OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Confirmable Get/Put/Post Requests"); OC_LOG(INFO, TAG, "-c 0 : Default auto-selection"); - OC_LOG(INFO, TAG, "-c 1 : IPv4 Connectivity Type"); + OC_LOG(INFO, TAG, "-c 1 : IP Connectivity Type"); } OCStackResult InvokeOCDoResource(std::ostringstream &query, - OCMethod method, OCQualityOfService qos, - OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions) + OCMethod method, + const OCDevAddr *dest, + OCQualityOfService qos, + OCClientResponseHandler cb, + OCHeaderOption * options, uint8_t numOptions) { OCStackResult ret; OCCallbackData cbData; @@ -106,7 +105,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query, cbData.context = NULL; cbData.cd = NULL; - ret = OCDoResource(NULL, method, query.str().c_str(), 0, + ret = OCDoResource(NULL, method, query.str().c_str(), dest, (method == OC_REST_PUT || method == OC_REST_POST) ? putPayload() : NULL, ocConnType, qos, &cbData, options, numOptions); @@ -118,7 +117,7 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query, return ret; } -OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) +OCStackApplicationResult putReqCB(void*, OCDoHandle, OCClientResponse * clientResponse) { OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully"); @@ -131,7 +130,7 @@ OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse return OC_STACK_DELETE_TRANSACTION; } -OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse) +OCStackApplicationResult postReqCB(void *, OCDoHandle, OCClientResponse *clientResponse) { OC_LOG(INFO, TAG, "Callback Context for POST recvd successfully"); @@ -144,7 +143,7 @@ OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientRespons return OC_STACK_DELETE_TRANSACTION; } -OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) +OCStackApplicationResult getReqCB(void*, OCDoHandle, OCClientResponse * clientResponse) { OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully"); @@ -159,7 +158,7 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse } // This is a function called back when a device is discovered -OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, +OCStackApplicationResult discoveryReqCB(void*, OCDoHandle, OCClientResponse * clientResponse) { OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully"); @@ -177,10 +176,11 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload); ocConnType = clientResponse->connType; + endpoint = clientResponse->devAddr; if (parseClientResponse(clientResponse) != -1) { - switch(TEST_CASE) + switch(TestCase) { case TEST_NON_CON_OP: InitGetRequest(OC_LOW_QOS); @@ -197,7 +197,7 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, } } - return (UNICAST_DISCOVERY) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ; + return (UnicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ; } @@ -205,9 +205,9 @@ int InitPutRequest(OCQualityOfService qos) { OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); std::ostringstream query; - query << (coapSecureResource ? "coaps://" : "coap://") << coapServerIP - << ":" << coapServerPort << coapServerResource; - return (InvokeOCDoResource(query, OC_REST_PUT, + query << coapServerResource; + endpoint.flags = (OCTransportFlags)(endpoint.flags|OC_SECURE); + return (InvokeOCDoResource(query, OC_REST_PUT, &endpoint, ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), putReqCB, NULL, 0)); } @@ -216,11 +216,11 @@ int InitPostRequest(OCQualityOfService qos) OCStackResult result; OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); std::ostringstream query; - query << (coapSecureResource ? "coaps://" : "coap://") << coapServerIP - << ":" << coapServerPort << coapServerResource; + query << coapServerResource; + endpoint.flags = (OCTransportFlags)(endpoint.flags|OC_SECURE); // First POST operation (to create an LED instance) - result = InvokeOCDoResource(query, OC_REST_POST, + result = InvokeOCDoResource(query, OC_REST_POST, &endpoint, ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), postReqCB, NULL, 0); if (OC_STACK_OK != result) @@ -230,7 +230,7 @@ int InitPostRequest(OCQualityOfService qos) } // Second POST operation (to create an LED instance) - result = InvokeOCDoResource(query, OC_REST_POST, + result = InvokeOCDoResource(query, OC_REST_POST, &endpoint, ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), postReqCB, NULL, 0); if (OC_STACK_OK != result) @@ -239,7 +239,7 @@ int InitPostRequest(OCQualityOfService qos) } // This POST operation will update the original resourced /a/led - return (InvokeOCDoResource(query, OC_REST_POST, + return (InvokeOCDoResource(query, OC_REST_POST, &endpoint, ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS: OC_LOW_QOS), postReqCB, NULL, 0)); } @@ -248,45 +248,38 @@ int InitGetRequest(OCQualityOfService qos) { OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__); std::ostringstream query; - query << (coapSecureResource ? "coaps://" : "coap://") << coapServerIP - << ":" << coapServerPort << coapServerResource; + query << coapServerResource; + endpoint.flags = (OCTransportFlags)(endpoint.flags|OC_SECURE); - return (InvokeOCDoResource(query, OC_REST_GET, (qos == OC_HIGH_QOS)? - OC_HIGH_QOS:OC_LOW_QOS, getReqCB, NULL, 0)); + return (InvokeOCDoResource(query, OC_REST_GET, &endpoint, + ((qos == OC_HIGH_QOS)? OC_HIGH_QOS:OC_LOW_QOS), + getReqCB, NULL, 0)); } int InitDiscovery() { OCStackResult ret; - OCMethod method; OCCallbackData cbData; - char szQueryUri[MAX_URI_LENGTH] = { 0 }; + char queryUri[200]; + char ipaddr[100] = { '\0' }; - if (UNICAST_DISCOVERY) + if (UnicastDiscovery) { - char ipv4addr[IPV4_ADDR_SIZE]; - OC_LOG(INFO, TAG, "Enter IPv4 address:port of the Server hosting secure resource"\ - "(Ex: 11.12.13.14:1234)\n"); - if (fgets(ipv4addr, IPV4_ADDR_SIZE, stdin)) + OC_LOG(INFO, TAG, "Enter IP address (with optional port) of the Server hosting resource\n"); + OC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n"); + OC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n"); + + if (fgets(ipaddr, sizeof (ipaddr), stdin)) { - //Strip newline char from ipv4addr - StripNewLineChar(ipv4addr); - snprintf(szQueryUri, sizeof(szQueryUri), UNICAST_DISCOVERY_QUERY, ipv4addr); + StripNewLineChar(ipaddr); //Strip newline char from ipaddr } else { - OC_LOG(ERROR, TAG, "!! Bad input for IPV4 address. !!"); + OC_LOG(ERROR, TAG, "!! Bad input for IP address. !!"); return OC_STACK_INVALID_PARAM; } - method = OC_REST_GET; - } - else - { - //Send discovery request on Wifi and Ethernet interface - discoveryReqConnType = CT_DEFAULT; - OICStrcpy(szQueryUri, sizeof(szQueryUri), MULTICAST_DISCOVERY_QUERY); - method = OC_REST_DISCOVER; } + snprintf(queryUri, sizeof (queryUri), DISCOVERY_QUERY, ipaddr); cbData.cb = discoveryReqCB; cbData.context = NULL; @@ -294,12 +287,11 @@ int InitDiscovery() /* Start a discovery query*/ OC_LOG_V(INFO, TAG, "Initiating %s Resource Discovery : %s\n", - (UNICAST_DISCOVERY) ? "Unicast" : "Multicast", - szQueryUri); + (UnicastDiscovery) ? "Unicast" : "Multicast", + queryUri); - ret = OCDoResource(NULL, method, szQueryUri, 0, 0, - discoveryReqConnType, OC_LOW_QOS, - &cbData, NULL, 0); + ret = OCDoResource(NULL, OC_REST_DISCOVER, queryUri, 0, 0, CT_DEFAULT, + OC_LOW_QOS, &cbData, NULL, 0); if (ret != OC_STACK_OK) { OC_LOG(ERROR, TAG, "OCStack resource error"); @@ -323,13 +315,13 @@ int main(int argc, char* argv[]) switch(opt) { case 'u': - UNICAST_DISCOVERY = atoi(optarg); + UnicastDiscovery = atoi(optarg); break; case 't': - TEST_CASE = atoi(optarg); + TestCase = atoi(optarg); break; case 'c': - CONN_TYPE = atoi(optarg); + ConnType = atoi(optarg); break; default: PrintUsage(); @@ -337,16 +329,16 @@ int main(int argc, char* argv[]) } } - if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) || - (TEST_CASE < TEST_DISCOVER_REQ || TEST_CASE >= MAX_TESTS)|| - (CONN_TYPE < CT_ADAPTER_DEFAULT || CONN_TYPE >= MAX_CT)) + if ((UnicastDiscovery != 0 && UnicastDiscovery != 1) || + (TestCase < TEST_DISCOVER_REQ || TestCase >= MAX_TESTS)|| + (ConnType < CT_ADAPTER_DEFAULT || ConnType >= MAX_CT)) { PrintUsage(); return -1; } - if(CONN_TYPE == CT_ADAPTER_DEFAULT || CONN_TYPE == CT_IP) + if(ConnType == CT_ADAPTER_DEFAULT || ConnType == CT_IP) { discoveryReqConnType = CT_DEFAULT; } @@ -358,12 +350,7 @@ int main(int argc, char* argv[]) // Initialize Persistent Storage for SVR database - OCPersistentStorage ps = {}; - ps.open = client_fopen; - ps.read = fread; - ps.write = fwrite; - ps.close = fclose; - ps.unlink = unlink; + OCPersistentStorage ps = { client_fopen, fread, fwrite, fclose, unlink }; OCRegisterPersistentStorageHandler(&ps); /* Initialize OCStack*/ @@ -401,41 +388,27 @@ int main(int argc, char* argv[]) return 0; } -std::string getPortTBServer(OCClientResponse * clientResponse) -{ - if(!clientResponse) return ""; - std::ostringstream ss; - ss << clientResponse->devAddr.port; - return ss.str(); -} - int parseClientResponse(OCClientResponse * clientResponse) { OCResourcePayload* res = ((OCDiscoveryPayload*)clientResponse->payload)->resources; // Initialize all global variables coapServerResource.clear(); - coapServerPort.clear(); - coapServerIP.clear(); coapSecureResource = 0; - while(res) + while (res) { coapServerResource.assign(res->uri); OC_LOG_V(INFO, TAG, "Uri -- %s", coapServerResource.c_str()); - if(res->secure) + if (res->secure) { + endpoint.port = res->port; coapSecureResource = 1; } OC_LOG_V(INFO, TAG, "Secure -- %s", coapSecureResource == 1 ? "YES" : "NO"); - std::ostringstream ss; - ss << res->port; - coapServerPort = ss.str(); - std::cout<<"PORT: "<next; } - coapServerIP = clientResponse->devAddr.addr; - - if(coapServerPort.length() == 0 || coapServerPort == "0") - { - coapServerPort = getPortTBServer(clientResponse); - OC_LOG_V(INFO, TAG, "Hosting Server Port -- %s", coapServerPort.c_str()); - } - return 0; } diff --git a/resource/csdk/stack/src/ocpayloadconvert.c b/resource/csdk/stack/src/ocpayloadconvert.c index d72c136..a95c618 100644 --- a/resource/csdk/stack/src/ocpayloadconvert.c +++ b/resource/csdk/stack/src/ocpayloadconvert.c @@ -19,6 +19,7 @@ //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #include "ocpayloadcbor.h" +#include "platform_features.h" #include #include "oic_malloc.h" #include "logger.h" @@ -28,29 +29,104 @@ #include "cbor.h" #define TAG PCF("OCPayloadConvert") +// Arbitrarily chosen size that seems to contain the majority of packages +#define INIT_SIZE (255) -static OCStackResult OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t** outPayload, +// Functions all return either a CborError, or a negative version of the OC_STACK return values +static int64_t OCConvertPayloadHelper(OCPayload* payload, uint8_t* outPayload, size_t* size); +static int64_t OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t* outPayload, size_t* size); -static OCStackResult OCConvertDevicePayload(OCDevicePayload* payload, uint8_t** outPayload, +static int64_t OCConvertDevicePayload(OCDevicePayload* payload, uint8_t* outPayload, size_t* size); -static OCStackResult OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t** outPayload, +static int64_t OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t* outPayload, size_t* size); -static OCStackResult OCConvertRepPayload(OCRepPayload* payload, uint8_t** outPayload, size_t* size); -static OCStackResult OCConvertPresencePayload(OCPresencePayload* payload, uint8_t** outPayload, +static int64_t OCConvertRepPayload(OCRepPayload* payload, uint8_t* outPayload, size_t* size); +static int64_t OCConvertPresencePayload(OCPresencePayload* payload, uint8_t* outPayload, size_t* size); -static OCStackResult OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t** outPayload, +static int64_t OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t* outPayload, size_t* size); +static int64_t OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload); +static int64_t OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* valArray); -bool AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen, +static int64_t AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen, const char* value); -bool ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen, +static int64_t ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen, const char* value); +#define STRINGIFY(s) XSTRINGIFY(s) +#define XSTRINGIFY(s) #s OCStackResult OCConvertPayload(OCPayload* payload, uint8_t** outPayload, size_t* size) { + // TinyCbor Version 47a78569c0 or better on master is required for the re-allocation + // strategy to work. If you receive the following assertion error, please do a git-pull + // from the extlibs/tinycbor/tinycbor directory + #define CborNeedsUpdating (CborErrorOutOfMemory < CborErrorDataTooLarge) + OC_STATIC_ASSERT(!CborNeedsUpdating, "tinycbor needs to be updated to at least 47a78569c0"); + #undef CborNeedsUpdating + if (!payload) + { + OC_LOG(ERROR, TAG, PCF("Payload parameter NULL")); + return OC_STACK_INVALID_PARAM; + } + + if (!outPayload || !size) + { + OC_LOG(ERROR, TAG, PCF("Out parameter/s parameter NULL")); + return OC_STACK_INVALID_PARAM; + } + OC_LOG_V(INFO, TAG, "Converting payload of type %d", payload->type); + + size_t curSize = INIT_SIZE; + uint8_t* out = (uint8_t*)OICCalloc(1, curSize); + int64_t err = OCConvertPayloadHelper(payload, out, &curSize); + + if (err == CborErrorOutOfMemory) + { + // reallocate "out" and try again! + uint8_t* out2 = (uint8_t*)OICRealloc(out, curSize); + + if (!out2) + { + OICFree(out); + return OC_STACK_NO_MEMORY; + } + + out = out2; + err = OCConvertPayloadHelper(payload, out, &curSize); + } + + if (err == 0) + { + if (curSize < INIT_SIZE) + { + uint8_t* out2 = (uint8_t*)OICRealloc(out, curSize); + + if (!out2) + { + OICFree(out); + return OC_STACK_NO_MEMORY; + } + } + + *size = curSize; + *outPayload = out; + return OC_STACK_OK; + } + else if (err < 0) + { + return (OCStackResult)-err; + } + else + { + return OC_STACK_ERROR; + } +} + +static int64_t OCConvertPayloadHelper(OCPayload* payload, uint8_t* outPayload, size_t* size) +{ switch(payload->type) { case PAYLOAD_TYPE_DISCOVERY: @@ -71,82 +147,66 @@ OCStackResult OCConvertPayload(OCPayload* payload, uint8_t** outPayload, size_t* } } -static OCStackResult OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t** outPayload, - size_t* size) +static int64_t checkError(int64_t err, CborEncoder* encoder, uint8_t* outPayload, size_t* size) { - *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH); - *size = MAX_REQUEST_LENGTH; - - if(!*outPayload) + if (err == CborErrorOutOfMemory) { - return OC_STACK_NO_MEMORY; + *size += encoder->ptr - encoder->end; + return err; } - + else if (err != 0) + { + OC_LOG_V(ERROR, TAG, "Convert Payload failed", err); + return err; + } + else + { + *size = encoder->ptr - outPayload; + return 0; + } +} +static int64_t OCConvertSecurityPayload(OCSecurityPayload* payload, uint8_t* outPayload, + size_t* size) +{ CborEncoder encoder; - bool err = false; + int64_t err = 0; - cbor_encoder_init(&encoder, *outPayload, *size, 0); + cbor_encoder_init(&encoder, outPayload, *size, 0); CborEncoder rootArray; - err = err || cbor_encoder_create_array(&encoder, &rootArray, 2); - err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_SECURITY); + err = err | cbor_encoder_create_array(&encoder, &rootArray, 2); + err = err | cbor_encode_uint(&rootArray, PAYLOAD_TYPE_SECURITY); CborEncoder map; - err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength); + err = err | cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength); if(payload->securityData) { - err = err || AddTextStringToMap(&map, OC_RSRVD_REPRESENTATION, + err = err | AddTextStringToMap(&map, OC_RSRVD_REPRESENTATION, sizeof(OC_RSRVD_REPRESENTATION) - 1, payload->securityData); } - err = err || cbor_encoder_close_container(&rootArray, &map); - - err = err || cbor_encoder_close_container(&encoder, &rootArray); - - if(err) - { - OC_LOG_V(ERROR, TAG, "Convert Security Payload failed", err); - OICFree(*outPayload); - return OC_STACK_ERROR; - } - - *size = encoder.ptr - *outPayload; - uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size); + err = err | cbor_encoder_close_container(&rootArray, &map); - if(!tempPayload) - { - OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!")); - OICFree(*outPayload); - return OC_STACK_ERROR; - } + err = err | cbor_encoder_close_container(&encoder, &rootArray); + return checkError(err, &encoder, outPayload, size); - *outPayload = tempPayload; - return OC_STACK_OK; } -static OCStackResult OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t** outPayload, +static int64_t OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint8_t* outPayload, size_t* size) { - *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH); - *size = MAX_REQUEST_LENGTH; - - if(!*outPayload) - { - return OC_STACK_NO_MEMORY; - } - CborEncoder encoder = {0}; - bool err = false; + int64_t err = 0; size_t resourceCount = OCDiscoveryPayloadGetResourceCount(payload); - cbor_encoder_init(&encoder, *outPayload, *size, 0); + cbor_encoder_init(&encoder, outPayload, *size, 0); CborEncoder rootArray; - err = err || cbor_encoder_create_array(&encoder, &rootArray, 1 + resourceCount); - err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DISCOVERY); + err = err | cbor_encoder_create_array(&encoder, &rootArray, 1 + resourceCount); + err = err | cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DISCOVERY); for(size_t i = 0; i < resourceCount; ++i) { @@ -155,333 +215,262 @@ static OCStackResult OCConvertDiscoveryPayload(OCDiscoveryPayload* payload, uint if(!resource) { - OICFree(*outPayload); return OC_STACK_INVALID_PARAM; } - err = err || cbor_encoder_create_map(&rootArray, &map, 3); + err = err | cbor_encoder_create_map(&rootArray, &map, 3); // Uri - err = err || AddTextStringToMap(&map, OC_RSRVD_HREF, + err = err | AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1, resource->uri); // Server ID - err = err || cbor_encode_text_string(&map, OC_RSRVD_SERVER_INSTANCE_ID, + err = err | cbor_encode_text_string(&map, OC_RSRVD_SERVER_INSTANCE_ID, sizeof(OC_RSRVD_SERVER_INSTANCE_ID) - 1); - err = err || cbor_encode_byte_string(&map, resource->sid, UUID_SIZE); + err = err | cbor_encode_byte_string(&map, resource->sid, UUID_SIZE); // Prop Tag { CborEncoder propMap; - err = err || cbor_encode_text_string(&map, OC_RSRVD_PROPERTY, + err = err | cbor_encode_text_string(&map, OC_RSRVD_PROPERTY, sizeof(OC_RSRVD_PROPERTY) -1 ); - err = err || cbor_encoder_create_map(&map, &propMap, 3); + err = err | cbor_encoder_create_map(&map, &propMap, 3); // Resource Type { CborEncoder rtArray; - err = err || cbor_encode_text_string(&propMap, OC_RSRVD_RESOURCE_TYPE, + err = err | cbor_encode_text_string(&propMap, OC_RSRVD_RESOURCE_TYPE, sizeof(OC_RSRVD_RESOURCE_TYPE) - 1); - err = err || cbor_encoder_create_array(&propMap, &rtArray, CborIndefiniteLength); + err = err | cbor_encoder_create_array(&propMap, &rtArray, CborIndefiniteLength); OCStringLL* rtPtr = resource->types; while(rtPtr) { - err = err || cbor_encode_text_string(&rtArray, rtPtr->value, + err = err | cbor_encode_text_string(&rtArray, rtPtr->value, strlen(rtPtr->value)); rtPtr = rtPtr->next; } - err = err || cbor_encoder_close_container(&propMap, &rtArray); + err = err | cbor_encoder_close_container(&propMap, &rtArray); } // Interface Types { CborEncoder ifArray; - err = err || cbor_encode_text_string(&propMap, OC_RSRVD_INTERFACE, + err = err | cbor_encode_text_string(&propMap, OC_RSRVD_INTERFACE, sizeof(OC_RSRVD_INTERFACE) - 1); - err = err || cbor_encoder_create_array(&propMap, &ifArray, CborIndefiniteLength); + err = err | cbor_encoder_create_array(&propMap, &ifArray, CborIndefiniteLength); OCStringLL* ifPtr = resource->interfaces; while(ifPtr) { - err = err || cbor_encode_text_string(&ifArray, ifPtr->value, + err = err | cbor_encode_text_string(&ifArray, ifPtr->value, strlen(ifPtr->value)); ifPtr= ifPtr->next; } - err = err || cbor_encoder_close_container(&propMap, &ifArray); + err = err | cbor_encoder_close_container(&propMap, &ifArray); } // Policy { CborEncoder policyMap; - err = err || cbor_encode_text_string(&propMap, OC_RSRVD_POLICY, + err = err | cbor_encode_text_string(&propMap, OC_RSRVD_POLICY, sizeof(OC_RSRVD_POLICY) - 1); - err = err || cbor_encoder_create_map(&propMap, &policyMap, CborIndefiniteLength); + err = err | cbor_encoder_create_map(&propMap, &policyMap, CborIndefiniteLength); // Bitmap - err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_BITMAP, + err = err | cbor_encode_text_string(&policyMap, OC_RSRVD_BITMAP, sizeof(OC_RSRVD_BITMAP) - 1); - err = err || cbor_encode_uint(&policyMap, resource->bitmap); + err = err | cbor_encode_uint(&policyMap, resource->bitmap); if(resource->secure) { - err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_SECURE, + err = err | cbor_encode_text_string(&policyMap, OC_RSRVD_SECURE, sizeof(OC_RSRVD_SECURE) - 1); - err = err || cbor_encode_boolean(&policyMap, OC_RESOURCE_SECURE); + err = err | cbor_encode_boolean(&policyMap, OC_RESOURCE_SECURE); if(resource->port != 0) { - err = err || cbor_encode_text_string(&policyMap, OC_RSRVD_HOSTING_PORT, + err = err | cbor_encode_text_string(&policyMap, OC_RSRVD_HOSTING_PORT, sizeof(OC_RSRVD_HOSTING_PORT) - 1); - err = err || cbor_encode_uint(&policyMap, resource->port); + err = err | cbor_encode_uint(&policyMap, resource->port); } } - err = err || cbor_encoder_close_container(&propMap, &policyMap); + err = err | cbor_encoder_close_container(&propMap, &policyMap); } // Close - err = err || cbor_encoder_close_container(&map, &propMap); + err = err | cbor_encoder_close_container(&map, &propMap); } // Close Item - err = err || cbor_encoder_close_container(&rootArray, &map); + err = err | cbor_encoder_close_container(&rootArray, &map); } // Close main array - err = err || cbor_encoder_close_container(&encoder, &rootArray); + err = err | cbor_encoder_close_container(&encoder, &rootArray); - if(err) - { - OC_LOG_V(ERROR, TAG, "Convert Discovery Payload failed with : %d", err); - return OC_STACK_ERROR; - } - - *size = encoder.ptr - *outPayload; - uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size); - - if(!tempPayload) - { - OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!")); - OICFree(*outPayload); - return OC_STACK_ERROR; - } - - *outPayload = tempPayload; - return OC_STACK_OK; + return checkError(err, &encoder, outPayload, size); } -static OCStackResult OCConvertDevicePayload(OCDevicePayload* payload, uint8_t** outPayload, +static int64_t OCConvertDevicePayload(OCDevicePayload* payload, uint8_t* outPayload, size_t* size) { - *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH); - *size = MAX_REQUEST_LENGTH; - - if(!*outPayload) - { - return OC_STACK_NO_MEMORY; - } - CborEncoder encoder = {0}; - bool err = false; + int64_t err = 0; - cbor_encoder_init(&encoder, *outPayload, *size, 0); + cbor_encoder_init(&encoder, outPayload, *size, 0); CborEncoder rootArray; - err = err || cbor_encoder_create_array(&encoder, &rootArray, 2); - err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DEVICE); + err = err | cbor_encoder_create_array(&encoder, &rootArray, 2); + err = err | cbor_encode_uint(&rootArray, PAYLOAD_TYPE_DEVICE); { CborEncoder map; - err = err || cbor_encoder_create_map(&rootArray, &map, 2); + err = err | cbor_encoder_create_map(&rootArray, &map, 2); // uri - err = err || AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1, + err = err | AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1, payload->uri); // Rep Map { CborEncoder repMap; - err = err || cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION, + err = err | cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION, sizeof(OC_RSRVD_REPRESENTATION) - 1); - err = err || cbor_encoder_create_map(&map, &repMap, 4); + err = err | cbor_encoder_create_map(&map, &repMap, 4); // Device ID - err = err || cbor_encode_text_string(&repMap, OC_RSRVD_DEVICE_ID, + err = err | cbor_encode_text_string(&repMap, OC_RSRVD_DEVICE_ID, sizeof(OC_RSRVD_DEVICE_ID) - 1); - err = err || cbor_encode_byte_string(&repMap, payload->sid, UUID_SIZE); + err = err | cbor_encode_byte_string(&repMap, payload->sid, UUID_SIZE); // Device Name - err = err || AddTextStringToMap(&repMap, OC_RSRVD_DEVICE_NAME, + err = err | AddTextStringToMap(&repMap, OC_RSRVD_DEVICE_NAME, sizeof(OC_RSRVD_DEVICE_NAME) - 1, payload->deviceName); // Device Spec Version - err = err || AddTextStringToMap(&repMap, OC_RSRVD_SPEC_VERSION, + err = err | AddTextStringToMap(&repMap, OC_RSRVD_SPEC_VERSION, sizeof(OC_RSRVD_SPEC_VERSION) - 1, payload->specVersion); // Device data Model Version - err = err || AddTextStringToMap(&repMap, OC_RSRVD_DATA_MODEL_VERSION, + err = err | AddTextStringToMap(&repMap, OC_RSRVD_DATA_MODEL_VERSION, sizeof(OC_RSRVD_DATA_MODEL_VERSION) - 1, payload->dataModelVersion); - err = err || cbor_encoder_close_container(&map, &repMap); + err = err | cbor_encoder_close_container(&map, &repMap); } // Close Map - err = err || cbor_encoder_close_container(&rootArray, &map); + err = err | cbor_encoder_close_container(&rootArray, &map); } // Close main array - err = err || cbor_encoder_close_container(&encoder, &rootArray); - - if(err) - { - OC_LOG_V(ERROR, TAG, "Convert Device Payload failed with : %d", err); - return OC_STACK_ERROR; - } - - *size = encoder.ptr - *outPayload; - uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size); - - if(!tempPayload) - { - OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!")); - OICFree(*outPayload); - return OC_STACK_ERROR; - } + err = err | cbor_encoder_close_container(&encoder, &rootArray); - *outPayload = tempPayload; - return OC_STACK_OK; + return checkError(err, &encoder, outPayload, size); } -static OCStackResult OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t** outPayload, +static int64_t OCConvertPlatformPayload(OCPlatformPayload* payload, uint8_t* outPayload, size_t* size) { - *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH); - *size = MAX_REQUEST_LENGTH; - - if(!*outPayload) - { - return OC_STACK_NO_MEMORY; - } - CborEncoder encoder = {0}; - bool err = false; + int64_t err = 0; - cbor_encoder_init(&encoder, *outPayload, *size, 0); + cbor_encoder_init(&encoder, outPayload, *size, 0); CborEncoder rootArray; - err = err || cbor_encoder_create_array(&encoder, &rootArray, 2); - err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PLATFORM); + err = err | cbor_encoder_create_array(&encoder, &rootArray, 2); + err = err | cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PLATFORM); { CborEncoder map; - err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength); + err = err | cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength); // uri - err = err || AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1, + err = err | AddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1, payload->uri); // Rep Map { CborEncoder repMap; - err = err || cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION, + err = err | cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION, sizeof(OC_RSRVD_REPRESENTATION) - 1); - err = err || cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength); + err = err | cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength); // Platform ID - err = err || AddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_ID, + err = err | AddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_ID, sizeof(OC_RSRVD_PLATFORM_ID) - 1, payload->info.platformID); // MFG Name - err = err || AddTextStringToMap(&repMap, OC_RSRVD_MFG_NAME, + err = err | AddTextStringToMap(&repMap, OC_RSRVD_MFG_NAME, sizeof(OC_RSRVD_MFG_NAME) - 1, payload->info.manufacturerName); // MFG Url - err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_URL, + err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_URL, sizeof(OC_RSRVD_MFG_URL) - 1, payload->info.manufacturerUrl); // Model Num - err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MODEL_NUM, + err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MODEL_NUM, sizeof(OC_RSRVD_MODEL_NUM) - 1, payload->info.modelNumber); // Date of Mfg - err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_DATE, + err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_MFG_DATE, sizeof(OC_RSRVD_MFG_DATE) - 1, payload->info.dateOfManufacture); // Platform Version - err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_VERSION, + err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_PLATFORM_VERSION, sizeof(OC_RSRVD_PLATFORM_VERSION) - 1, payload->info.platformVersion); // OS Version - err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_OS_VERSION, + err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_OS_VERSION, sizeof(OC_RSRVD_OS_VERSION) - 1, payload->info.operatingSystemVersion); // Hardware Version - err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_HARDWARE_VERSION, + err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_HARDWARE_VERSION, sizeof(OC_RSRVD_HARDWARE_VERSION) - 1, payload->info.hardwareVersion); // Firmware Version - err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_FIRMWARE_VERSION, + err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_FIRMWARE_VERSION, sizeof(OC_RSRVD_FIRMWARE_VERSION) - 1, payload->info.firmwareVersion); // Support URL - err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SUPPORT_URL, + err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SUPPORT_URL, sizeof(OC_RSRVD_SUPPORT_URL) - 1, payload->info.supportUrl); // System Time - err = err || ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SYSTEM_TIME, + err = err | ConditionalAddTextStringToMap(&repMap, OC_RSRVD_SYSTEM_TIME, sizeof(OC_RSRVD_SYSTEM_TIME) - 1, payload->info.systemTime); - err = err || cbor_encoder_close_container(&map, &repMap); + err = err | cbor_encoder_close_container(&map, &repMap); } // Close Map - err = err || cbor_encoder_close_container(&rootArray, &map); + err = err | cbor_encoder_close_container(&rootArray, &map); } // Close main array - err = err || cbor_encoder_close_container(&encoder, &rootArray); - - if(err) - { - OC_LOG_V(ERROR, TAG, "Convert Platform Payload failed with : %d", err); - return OC_STACK_ERROR; - } - - *size = encoder.ptr - *outPayload; - uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size); - - if(!tempPayload) - { - OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!")); - OICFree(*outPayload); - return OC_STACK_ERROR; - } - - *outPayload = tempPayload; + err = err | cbor_encoder_close_container(&encoder, &rootArray); - return OC_STACK_OK; + return checkError(err, &encoder, outPayload, size); } -static bool OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload); - -static bool OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* valArray) +static int64_t OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* valArray) { CborEncoder array; - bool err = false; + int64_t err = 0; - err = err || cbor_encoder_create_array(parent, &array, CborIndefiniteLength); - err = err || cbor_encode_uint(&array, valArray->type); + err = err | cbor_encoder_create_array(parent, &array, CborIndefiniteLength); + err = err | cbor_encode_uint(&array, valArray->type); for(int i = 0; i < MAX_REP_ARRAY_DEPTH; ++i) { - err = err || cbor_encode_uint(&array, valArray->dimensions[i]); + err = err | cbor_encode_uint(&array, valArray->dimensions[i]); } size_t dimTotal = calcDimTotal(valArray->dimensions); @@ -495,16 +484,16 @@ static bool OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* va err = CborUnknownError; break; case OCREP_PROP_INT: - err = err || cbor_encode_int(&array, valArray->iArray[i]); + err = err | cbor_encode_int(&array, valArray->iArray[i]); break; case OCREP_PROP_DOUBLE: - err = err || cbor_encode_double(&array, valArray->dArray[i]); + err = err | cbor_encode_double(&array, valArray->dArray[i]); break; case OCREP_PROP_BOOL: - err = err || cbor_encode_boolean(&array, valArray->bArray[i]); + err = err | cbor_encode_boolean(&array, valArray->bArray[i]); break; case OCREP_PROP_STRING: - err = err || cbor_encode_text_string(&array, valArray->strArray[i], + err = err | cbor_encode_text_string(&array, valArray->strArray[i], strlen(valArray->strArray[i])); break; case OCREP_PROP_OBJECT: @@ -517,18 +506,18 @@ static bool OCConvertArray(CborEncoder* parent, const OCRepPayloadValueArray* va } } - err = err || cbor_encoder_close_container(parent, &array); + err = err | cbor_encoder_close_container(parent, &array); return err; } -static bool OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload) +static int64_t OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* payload) { - bool err = false; + int64_t err = 0; CborEncoder map; - err = err || cbor_encoder_create_map(parent, &map, CborIndefiniteLength); + err = err | cbor_encoder_create_map(parent, &map, CborIndefiniteLength); // Uri - err = err || ConditionalAddTextStringToMap(&map, OC_RSRVD_HREF, + err = err | ConditionalAddTextStringToMap(&map, OC_RSRVD_HREF, sizeof(OC_RSRVD_HREF) - 1, payload->uri); @@ -537,83 +526,83 @@ static bool OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* p if(payload->types || payload->interfaces) { OC_LOG_V(INFO, TAG, "Payload has types or interfaces"); - err = err || cbor_encode_text_string(&map, + err = err | cbor_encode_text_string(&map, OC_RSRVD_PROPERTY, sizeof(OC_RSRVD_PROPERTY) - 1); CborEncoder propMap; - err = err || cbor_encoder_create_map(&map, &propMap, 2); + err = err | cbor_encoder_create_map(&map, &propMap, 2); CborEncoder curArray; if(payload->types) { - err = err || cbor_encode_text_string(&propMap, + err = err | cbor_encode_text_string(&propMap, OC_RSRVD_RESOURCE_TYPE, sizeof(OC_RSRVD_RESOURCE_TYPE) - 1); - err = err || cbor_encoder_create_array(&propMap, &curArray, CborIndefiniteLength); + err = err | cbor_encoder_create_array(&propMap, &curArray, CborIndefiniteLength); OCStringLL* val = payload->types; while(val) { - err = err || cbor_encode_text_string(&curArray, val->value, strlen(val->value)); + err = err | cbor_encode_text_string(&curArray, val->value, strlen(val->value)); val = val->next; } - err = err || cbor_encoder_close_container(&propMap, &curArray); + err = err | cbor_encoder_close_container(&propMap, &curArray); } if(payload->interfaces) { - err = err || cbor_encode_text_string(&propMap, + err = err | cbor_encode_text_string(&propMap, OC_RSRVD_INTERFACE, sizeof(OC_RSRVD_INTERFACE) - 1); - err = err || cbor_encoder_create_array(&propMap, &curArray, CborIndefiniteLength); + err = err | cbor_encoder_create_array(&propMap, &curArray, CborIndefiniteLength); OCStringLL* val = payload->interfaces; while(val) { - err = err || cbor_encode_text_string(&curArray, val->value, strlen(val->value)); + err = err | cbor_encode_text_string(&curArray, val->value, strlen(val->value)); val = val->next; } - err = err || cbor_encoder_close_container(&propMap, &curArray); + err = err | cbor_encoder_close_container(&propMap, &curArray); } - err = err || cbor_encoder_close_container(&map, &propMap); + err = err | cbor_encoder_close_container(&map, &propMap); } // Rep Map { CborEncoder repMap; - err = err || cbor_encode_text_string(&map, + err = err | cbor_encode_text_string(&map, OC_RSRVD_REPRESENTATION, sizeof(OC_RSRVD_REPRESENTATION) - 1); - err = err || cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength); + err = err | cbor_encoder_create_map(&map, &repMap, CborIndefiniteLength); OCRepPayloadValue* value = payload->values; while(value) { - err = err || cbor_encode_text_string(&repMap, + err = err | cbor_encode_text_string(&repMap, value->name, strlen(value->name)); switch(value->type) { case OCREP_PROP_NULL: - err = err || cbor_encode_null(&repMap); + err = err | cbor_encode_null(&repMap); break; case OCREP_PROP_INT: - err = err || cbor_encode_int(&repMap, + err = err | cbor_encode_int(&repMap, value->i); break; case OCREP_PROP_DOUBLE: - err = err || cbor_encode_double(&repMap, + err = err | cbor_encode_double(&repMap, value->d); break; case OCREP_PROP_BOOL: - err = err || cbor_encode_boolean(&repMap, + err = err | cbor_encode_boolean(&repMap, value->b); break; case OCREP_PROP_STRING: - err = err || cbor_encode_text_string(&repMap, + err = err | cbor_encode_text_string(&repMap, value->str, strlen(value->str)); break; case OCREP_PROP_OBJECT: - err = err || OCConvertSingleRepPayload(&repMap, value->obj); + err = err | OCConvertSingleRepPayload(&repMap, value->obj); break; case OCREP_PROP_ARRAY: - err = err || OCConvertArray(&repMap, &value->arr); + err = err | OCConvertArray(&repMap, &value->arr); break; default: OC_LOG_V(ERROR, TAG, "Invalid Prop type: %d", @@ -623,145 +612,93 @@ static bool OCConvertSingleRepPayload(CborEncoder* parent, const OCRepPayload* p value = value->next; } - err = err || cbor_encoder_close_container(&map, &repMap); + err = err | cbor_encoder_close_container(&map, &repMap); } // Close Map - err = err || cbor_encoder_close_container(parent, &map); + err = err | cbor_encoder_close_container(parent, &map); return err; } -static OCStackResult OCConvertRepPayload(OCRepPayload* payload, uint8_t** outPayload, size_t* size) +static int64_t OCConvertRepPayload(OCRepPayload* payload, uint8_t* outPayload, size_t* size) { - *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH); - *size = MAX_REQUEST_LENGTH; - - if(!*outPayload) - { - return OC_STACK_NO_MEMORY; - } - CborEncoder encoder = {0}; - bool err = false; + int64_t err = 0; - cbor_encoder_init(&encoder, *outPayload, *size, 0); + cbor_encoder_init(&encoder, outPayload, *size, 0); CborEncoder rootArray; - err = err || cbor_encoder_create_array(&encoder, &rootArray, CborIndefiniteLength); - err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_REPRESENTATION); + err = err | cbor_encoder_create_array(&encoder, &rootArray, CborIndefiniteLength); + err = err | cbor_encode_uint(&rootArray, PAYLOAD_TYPE_REPRESENTATION); - while(payload != NULL && !err) + while(payload != NULL && (err == 0 || err == CborErrorOutOfMemory)) { - err = err || OCConvertSingleRepPayload(&rootArray, payload); + err = err | OCConvertSingleRepPayload(&rootArray, payload); payload = payload->next; } // Close main array - err = err || cbor_encoder_close_container(&encoder, &rootArray); - - if(err) - { - OC_LOG_V(ERROR, TAG, "Convert Rep Payload failed with : %d", err); - return OC_STACK_ERROR; - } - - *size = encoder.ptr - *outPayload; - uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size); - - if(!tempPayload) - { - OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!")); - OICFree(*outPayload); - return OC_STACK_ERROR; - } - - *outPayload = tempPayload; + err = err | cbor_encoder_close_container(&encoder, &rootArray); - return OC_STACK_OK; + return checkError(err, &encoder, outPayload, size); } -static OCStackResult OCConvertPresencePayload(OCPresencePayload* payload, - uint8_t** outPayload, size_t* size) +static int64_t OCConvertPresencePayload(OCPresencePayload* payload, + uint8_t* outPayload, size_t* size) { - *outPayload = (uint8_t*)OICCalloc(1, MAX_REQUEST_LENGTH); - *size = MAX_REQUEST_LENGTH; - - if(!*outPayload) - { - return OC_STACK_NO_MEMORY; - } - CborEncoder encoder = {0}; - bool err = false; + int64_t err = 0; - cbor_encoder_init(&encoder, *outPayload, *size, 0); + cbor_encoder_init(&encoder, outPayload, *size, 0); CborEncoder rootArray; - err = err || cbor_encoder_create_array(&encoder, &rootArray, 2); - err = err || cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PRESENCE); + err = err | cbor_encoder_create_array(&encoder, &rootArray, 2); + err = err | cbor_encode_uint(&rootArray, PAYLOAD_TYPE_PRESENCE); CborEncoder map; - err = err || cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength); + err = err | cbor_encoder_create_map(&rootArray, &map, CborIndefiniteLength); // Sequence Number - err = err || cbor_encode_text_string(&map, + err = err | cbor_encode_text_string(&map, OC_RSRVD_NONCE, sizeof(OC_RSRVD_NONCE) - 1); - err = err || cbor_encode_uint(&map, payload->sequenceNumber); + err = err | cbor_encode_uint(&map, payload->sequenceNumber); // Max Age - err = err || cbor_encode_text_string(&map, + err = err | cbor_encode_text_string(&map, OC_RSRVD_TTL, sizeof(OC_RSRVD_TTL) - 1); - err = err || cbor_encode_uint(&map, payload->maxAge); + err = err | cbor_encode_uint(&map, payload->maxAge); // Trigger const char* triggerStr = convertTriggerEnumToString(payload->trigger); - err = err || AddTextStringToMap(&map, OC_RSRVD_TRIGGER, sizeof(OC_RSRVD_TRIGGER) - 1, + err = err | AddTextStringToMap(&map, OC_RSRVD_TRIGGER, sizeof(OC_RSRVD_TRIGGER) - 1, triggerStr); // Resource type name if(payload->trigger != OC_PRESENCE_TRIGGER_DELETE) { - err = err || ConditionalAddTextStringToMap(&map, OC_RSRVD_RESOURCE_TYPE, + err = err | ConditionalAddTextStringToMap(&map, OC_RSRVD_RESOURCE_TYPE, sizeof(OC_RSRVD_RESOURCE_TYPE) - 1, payload->resourceType); } // Close Map - err = err || cbor_encoder_close_container(&rootArray, &map); - err = err || cbor_encoder_close_container(&encoder, &rootArray); - - if(err) - { - OC_LOG_V(ERROR, TAG, "Convert Presence Payload failed with : %d", err); - return OC_STACK_ERROR; - } - - *size = encoder.ptr - *outPayload; - uint8_t* tempPayload = (uint8_t*)OICRealloc(*outPayload, *size); - - if(!tempPayload) - { - OC_LOG_V(ERROR, TAG, PCF("Payload realloc failed!")); - OICFree(*outPayload); - return OC_STACK_ERROR; - } - - *outPayload = tempPayload; + err = err | cbor_encoder_close_container(&rootArray, &map); + err = err | cbor_encoder_close_container(&encoder, &rootArray); - return OC_STACK_OK; + return checkError(err, &encoder, outPayload, size); } -bool AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen, +static int64_t AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen, const char* value) { - return cbor_encode_text_string(map, key, keylen) || + return cbor_encode_text_string(map, key, keylen) | cbor_encode_text_string(map, value, strlen(value)); } -bool ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen, +static int64_t ConditionalAddTextStringToMap(CborEncoder* map, const char* key, size_t keylen, const char* value) { - return value ? AddTextStringToMap(map, key, keylen, value) : false; + return value ? AddTextStringToMap(map, key, keylen, value) : 0; } diff --git a/resource/csdk/stack/src/ocpayloadparse.c b/resource/csdk/stack/src/ocpayloadparse.c index 05c6b59..aa63c53 100644 --- a/resource/csdk/stack/src/ocpayloadparse.c +++ b/resource/csdk/stack/src/ocpayloadparse.c @@ -635,7 +635,7 @@ static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* contain err = err || cbor_value_get_boolean(&insideArray, &(((bool*)arr)[i])); err = err || cbor_value_advance_fixed(&insideArray); } - if(err && !OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions)) + if(err || !OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions)) { OICFree(arr); err = true; diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index da12be7..e438bc6 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -669,7 +669,7 @@ static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds) cbNode->presence->TTL = maxAgeSeconds; - for(int index = 0; index < PresenceTimeOutSize; index++) + for (int index = 0; index < PresenceTimeOutSize; index++) { // Guard against overflow if (cbNode->presence->TTL < (UINT32_MAX/(MILLISECONDS_PER_SECOND*PresenceTimeOut[index])) @@ -817,7 +817,7 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint, // check for unicast presence uriLen = FormCanonicalPresenceUri(endpoint, OC_RSRVD_PRESENCE_URI, presenceUri); - if (uriLen < 0 || uriLen >= sizeof (presenceUri)) + if (uriLen < 0 || (size_t)uriLen >= sizeof (presenceUri)) { return OC_STACK_INVALID_URI; } @@ -1046,6 +1046,9 @@ void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* res CopyEndpointToDevAddr(endPoint, &response.devAddr); FixUpClientResponse(&response); response.resourceUri = responseInfo->info.resourceUri; + memcpy(response.identity.id, responseInfo->info.identity.id, + sizeof (response.identity.id)); + response.identity.id_length = responseInfo->info.identity.id_length; response.result = CAToOCStackResult(responseInfo->result); cbNode->callBack(cbNode->context, @@ -1063,6 +1066,9 @@ void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* res CopyEndpointToDevAddr(endPoint, &response.devAddr); FixUpClientResponse(&response); response.resourceUri = responseInfo->info.resourceUri; + memcpy(response.identity.id, responseInfo->info.identity.id, + sizeof (response.identity.id)); + response.identity.id_length = responseInfo->info.identity.id_length; response.result = CAToOCStackResult(responseInfo->result); if(responseInfo->info.payload && @@ -1569,13 +1575,6 @@ OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode) { (void) ipAddr; (void) port; -#ifdef RA_ADAPTER - if(!gRASetInfo) - { - OC_LOG(ERROR, TAG, PCF("Need to call OCSetRAInfo before calling OCInit")); - return OC_STACK_ERROR; - } -#endif return OCInit1(mode, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS); } @@ -1588,6 +1587,14 @@ OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlag return OC_STACK_OK; } +#ifdef RA_ADAPTER + if(!gRASetInfo) + { + OC_LOG(ERROR, TAG, PCF("Need to call OCSetRAInfo before calling OCInit")); + return OC_STACK_ERROR; + } +#endif + OCStackResult result = OC_STACK_ERROR; OC_LOG(INFO, TAG, PCF("Entering OCInit")); @@ -1611,12 +1618,12 @@ OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlag caglobals.serverFlags = (CATransportFlags_t)serverFlags; if (!(caglobals.serverFlags & CA_IPFAMILY_MASK)) { - caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4); + caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4|CA_IPV6); } caglobals.clientFlags = (CATransportFlags_t)clientFlags; if (!(caglobals.clientFlags & CA_IPFAMILY_MASK)) { - caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4); + caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4|CA_IPV6); } defaultDeviceHandler = NULL; @@ -1653,7 +1660,7 @@ OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlag VERIFY_SUCCESS(result, OC_STACK_OK); #ifdef WITH_PRESENCE - PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1; + PresenceTimeOutSize = sizeof (PresenceTimeOut) / sizeof (PresenceTimeOut[0]) - 1; #endif // WITH_PRESENCE //Update Stack state to initialized @@ -2057,6 +2064,8 @@ OCStackResult OCDoResource(OCDoHandle *handle, } else { + tmpDevAddr.adapter = adapter; + tmpDevAddr.flags = flags; destination = &tmpDevAddr; requestInfo.isMulticast = true; } @@ -2394,7 +2403,7 @@ OCStackResult OCProcessPresence() cbNode->presence->TTLlevel); OC_LOG_V(DEBUG, TAG, "current ticks %d", now); - if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1)) + if (cbNode->presence->TTLlevel > PresenceTimeOutSize) { goto exit; } @@ -2404,7 +2413,6 @@ OCStackResult OCProcessPresence() OC_LOG_V(DEBUG, TAG, "timeout ticks %d", cbNode->presence->timeOut[cbNode->presence->TTLlevel]); } - if (cbNode->presence->TTLlevel >= PresenceTimeOutSize) { OC_LOG(DEBUG, TAG, PCF("No more timeout ticks")); @@ -3771,7 +3779,7 @@ OCStackResult getQueryFromUri(const char * uri, char** query, char ** uriWithout char *pointerToDelimiter = strstr(uri, "?"); - uriWithoutQueryLen = pointerToDelimiter == NULL ? uriLen : pointerToDelimiter - uri; + uriWithoutQueryLen = pointerToDelimiter == NULL ? uriLen : (size_t)(pointerToDelimiter - uri); queryLen = pointerToDelimiter == NULL ? 0 : uriLen - uriWithoutQueryLen - 1; if (uriWithoutQueryLen) diff --git a/resource/examples/simpleclient.cpp b/resource/examples/simpleclient.cpp index 7106d9e..b19f521 100644 --- a/resource/examples/simpleclient.cpp +++ b/resource/examples/simpleclient.cpp @@ -85,7 +85,7 @@ void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep, std::cout << "\tpower: " << mylight.m_power << std::endl; std::cout << "\tname: " << mylight.m_name << std::endl; - if(observe_count() > 10) + if(observe_count() == 11) { std::cout<<"Cancelling Observe..."<cancelObserve(); diff --git a/resource/examples/simpleclientHQ.cpp b/resource/examples/simpleclientHQ.cpp index 5e69f01..61f8a92 100644 --- a/resource/examples/simpleclientHQ.cpp +++ b/resource/examples/simpleclientHQ.cpp @@ -97,7 +97,7 @@ void onObserve(const HeaderOptions headerOptions, const OCRepresentation& rep, std::cout << "\tpower: " << mylight.m_power << std::endl; std::cout << "\tname: " << mylight.m_name << std::endl; - if(observe_count() > 10) + if(observe_count() == 11) { std::cout<<"Cancelling Observe..."<cancelObserve(OC::QualityOfService::HighQos); diff --git a/resource/src/OCRepresentation.cpp b/resource/src/OCRepresentation.cpp index 01969fc..f61edb3 100644 --- a/resource/src/OCRepresentation.cpp +++ b/resource/src/OCRepresentation.cpp @@ -398,13 +398,6 @@ namespace OC } } - OCRepPayload* cur = root; - for(auto& child : this->getChildren()) - { - cur->next = child.getPayload(); - cur = cur->next; - } - return root; } diff --git a/resource/third_party_libs.scons b/resource/third_party_libs.scons index 46b80bd..bac4cfb 100644 --- a/resource/third_party_libs.scons +++ b/resource/third_party_libs.scons @@ -57,11 +57,11 @@ if target_os == 'android': if target_arch == 'armeabi-v7a-hard': target_arch = 'armeabi-v7a' - if target_arch not in ['x86', 'armeabi', 'armeabi-v7a']: + if target_arch not in ['x86', 'x86_64','armeabi', 'armeabi-v7a']: if not env.GetOption('help') and not env.GetOption('clean'): print ''' *********************************** Warning *********************************** -* current only x86, armeabi, armeabi-v7a libraries are provided! * +* current only x86, x86_64, armeabi, armeabi-v7a libraries are provided! * ******************************************************************************* ''' else: diff --git a/service/SConscript b/service/SConscript index 5389725..a406ae1 100644 --- a/service/SConscript +++ b/service/SConscript @@ -43,7 +43,7 @@ if target_os not in ['arduino','darwin','ios']: SConscript('notification-manager/SConscript') # Build resource-encapsulation project - if target_os not in ['android', 'tizen']: + if target_os not in ['tizen']: SConscript('resource-encapsulation/SConscript') #else: # SConscript('notification-manager/SampleApp/arduino/SConscript') diff --git a/service/notification-manager/NotificationManager/src/ResourceHosting.cpp b/service/notification-manager/NotificationManager/src/ResourceHosting.cpp index b41bfe9..a85a853 100644 --- a/service/notification-manager/NotificationManager/src/ResourceHosting.cpp +++ b/service/notification-manager/NotificationManager/src/ResourceHosting.cpp @@ -184,9 +184,9 @@ void ResourceHosting::requestMulticastDiscovery() void ResourceHosting::requestDiscovery(std::string address) { std::string host = address; - std::string uri = OC_RSRVD_WELL_KNOWN_URI + std::string("?rt=") + HOSTING_RESOURSE_TYPE; RCSAddress rcsAddress = RCSAddress::unicast(host); - discoveryManager->discoverResource(rcsAddress, uri, pDiscoveryCB); + discoveryManager->discoverResourceByType(rcsAddress, OC_RSRVD_WELL_KNOWN_URI, + HOSTING_RESOURSE_TYPE, pDiscoveryCB); } void ResourceHosting::discoverHandler(RemoteObjectPtr remoteResource) diff --git a/service/protocol-plugin/plugins/mqtt-light/lib/cpp/test.txt b/service/protocol-plugin/plugins/mqtt-light/lib/cpp/test.txt deleted file mode 100644 index c6ba667..0000000 --- a/service/protocol-plugin/plugins/mqtt-light/lib/cpp/test.txt +++ /dev/null @@ -1,883 +0,0 @@ -/usr/lib/i386-linux-gnu/mesa-egl: - libOpenVG.so.1 -> libOpenVG.so.1.0.0 - libwayland-egl.so.1 -> libwayland-egl.so.1.0.0 - libEGL.so.1 -> libEGL.so.1.0.0 -/usr/lib/i386-linux-gnu/mesa: - libGL.so.1 -> libGL.so.1.2.0 -/lib/i386-linux-gnu: - libblkid.so.1 -> libblkid.so.1.1.0 - libnss_dns.so.2 -> libnss_dns-2.15.so - libnss_compat.so.2 -> libnss_compat-2.15.so - libwrap.so.0 -> libwrap.so.0.7.6 - libpcsclite.so.1 -> libpcsclite.so.1.0.0 - libkeyutils.so.1 -> libkeyutils.so.1.4 - libntfs-3g.so.831 -> libntfs-3g.so.831.0.0 - libpcprofile.so -> libpcprofile.so - libext2fs.so.2 -> libext2fs.so.2.4 - libslang.so.2 -> libslang.so.2.2.4 - libpci.so.3 -> libpci.so.3.1.8 - libparted.so.0 -> libparted.so.0.0.1 - libdl.so.2 -> libdl-2.15.so - libutil.so.1 -> libutil-2.15.so - libgcc_s.so.1 -> libgcc_s.so.1 - libnss_nisplus.so.2 -> libnss_nisplus-2.15.so - libbsd.so.0 -> libbsd.so.0.3.0 - libpng12.so.0 -> libpng12.so.0.46.0 - librt.so.1 -> librt-2.15.so - ld-linux.so.2 -> ld-2.15.so - libncurses.so.5 -> libncurses.so.5.9 - libcrypto.so.1.0.0 -> libcrypto.so.1.0.0 - libacl.so.1 -> libacl.so.1.1.0 - libgcrypt.so.11 -> libgcrypt.so.11.7.0 - libnsl.so.1 -> libnsl-2.15.so - libpam.so.0 -> libpam.so.0.83.0 - libmount.so.1 -> libmount.so.1.1.0 - libselinux.so.1 -> libselinux.so.1 - libpcre.so.3 -> libpcre.so.3.12.1 - libdbus-1.so.3 -> libdbus-1.so.3.5.8 - libuuid.so.1 -> libuuid.so.1.3.0 - libexpat.so.1 -> libexpat.so.1.5.2 - libnss_files.so.2 -> libnss_files-2.15.so - libcom_err.so.2 -> libcom_err.so.2.1 - libnss_nis.so.2 -> libnss_nis-2.15.so - libatasmart.so.4 -> libatasmart.so.4.0.4 - libssl.so.1.0.0 -> libssl.so.1.0.0 - libthread_db.so.1 -> libthread_db-1.0.so - libncursesw.so.5 -> libncursesw.so.5.9 - libgpg-error.so.0 -> libgpg-error.so.0.8.0 - libe2p.so.2 -> libe2p.so.2.3 - libss.so.2 -> libss.so.2.0 - libBrokenLocale.so.1 -> libBrokenLocale-2.15.so - libcidn.so.1 -> libcidn-2.15.so - libpamc.so.0 -> libpamc.so.0.82.1 - libmemusage.so -> libmemusage.so - libglib-2.0.so.0 -> libglib-2.0.so.0.3200.4 - libnss_hesiod.so.2 -> libnss_hesiod-2.15.so - libanl.so.1 -> libanl-2.15.so - libcap.so.2 -> libcap.so.2.22 - libresolv.so.2 -> libresolv-2.15.so - libattr.so.1 -> libattr.so.1.1.0 - libpthread.so.0 -> libpthread-2.15.so - libm.so.6 -> libm-2.15.so - libz.so.1 -> libz.so.1.2.3.4 - libhistory.so.6 -> libhistory.so.6.2 - libnih-dbus.so.1 -> libnih-dbus.so.1.0.0 - libSegFault.so -> libSegFault.so - libudev.so.0 -> libudev.so.0.13.0 - libreadline.so.6 -> libreadline.so.6.2 - libusb-1.0.so.0 -> libusb-1.0.so.0.1.0 - libcrypt.so.1 -> libcrypt-2.15.so - libpam_misc.so.0 -> libpam_misc.so.0.82.0 - libnih.so.1 -> libnih.so.1.0.0 - libtinfo.so.5 -> libtinfo.so.5.9 - libpopt.so.0 -> libpopt.so.0.0.0 - libbz2.so.1.0 -> libbz2.so.1.0.4 - libc.so.6 -> libc-2.15.so - libusb-0.1.so.4 -> libusb-0.1.so.4.4.4 -/usr/lib/i386-linux-gnu: - libnss3.so -> libnss3.so - libsmbclient.so.0 -> libsmbclient.so.0 - libgobject-2.0.so.0 -> libgobject-2.0.so.0.3200.4 - libpoppler-glib.so.8 -> libpoppler-glib.so.8.2.0 - libavcodec.so.53 -> libavcodec.so.53.35.0 - libwbclient.so.0 -> libwbclient.so.0 - libbonoboui-2.so.0 -> libbonoboui-2.so.0.0.0 - libjasper.so.1 -> libjasper.so.1.0.0 - libsqlite3.so.0 -> libsqlite3.so.0.8.6 - libgstbasevideo-1.0.so.0 -> libgstbasevideo-1.0.so.0.5.0 - librtmp.so.0 -> librtmp.so.0 - libframe.so.6 -> libframe.so.6.0.0 - libnspr4.so -> libnspr4.so - libportaudio.so.2 -> libportaudio.so.2.0.0 - libXdmcp.so.6 -> libXdmcp.so.6.0.0 - libcanberra-gtk3.so.0 -> libcanberra-gtk3.so.0.1.8 - libnettle.so.4 -> libnettle.so.4.3 - libcups.so.2 -> libcups.so.2 - libxcb-shape.so.0 -> libxcb-shape.so.0.0.0 - libunistring.so.0 -> libunistring.so.0.1.2 - libQtDeclarative.so.4 -> libQtDeclarative.so.4.8.1 - libdbusmenu-gtk3.so.4 -> libdbusmenu-gtk3.so.4.0.13 - libgsttag-0.10.so.0 -> libgsttag-0.10.so.0.25.0 - libwmflite-0.2.so.7 -> libwmflite-0.2.so.7.0.1 - libapt-pkg.so.4.12 -> libapt-pkg.so.4.12.0 - libQtNetwork.so.4 -> libQtNetwork.so.4.8.1 - libgnomecanvas-2.so.0 -> libgnomecanvas-2.so.0.3000.3 - libtheoradec.so.1 -> libtheoradec.so.1.1.4 - libcanberra.so.0 -> libcanberra.so.0.2.5 - libgnutls-extra.so.26 -> libgnutls-extra.so.26.21.8 - libxcb-render.so.0 -> libxcb-render.so.0.0.0 - libgpm.so.2 -> libgpm.so.2 - libxcb-util.so.0 -> libxcb-util.so.0.0.0 - libraw1394.so.11 -> libraw1394.so.11.0.1 - libpangocairo-1.0.so.0 -> libpangocairo-1.0.so.0.3000.0 - libssl3.so -> libssl3.so - libgstcontroller-0.10.so.0 -> libgstcontroller-0.10.so.0.30.0 - libcupsimage.so.2 -> libcupsimage.so.2 - liblcms2.so.2 -> liblcms2.so.2.0.2 - libgio-2.0.so.0 -> libgio-2.0.so.0.3200.4 - libtxc_dxtn_s2tc.so.0 -> libtxc_dxtn_s2tc.so.0.0.0 - libdbus-glib-1.so.2 -> libdbus-glib-1.so.2.2.2 - libgstallocators-1.0.so.0 -> libgstallocators-1.0.so.0.201.0 - libXi.so.6 -> libXi.so.6.1.0 - libsvn_ra_svn-1.so.1 -> libsvn_ra_svn-1.so.1.0.0 - liblber-2.4.so.2 -> liblber.so - libgstsignalprocessor-1.0.so.0 -> libgstsignalprocessor-1.0.so.0.5.0 - libhcrypto.so.4 -> libhcrypto.so.4.1.0 - libcanberra-gtk.so.0 -> libcanberra-gtk.so.0.1.8 - libavahi-glib.so.1 -> libavahi-glib.so.1.0.2 - libedit.so.2 -> libedit.so.2.11 - libavahi-ui-gtk3.so.0 -> libavahi-ui-gtk3.so.0.1.4 - libx264.so.120 -> libx264.so.120 - libgstsdp-1.0.so.0 -> libgstsdp-1.0.so.0.201.0 - libgstnet-0.10.so.0 -> libgstnet-0.10.so.0.30.0 - libfarstream-0.1.so.0 -> libfarstream-0.1.so.0.0.1 - libgstfft-0.10.so.0 -> libgstfft-0.10.so.0.25.0 - libgstcdda-0.10.so.0 -> libgstcdda-0.10.so.0.25.0 - libbamf3.so.0 -> libbamf3.so.0.0.0 - libgstbasecamerabinsrc-1.0.so.0 -> libgstbasecamerabinsrc-1.0.so.0.7.0 - libexempi.so.3 -> libexempi.so.3.2.2 - libXss.so.1 -> libXss.so.1.0.0 - libffi.so.6 -> libffi.so.6.0.0 - libavformat.so.53 -> libavformat.so.53.21.1 - libgstpbutils-0.10.so.0 -> libgstpbutils-0.10.so.0.25.0 - libcdda_paranoia.so.0 -> libcdda_paranoia.so.0.10.2 - libavahi-gobject.so.0 -> libavahi-gobject.so.0.0.4 - libpolkit-gobject-1.so.0 -> libpolkit-gobject-1.so.0.0.0 - libXfixes.so.3 -> libXfixes.so.3.1.0 - libp11-kit.so.0 -> libp11-kit.so.0.0.0 - libpng12.so.0 -> libpng.so - libswscale.so.2 -> libswscale.so.2.1.0 - libxkbfile.so.1 -> libxkbfile.so.1.0.2 - libcupscgi.so.1 -> libcupscgi.so.1 - libtic.so.5 -> libtic.so.5.9 - libSDL-1.2.so.0 -> libSDL-1.2.so.0.11.3 - libgettextpo.so.0 -> libgettextpo.so.0.5.1 - libgoa-1.0.so.0 -> libgoa-1.0.so.0.0.0 - libvisual-0.4.so.0 -> libvisual-0.4.so.0.0.0 - libQtXml.so.4 -> libQtXml.so.4.8.1 - libdrm_intel.so.1 -> libdrm_intel.so.1.0.0 - libltdl.so.7 -> libltdl.so.7.3.0 - libgomp.so.1 -> libgomp.so.1.0.0 - libXtst.so.6 -> libXtst.so.6.1.0 - libgtk-3.so.0 -> libgtk-3.so.0.400.2 - libogg.so.0 -> libogg.so.0.7.1 - libXaw.so.7 -> libXaw7.so.7.0.0 - libssh.so.4 -> libssh.so.4.2.2 - libtdb.so.1 -> libtdb.so.1.2.9 - libsvn_ra-1.so.1 -> libsvn_ra-1.so.1.0.0 - libiec61883.so.0 -> libiec61883.so.0.1.1 - libk5crypto.so.3 -> libk5crypto.so.3.1 - libXinerama.so.1 -> libXinerama.so.1.0.0 - libcupsfilters.so.1 -> libcupsfilters.so.1 - libfontconfig.so.1 -> libfontconfig.so.1.4.4 - libXrandr_ltss.so.2 -> libXrandr_ltss.so.2.2.0 - libcupsdriver.so.1 -> libcupsdriver.so.1 - libgstcontroller-1.0.so.0 -> libgstcontroller-1.0.so.0.201.0 - libgnutlsxx.so.27 -> libgnutlsxx.so.27.0.0 - libICE.so.6 -> libICE.so.6.3.0 - libQtGui.so.4 -> libQtGui.so.4.8.1 - libgssrpc.so.4 -> libgssrpc.so.4.1 - librsvg-2.so.2 -> librsvg-2.so.2.36.1 - libgdk-x11-2.0.so.0 -> libgdk-x11-2.0.so.0.2400.10 - libsvn_subr-1.so.1 -> libsvn_subr-1.so.1.0.0 - libgphoto2.so.2 -> libgphoto2.so.2.4.0 - libtiff.so.4 -> libtiff.so.4.3.4 - libv4l1.so.0 -> libv4l1.so.0 - libgstsdp-0.10.so.0 -> libgstsdp-0.10.so.0.25.0 - libORBitCosNaming-2.so.0 -> libORBitCosNaming-2.so.0.1.0 - libdatrie.so.1 -> libdatrie.so.1.1.0 - libplc4.so -> libplc4.so - libwacom.so.2 -> libwacom.so.2.0.0 - libsoup-gnome-2.4.so.1 -> libsoup-gnome-2.4.so.1.5.0 - libwayland_ltss-server.so.0 -> libwayland_ltss-server.so.0.0.0 - libgstpbutils-1.0.so.0 -> libgstpbutils-1.0.so.0.201.0 - libpangoxft-1.0.so.0 -> libpangoxft-1.0.so.0.3000.0 - libglibmm-2.4.so.1 -> libglibmm-2.4.so.1.3.0 - libpulse.so.0 -> libpulse.so.0.13.5 - libbonobo-activation.so.4 -> libbonobo-activation.so.4.0.0 - libpolkit-agent-1.so.0 -> libpolkit-agent-1.so.0.0.0 - libtag.so.1 -> libtag.so.1.7.0 - libGLEWmx.so.1.6 -> libGLEWmx.so.1.6.0 - libatspi.so.0 -> libatspi.so.0.0.1 - libgphoto2_port.so.0 -> libgphoto2_port.so.0.8.0 - libcurl-gnutls.so.4 -> libcurl.so - libgbm.so.1 -> libgbm.so.1.0.0 - libgstapp-0.10.so.0 -> libgstapp-0.10.so.0.25.0 - libsndfile.so.1 -> libsndfile.so.1.0.25 - libgmodule-2.0.so.0 -> libgmodule-2.0.so.0.3200.4 - libXmu.so.6 -> libXmu.so.6.2.0 - libaudiofile.so.1 -> libaudiofile.so.1.0.0 - libexif.so.12 -> libexif.so.12.3.2 - libXau.so.6 -> libXau.so.6.0.0 - libglapi.so.0 -> libglapi.so.0.0.0 - libgtksourceview-3.0.so.0 -> libgtksourceview-3.0.so.0.0.0 - liborc-0.4.so.0 -> liborc-0.4.so.0.18.0 - libnotify.so.4 -> libnotify.so.4.0.0 - libwind.so.0 -> libwind.so.0.0.0 - libldap_r-2.4.so.2 -> libldap_r.so - libpcrecpp.so.0 -> libpcrecpp.so.0.0.0 - libgstinterfaces-0.10.so.0 -> libgstinterfaces-0.10.so.0.25.0 - libelf.so.1 -> libelf-0.152.so - libdrm_nouveau.so.1 -> libdrm_nouveau1.so - libthai.so.0 -> libthai.so.0.1.6 - libgstnet-1.0.so.0 -> libgstnet-1.0.so.0.201.0 - libcares.so.2 -> libcares.so.2.0.0 - liborc-test-0.4.so.0 -> liborc-test-0.4.so.0.18.0 - libaa.so.1 -> libaa.so.1.0.4 - libsvn_ra_local-1.so.1 -> libsvn_ra_local-1.so.1.0.0 - libdrm.so.2 -> libdrm.so.2.4.0 - libLLVM-3.3.so.1 -> libLLVM-3.3.so.1 - libpcap.so.0.8 -> libpcap.so.1.1.1 - libcupsmime.so.1 -> libcupsmime.so.1 - libxcb.so.1 -> libxcb.so.1.1.0 - libSM.so.6 -> libSM.so.6.0.1 - libkms.so.1 -> libkms.so.1.0.0 - libdbusmenu-gtk.so.4 -> libdbusmenu-gtk.so.4.0.13 - libFLAC.so.8 -> libFLAC.so.8.2.0 - libxcb-xfixes.so.0 -> libxcb-xfixes.so.0.0.0 - libgstriff-1.0.so.0 -> libgstriff-1.0.so.0.201.0 - libidn.so.11 -> libidn.so.11.6.6 - libIDL-2.so.0 -> libIDL-2.so.0.0.0 - libdbusmenu-qt.so.2 -> libdbusmenu-qt.so.2.6.0 - libQtScript.so.4 -> libQtScript.so.4.8.1 - libcairo-gobject.so.2 -> libcairo-gobject.so.2.11000.2 - libluajit-5.1.so.2 -> libluajit-5.1.so.2.0.0 - libpangomm-1.4.so.1 -> libpangomm-1.4.so.1.0.30 - libXpm.so.4 -> libXpm.so.4.11.0 - libsvn_diff-1.so.1 -> libsvn_diff-1.so.1.0.0 - libdbusmenu-glib.so.4 -> libdbusmenu-glib.so.4.0.13 - liblua5.1.so.0 -> liblua5.1.so.0.0.0 - libbonobo-2.so.0 -> libbonobo-2.so.0.0.0 - libpulse-mainloop-glib.so.0 -> libpulse-mainloop-glib.so.0.0.4 - libexslt.so.0 -> libexslt.so.0.8.15 - libmp3lame.so.0 -> libmp3lame.so.0.0.0 - libpcreposix.so.3 -> libpcreposix.so.3.12.1 - libquvi.so.7 -> libquvi.so.7.0.0 - libaudio.so.2 -> libaudio.so.2.4 - libpulse-simple.so.0 -> libpulse-simple.so.0.0.3 - liboauth.so.0 -> liboauth.so.0.8.1 - libQtCore.so.4 -> libQtCore.so.4.8.1 - libwayland_ltss-client.so.0 -> libwayland_ltss-client.so.0.1.0 - libQtDBus.so.4 -> libQtDBus.so.4.8.1 - libtheoraenc.so.1 -> libtheoraenc.so.1.1.2 - libatkmm-1.6.so.1 -> libatkmm-1.6.so.1.1.0 - libgailutil-3.so.0 -> libgailutil-3.so.0.0.0 - libgsttag-1.0.so.0 -> libgsttag-1.0.so.0.201.0 - libgdk_pixbuf_xlib-2.0.so.0 -> libgdk_pixbuf_xlib-2.0.so.0.2600.1 - libkrb5.so.3 -> libkrb5.so.3.3 - libgnome-2.so.0 -> libgnome-2.so.0.3200.1 - libgallium.so.0 -> libgallium.so.0.0.0 - libXcomposite.so.1 -> libXcomposite.so.1.0.0 - libsvn_fs-1.so.1 -> libsvn_fs-1.so.1.0.0 - libgstreamer-0.10.so.0 -> libgstreamer-0.10.so.0.30.0 - libXrender.so.1 -> libXrender.so.1.3.0 - libmng.so.1 -> libmng.so.1.1.0.10 - libgdu.so.0 -> libgdu.so.0.0.0 - libxatracker.so.1 -> libxatracker.so.1.0.0 - librom1394.so.0 -> librom1394.so.0.3.0 - liblua5.1-c++.so.0 -> liblua5.1-c++.so.0.0.0 - libplds4.so -> libplds4.so - libbamf.so.0 -> libbamf.so.0.0.0 - libheimntlm.so.0 -> libheimntlm.so.0.1.0 - libarchive.so.12 -> libarchive.so.12.0.3 - libmad.so.0 -> libmad.so.0.2.1 - libgthread-2.0.so.0 -> libgthread-2.0.so.0.3200.4 - libgstaudio-1.0.so.0 -> libgstaudio-1.0.so.0.201.0 - libgudev-1.0.so.0 -> libgudev-1.0.so.0.1.1 - libvpx.so.1 -> libvpx.so.1.2.0 - libgailutil.so.18 -> libgailutil.so.18.0.1 - libsvn_client-1.so.1 -> libsvn_client-1.so.1.0.0 - libdricore9.2.1.so.1 -> libdricore9.2.1.so.1.0.0 - libQtOpenGL.so.4 -> libQtOpenGL.so.4.8.1 - libhunspell-1.3.so.0 -> libhunspell-1.3.so.0.0.0 - libcupsppdc.so.1 -> libcupsppdc.so.1 - libkdb5.so.6 -> libkdb5.so.6.0 - libpixman-1.so.0 -> libpixman-1.so.0.30.2 - libpolkit-backend-1.so.0 -> libpolkit-backend-1.so.0.0.0 - libibus-1.0.so.0 -> libibus-1.0.so.0.401.0 - libxcb-dri2.so.0 -> libxcb-dri2.so.0.0.0 - libgstcheck-0.10.so.0 -> libgstcheck-0.10.so.0.30.0 - libXp.so.6 -> libXp.so.6.2.0 - libart_lgpl_2.so.2 -> libart_lgpl_2.so.2.3.21 - libhx509.so.5 -> libhx509.so.5.0.0 - libform.so.5 -> libform.so.5.9 - libgstbase-1.0.so.0 -> libgstbase-1.0.so.0.201.0 - libX11-xcb.so.1 -> libX11-xcb.so.1.0.0 - libgstaudio-0.10.so.0 -> libgstaudio-0.10.so.0.25.0 - libjson-glib-1.0.so.0 -> libjson-glib-1.0.so.0.1400.2 - libspeex.so.1 -> libspeex.so.1.5.0 - libsvn_fs_util-1.so.1 -> libsvn_fs_util-1.so.1.0.0 - libpoppler.so.19 -> libpoppler.so.19.0.0 - libdconf.so.0 -> libdconf.so.0.0.0 - libavahi-common.so.3 -> libavahi-common.so.3.5.3 - libyajl.so.1 -> libyajl.so.1.0.12 - libvorbis.so.0 -> libvorbis.so.0.4.5 - libavc1394.so.0 -> libavc1394.so.0.3.0 - libv4l2.so.0 -> libv4l2.so.0 - libcolord.so.1 -> libcolord.so.1.0.8 - libcairo.so.2 -> libcairo.so.2.11000.2 - libGLEW.so.1.6 -> libGLEW.so.1.6.0 - libgdbm_compat.so.3 -> libgdbm_compat.so.3.0.0 - libdb-5.1.so -> libdb-5.1.so - libXt.so.6 -> libXt.so.6.0.0 - libwavpack.so.1 -> libwavpack.so.1.1.4 - libmpfr.so.4 -> libmpfr.so.4.1.0 - libpangoft2-1.0.so.0 -> libpangoft2-1.0.so.0.3000.0 - libieee1284.so.3 -> libieee1284.so.3.2.2 - libfreetype.so.6 -> libfreetype.so.6.8.0 - libdrm_nouveau.so.2 -> libdrm_nouveau.so.2.0.0 - libgssapi.so.3 -> libgssapi.so.3.0.0 - libspeexdsp.so.1 -> libspeexdsp.so.1.5.0 - libdconf-dbus-1.so.0 -> libdconf-dbus-1.so.0.0.0 - libgmp.so.10 -> libgmp.so.10.0.2 - libcaca.so.0 -> libcucul.so.0.99.17 - libcairomm-1.0.so.1 -> libcairomm-1.0.so.1.4.0 - libsvn_repos-1.so.1 -> libsvn_repos-1.so.1.0.0 - libgupnp-igd-1.0.so.4 -> libgupnp-igd-1.0.so.4.1.0 - libgstvideo-1.0.so.0 -> libgstvideo-1.0.so.0.201.0 - libXdamage.so.1 -> libXdamage.so.1.1.0 - libasn1.so.8 -> libasn1.so.8.0.0 - libsvn_fs_base-1.so.1 -> libsvn_fs_base-1.so.1.0.0 - libvorbisenc.so.2 -> libvorbisenc.so.2.0.8 - libgstapp-1.0.so.0 -> libgstapp-1.0.so.0.201.0 - libvo-amrwbenc.so.0 -> libvo-amrwbenc.so.0.0.2 - libtalloc.so.2 -> libtalloc.so.2.0.7 - libshout.so.3 -> libshout.so.3.2.0 - libnice.so.10 -> libnice.so.10.0.1 - libbluetooth.so.3 -> libbluetooth.so.3.11.5 - libgrail.so.5 -> libgrail.so.5.0.0 - libgutenprint.so.3 -> libgutenprint.so.3.0.0 - libmenuw.so.5 -> libmenuw.so.5.9 - libpanelw.so.5 -> libpanelw.so.5.9 - libkrb5.so.26 -> libkrb5.so.26.0.0 - libgdu-gtk.so.0 -> libgdu-gtk.so.0.0.0 - libgdbm.so.3 -> libgdbm.so.3.0.0 - libgnutls-openssl.so.27 -> libgnutls-openssl.so.27.0.0 - libmenu.so.5 -> libmenu.so.5.9 - libpangox-1.0.so.0 -> libpangox-1.0.so.0.3000.0 - libXft.so.2 -> libXft.so.2.2.0 - libsensors.so.4 -> libsensors.so.4.3.1 - libgstphotography-0.10.so.0 -> libgstphotography-0.10.so.0.0.0 - libstartup-notification-1.so.0 -> libstartup-notification-1.so.0.0.0 - libatk-1.0.so.0 -> libatk-1.0.so.0.20409.1 - libsvn_auth_gnome_keyring-1.so.1 -> libsvn_auth_gnome_keyring-1.so.1.0.0 - libquadmath.so.0 -> libquadmath.so.0.0.0 - libgif.so.4 -> libungif.so.4.1.6 - libstdc++.so.6 -> libstdc++.so.6.0.16 - liblzma.so.5 -> liblzma.so.5.0.0 - libass.so.4 -> libass.so.4.1.0 - libproxy.so.1 -> libproxy.so.1.0.0 - libcaca++.so.0 -> libcucul++.so.0.99.17 - libglade-2.0.so.0 -> libglade-2.0.so.0.0.7 - libavutil.so.51 -> libavutil.so.51.22.2 - libxslt.so.1 -> libxslt.so.1.1.26 - libva.so.1 -> libva.so.1.3200.0 - libsmime3.so -> libsmime3.so - libdv.so.4 -> libdv.so.4.0.3 - libavahi-client.so.3 -> libavahi-client.so.3.2.9 - libsvn_fs_fs-1.so.1 -> libsvn_fs_fs-1.so.1.0.0 - libgiomm-2.4.so.1 -> libgiomm-2.4.so.1.3.0 - libgstrtp-1.0.so.0 -> libgstrtp-1.0.so.0.201.0 - libgnutls.so.26 -> libgnutls.so.26.21.8 - libQtXmlPatterns.so.4 -> libQtXmlPatterns.so.4.8.1 - libao.so.4 -> libao.so.4.0.0 - libpulsecommon-1.1.so -> libpulsecommon-1.1.so - libQtCLucene.so.4 -> libQtCLucene.so.4.8.1 - libgstbase-0.10.so.0 -> libgstbase-0.10.so.0.30.0 - libsvn_auth_kwallet-1.so.1 -> libsvn_auth_kwallet-1.so.1.0.0 - libjpeg.so.8 -> libjpeg.so.8.0.2 - libsamplerate.so.0 -> libsamplerate.so.0.1.8 - libcurl.so.4 -> libcurl.so.4.2.0 - libpipeline.so.1 -> libpipeline.so.1.2.1 - libglamor_ltss.so.0 -> libglamor_ltss.so.0.0.0 - libpciaccess.so.0 -> libpciaccess.so.0.11.0 - libnssutil3.so -> libnssutil3.so - libgstriff-0.10.so.0 -> libgstriff-0.10.so.0.25.0 - libXcursor.so.1 -> libXcursor.so.1.0.2 - libformw.so.5 -> libformw.so.5.9 - libjson.so.0 -> libjson.so.0.0.1 - libgconf-2.so.4 -> libgconf-2.so.4.1.5 - libkrb5support.so.0 -> libkrb5support.so.0.1 - libwmf-0.2.so.7 -> libwmf-0.2.so.7.1.0 - libdiscid.so.0 -> libdiscid.so.0.2.1 - libjacknet.so.0 -> libjacknet.so.0.1.0 - libgstbasecamerabinsrc-0.10.so.0 -> libgstbasecamerabinsrc-0.10.so.0.0.0 - libgee.so.2 -> libgee.so.2.0.0 - libavahi-core.so.7 -> libavahi-core.so.7.0.2 - liblcms.so.1 -> liblcms.so.1.0.19 - liblockfile.so.1 -> liblockfile.so.1.0 - libdb-4.8.so -> libdb-4.8.so - libxcb-glx.so.0 -> libxcb-glx.so.0.0.0 - libtiffxx.so.0 -> libtiffxx.so.0.0.8 - libasyncns.so.0 -> libasyncns.so.0.3.1 - libcdda_interface.so.0 -> libcdda_interface.so.0.10.2 - libgstrtsp-0.10.so.0 -> libgstrtsp-0.10.so.0.25.0 - libtheora.so.0 -> libtheora.so.0.3.10 - libvo-aacenc.so.0 -> libvo-aacenc.so.0.0.2 - libORBit-2.so.0 -> libORBit-2.so.0.1.0 - libv4lconvert.so.0 -> libv4lconvert.so.0 - libXv.so.1 -> libXv.so.1.0.0 - libgnomeui-2.so.0 -> libgnomeui-2.so.0.2400.5 - libsvn_wc-1.so.1 -> libsvn_wc-1.so.1.0.0 - libgstphotography-1.0.so.0 -> libgstphotography-1.0.so.0.7.0 - libasound.so.2 -> libasound.so.2.0.0 - libsvn_ra_neon-1.so.1 -> libsvn_ra_neon-1.so.1.0.0 - libcroco-0.6.so.3 -> libcroco-0.6.so.3.0.1 - libopus.so.0 -> libopus.so.0.5.0 - libXext.so.6 -> libXext.so.6.4.0 - libXrandr.so.2 -> libXrandr.so.2.2.0 - libQtSql.so.4 -> libQtSql.so.4.8.1 - libsonic.so.0 -> libsonic.so.0.1.17 - libapt-inst.so.1.4 -> libapt-inst.so.1.4.0 - libgstvideo-0.10.so.0 -> libgstvideo-0.10.so.0.25.0 - libpanel.so.5 -> libpanel.so.5.9 - libSoundTouch.so.0 -> libSoundTouch.so.0.0.0 - libgd.so.2 -> libgd.so.2.0.0 - libXxf86vm.so.1 -> libXxf86vm.so.1.0.0 - libpulsedsp.so -> libpulsedsp.so - libGLU.so.1 -> libGLU.so.1.3.08004 - libmpc.so.2 -> libmpc.so.2.0.0 - libgdk_pixbuf-2.0.so.0 -> libgdk_pixbuf-2.0.so.0.2600.1 - libroken.so.18 -> libroken.so.18.1.0 - libtasn1.so.3 -> libtasn1.so.3.1.12 - libsvn_delta-1.so.1 -> libsvn_delta-1.so.1.0.0 - libgstrtp-0.10.so.0 -> libgstrtp-0.10.so.0.25.0 - libgstnetbuffer-0.10.so.0 -> libgstnetbuffer-0.10.so.0.25.0 - libgstfft-1.0.so.0 -> libgstfft-1.0.so.0.201.0 - libORBit-imodule-2.so.0 -> libORBit-imodule-2.so.0.0.0 - libkadm5srv_mit.so.8 -> libkadm5srv_mit.so.8.0 - libgssapi_krb5.so.2 -> libgssapi_krb5.so.2.2 - libdrm_radeon.so.1 -> libdrm_radeon.so.1.0.1 - libgoa-backend-1.0.so.0 -> libgoa-backend-1.0.so.0.0.0 - libXmuu.so.1 -> libXmuu.so.1.0.0 - libpango-1.0.so.0 -> libpango-1.0.so.0.3000.0 - libsigc-2.0.so.0 -> libsigc-2.0.so.0.0.0 - libsoup-2.4.so.1 -> libsoup-2.4.so.1.5.0 - libssh_threads.so.4 -> libssh_threads.so.4.2.2 - libkadm5clnt_mit.so.8 -> libkadm5clnt_mit.so.8.0 - libgstcodecparsers-1.0.so.0 -> libgstcodecparsers-1.0.so.0.5.0 - libgstrtsp-1.0.so.0 -> libgstrtsp-1.0.so.0.201.0 - libgtk-x11-2.0.so.0 -> libgtk-x11-2.0.so.0.2400.10 - libespeak.so.1 -> libespeak.so.1.1.46 - libjack.so.0 -> libjack.so.0.1.0 - libxcb-shm.so.0 -> libxcb-shm.so.0.0.0 - libQtSvg.so.4 -> libQtSvg.so.4.8.1 - libglibmm_generate_extra_defs-2.4.so.1 -> libglibmm_generate_extra_defs-2.4.so.1.3.0 - libcurl-nss.so.4 -> libcurl-nss.so.4.2.0 - libtelepathy-logger.so.2 -> libtelepathy-logger.so.2.2.1 - libX11.so.6 -> libX11.so.6.3.0 - libexpatw.so.1 -> libexpatw.so.1.5.2 - libxml2.so.2 -> libxml2.so.2.7.8 - libsane.so.1 -> libsane.so.1.0.22 - libgeis.so.1 -> libgeis.so.1.3.0 - libgnome-keyring.so.0 -> libgnome-keyring.so.0.2.0 - libgdk-3.so.0 -> libgdk-3.so.0.400.2 - libgstreamer-1.0.so.0 -> libgstreamer-1.0.so.0.201.0 - libgstcheck-1.0.so.0 -> libgstcheck-1.0.so.0.201.0 - libheimbase.so.1 -> libheimbase.so.1.0.0 - libsasl2.so.2 -> libsasl2.so.2.0.25 - liblouis.so.2 -> liblouis.so.2.2.3 - libgnomevfs-2.so.0 -> libgnomevfs-2.so.0.2400.4 - libgstdataprotocol-0.10.so.0 -> libgstdataprotocol-0.10.so.0.30.0 - libvorbisfile.so.3 -> libvorbisfile.so.3.3.4 -/usr/local/lib: - libefreet.so.1 -> libefreet.so.1.9.3 - libecore_ipc.so.1 -> libecore_ipc.so.1.9.3 - libefreet_trash.so.1 -> libefreet_trash.so.1.9.3 - libecore_evas.so.1 -> libecore_evas.so.1.9.3 - libecore.so.1 -> libecore.so.1.9.3 - libmosquittopp.so.1 -> libmosquittopp.so.1 - libeina.so.1 -> libeina.so.1.9.3 - libeet.so.1 -> libeet.so.1.9.3 - libecore_imf_evas.so.1 -> libecore_imf_evas.so.1.9.3 - libembryo.so.1 -> libembryo.so.1.9.3 - libecore_avahi.so.1 -> libecore_avahi.so.1.9.3 - libeldbus.so.1 -> libeldbus.so.1.9.3 - libethumb.so.1 -> libethumb.so.1.9.3 - libemotion.so.1 -> libemotion.so.1.9.3 - libecore_con.so.1 -> libecore_con.so.1.9.3 - libecore_imf.so.1 -> libecore_imf.so.1.9.3 - libeeze.so.1 -> libeeze.so.1.9.3 - libecore_input.so.1 -> libecore_input.so.1.9.3 - libedje.so.1 -> libedje.so.1.9.3 - libeo.so.1 -> libeo.so.1.9.3 - libethumb_client.so.1 -> libethumb_client.so.1.9.3 - libecore_file.so.1 -> libecore_file.so.1.9.3 - libeio.so.1 -> libeio.so.1.9.3 - libmosquitto.so.1 -> libmosquitto.so.1 - libelementary.so.1 -> libelementary.so.1.9.3 - libecore_audio.so.1 -> libecore_audio.so.1.9.3 - libevas.so.1 -> libevas.so.1.9.3 - libecore_input_evas.so.1 -> libecore_input_evas.so.1.9.3 - libefreet_mime.so.1 -> libefreet_mime.so.1.9.3 - libecore_x.so.1 -> libecore_x.so.1.9.3 -/lib: - libnl-genl-3.so.200 -> libnl-genl-3.so.200.3.0 - libnss_mdns6_minimal.so.2 -> libnss_mdns6_minimal.so.2 - libip6tc.so.0 -> libip6tc.so.0.0.0 - libply.so.2 -> libply.so.2.0.0 - libnss_mdns6.so.2 -> libnss_mdns6.so.2 - libipq_pic.so.0 -> libipq_pic.so.0.0.0 - liblvm2app.so.2.2 -> liblvm2app.so.2.2 - libdevmapper.so.1.02.1 -> libdevmapper.so.1.02.1 - libcryptsetup.so.4 -> libcryptsetup.so.4.0.0 - libnss_mdns.so.2 -> libnss_mdns.so.2 - libnss_mdns_minimal.so.2 -> libnss_mdns_minimal.so.2 - libfuse.so.2 -> libfuse.so.2.8.6 - libiw.so.30 -> libiw.so.30 - libdevmapper-event.so.1.02.1 -> libdevmapper-event.so.1.02.1 - libply-splash-graphics.so.2 -> libply-splash-graphics.so.2.0.0 - libply-splash-core.so.2 -> libply-splash-core.so.2.0.0 - libsysfs.so.2 -> libsysfs.so.2.0.1 - libply-boot-client.so.2 -> libply-boot-client.so.2.0.0 - libnss_mdns4.so.2 -> libnss_mdns4.so.2 - libnss_mdns4_minimal.so.2 -> libnss_mdns4_minimal.so.2 - libproc-3.2.8.so -> libproc-3.2.8.so - libbrlapi.so.0.5 -> libbrlapi.so.0.5.6 - libnewt.so.0.52 -> libnewt.so.0.52.11 - libipq.so.0 -> libipq.so.0.0.0 - libiptc.so.0 -> libiptc.so.0.0.0 - libulockmgr.so.1 -> libulockmgr.so.1.0.1 - libnl-3.so.200 -> libnl-3.so.200.3.0 - libxtables.so.7 -> libxtables.so.7.0.0 - libip4tc.so.0 -> libip4tc.so.0.0.0 - libx86.so.1 -> libx86.so.1 -/usr/lib: - liba52-0.7.4.so -> liba52-0.7.4.so - libvncserver.so.0 -> libvncserver.so.0.0.0 - libspandsp.so.2 -> libspandsp.so.2.0.0 - libflite_usenglish.so.1 -> libflite_usenglish.so.1.4 - libido3-0.1.so.0 -> libido3-0.1.so.0.0.0 - libicui18n.so.48 -> libicui18n.so.48.1.1 - libXvMC.so.1 -> libXvMC.so.1.0.0 - libdmapsharing-3.0.so.2 -> libdmapsharing-3.0.so.2.9.14 - libgmime-2.6.so.0 -> libgmime-2.6.so.0.600.7 - libefreet_trash.so.1 -> libefreet_trash.so.1.0.0 - libQtGConf.so.1 -> libQtGConf.so.1.0.0 - libbfd-2.22-system.so -> libbfd-2.22-system.so - libgs.so.9 -> libgs.so.9.05 - libedbus.so.1 -> libedbus.so.1.0.0 - libperl.so.5.14 -> libperl.so.5.14.2 - libgdkmm-3.0.so.1 -> libgdkmm-3.0.so.1.1.0 - libeconnman.so.1 -> libeconnman.so.1.0.0 - libxklavier.so.16 -> libxklavier.so.16.2.0 - libnux-2.0.so.0 -> libnux-2.0.so.0.1401.0 - libvlccore.so.5 -> libvlccore.so.5.1.1 - libopcodes-2.22-system.so -> libopcodes-2.22-system.so - libaccountsservice.so.0 -> libaccountsservice.so.0.0.0 - libnm-util.so.2 -> libnm-util.so.2.3.0 - libjavascriptcoregtk-1.0.so.0 -> libjavascriptcoregtk-1.0.so.0.13.4 - libpulsecore-1.1.so -> libpulsecore-1.1.so - libflite_cmu_us_slt.so.1 -> libflite_cmu_us_slt.so.1.4 - libkeybinder.so.0 -> libkeybinder.so.0.0.1 - libguile-srfi-srfi-1-v-3.so.3 -> libguile-srfi-srfi-1-v-3.so.3.0.2 - libindicator-messages-status-provider.so.1 -> libindicator-messages-status-provider.so.1.0.0 - libopencore-amrwb.so.0 -> libopencore-amrwb.so.0.0.2 - libfolks.so.25 -> libfolks.so.25.7.0 - libisccc.so.80 -> libisccc.so.80.0.0 - libutempter.so.0 -> libutempter.so.1.1.5 - libijs-0.35.so -> libijs-0.35.so - libefreet.so.1 -> libefreet.so.1.0.0 - libflite_cmu_us_awb.so.1 -> libflite_cmu_us_awb.so.1.4 - libwpg-0.2.so.2 -> libwpg-0.2.so.2.0.1 - libvte2_90.so.9 -> libvte2_90.so.9.3200.1 - libvncclient.so.0 -> libvncclient.so.0.0.0 - libtcl8.5.so.0 -> libtcl8.5.so.0 - libgnome-control-center.so.1 -> libgnome-control-center.so.1.0.0 - libpyglib-gi-2.0-python2.7.so.0 -> libpyglib-gi-2.0-python2.7.so.0.0.0 - libisc.so.83 -> libisc.so.83.0.1 - libenotify.so.1 -> libenotify.so.1.0.0 - libwps-0.2.so.2 -> libwps-0.2.so.2.0.4 - libschroedinger-1.0.so.0 -> libschroedinger-1.0.so.0.11.0 - libgtkmm-3.0.so.1 -> libgtkmm-3.0.so.1.1.0 - librest-0.7.so.0 -> librest-0.7.so.0.0.0 - libicalss.so.0 -> libicalss.so.0.48.0 - libgrip.so.0 -> libgrip.so.0.305.0 - libtimezonemap.so.1 -> libtimezonemap.so.1.0.0 - libecore_evas.so.1 -> libecore_evas.so.1.0.0 - libvte.so.9 -> libvte.so.9.2800.2 - libmetacity-private.so.0 -> libmetacity-private.so.0.0.0 - libXxf86dga.so.1 -> libXxf86dga.so.1.0.0 - libgck-1.so.0 -> libgck-1.so.0.0.0 - libicutu.so.48 -> libicutu.so.48.1.1 - libedje.so.1 -> libedje.so.1.0.0 - libgwibber-gtk.so.2 -> libgwibber-gtk.so.2.0.0 - libpurple-client.so.0 -> libpurple-client.so.0.10.3 - libhpip.so.0 -> libhpip.so.0.0.1 - libwnck-1.so.22 -> libwnck-1.so.22.3.31 - libfreerdp-core.so.1.0 -> libfreerdp-core.so.1.0.1 - libmhash.so.2 -> libmhash.so.2.0.1 - libindicator3.so.7 -> libindicator3.so.7.0.0 - libfreerdp-codec.so.1.0 -> libfreerdp-codec.so.1.0.1 - libflite.so.1 -> libflite.so.1.4 - libgweather-3.so.0 -> libgweather-3.so.0.0.6 - libpeas-1.0.so.0 -> libpeas-1.0.so.0.200.0 - libbind9.so.80 -> libbind9.so.80.0.3 - libgnomekbd.so.7 -> libgnomekbd.so.7.0.0 - libcrypto.so.1.0.0 -> libcrypto.so.1.0.0 - libwnck-3.so.0 -> libwnck-3.so.0.2.0 - libeina.so.1 -> libeina.so.1.0.0 - libebook-1.2.so.12 -> libebook-1.2.so.12.3.1 - libFS.so.6 -> libFS.so.6.0.0 - libnetsnmpagent.so.15 -> libnetsnmpagent.so.15.1.2 - libdaemon.so.0 -> libdaemon.so.0.5.0 - libfribidi.so.0 -> libfribidi.so.0.3.1 - libeet.so.1 -> libeet.so.1.4.0 - libunity-misc.so.4 -> libunity-misc.so.4.1.0 - libbulletml.so.0d2 -> libbulletml.so.0d2.0 - libebluez.so.1 -> libebluez.so.1.0.0 - libindicate.so.5 -> libindicate.so.5.0.7 - libicule.so.48 -> libicule.so.48.1.1 - libmtdev.so.1 -> libmtdev.so.1.0.0 - libgnome-media-profiles-3.0.so.0 -> libgnome-media-profiles-3.0.so.0.0.0 - libnetsnmpmibs.so.15 -> libnetsnmpmibs.so.15.1.2 - liboverlay-scrollbar-0.2.so.0 -> liboverlay-scrollbar-0.2.so.0.0.16 - libecore_imf_evas.so.1 -> libecore_imf_evas.so.1.0.0 - libpaper.so.1 -> libpaper.so.1.1.2 - libjte.so.1 -> libjte.so.1.0.0 - libdotconf-1.0.so.0 -> libdotconf-1.0.so.0.10.4 - libicutest.so.48 -> libicutest.so.48.1.1 - libmimic.so.0 -> libmimic.so.0.0.1 - libeukit.so.1 -> libeukit.so.1.0.0 - libtotem-plparser.so.17 -> libtotem-plparser.so.17.0.3 - libfolks-telepathy.so.25 -> libfolks-telepathy.so.25.7.0 - libgtop-2.0.so.7 -> libgtop-2.0.so.7.2.0 - libtwolame.so.0 -> libtwolame.so.0.0.0 - libgwibber.so.2 -> libgwibber.so.2.0.0 - libfreerdp-utils.so.1.0 -> libfreerdp-utils.so.1.0.1 - libgnome-menu.so.2 -> libgnome-menu.so.2.4.13 - libecore_file.so.1 -> libecore_file.so.1.0.0 - libedataserver-1.2.so.15 -> libedataserver-1.2.so.15.0.0 - librasqal.so.3 -> librasqal.so.3.0.0 - libgexiv2.so.1 -> libgexiv2.so.1.0.0 - libgettextlib-0.18.1.so -> libgettextlib.so - libmythes-1.2.so.0 -> libmythes-1.2.so.0.0.0 - libprotoc.so.7 -> libprotoc.so.7.0.0 - libfreerdp-rail.so.1.0 -> libfreerdp-rail.so.1.0.1 - libsgutils2.so.2 -> libsgutils2.so.2.0.0 - libaprutil-1.so.0 -> libaprutil-1.so.0.3.12 - libraptor2.so.0 -> libraptor2.so.0.0.0 - libgirepository-1.0.so.1 -> libgirepository-1.0.so.1.0.0 - libunity-core-5.0.so.5 -> libunity-core-5.0.so.5.0.0 - libflite_cmu_us_kal16.so.1 -> libflite_cmu_us_kal16.so.1.4 - libecore_con.so.1 -> libecore_con.so.1.0.0 - libecore_input_evas.so.1 -> libecore_input_evas.so.1.0.0 - libjbig2dec.so.0 -> libjbig2dec.so.0.0.0 - libnetsnmp.so.15 -> libnetsnmp.so.15.1.2 - libzbar.so.0 -> libzbar.so.0.2.0 - libXRes.so.1 -> libXRes.so.1.0.0 - libcdio_paranoia.so.1 -> libcdio_paranoia.so.1.0.0 - libedata-book-1.2.so.11 -> libedata-book-1.2.so.11.0.0 - libnetsnmphelpers.so.15 -> libnetsnmphelpers.so.15.1.2 - libgksu2.so.0 -> libgksu2.so.0.0.2 - libQtBamf.so.1 -> libQtBamf.so.1.0.0 - libnautilus-extension.so.1 -> libnautilus-extension.so.1.4.0 - libebackend-1.2.so.1 -> libebackend-1.2.so.1.0.0 - libI810XvMC.so.1 -> libI810XvMC.so.1.0.0 - libembryo.so.1 -> libembryo.so.1.0.0 - libmission-control-plugins.so.0 -> libmission-control-plugins.so.0.3.1 - libguilereadline-v-17.so.17 -> libguilereadline-v-17.so.17.0.3 - libsox.so.1 -> libsox.so.1.0.0 - libcdio.so.13 -> libcdio.so.13.0.0 - libsqlite.so.0 -> libsqlite.so.0.8.6 - libecore_imf.so.1 -> libecore_imf.so.1.0.0 - libevdocument3.so.4 -> libevdocument3.so.4.0.0 - libehal.so.1 -> libehal.so.1.0.0 - libt1.so.5 -> libt1.so.5.1.2 - libdconf-qt.so.0 -> libdconf-qt.so.0.0.0 - libboost_wserialization.so.1.46.1 -> libboost_wserialization.so.1.46.1 - libaspell.so.15 -> libaspell.so.15.2.0 - libusbmuxd.so.1 -> libusbmuxd.so.1.0.7 - libevent-2.0.so.5 -> libevent-2.0.so.5.1.4 - libdee-1.0.so.4 -> libdee-1.0.so.4.1.1 - libimobiledevice.so.2 -> libimobiledevice.so.2.0.1 - libtotem.so.0 -> libtotem.so.0.0.0 - libopencore-amrnb.so.0 -> libopencore-amrnb.so.0.0.2 - libgtkspell-3.so.0 -> libgtkspell-3.so.0.0.0 - libsyncdaemon-1.0.so.1 -> libsyncdaemon-1.0.so.1.0.0 - libid3tag.so.0 -> libid3tag.so.0.3.0 - libxcb-keysyms.so.1 -> libxcb-keysyms.so.1.0.0 - liblwres.so.80 -> liblwres.so.80.0.1 - libgnome-menu-3.so.0 -> libgnome-menu-3.so.0.0.1 - libgpgme-pthread.so.11 -> libgpgme-pthread.so.11.7.0 - libXvMCW.so.1 -> libXvMCW.so.1.0.0 - libenchant.so.1 -> libenchant.so.1.6.0 - libgupnp-1.0.so.4 -> libgupnp-1.0.so.4.0.0 - liblightdm-gobject-1.so.0 -> liblightdm-gobject-1.so.0.0.0 - libasprintf.so.0 -> libasprintf.so.0.0.0 - libprotobuf.so.7 -> libprotobuf.so.7.0.0 - libwebkitgtk-1.0.so.0 -> libwebkitgtk-1.0.so.0.13.4 - libmpeg2.so.0 -> libmpeg2.so.0.0.0 - libssl.so.1.0.0 -> libssl.so.1.0.0 - libfreerdp-gdi.so.1.0 -> libfreerdp-gdi.so.1.0.1 - libgpgme.so.11 -> libgpgme.so.11.7.0 - libplist.so.1 -> libplist.so.1.1.8 - libmtp.so.9 -> libmtp.so.9.0.3 - libecore_x.so.1 -> libecore_x.so.1.0.0 - libcap-ng.so.0 -> libcap-ng.so.0.0.0 - libnux-core-2.0.so.0 -> libnux-core-2.0.so.0.1401.0 - libpyglib-2.0-python2.7.so.0 -> libpyglib-2.0-python2.7.so.0.0.0 - libsidplay.so.1 -> libsidplay.so.1.0.3 - libXfont.so.1 -> libXfont.so.1.4.1 - libical.so.0 -> libical.so.0.48.0 - libdvdnav.so.4 -> libdvdnav.so.4.2.0 - libfreerdp-cache.so.1.0 -> libfreerdp-cache.so.1.0.1 - libexttextcat.so.0 -> libexttextcat.so.0.0.0 - libboost_serialization.so.1.46.1 -> libboost_serialization.so.1.46.1 - libmagic.so.1 -> libmagic.so.1.0.0 - libcamel-provider-1.2.so.29 -> libcamel-provider-1.2.so.29.0.0 - libedata-cal-1.2.so.13 -> libedata-cal-1.2.so.13.0.0 - libxcb-image.so.0 -> libxcb-image.so.0.0.0 - librpmbuild.so.2 -> librpmbuild.so.2.0.1 - libzeitgeist-1.0.so.1 -> libzeitgeist-1.0.so.1.1.4 - libmpeg2convert.so.0 -> libmpeg2convert.so.0.0.0 - libecore.so.1 -> libecore.so.1.0.0 - libwpd-0.9.so.9 -> libwpd-0.9.so.9.0.4 - libmms.so.0 -> libmms.so.0.0.2 - libstlport_gcc.so.4.6 -> libstlport_gcc.so.4.6 - libopencc.so.1 -> libopencc.so.1.0.0 - libck-connector.so.0 -> libck-connector.so.0.0.0 - libcdio_cdda.so.1 -> libcdio_cdda.so.1.0.0 - librdf.so.0 -> librdf.so.0.0.0 - libtelepathy-glib.so.0 -> libtelepathy-glib.so.0.70.2 - libGeoIPUpdate.so.0 -> libGeoIPUpdate.so.0.0.0 - libraw_r.so.5 -> libraw_r.so.5.0.0 - libwebkitgtk-3.0.so.0 -> libwebkitgtk-3.0.so.0.13.4 - libbrasero-utils3.so.1 -> libbrasero-utils3.so.1.2.3 - libgcr-3.so.1 -> libgcr-3.so.1.0.0 - libdca.so.0 -> libdca.so.0.0.0 - libcompizconfig.so.0 -> libcompizconfig.so.0.0.0 - librpmsign.so.0 -> librpmsign.so.0.0.1 - libburn.so.4 -> libburn.so.4.71.0 - libzephyr.so.4 -> libzephyr.so.4.0.0 - libcamel-1.2.so.29 -> libcamel-1.2.so.29.0.0 - libmodplug.so.1 -> libmodplug.so.1.0.0 - liblrdf.so.0 -> liblrdf.so.0.0.0 - libflite_cmu_us_kal.so.1 -> libflite_cmu_us_kal.so.1.4 - libjavascriptcoregtk-3.0.so.0 -> libjavascriptcoregtk-3.0.so.0.13.4 - libiculx.so.48 -> libiculx.so.48.1.1 - libgdata.so.13 -> libgdata.so.13.2.0 - libedataserverui-3.0.so.1 -> libedataserverui-3.0.so.1.0.0 - libecore_ipc.so.1 -> libecore_ipc.so.1.0.0 - libindicate-gtk.so.3 -> libindicate-gtk.so.3.0.3 - libexiv2.so.11 -> libexiv2.so.11.0.0 - libyelp.so.0 -> libyelp.so.0.0.0 - libxapian.so.22 -> libxapian.so.22.4.2 - libnm-glib.so.4 -> libnm-glib.so.4.3.0 - libflite_cmu_time_awb.so.1 -> libflite_cmu_time_awb.so.1.4 - libhpmud.so.0 -> libhpmud.so.0.0.6 - librarian.so.0 -> librarian.so.0.0.0 - libnetsnmptrapd.so.15 -> libnetsnmptrapd.so.15.1.2 - libGeoIP.so.1 -> libGeoIP.so.1.4.8 - libgettextsrc-0.18.1.so -> libgettextsrc.so - libpackagekit-glib2.so.14 -> libpackagekit-glib2.so.14.0.11 - libecore_fb.so.1 -> libecore_fb.so.1.0.0 - libgnome-bluetooth.so.8 -> libgnome-bluetooth.so.8.0.0 - libminiupnpc.so.8 -> libminiupnpc.so.8 - libguile-srfi-srfi-13-14-v-3.so.3 -> libguile-srfi-srfi-13-14-v-3.so.3.0.1 - libraw.so.5 -> libraw.so.5.0.0 - librhythmbox-core.so.5 -> librhythmbox-core.so.5.0.0 - libxdelta.so.2 -> libxdelta.so.2.0.0 - libgeoclue.so.0 -> libgeoclue.so.0.0.0 - libfreerdp-channels.so.1.0 -> libfreerdp-channels.so.1.0.1 - libgsm.so.1 -> libgsm.so.1.0.12 - libgme.so.0 -> libgme.so.0.5.3 - librpmio.so.2 -> librpmio.so.2.0.1 - libnetfilter_conntrack.so.3 -> libnetfilter_conntrack.so.3.1.3 - libappindicator3.so.1 -> libappindicator3.so.1.0.0 - libicudata.so.48 -> libicudata.so.48.1.1 - libnl-route-3.so.200 -> libnl-route-3.so.200.3.0 - libicuuc.so.48 -> libicuuc.so.48.1.1 - libIntelXvMC.so.1 -> libIntelXvMC.so.1.0.0 - libraptor.so.1 -> libraptor.so.1.2.0 - libgedit-private.so.0 -> libgedit-private.so.0.0.0 - libindicator.so.7 -> libindicator.so.7.0.0 - libsnmp.so.15 -> libsnmp.so.15.1.2 - libguile.so.17 -> libguile.so.17.4.0 - libcompiz_core.so.ABI-20120305 -> libcompiz_core.so.0.9.7.12 - libunique-3.0.so.0 -> libunique-3.0.so.0.0.2 - libfaad.so.2 -> libfaad.so.2.0.0 - libneon-gnutls.so.27 -> libneon-gnutls.so.27.2.6 - libpython2.7.so.1.0 -> libpython2.7.so.1.0 - libspeechd.so.2 -> libspeechd.so.2.3.0 - libecal-1.2.so.10 -> libecal-1.2.so.10.2.2 - libwpd-stream-0.9.so.9 -> libwpd-stream-0.9.so.9.0.4 - liboverlay-scrollbar3-0.2.so.0 -> liboverlay-scrollbar3-0.2.so.0.0.16 - libunity.so.9 -> libunity.so.9.0.2 - libhyphen.so.0 -> libhyphen.so.0.2.1 - libbrasero-media3.so.1 -> libbrasero-media3.so.1.2.3 - libelementary-ver-pre-svn-09.so.0 -> libelementary.so - libkpathsea.so.5 -> libkpathsea.so.5.0.0 - libvlc.so.5 -> libvlc.so.5.3.2 - libflite_cmulex.so.1 -> libflite_cmulex.so.1.4 - libopenobex.so.1 -> libopenobex.so.1.5.0 - libdns.so.81 -> libdns.so.81.3.1 - libfreerdp-kbd.so.1.0 -> libfreerdp-kbd.so.1.0.1 - libpspell.so.15 -> libpspell.so.15.2.0 - libfolks-eds.so.25 -> libfolks-eds.so.25.7.0 - libisofs.so.6 -> libisofs.so.6.54.0 - libecore_input.so.1 -> libecore_input.so.1.0.0 - libpurple.so.0 -> libpurple.so.0.10.3 - librsync.so.1 -> librsync.so.1.0.2 - librpm.so.2 -> librpm.so.2.0.1 - libmeanwhile.so.1 -> libmeanwhile.so.1.0.2 - libevas.so.1 -> libevas.so.1.0.0 - libapr-1.so.0 -> libapr-1.so.0.4.6 - liblirc_client.so.0 -> liblirc_client.so.0.2.1 - libexpect.so.5.45 -> libexpect.so.5.45 - libgucharmap_2_90.so.7 -> libgucharmap_2_90.so.7.0.0 - libicuio.so.48 -> libicuio.so.48.1.1 - libgpod.so.4 -> libgpod.so.4.3.2 - libfontenc.so.1 -> libfontenc.so.1.0.0 - libchromeXvMC.so.1 -> libchromeXvMC.so.1.0.0 - libgssdp-1.0.so.3 -> libgssdp-1.0.so.3.0.0 - libguile-srfi-srfi-4-v-3.so.3 -> libguile-srfi-srfi-4-v-3.so.3.0.1 - libflite_cmu_us_rms.so.1 -> libflite_cmu_us_rms.so.1.4 - liblaunchpad-integration-3.0.so.1 -> liblaunchpad-integration-3.0.so.1.0.0 - libdjvulibre.so.21 -> libdjvulibre.so.21.3.0 - libdecoration.so.0 -> libdecoration.so.0.0.0 - libnm-gtk.so.0 -> libnm-gtk.so.0.0.0 - libcmis-0.2.so.0 -> libcmis-0.2.so.0.0.0 - libgpgme-pth.so.11 -> libgpgme-pth.so.11.7.0 - libguile-srfi-srfi-60-v-2.so.2 -> libguile-srfi-srfi-60-v-2.so.2.0.2 - libgnome-desktop-3.so.2 -> libgnome-desktop-3.so.2.1.4 - libnfnetlink.so.0 -> libnfnetlink.so.0.2.0 - libpeas-gtk-1.0.so.0 -> libpeas-gtk-1.0.so.0.200.0 - libevview3.so.3 -> libevview3.so.3.0.0 - libappindicator.so.1 -> libappindicator.so.1.0.0 - libisccfg.so.82 -> libisccfg.so.82.0.0 - libt1x.so.5 -> libt1x.so.5.1.2 - libtotem-plparser-mini.so.17 -> libtotem-plparser-mini.so.17.0.3 - libgnomekbdui.so.7 -> libgnomekbdui.so.7.0.0 - libspectre.so.1 -> libspectre.so.1.1.6 - libnm-glib-vpn.so.1 -> libnm-glib-vpn.so.1.1.0 - libdvdread.so.4 -> libdvdread.so.4.2.0 - libQtDee.so.2 -> libQtDee.so.2.0.0 - libnux-graphics-2.0.so.0 -> libnux-graphics-2.0.so.0.1401.0 - libslp.so.1 -> libslp.so.1.0.1 - libdvdnavmini.so.4 -> libdvdnavmini.so.4.2.0 - libnux-image-2.0.so.0 -> libnux-image-2.0.so.0.1401.0 - libunity-2d-private.so.0 -> libunity-2d-private.so.0.0.0 - libtelepathy-farstream.so.2 -> libtelepathy-farstream.so.2.0.1 - libedsio.so.0 -> libedsio.so.0.0.0 - libmusicbrainz3.so.6 -> libmusicbrainz3.so.6.2.0 - libefreet_mime.so.1 -> libefreet_mime.so.1.0.0 - libenca.so.0 -> libenca.so.0.5.1 - libpth.so.20 -> libpth.so.20.0.27 - libchromeXvMCPro.so.1 -> libchromeXvMCPro.so.1.0.0 - libicalvcal.so.0 -> libicalvcal.so.0.48.0 - libbrasero-burn3.so.1 -> libbrasero-burn3.so.1.2.3 - libupower-glib.so.1 -> libupower-glib.so.1.0.1 -/usr/lib/i386-linux-gnu/sse2: (hwcap: 0x0000000004000000) - libspeex.so.1 -> libspeex.so.1.5.0 - libspeexdsp.so.1 -> libspeexdsp.so.1.5.0 -/usr/lib/i386-linux-gnu/i686: (hwcap: 0x0008000000000000) -/usr/lib/sse2: (hwcap: 0x0000000004000000) - libxapian.so.22 -> libxapian.so.22.4.2 -/usr/lib/i386-linux-gnu/i686/sse2: (hwcap: 0x0008000004000000) - libx264.so.120 -> libx264.so.120 -/usr/lib/i386-linux-gnu/i686/cmov: (hwcap: 0x0008000000008000) - libavcodec.so.53 -> libavcodec.so.53.35.0 - libavformat.so.53 -> libavformat.so.53.21.1 - libswscale.so.2 -> libswscale.so.2.1.0 - libavutil.so.51 -> libavutil.so.51.22.2 diff --git a/service/resource-encapsulation/SConscript b/service/resource-encapsulation/SConscript index bf0ad09..022feff 100644 --- a/service/resource-encapsulation/SConscript +++ b/service/resource-encapsulation/SConscript @@ -60,7 +60,7 @@ resourceClient_env.AppendUnique(CPPPATH = [ 'src/resourceCache/include' ]) -resourceClient_env.PrependUnique(LIBS = ['oc', 'rcs_common', 'octbstack', 'gnustl_shared','oc_logger', 'compatibility', 'log']) +resourceClient_env.PrependUnique(LIBS = ['oc', 'rcs_common', 'octbstack','oc_logger']) if target_os not in ['windows', 'winrt']: resourceClient_env.AppendUnique(CXXFLAGS = ['-O2', '-g', '-Wall', '-fmessage-length=0', '-std=c++0x']) @@ -69,7 +69,7 @@ if target_os == 'linux': if target_os == 'android': resourceClient_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions']) - resourceClient_env.PrependUnique(LIBS = ['gnustl_shared', 'compatibility', 'log']) + resourceClient_env.PrependUnique(LIBS = ['gnustl_shared', 'log']) resourceClient_env.AppendUnique(LIBS = ['dl']) @@ -90,8 +90,11 @@ client_src = [ RESOURCECLIENT_DIR + 'RCSDiscoveryManager.cpp', RESOURCECLIENT_DIR + 'RCSRemoteResourceObject.cpp' ] -ResourceClientsdk = resourceClient_env.StaticLibrary('rcs_client', client_src) -resourceClient_env.InstallTarget(ResourceClientsdk , 'librcs_client') +ResourceClientsdk_static = resourceClient_env.StaticLibrary('rcs_client', client_src) +ResourceClientsdk_shared = resourceClient_env.SharedLibrary('rcs_client', client_src) + +resourceClient_env.InstallTarget([ResourceClientsdk_static,ResourceClientsdk_shared], 'librcs_client') +resourceClient_env.UserInstallTargetLib([ResourceClientsdk_static,ResourceClientsdk_shared], 'librcs_client') ###################################################################### # Build Sample App: SampleResourceClient & SampleResourceServer @@ -101,7 +104,8 @@ SConscript('examples/SConscript') ###################################################################### # Build UnitTests Resource Client , resourceCache and resourceBroker ################################################ ###################### -SConscript('unittests/SConscript') -SConscript('src/resourceCache/unittests/SConscript') -SConscript('src/resourceBroker/unittest/SConscript') +if target_os == 'linux': + SConscript('unittests/SConscript') + SConscript('src/resourceCache/unittests/SConscript') + SConscript('src/resourceBroker/unittest/SConscript') diff --git a/service/resource-encapsulation/examples/linux/SampleResourceClient.cpp b/service/resource-encapsulation/examples/linux/SampleResourceClient.cpp index 316042e..b905977 100644 --- a/service/resource-encapsulation/examples/linux/SampleResourceClient.cpp +++ b/service/resource-encapsulation/examples/linux/SampleResourceClient.cpp @@ -39,8 +39,8 @@ constexpr int QUIT_INPUT = 3; std::shared_ptr resource; const std::string defaultKey = "Temperature"; -const std::string resourceType = "?rt=core.TemperatureSensor"; -const std::string targetUri = OC_RSRVD_WELL_KNOWN_URI + resourceType; +const std::string resourceType = "core.TemperatureSensor"; +const std::string relativetUri = OC_RSRVD_WELL_KNOWN_URI; std::mutex mtx; std::condition_variable cond; @@ -397,8 +397,8 @@ bool discoverResource() { std::cout << "Wait 2 seconds until discovered." << std::endl; - RCSDiscoveryManager::getInstance()->discoverResource(RCSAddress::multicast(), targetUri, - &onResourceDiscovered); + RCSDiscoveryManager::getInstance()->discoverResourceByType(RCSAddress::multicast(), + relativetUri, resourceType, &onResourceDiscovered); std::unique_lock lck(mtx); cond.wait_for(lck,std::chrono::seconds(2)); diff --git a/service/resource-encapsulation/include/RCSDiscoveryManager.h b/service/resource-encapsulation/include/RCSDiscoveryManager.h index 53ad2b1..2105647 100644 --- a/service/resource-encapsulation/include/RCSDiscoveryManager.h +++ b/service/resource-encapsulation/include/RCSDiscoveryManager.h @@ -21,7 +21,7 @@ /** * @file * - * This file contains the RCSDiscoveryManager class which provide API to discover the Resource in the network + * This file contains the RCSDiscoveryManager class which provide APIs to discover the Resource in the network * */ @@ -35,54 +35,104 @@ namespace OIC { namespace Service { - class RCSRemoteResourceObject; class RCSAddress; /** - * This class contains the resource discovery method. + * This class contains the resource discovery methods. * * @see RCSRemoteResourceObject */ class RCSDiscoveryManager { - public: + public: + + /** + * Typedef for callback of discoverResource APIs + * + * @see discoverResource + */ + typedef std::function< void(std::shared_ptr< RCSRemoteResourceObject >) > + ResourceDiscoveredCallback; + + /** + * Returns RCSDiscoveryManager instance. + * + */ + static RCSDiscoveryManager* getInstance(); + + /** + * API for discovering the resource of Interest, regardless of URI and resource type + * + * @param address A RCSAddress object + * @param cb A callback to obtain discovered resource + * + * @throws InvalidParameterException If cb is empty. + * + * @note The callback will be invoked in an internal thread. + * + * @see RCSAddress + * + */ + void discoverResource(const RCSAddress& address, ResourceDiscoveredCallback cb); - /** - * Typedef for callback of discoverResource API - * - * @see discoverResource - */ - typedef std::function< void(std::shared_ptr< RCSRemoteResourceObject >) > - ResourceDiscoveredCallback; + /** + * API for discovering the resource of Interest, regardless of resource type + * + * @param address A RCSAddress object + * @param relativeURI The relative uri of resource to be searched + * @param cb A callback to obtain discovered resource + * + * @throws InvalidParameterException If cb is empty. + * + * @note The callback will be invoked in an internal thread. + * + * @see RCSAddress + * + */ + void discoverResource(const RCSAddress& address, const std::string& relativeURI, + ResourceDiscoveredCallback cb); - /** - * Returns RCSDiscoveryManager instance. - * - */ - static RCSDiscoveryManager* getInstance(); + /** + * API for discovering the resource of Interest by Resource type. + * + * @param address A RCSAddress object + * @param resourceType Ressource Type + * @param cb A callback to obtain discovered resource + * + * @throws InvalidParameterException If cb is empty. + * + * @note The callback will be invoked in an internal thread. + * + * @see RCSAddress + * + */ + void discoverResourceByType(const RCSAddress& address, const std::string& resourceType, + ResourceDiscoveredCallback cb); - /** - * API for discovering the resource of Interest. - * - * @param address A RCSAddress object - * @param resourceURI The uri of resource to be searched - * @param cb A callback to obtain discovered resource - * - * @throws InvalidParameterException If cb is empty. - * - * @note The callback will be invoked in an internal thread. - * - * @see RCSAddress - * - */ - void discoverResource(const RCSAddress& address, const std::string& resourceURI, - ResourceDiscoveredCallback cb); + /** + * API for discovering the resource of Interest by Resource type with provided relativeURI + * + * @param address A RCSAddress object + * @param relativeURI The relative uri of resource to be searched + * @param resourceType Ressource Type + * @param cb A callback to obtain discovered resource + * + * @throws InvalidParameterException If cb is empty. + * + * @note The callback will be invoked in an internal thread. + * + * @see RCSAddress + * + */ + void discoverResourceByType(const RCSAddress& address, const std::string& relativeURI, + const std::string& resourceType, + ResourceDiscoveredCallback cb); - private: - RCSDiscoveryManager() = default; - ~RCSDiscoveryManager() = default; + private: + RCSDiscoveryManager() = default; + ~RCSDiscoveryManager() = default; }; } } diff --git a/service/resource-encapsulation/include/RCSResourceAttributes.h b/service/resource-encapsulation/include/RCSResourceAttributes.h index 5ab8c92..193f21e 100644 --- a/service/resource-encapsulation/include/RCSResourceAttributes.h +++ b/service/resource-encapsulation/include/RCSResourceAttributes.h @@ -96,7 +96,7 @@ namespace OIC class KeyValueVisitorHelper: public boost::static_visitor< > { public: - KeyValueVisitorHelper(VISITOR& visitor) : + KeyValueVisitorHelper(VISITOR& visitor) noexcept : m_visitor( visitor ) { } @@ -159,7 +159,7 @@ namespace OIC * * @return Identifier of type. */ - TypeId getId() const; + TypeId getId() const noexcept; /** * Factory method to create Type instance from T. @@ -171,18 +171,18 @@ namespace OIC * @see is_supported_type */ template < typename T > - static Type typeOf(const T& value) + static Type typeOf(const T& value) noexcept { return Type(value); } //! @cond - friend bool operator==(const Type&, const Type&); + friend bool operator==(const Type&, const Type&) noexcept; //! @endcond private: template < typename T > - explicit Type(const T&) : + explicit Type(const T&) noexcept : m_which{ IndexOfType< T >::value } { } @@ -207,7 +207,7 @@ namespace OIC Value(); Value(const Value&); - Value(Value&&); + Value(Value&&) noexcept; /** * Constructs a Value if T is a supported type.
@@ -276,7 +276,7 @@ namespace OIC /** * Exchanges the content of the object by the content of the parameter. */ - void swap(Value&); + void swap(Value&) noexcept; //! @cond friend class RCSResourceAttributes; @@ -328,32 +328,32 @@ namespace OIC /** * Returns an {@link iterator} referring to the first element. */ - iterator begin(); + iterator begin() noexcept; /** * Returns an {@link iterator} referring to the past-the-end element. */ - iterator end(); + iterator end() noexcept; /** * @copydoc cbegin() */ - const_iterator begin() const; + const_iterator begin() const noexcept; /** * @copydoc cend() */ - const_iterator end() const; + const_iterator end() const noexcept; /** * Returns a const_iterator referring to the first element. */ - const_iterator cbegin() const; + const_iterator cbegin() const noexcept; /** * Returns a const_iterator referring to the past-the-end element. */ - const_iterator cend() const; + const_iterator cend() const noexcept; /** * Accesses a value. @@ -427,7 +427,7 @@ namespace OIC /** * Removes all elements. */ - void clear(); + void clear() noexcept; /** * Removes a single element. @@ -452,14 +452,14 @@ namespace OIC * * @see size */ - bool empty() const; + bool empty() const noexcept; /** * Returns the number of elements. * * @see empty */ - size_t size() const; + size_t size() const noexcept; private: template< typename VISITOR > @@ -538,7 +538,8 @@ namespace OIC * * @return true if the objects are equal, false otherwise. */ - bool operator==(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&); + bool operator==(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&) + noexcept; /** * @relates RCSResourceAttributes::Type @@ -547,7 +548,8 @@ namespace OIC * * @return true if the objects are not equal, false otherwise. */ - bool operator!=(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&); + bool operator!=(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&) + noexcept; /** * @relates RCSResourceAttributes::Value @@ -638,32 +640,32 @@ namespace OIC class KeyVisitor: public boost::static_visitor< const std::string& > { public: - result_type operator()(iterator*) const; - result_type operator()(const_iterator*) const; + result_type operator()(iterator*) const noexcept; + result_type operator()(const_iterator*) const noexcept; }; class ValueVisitor: public boost::static_visitor< Value& > { public: - result_type operator()(iterator*); + result_type operator()(iterator*) noexcept; result_type operator()(const_iterator*); }; class ConstValueVisitor: public boost::static_visitor< const Value& > { public: - result_type operator()(iterator*) const; - result_type operator()(const_iterator*) const; + result_type operator()(iterator*) const noexcept; + result_type operator()(const_iterator*) const noexcept; }; public: - const std::string& key() const; - const RCSResourceAttributes::Value& value() const; + const std::string& key() const noexcept; + const RCSResourceAttributes::Value& value() const noexcept; RCSResourceAttributes::Value& value(); private: KeyValuePair(const KeyValuePair&) = default; - KeyValuePair(boost::variant< iterator*, const_iterator* >&&); + KeyValuePair(boost::variant< iterator*, const_iterator* >&&) noexcept; KeyValuePair& operator=(const KeyValuePair&) = default; diff --git a/service/resource-encapsulation/include/RCSResourceObject.h b/service/resource-encapsulation/include/RCSResourceObject.h index 7c0c636..85c7848 100644 --- a/service/resource-encapsulation/include/RCSResourceObject.h +++ b/service/resource-encapsulation/include/RCSResourceObject.h @@ -31,8 +31,6 @@ #include #include -#include - #include #include #include @@ -59,6 +57,11 @@ namespace OIC NoLockException(std::string &&what) : RCSException { std::move(what) } {} }; + //! @cond + template < typename T > + class AtomicWrapper; + //! @endcond + /** * @brief RCSResourceObject represents a resource. It handles any requests from * clients automatically with attributes. @@ -76,6 +79,8 @@ namespace OIC private: class WeakGuard; + typedef AtomicWrapper< std::thread::id > AtomicThreadId; + public: /** * @brief represents the policy of AutoNotify function. @@ -433,6 +438,10 @@ namespace OIC void expectOwnLock() const; + std::thread::id getLockOwner() const noexcept; + + void setLockOwner(std::thread::id&&) const noexcept; + void autoNotify(bool, AutoNotifyPolicy) const; void autoNotify(bool) const; @@ -455,7 +464,7 @@ namespace OIC std::unordered_map< std::string, AttributeUpdatedListener > m_keyAttributesUpdatedListeners; - mutable boost::atomic< std::thread::id > m_lockOwner; + mutable std::unique_ptr< AtomicThreadId > m_lockOwner; mutable std::mutex m_mutex; std::mutex m_mutexKeyAttributeUpdate; diff --git a/service/resource-encapsulation/src/common/SConscript b/service/resource-encapsulation/src/common/SConscript index fd10311..e0d38be 100644 --- a/service/resource-encapsulation/src/common/SConscript +++ b/service/resource-encapsulation/src/common/SConscript @@ -62,7 +62,7 @@ if target_os not in ['darwin', 'ios', 'windows', 'winrt']: if target_os == 'android': rcs_common_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions']) - rcs_common_env.PrependUnique(LIBS = ['gnustl_shared', 'compatibility', 'log']) + rcs_common_env.PrependUnique(LIBS = ['gnustl_shared', 'log']) rcs_common_env.AppendUnique(LIBS = ['dl', 'oc']) @@ -91,42 +91,41 @@ rcs_common_shared = rcs_common_env.SharedLibrary('rcs_common', rcs_common_src) rcs_common_env.InstallTarget([rcs_common_static,rcs_common_shared], 'rcs_common') ###################################################################### -# Build Test primitive Resource +# Build Test Expiry Timer and primitive Resource ###################################################################### -rcs_common_test_env = rcs_common_env.Clone(); - -rcs_common_test_env.PrependUnique(CPPPATH = [ - env.get('SRC_DIR')+'/extlibs/hippomocks-master', - gtest_dir + '/include', - 'utils/include' - ]) - -gtest = File(gtest_dir + '/lib/.libs/libgtest.a') -gtest_main = File(gtest_dir + '/lib/.libs/libgtest_main.a') - -rcs_common_test_env.PrependUnique(LIBS = [ - 'octbstack', - 'oc_logger', - 'connectivity_abstraction', - 'coap', - 'rcs_common', - gtest, - gtest_main, - 'pthread' - ]) - -rcs_common_test_src = [ - env.Glob('primitiveResource/unittests/*.cpp'), - 'expiryTimer/unittests/ExpiryTimerTest.cpp' - ] - -rcs_common_test = rcs_common_test_env.Program('rcs_common_test', rcs_common_test_src) -Alias("rcs_common_test", rcs_common_test) -env.AppendTarget('rcs_common_test') - -if env.get('TEST') == '1': - target_os = env.get('TARGET_OS') - if target_os == 'linux': - from tools.scons.RunTest import * - run_test(rcs_common_test_env, '', - 'service/resource-encapsulation/src/common/rcs_common_test') +if target_os == 'linux': + rcs_common_test_env = rcs_common_env.Clone(); + + rcs_common_test_env.PrependUnique(CPPPATH = [ + env.get('SRC_DIR')+'/extlibs/hippomocks-master', + gtest_dir + '/include', + 'utils/include' + ]) + + gtest = File(gtest_dir + '/lib/.libs/libgtest.a') + gtest_main = File(gtest_dir + '/lib/.libs/libgtest_main.a') + + rcs_common_test_env.PrependUnique(LIBS = [ + 'octbstack', + 'oc_logger', + 'connectivity_abstraction', + 'coap', + 'rcs_common', + gtest, + gtest_main, + 'pthread' + ]) + + rcs_common_test_src = [ + env.Glob('primitiveResource/unittests/*.cpp'), + 'expiryTimer/unittests/ExpiryTimerTest.cpp' + ] + + rcs_common_test = rcs_common_test_env.Program('rcs_common_test', rcs_common_test_src) + Alias("rcs_common_test", rcs_common_test) + env.AppendTarget('rcs_common_test') + + if env.get('TEST') == '1': + from tools.scons.RunTest import * + run_test(rcs_common_test_env, '', + 'service/resource-encapsulation/src/common/rcs_common_test') diff --git a/service/resource-encapsulation/src/common/primitiveResource/src/RCSResourceAttributes.cpp b/service/resource-encapsulation/src/common/primitiveResource/src/RCSResourceAttributes.cpp index 99de4a6..dc4e53b 100644 --- a/service/resource-encapsulation/src/common/primitiveResource/src/RCSResourceAttributes.cpp +++ b/service/resource-encapsulation/src/common/primitiveResource/src/RCSResourceAttributes.cpp @@ -103,13 +103,15 @@ namespace template< > struct TypeInfoConverter< std::nullptr_t > { - static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::NULL_T; + static constexpr RCSResourceAttributes::TypeId typeId = + RCSResourceAttributes::TypeId::NULL_T; }; template< > struct TypeInfoConverter< double > { - static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::DOUBLE; + static constexpr RCSResourceAttributes::TypeId typeId = + RCSResourceAttributes::TypeId::DOUBLE; }; template< > @@ -121,13 +123,15 @@ namespace template< > struct TypeInfoConverter< std::string > { - static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::STRING; + static constexpr RCSResourceAttributes::TypeId typeId = + RCSResourceAttributes::TypeId::STRING; }; template< > struct TypeInfoConverter< RCSResourceAttributes > { - static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::ATTRIBUTES; + static constexpr RCSResourceAttributes::TypeId typeId = + RCSResourceAttributes::TypeId::ATTRIBUTES; }; struct TypeInfo @@ -154,7 +158,7 @@ namespace }; template< typename VARIANT, int POS > - constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< POS >) + constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< POS >) noexcept { auto&& vec = getTypeInfo< VARIANT >(Int2Type< POS - 1 >{ }); vec.push_back(TypeInfo::get< VARIANT, POS >()); @@ -162,13 +166,13 @@ namespace } template< typename VARIANT > - constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< 0 >) + constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< 0 >) noexcept { return { TypeInfo::get< VARIANT, 0 >() }; } template< typename VARIANT > - inline TypeInfo getTypeInfo(int which) + inline TypeInfo getTypeInfo(int which) noexcept { static constexpr int variantEnd = boost::mpl::size< typename VARIANT::types >::value - 1; static const std::vector< TypeInfo > typeInfos = getTypeInfo< VARIANT >( @@ -196,12 +200,14 @@ namespace OIC return *m_valueRef.m_data == *rhs.m_valueRef.m_data; } - bool operator==(const RCSResourceAttributes::Type& lhs, const RCSResourceAttributes::Type& rhs) + bool operator==(const RCSResourceAttributes::Type& lhs, + const RCSResourceAttributes::Type& rhs) noexcept { return lhs.m_which == rhs.m_which; } - bool operator!=(const RCSResourceAttributes::Type& lhs, const RCSResourceAttributes::Type& rhs) + bool operator!=(const RCSResourceAttributes::Type& lhs, + const RCSResourceAttributes::Type& rhs) noexcept { return !(lhs == rhs); } @@ -228,7 +234,7 @@ namespace OIC return !(lhs == rhs); } - auto RCSResourceAttributes::Type::getId() const -> TypeId + auto RCSResourceAttributes::Type::getId() const noexcept -> TypeId { return ::getTypeInfo< ValueVariant >(m_which).typeId; } @@ -243,10 +249,10 @@ namespace OIC { } - RCSResourceAttributes::Value::Value(Value&& from) : + RCSResourceAttributes::Value::Value(Value&& from) noexcept : m_data{ new ValueVariant{} } { - m_data->swap(*from.m_data); + m_data.swap(from.m_data); } RCSResourceAttributes::Value::Value(const char* value) : @@ -289,24 +295,24 @@ namespace OIC return boost::apply_visitor(ToStringVisitor(), *m_data); } - void RCSResourceAttributes::Value::swap(Value& rhs) + void RCSResourceAttributes::Value::swap(Value& rhs) noexcept { m_data.swap(rhs.m_data); } auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()( - iterator* iter) const -> result_type + iterator* iter) const noexcept -> result_type { return iter->m_cur->first; } auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()( - const_iterator* iter) const -> result_type + const_iterator* iter) const noexcept -> result_type { return iter->m_cur->first; } - auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (iterator* iter) + auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (iterator* iter) noexcept -> result_type { return iter->m_cur->second; @@ -320,23 +326,23 @@ namespace OIC } auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()( - iterator*iter) const -> result_type + iterator*iter) const noexcept -> result_type { return iter->m_cur->second; } auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()( - const_iterator* iter) const -> result_type + const_iterator* iter) const noexcept -> result_type { return iter->m_cur->second; } - auto RCSResourceAttributes::KeyValuePair::key() const -> const std::string& + auto RCSResourceAttributes::KeyValuePair::key() const noexcept -> const std::string& { return boost::apply_visitor(m_keyVisitor, m_iterRef); } - auto RCSResourceAttributes::KeyValuePair::value() const -> const Value& + auto RCSResourceAttributes::KeyValuePair::value() const noexcept -> const Value& { return boost::apply_visitor(m_constValueVisitor, m_iterRef); } @@ -347,7 +353,7 @@ namespace OIC } RCSResourceAttributes::KeyValuePair::KeyValuePair(boost::variant&& ref) : + const_iterator*>&& ref) noexcept : m_iterRef{ ref } { } @@ -415,8 +421,9 @@ namespace OIC { } - auto RCSResourceAttributes::const_iterator::operator=(const RCSResourceAttributes::iterator& iter) - -> const_iterator& { + auto RCSResourceAttributes::const_iterator::operator=( + const RCSResourceAttributes::iterator& iter) -> const_iterator& + { m_cur = iter.m_cur; return *this; } @@ -425,6 +432,7 @@ namespace OIC { return m_keyValuePair; } + auto RCSResourceAttributes::const_iterator::operator->() const -> pointer { return &m_keyValuePair; @@ -453,32 +461,33 @@ namespace OIC return !(*this == rhs); } - auto RCSResourceAttributes::begin() -> iterator + + auto RCSResourceAttributes::begin() noexcept -> iterator { return iterator{ m_values.begin() }; } - auto RCSResourceAttributes::end() -> iterator + auto RCSResourceAttributes::end() noexcept -> iterator { return iterator{ m_values.end() }; } - auto RCSResourceAttributes::begin() const -> const_iterator + auto RCSResourceAttributes::begin() const noexcept -> const_iterator { return const_iterator{ m_values.begin() }; } - auto RCSResourceAttributes::end() const -> const_iterator + auto RCSResourceAttributes::end() const noexcept -> const_iterator { return const_iterator{ m_values.end() }; } - auto RCSResourceAttributes::cbegin() const -> const_iterator + auto RCSResourceAttributes::cbegin() const noexcept -> const_iterator { return const_iterator{ m_values.begin() }; } - auto RCSResourceAttributes::cend() const -> const_iterator + auto RCSResourceAttributes::cend() const noexcept -> const_iterator { return const_iterator{ m_values.end() }; } @@ -517,7 +526,7 @@ namespace OIC } } - void RCSResourceAttributes::clear() + void RCSResourceAttributes::clear() noexcept { return m_values.clear(); } @@ -532,12 +541,12 @@ namespace OIC return m_values.find(key) != m_values.end(); } - bool RCSResourceAttributes::empty() const + bool RCSResourceAttributes::empty() const noexcept { return m_values.empty(); } - size_t RCSResourceAttributes::size() const + size_t RCSResourceAttributes::size() const noexcept { return m_values.size(); } @@ -600,5 +609,6 @@ namespace OIC return replacedList; } + } } diff --git a/service/resource-encapsulation/src/common/utils/include/AtomicHelper.h b/service/resource-encapsulation/src/common/utils/include/AtomicHelper.h new file mode 100644 index 0000000..9a48d37 --- /dev/null +++ b/service/resource-encapsulation/src/common/utils/include/AtomicHelper.h @@ -0,0 +1,306 @@ +//****************************************************************** +// +// Copyright 2015 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef COMMON_UTILS_ATOMICHELPER_H +#define COMMON_UTILS_ATOMICHELPER_H + +#include +#include + +#ifdef __GNUC__ +#define RCS_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +#if defined(RCS_GCC_VERSION) && RCS_GCC_VERSION >= 40700 +#define RCS_USE_STD_ATOMIC +#elif BOOST_VERSION >= 105300 +#include +#define RCS_USE_BOOST_ATOMIC +#else +#define RCS_USE_CUSTOM_ATOMIC +#endif + +namespace OIC +{ + namespace Service + { + namespace Detail + { + + class ScopedLock + { + public: + explicit ScopedLock(std::atomic_flag& flag) noexcept : + m_flag(flag) + { + while (m_flag.test_and_set(std::memory_order_acquire)); + } + + ~ScopedLock() noexcept + { + m_flag.clear(std::memory_order_release); + } + + ScopedLock(const ScopedLock&) = delete; + ScopedLock& operator=(const ScopedLock&) = delete; + + private: + std::atomic_flag& m_flag; + }; + + template< typename T > + class CustomAtomic + { + public: + CustomAtomic() noexcept : + m_value { }, + m_flag { ATOMIC_FLAG_INIT } + { + + } + ~CustomAtomic() = default; + + CustomAtomic(const CustomAtomic&) = delete; + + CustomAtomic& operator=(const CustomAtomic&) = delete; + CustomAtomic& operator=(const CustomAtomic&) volatile = delete; + + explicit CustomAtomic(T v) noexcept : + m_value{ v }, + m_flag { ATOMIC_FLAG_INIT } + { + } + + operator T() const noexcept + { + return load(); + } + + operator T() const volatile noexcept + { + return load(); + } + + T operator=(T v) noexcept + { + store(v); + return v; + } + + T operator=(T v) volatile noexcept + { + store(v); + return v; + } + + bool is_lock_free() const noexcept + { + return false; + } + + bool is_lock_free() const volatile noexcept + { + return false; + } + + void store(T v, std::memory_order = std::memory_order_seq_cst) noexcept + { + ScopedLock guard(m_flag); + memcpy(&m_value, &v, sizeof(T)); + } + + void store(T v, std::memory_order = std::memory_order_seq_cst) volatile noexcept + { + ScopedLock guard(m_flag); + memcpy(&m_value, &v, sizeof(T)); + } + + T load(std::memory_order = std::memory_order_seq_cst) const noexcept + { + ScopedLock guard(m_flag); + + T v; + memcpy(&v, &m_value, sizeof(T)); + return v; + } + + T load(std::memory_order = std::memory_order_seq_cst) const volatile noexcept + { + ScopedLock guard(m_flag); + + T v; + memcpy(&v, &m_value, sizeof(T)); + return v; + } + + T exchange(T v, std::memory_order = std::memory_order_seq_cst) noexcept + { + ScopedLock guard(m_flag); + + T tmp; + memcpy(&tmp, &m_value, sizeof(T)); + + memcpy(&m_value, &v, sizeof(T)); + return tmp; + } + + T exchange(T v, std::memory_order = std::memory_order_seq_cst) volatile noexcept + { + ScopedLock guard(m_flag); + + T tmp; + memcpy(&tmp, &m_value, sizeof(T)); + + memcpy(&m_value, &v, sizeof(T)); + return tmp; + } + + bool compare_exchange_weak(T& expected, T desired, std::memory_order success, + std::memory_order failure) volatile noexcept + { + return compare_exchange_strong(expected, desired, success, failure); + } + + bool compare_exchange_weak(T& expected, T desired, + std::memory_order m = std::memory_order_seq_cst) volatile noexcept + { + return compare_exchange_weak(expected, desired, m, m); + } + + bool compare_exchange_strong(T& expected, T desired, std::memory_order /*success*/, + std::memory_order /*failure*/) volatile noexcept + { + ScopedLock guard(m_flag); + + if (memcmp(&m_value, &expected, sizeof(T)) == 0) { + memcpy(&m_value, &desired, sizeof(T)); + return true; + } else { + memcpy(&expected, &m_value, sizeof(T)); + return false; + } + } + + bool compare_exchange_strong(T& expected, T desired, + std::memory_order m = std::memory_order_seq_cst) volatile noexcept + { + return compare_exchange_strong(expected, desired, m, m); + } + + private: + T m_value; + mutable std::atomic_flag m_flag; + }; + +#if defined(RCS_USE_BOOST_ATOMIC) + inline boost::memory_order convertMemoryOrder(std::memory_order m) noexcept + { + switch(m) + { + case std::memory_order_relaxed: return boost::memory_order_relaxed; + case std::memory_order_consume: return boost::memory_order_consume; + case std::memory_order_acquire: return boost::memory_order_acquire; + case std::memory_order_release: return boost::memory_order_release; + case std::memory_order_acq_rel: return boost::memory_order_acq_rel; + case std::memory_order_seq_cst: return boost::memory_order_seq_cst; + } + return boost::memory_order_seq_cst; + } +#else + inline std::memory_order convertMemoryOrder(std::memory_order m) noexcept + { + return m; + } +#endif + + } // namespace detail + + template < typename T > + struct AtomicBase + { +#if defined(RCS_USE_STD_ATOMIC) + typedef std::atomic< T > type; +#elif defined(RCS_USE_BOOST_ATOMIC) + typedef boost::atomic< T > type; +#else + typedef typename std::conditional< std::is_integral< T >::value, std::atomic< T >, + Detail::CustomAtomic< T > >::type type; +#endif + }; + + template< typename T > + class AtomicWrapper + { + public: + AtomicWrapper() = default; + + AtomicWrapper(T v) : + m_base{ v } + { + } + + AtomicWrapper(const AtomicWrapper&) = delete; + AtomicWrapper& operator=(const AtomicWrapper&) = delete; + + operator T() const noexcept + { + return load(); + } + + operator T() const volatile noexcept + { + return load(); + } + + T operator=(T v) noexcept + { + store(v); + return v; + } + + T operator=(T v) volatile noexcept + { + store(v); + return v; + } + + T load(std::memory_order order = std::memory_order_seq_cst) const noexcept + { + return m_base.load(Detail::convertMemoryOrder(order)); + } + + T load(std::memory_order order = std::memory_order_seq_cst) const volatile noexcept + { + return m_base.load(Detail::convertMemoryOrder(order)); + } + + void store(T v, std::memory_order order = std::memory_order_seq_cst) noexcept + { + m_base.store(v, Detail::convertMemoryOrder(order)); + } + + private: + typename AtomicBase< T >::type m_base; + }; + + } +} + +#endif // COMMON_UTILS_ATOMICHELPER_H diff --git a/service/resource-encapsulation/src/resourceBroker/include/ResourcePresence.h b/service/resource-encapsulation/src/resourceBroker/include/ResourcePresence.h index acb54b6..220bc77 100644 --- a/service/resource-encapsulation/src/resourceBroker/include/ResourcePresence.h +++ b/service/resource-encapsulation/src/resourceBroker/include/ResourcePresence.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -64,7 +64,7 @@ namespace OIC BROKER_MODE mode; bool isWithinTime; - boost::atomic_long receivedTime; + std::atomic_long receivedTime; std::mutex cbMutex; unsigned int timeoutHandle; diff --git a/service/resource-encapsulation/src/resourceBroker/src/ResourcePresence.cpp b/service/resource-encapsulation/src/resourceBroker/src/ResourcePresence.cpp index e6ab0ef..bb80de3 100644 --- a/service/resource-encapsulation/src/resourceBroker/src/ResourcePresence.cpp +++ b/service/resource-encapsulation/src/resourceBroker/src/ResourcePresence.cpp @@ -218,8 +218,7 @@ namespace OIC time(¤tTime); currentTime += 0L; - if((receivedTime.load(boost::memory_order_consume) == 0) || - ((receivedTime + BROKER_SAFE_SECOND) > currentTime )) + if((receivedTime == 0) || ((receivedTime + BROKER_SAFE_SECOND) > currentTime )) { this->isWithinTime = true; return; diff --git a/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManager.cpp b/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManager.cpp index c51b733..7e19d4d 100644 --- a/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManager.cpp +++ b/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManager.cpp @@ -57,18 +57,39 @@ namespace OIC } void RCSDiscoveryManager::discoverResource(const RCSAddress& address, - const std::string& resourceURI, ResourceDiscoveredCallback cb) + ResourceDiscoveredCallback cb) { - SCOPE_LOG_F(DEBUG, TAG); + discoverResourceByType(address, OC_RSRVD_WELL_KNOWN_URI, "", std::move(cb)); + } + + void RCSDiscoveryManager::discoverResource(const RCSAddress& address, + const std::string& relativeURI, ResourceDiscoveredCallback cb) + { + discoverResourceByType(address, relativeURI, "", std::move(cb)); + } + + void RCSDiscoveryManager::discoverResourceByType(const RCSAddress& address, + const std::string& resourceType, + ResourceDiscoveredCallback cb) + { + discoverResourceByType(address, OC_RSRVD_WELL_KNOWN_URI, resourceType, std::move(cb)); + } + void RCSDiscoveryManager::discoverResourceByType(const RCSAddress& address, + const std::string& relativeURI, const std::string& resourceType, + ResourceDiscoveredCallback cb) + { if (!cb) { - OC_LOG(ERROR, TAG, "discoverResource NULL Callback"); - throw InvalidParameterException{ "discoverResource NULL Callback'" }; + OC_LOG(ERROR, TAG, "discoverResourceByType NULL Callback"); + throw InvalidParameterException { "discoverResourceByType NULL Callback'" }; } - - OIC::Service::discoverResource(address, resourceURI, + else + { + std::string resourceURI = relativeURI + "?rt=" + resourceType; + OIC::Service::discoverResource(address, resourceURI, std::bind(findCallback, std::placeholders::_1, std::move(cb))); + } } } } diff --git a/service/resource-encapsulation/src/resourceContainer/SConscript b/service/resource-encapsulation/src/resourceContainer/SConscript index 6bf95d1..2934a06 100644 --- a/service/resource-encapsulation/src/resourceContainer/SConscript +++ b/service/resource-encapsulation/src/resourceContainer/SConscript @@ -93,7 +93,7 @@ if target_os not in ['darwin', 'ios', 'windows', 'winrt']: if target_os == 'android': resource_container_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions']) - resource_container_env.PrependUnique(LIBS = ['gnustl_shared', 'compatibility', 'log']) + resource_container_env.PrependUnique(LIBS = ['gnustl_shared', 'log']) try: resource_container_env.AppendUnique(LIBPATH = [os.environ['JAVA_LIB']]) @@ -127,24 +127,24 @@ resource_container_env.InstallTarget([res_container_static,res_container_shared] ###################################################################### # build soft sensor sample bundle ###################################################################### +if target_os == 'linux': + ss_resource_bundle_env = resource_container_env.Clone() + ss_resource_bundle_env.AppendUnique(CCFLAGS = ['-fPIC']) + + SS_RESOURCE_BUNDLE_DIR = 'examples/SoftSensorSampleBundle/' + ss_resource_bundle_env.AppendUnique(CPPPATH = [ + SS_RESOURCE_BUNDLE_DIR + 'include', + 'include/', + '../../include', + ]) -ss_resource_bundle_env = resource_container_env.Clone() -ss_resource_bundle_env.AppendUnique(CCFLAGS = ['-fPIC']) - -SS_RESOURCE_BUNDLE_DIR = 'examples/SoftSensorSampleBundle/' -ss_resource_bundle_env.AppendUnique(CPPPATH = [ - SS_RESOURCE_BUNDLE_DIR + 'include', - 'include/', - '../../include', - ]) - -ss_resource_bundle_env.PrependUnique(LIBS = ['rcs_container']) - -ss_resource_bundle_src = [ Glob(SS_RESOURCE_BUNDLE_DIR + 'src/*.cpp')] + ss_resource_bundle_env.PrependUnique(LIBS = ['rcs_container']) -SoftSensorBundle = ss_resource_bundle_env.SharedLibrary('SoftSensorBundle', ss_resource_bundle_src) -ss_resource_bundle_env.InstallTarget(SoftSensorBundle, 'libSoftSensorBundle') + ss_resource_bundle_src = [ Glob(SS_RESOURCE_BUNDLE_DIR + 'src/*.cpp')] + SoftSensorBundle = ss_resource_bundle_env.SharedLibrary('SoftSensorBundle', ss_resource_bundle_src) + ss_resource_bundle_env.InstallTarget(SoftSensorBundle, 'libSoftSensorBundle') + ###################################################################### # build hue sample bundle ###################################################################### @@ -182,7 +182,8 @@ else: ###################################################################### # build resource container unit tests ###################################################################### -SConscript('unittests/SConscript') +if target_os == 'linux': + SConscript('unittests/SConscript') ###################################################################### # Build Container Sample diff --git a/service/resource-encapsulation/src/resourceContainer/src/ResourceContainerImpl.cpp b/service/resource-encapsulation/src/resourceContainer/src/ResourceContainerImpl.cpp index 25164cf..f4dd364 100644 --- a/service/resource-encapsulation/src/resourceContainer/src/ResourceContainerImpl.cpp +++ b/service/resource-encapsulation/src/resourceContainer/src/ResourceContainerImpl.cpp @@ -252,7 +252,7 @@ namespace OIC void *bundleHandle = m_bundles[id]->getBundleHandle(); info_logger() << "Unregister bundle: " << m_bundles[id]->getID() << ", " << m_bundles[id]->getID() << endl; - char *error; + const char *error; dlclose(bundleHandle); if ((error = dlerror()) != NULL) { @@ -551,7 +551,7 @@ namespace OIC void ResourceContainerImpl::registerSoBundle(RCSBundleInfo *bundleInfo) { - char *error; + const char *error; activator_t *bundleActivator = NULL; deactivator_t *bundleDeactivator = NULL; diff --git a/service/resource-encapsulation/src/serverBuilder/SConscript b/service/resource-encapsulation/src/serverBuilder/SConscript index 98e0cb7..1ec21b7 100644 --- a/service/resource-encapsulation/src/serverBuilder/SConscript +++ b/service/resource-encapsulation/src/serverBuilder/SConscript @@ -42,6 +42,7 @@ release = env.get('RELEASE') ###################################################################### server_builder_env.AppendUnique(CPPPATH = [ '../common/primitiveResource/include', + '../common/utils/include', '../../include', ]) @@ -59,7 +60,7 @@ if target_os not in ['darwin', 'ios', 'windows', 'winrt']: if target_os == 'android': server_builder_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions']) - server_builder_env.PrependUnique(LIBS = ['gnustl_shared', 'compatibility', 'log']) + server_builder_env.PrependUnique(LIBS = ['gnustl_shared', 'log']) server_builder_env.AppendUnique(LIBS = ['dl', 'oc', 'rcs_common']) @@ -83,37 +84,36 @@ server_builder_env.InstallTarget([server_builder_static, server_builder_shared], ###################################################################### # Build Test ###################################################################### -server_builder_test_env = server_builder_env.Clone(); - -server_builder_test_env.AppendUnique(CPPPATH = [ - env.get('SRC_DIR')+'/extlibs/hippomocks-master', - gtest_dir + '/include', - '../common/utils/include' - ]) - -gtest = File(gtest_dir + '/lib/.libs/libgtest.a') -gtest_main = File(gtest_dir + '/lib/.libs/libgtest_main.a') - -server_builder_test_env.PrependUnique(LIBS = [ - 'rcs_server', - 'octbstack', - 'oc_logger', - 'connectivity_abstraction', - 'coap', - gtest, - gtest_main, - 'pthread', - ]) - -server_builder_test_src = env.Glob('unittests/*.cpp') - -server_builder_test = server_builder_test_env.Program('rcs_server_test', server_builder_test_src) -Alias("rcs_server_test", server_builder_test) -env.AppendTarget('rcs_server_test') - -if env.get('TEST') == '1': - target_os = env.get('TARGET_OS') - if target_os == 'linux': - from tools.scons.RunTest import * - run_test(server_builder_test_env, '', - 'service/resource-encapsulation/src/serverBuilder/rcs_server_test') \ No newline at end of file +if target_os == 'linux': + server_builder_test_env = server_builder_env.Clone(); + + server_builder_test_env.AppendUnique(CPPPATH = [ + env.get('SRC_DIR')+'/extlibs/hippomocks-master', + gtest_dir + '/include', + '../common/utils/include' + ]) + + gtest = File(gtest_dir + '/lib/.libs/libgtest.a') + gtest_main = File(gtest_dir + '/lib/.libs/libgtest_main.a') + + server_builder_test_env.PrependUnique(LIBS = [ + 'rcs_server', + 'octbstack', + 'oc_logger', + 'connectivity_abstraction', + 'coap', + gtest, + gtest_main, + 'pthread', + ]) + + server_builder_test_src = env.Glob('unittests/*.cpp') + + server_builder_test = server_builder_test_env.Program('rcs_server_test', server_builder_test_src) + Alias("rcs_server_test", server_builder_test) + env.AppendTarget('rcs_server_test') + + if env.get('TEST') == '1': + from tools.scons.RunTest import * + run_test(server_builder_test_env, '', + 'service/resource-encapsulation/src/serverBuilder/rcs_server_test') diff --git a/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp b/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp index 1d3a0cb..ffbf522 100644 --- a/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp +++ b/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -199,6 +200,7 @@ namespace OIC m_mutex{ }, m_mutexKeyAttributeUpdate{ } { + m_lockOwner.reset(new AtomicThreadId); } RCSResourceObject::~RCSResourceObject() @@ -306,12 +308,22 @@ namespace OIC void RCSResourceObject::expectOwnLock() const { - if (m_lockOwner != std::this_thread::get_id()) + if (getLockOwner() != std::this_thread::get_id()) { throw NoLockException{ "Must acquire the lock first using LockGuard." }; } } + std::thread::id RCSResourceObject::getLockOwner() const noexcept + { + return *m_lockOwner; + } + + void RCSResourceObject::setLockOwner(std::thread::id&& id) const noexcept + { + m_lockOwner->store(std::move(id)); + } + bool RCSResourceObject::isObservable() const { return ::hasProperty(m_properties, OC_OBSERVABLE); @@ -480,14 +492,14 @@ namespace OIC AttrKeyValuePairs replaced = requestHandler->applyAcceptanceMethod( response.getAcceptanceMethod(), *this, attrs); - for (const auto& it : replaced) + for (const auto& attrKeyValPair : replaced) { std::lock_guard lock(m_mutexKeyAttributeUpdate); - auto keyAttribute = m_keyAttributesUpdatedListeners.find(it.first); - if(keyAttribute != m_keyAttributesUpdatedListeners.end()) + auto keyAttrListener = m_keyAttributesUpdatedListeners.find(attrKeyValPair.first); + if(keyAttrListener != m_keyAttributesUpdatedListeners.end()) { - keyAttribute-> second(it.second, attrs[it.first]); + keyAttrListener-> second(attrKeyValPair.second, attrs[attrKeyValPair.first]); } } @@ -496,10 +508,8 @@ namespace OIC } OCEntityHandlerResult RCSResourceObject::handleObserve( - std::shared_ptr< OC::OCResourceRequest > request) + std::shared_ptr< OC::OCResourceRequest >) { - assert(request != nullptr); - if (!isObservable()) { return OC_EH_ERROR; @@ -549,17 +559,17 @@ namespace OIC if (m_isOwningLock) { - m_resourceObject.m_lockOwner = std::thread::id{ }; + m_resourceObject.setLockOwner(std::thread::id{ }); m_resourceObject.m_mutex.unlock(); } } void RCSResourceObject::LockGuard::init() { - if (m_resourceObject.m_lockOwner != std::this_thread::get_id()) + if (m_resourceObject.getLockOwner() != std::this_thread::get_id()) { m_resourceObject.m_mutex.lock(); - m_resourceObject.m_lockOwner = std::this_thread::get_id(); + m_resourceObject.setLockOwner(std::this_thread::get_id()); m_isOwningLock = true; } m_autoNotifyFunc = ::createAutoNotifyInvoker(&RCSResourceObject::autoNotify, @@ -571,10 +581,10 @@ namespace OIC m_isOwningLock{ false }, m_resourceObject(resourceObject) { - if (resourceObject.m_lockOwner != std::this_thread::get_id()) + if (m_resourceObject.getLockOwner() != std::this_thread::get_id()) { m_resourceObject.m_mutex.lock(); - m_resourceObject.m_lockOwner = std::this_thread::get_id(); + m_resourceObject.setLockOwner(std::this_thread::get_id()); m_isOwningLock = true; } } @@ -583,7 +593,7 @@ namespace OIC { if (m_isOwningLock) { - m_resourceObject.m_lockOwner = std::thread::id{ }; + m_resourceObject.setLockOwner(std::thread::id{ }); m_resourceObject.m_mutex.unlock(); } } @@ -592,5 +602,6 @@ namespace OIC { return m_isOwningLock; } + } } diff --git a/service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp b/service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp index 33cfaa6..435859d 100644 --- a/service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp +++ b/service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp @@ -287,7 +287,8 @@ public: { auto request = make_shared(); - OCEntityHandlerRequest ocEntityHandlerRequest { 0 }; + OCEntityHandlerRequest ocEntityHandlerRequest; + memset(&ocEntityHandlerRequest, 0, sizeof(OCEntityHandlerRequest)); OC::MessageContainer mc; mc.addRepresentation(ocRep); diff --git a/service/resource-encapsulation/unittests/ResourceClientTest.cpp b/service/resource-encapsulation/unittests/ResourceClientTest.cpp index c51d1a5..08b58cd 100644 --- a/service/resource-encapsulation/unittests/ResourceClientTest.cpp +++ b/service/resource-encapsulation/unittests/ResourceClientTest.cpp @@ -102,10 +102,11 @@ private: { while (checkObject()) { - RCSDiscoveryManager::getInstance()->discoverResource(RCSAddress::multicast(), - "/oic/res?rt=Resource.Hosting", std::bind(resourceDiscovered, this, finished, - std::placeholders::_1)); - + const std::string uri = "/oic/res"; + const std::string type = "Resource.Hosting"; + RCSDiscoveryManager::getInstance()->discoverResourceByType(RCSAddress::multicast(), + uri, type, std::bind(resourceDiscovered, this, finished, + std::placeholders::_1)); Wait(1000); } } diff --git a/service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/DataReader.java b/service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/DataReader.java index 2679850..2171753 100644 --- a/service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/DataReader.java +++ b/service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/DataReader.java @@ -37,9 +37,9 @@ import java.util.List; public class DataReader { - private int pDataReaderInstance; + private long pDataReaderInstance; - public DataReader(int dataReaderInstance) + private DataReader(long dataReaderInstance) { pDataReaderInstance = dataReaderInstance; } diff --git a/service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/ModelData.java b/service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/ModelData.java index c276f83..fc408da 100644 --- a/service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/ModelData.java +++ b/service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/ModelData.java @@ -36,9 +36,9 @@ package org.iotivity.service.ssm; public class ModelData { - private int pIModelDataInstance; + private long pIModelDataInstance; - public ModelData(int iModelDataInstance) + private ModelData(long iModelDataInstance) { pIModelDataInstance = iModelDataInstance; } @@ -97,4 +97,4 @@ public class ModelData return CoreController.getInstance().getPropertyValue( pIModelDataInstance, propertyIndex); } -} \ No newline at end of file +} diff --git a/service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/QueryEngine.java b/service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/QueryEngine.java index 348e51d..8acc1a9 100644 --- a/service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/QueryEngine.java +++ b/service/soft-sensor-manager/SDK/java/org/iotivity/service/ssm/QueryEngine.java @@ -36,9 +36,9 @@ package org.iotivity.service.ssm; */ public class QueryEngine { - private int pQueryEngineInstance; + private long pQueryEngineInstance; - public QueryEngine(int queryEngineInstance) + private QueryEngine(long queryEngineInstance) { pQueryEngineInstance = queryEngineInstance; } @@ -50,7 +50,7 @@ public class QueryEngine * @return int - Instance of the query engine object, set on object's creation * */ - public int getQueryEngineInstance() + public long getQueryEngineInstance() { return pQueryEngineInstance; } @@ -100,4 +100,4 @@ public class QueryEngine CoreController.getInstance().killContextQuery(pQueryEngineInstance, cqid); } -} \ No newline at end of file +} diff --git a/service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.cpp b/service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.cpp index f088ed2..05ec0d6 100644 --- a/service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.cpp +++ b/service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.cpp @@ -109,14 +109,18 @@ class QueryEngineEventReceiver env->GetMethodID(g_ClassQueryEngineEvent, "onQueryEngineEvent", "(ILorg/iotivity/service/ssm/DataReader;)V"); - jmethodID cid_DataReader = env->GetMethodID(g_ClassDataReader, "", "(I)V"); + jmethodID cid_DataReader = env->GetMethodID(g_ClassDataReader, "", "(J)V"); if (cid_DataReader == NULL) return SSM_E_FAIL; - env->CallVoidMethod(m_objQueryEngineEvent, midQueryEngineEvent, + env->CallVoidMethod(m_objQueryEngineEvent, + midQueryEngineEvent, (jint)cqid, - env->NewObject(g_ClassDataReader, cid_DataReader, (jint)pResult)); + env->NewObject( + g_ClassDataReader, + cid_DataReader, + reinterpret_cast(pResult))); DETACH_CURRENT_THREAD(g_JVM); @@ -240,12 +244,12 @@ JNIEXPORT jobject JNICALL Java_org_iotivity_service_ssm_CoreController_createQue return NULL; } - jmethodID cid_QueryEngine = env->GetMethodID(g_ClassQueryEngine, "", "(I)V"); + jmethodID cid_QueryEngine = env->GetMethodID(g_ClassQueryEngine, "", "(J)V"); if (cid_QueryEngine == NULL) return NULL; - return env->NewObject(g_ClassQueryEngine, cid_QueryEngine, (jint)pQueryEngine); + return env->NewObject(g_ClassQueryEngine, cid_QueryEngine, reinterpret_cast(pQueryEngine)); } JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_releaseQueryEngine @@ -265,7 +269,7 @@ JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_releaseQuery } JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_executeContextQuery -(JNIEnv *env, jclass clz, jint pQueryEngineInstance, jstring jstrContextQuery) +(JNIEnv *env, jclass clz, jlong pQueryEngineInstance, jstring jstrContextQuery) { int cqid = -1; if (jstrContextQuery == NULL) @@ -289,7 +293,7 @@ JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_executeConte } JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_registerQueryEvent -(JNIEnv *env, jclass clz, jint pQueryEngineInstance, jobject queryEngineEvent) +(JNIEnv *env, jclass clz, jlong pQueryEngineInstance, jobject queryEngineEvent) { IQueryEngine *pQueryEngine = (IQueryEngine *)pQueryEngineInstance; @@ -304,7 +308,7 @@ JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_registerQuer } JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_killContextQuery -(JNIEnv *env, jclass clz, jint pQueryEngineInstance, jint cqid) +(JNIEnv *env, jclass clz, jlong pQueryEngineInstance, jint cqid) { IQueryEngine *pQueryEngine = (IQueryEngine *)pQueryEngineInstance; @@ -315,7 +319,7 @@ JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_killContextQ } JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getDataId -(JNIEnv *env, jclass clz, jint pDataReaderInstance) +(JNIEnv *env, jclass clz, jlong pDataReaderInstance) { IModelData *pDataReader = (IModelData *)pDataReaderInstance; @@ -323,7 +327,7 @@ JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getDataId } JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyCount -(JNIEnv *env, jclass clz, jint pIModelDataInstance ) +(JNIEnv *env, jclass clz, jlong pIModelDataInstance ) { IModelData *pModelData = (IModelData *)pIModelDataInstance; @@ -331,7 +335,7 @@ JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyC } JNIEXPORT jstring JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyName -(JNIEnv *env, jclass clz, jint pIModelDataInstance, jint propertyIndex ) +(JNIEnv *env, jclass clz, jlong pIModelDataInstance, jint propertyIndex ) { IModelData *pModelData = (IModelData *)pIModelDataInstance; @@ -339,7 +343,7 @@ JNIEXPORT jstring JNICALL Java_org_iotivity_service_ssm_CoreController_getProper } JNIEXPORT jstring JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyValue -(JNIEnv *env, jclass clz, jint pIModelDataInstance, jint propertyIndex ) +(JNIEnv *env, jclass clz, jlong pIModelDataInstance, jint propertyIndex ) { IModelData *pModelData = (IModelData *)pIModelDataInstance; @@ -347,7 +351,7 @@ JNIEXPORT jstring JNICALL Java_org_iotivity_service_ssm_CoreController_getProper } JNIEXPORT jobject JNICALL Java_org_iotivity_service_ssm_CoreController_getAffectedModels -(JNIEnv *env, jclass clz, jint pDataReaderInstance) +(JNIEnv *env, jclass clz, jlong pDataReaderInstance) { IDataReader *pDataReader = (IDataReader *)pDataReaderInstance; std::vector affectedModels; @@ -372,7 +376,7 @@ JNIEXPORT jobject JNICALL Java_org_iotivity_service_ssm_CoreController_getAffect } JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getModelDataCount -(JNIEnv *env, jclass clz, jint pDataReaderInstance, jstring jstrModelName) +(JNIEnv *env, jclass clz, jlong pDataReaderInstance, jstring jstrModelName) { IDataReader *pDataReader = (IDataReader *)pDataReaderInstance; int modelCount = 0; @@ -389,7 +393,7 @@ JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getModelData } //return IModelData JNIEXPORT jobject JNICALL Java_org_iotivity_service_ssm_CoreController_getModelData -(JNIEnv *env, jclass clz, jint pDataReaderInstance, jstring jstrModelName, jint jintDataIndex ) +(JNIEnv *env, jclass clz, jlong pDataReaderInstance, jstring jstrModelName, jint jintDataIndex ) { IDataReader *pDataReader = (IDataReader *)pDataReaderInstance; IModelData *pModelData = NULL; @@ -401,12 +405,12 @@ JNIEXPORT jobject JNICALL Java_org_iotivity_service_ssm_CoreController_getModelD return NULL; } - jmethodID cid_ModelData = env->GetMethodID(g_ClassModelData, "", "(I)V"); + jmethodID cid_ModelData = env->GetMethodID(g_ClassModelData, "", "(J)V"); if (cid_ModelData == NULL) return NULL; - return env->NewObject(g_ClassModelData, cid_ModelData, (jint)pModelData); + return env->NewObject(g_ClassModelData, cid_ModelData, reinterpret_cast(pModelData)); } JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_registerReportReceiver diff --git a/service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.h b/service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.h index d950bce..1d4a707 100644 --- a/service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.h +++ b/service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.h @@ -45,34 +45,34 @@ JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_releaseQuery (JNIEnv *env, jclass clz, jobject queryEngine); JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_executeContextQuery -(JNIEnv *env, jclass clz, jint pQueryEngineInstance, jstring jstrContextQuery); +(JNIEnv *env, jclass clz, jlong pQueryEngineInstance, jstring jstrContextQuery); JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_registerQueryEvent -(JNIEnv *env, jclass clz, jint pQueryEngineInstance, jobject queryEngineEvent); +(JNIEnv *env, jclass clz, jlong pQueryEngineInstance, jobject queryEngineEvent); JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_killContextQuery -(JNIEnv *env, jclass clz, jint pQueryEngineInstance, jint cqid); +(JNIEnv *env, jclass clz, jlong pQueryEngineInstance, jint cqid); JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getDataId -(JNIEnv *env, jclass clz, jint pDataReaderInstance); +(JNIEnv *env, jclass clz, jlong pDataReaderInstance); JNIEXPORT jobject JNICALL Java_org_iotivity_service_ssm_CoreController_getAffectedModels -(JNIEnv *env, jclass clz, jint pDataReaderInstance); +(JNIEnv *env, jclass clz, jlong pDataReaderInstance); JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getModelDataCount -(JNIEnv *env, jclass clz, jint pDataReaderInstance, jstring jstrModelName); +(JNIEnv *env, jclass clz, jlong pDataReaderInstance, jstring jstrModelName); JNIEXPORT jobject JNICALL Java_org_iotivity_service_ssm_CoreController_getModelData -(JNIEnv *env, jclass clz, jint pDataReaderInstance, jstring jstrModelName, jint jintDataIndex ); +(JNIEnv *env, jclass clz, jlong pDataReaderInstance, jstring jstrModelName, jint jintDataIndex ); JNIEXPORT jint JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyCount -(JNIEnv *env, jclass clz, jint pIModelDataInstance ); +(JNIEnv *env, jclass clz, jlong pIModelDataInstance ); JNIEXPORT jstring JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyName -(JNIEnv *env, jclass clz, jint pIModelDataInstance, jint propertyIndex ); +(JNIEnv *env, jclass clz, jlong pIModelDataInstance, jint propertyIndex ); JNIEXPORT jstring JNICALL Java_org_iotivity_service_ssm_CoreController_getPropertyValue -(JNIEnv *env, jclass clz, jint pIModelDataInstance, jint propertyIndex ); +(JNIEnv *env, jclass clz, jlong pIModelDataInstance, jint propertyIndex ); JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_registerReportReceiver (JNIEnv *env, jclass clz, jobject reportReceiver ); @@ -81,4 +81,4 @@ JNIEXPORT void JNICALL Java_org_iotivity_service_ssm_CoreController_registerRepo } #endif -#endif \ No newline at end of file +#endif diff --git a/service/third_party_libs.scons b/service/third_party_libs.scons index 6ddeebc..6fda850 100644 --- a/service/third_party_libs.scons +++ b/service/third_party_libs.scons @@ -78,11 +78,11 @@ if target_os == 'android': if target_arch == 'armeabi-v7a-hard': target_arch = 'armeabi-v7a' - if target_arch not in ['x86', 'armeabi', 'armeabi-v7a']: + if target_arch not in ['x86', 'x86_64','armeabi', 'armeabi-v7a']: if not env.GetOption('help') and not env.GetOption('clean'): print ''' *********************************** Warning *********************************** -* current only x86, armeabi, armeabi-v7a libraries are provided! * +* current only x86, x86_64, armeabi, armeabi-v7a libraries are provided! * ******************************************************************************* ''' else: -- 2.7.4