Merge pull request #691 from mburshteyn1/textdescriptorreader-fix
Fix error in TextDescriptorReader when data contains leading empty spaces
diff --git a/Makefile-iOS b/Makefile-iOS
index 4d8c33f..b9b9de6 100644
--- a/Makefile-iOS
+++ b/Makefile-iOS
@@ -111,7 +111,9 @@
TargetTupleStem = apple-darwin
TargetTuple = $(TargetTupleStem)-ios
-ARCHS = arm64 armv7 armv7s i386 x86_64
+DEVICE_ARCHS = arm64 armv7 armv7s
+SIMULATOR_ARCHS = i386 x86_64
+ARCHS = $(DEVICE_ARCHS) $(SIMULATOR_ARCHS)
TopTargetLibDir = $(TopResultDir)/$(if $(1),$(1)-,)$(TargetTuple)/lib
@@ -138,11 +140,14 @@
FrameworkModuleMap = $(Framework)/$(FrameworkModulesDirName)/$(FrameworkModuleMapName)
FRAMEWORK_ARCHFLAGS = $(addprefix -arch ,$(ARCHS))
+DEVICE_XARCHS = $(foreach arch, $(DEVICE_ARCHS),-Xarch_$(arch) -isysroot$(IOS_DEVICE_SDK))
+SIMULATOR_XARCHS = $(foreach arch, $(SIMULATOR_ARCHS),-Xarch_$(arch) -isysroot$(IOS_SIMULATOR_SDK))
FRAMEWORK_FLAGS = \
$(FRAMEWORK_ARCHFLAGS) \
$(IOS_MIN_VERSION_FLAG) \
$(FRAMEWORK_ARCHFLAGS) \
- -isysroot $(IOS_DEVICE_SDK) \
+ $(DEVICE_XARCHS) \
+ $(SIMULATOR_XARCHS) \
-I$(IOS_DEVICE_SDK)/$(CoreFoundationHeaders) \
-fpic \
-lc++ \
diff --git a/build/config/android/WeaveProjectConfig.h b/build/config/android/WeaveProjectConfig.h
index 5318eb0..60e96c4 100644
--- a/build/config/android/WeaveProjectConfig.h
+++ b/build/config/android/WeaveProjectConfig.h
@@ -26,7 +26,7 @@
#define WEAVEPROJECTCONFIG_H
// Enable use of an ephemeral UDP source port for locally initiated Weave exchanges.
-#define WEAVE_CONFIG_ENABLE_EPHEMERAL_UDP_PORT 1
+#define WEAVE_CONFIG_ENABLE_EPHEMERAL_UDP_PORT 0
// Enable UDP listening on demand in the WeaveDeviceManager
#define WEAVE_CONFIG_DEVICE_MGR_DEMAND_ENABLE_UDP 1
diff --git a/build/config/ios/WeaveProjectConfig.h b/build/config/ios/WeaveProjectConfig.h
index a2ec644..e28c206 100644
--- a/build/config/ios/WeaveProjectConfig.h
+++ b/build/config/ios/WeaveProjectConfig.h
@@ -26,7 +26,7 @@
#define WEAVEPROJECTCONFIG_H
// Enable use of an ephemeral UDP source port for locally initiated Weave exchanges.
-#define WEAVE_CONFIG_ENABLE_EPHEMERAL_UDP_PORT 1
+#define WEAVE_CONFIG_ENABLE_EPHEMERAL_UDP_PORT 0
// Enable UDP listening on demand in the WeaveDeviceManager
#define WEAVE_CONFIG_DEVICE_MGR_DEMAND_ENABLE_UDP 1
diff --git a/src/ble/BleApplicationDelegate.h b/src/ble/BleApplicationDelegate.h
index c2f2111..e5d7690 100644
--- a/src/ble/BleApplicationDelegate.h
+++ b/src/ble/BleApplicationDelegate.h
@@ -36,6 +36,9 @@
class NL_DLL_EXPORT BleApplicationDelegate
{
public:
+ virtual ~BleApplicationDelegate() {
+ }
+
// Weave calls this function once it closes the last BLEEndPoint associated with a BLE given connection object.
// A call to this function means Weave no longer cares about the state of the given BLE connection.
// The application can use this callback to e.g. close the underlying BLE conection if it is no longer needed,
diff --git a/src/ble/BlePlatformDelegate.h b/src/ble/BlePlatformDelegate.h
index 4425cec..e79dd8e 100644
--- a/src/ble/BlePlatformDelegate.h
+++ b/src/ble/BlePlatformDelegate.h
@@ -40,6 +40,9 @@
class NL_DLL_EXPORT BlePlatformDelegate
{
public:
+ virtual ~BlePlatformDelegate() {
+ }
+
// Following APIs must be implemented by platform:
// Subscribe to updates and indications on the specfied characteristic
diff --git a/src/device-manager/WeaveDataManagementClient.cpp b/src/device-manager/WeaveDataManagementClient.cpp
index e47e672..8be8697 100644
--- a/src/device-manager/WeaveDataManagementClient.cpp
+++ b/src/device-manager/WeaveDataManagementClient.cpp
@@ -575,7 +575,6 @@
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
TraitSchemaEngine::IGetDataDelegate * getDataDelegate = NULL;
- TLVType dummyContainerType;
nl::Weave::TLV::TLVWriter writer;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;
@@ -751,8 +750,6 @@
WEAVE_ERROR GenericTraitUpdatableDataSink::DeleteData(const char * apPath)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
- nl::Weave::TLV::TLVReader reader;
- PacketBuffer * pMsgBuf = NULL;
PropertyPathHandle propertyPathHandle = kNullPropertyPathHandle;
std::map<PropertyPathHandle, PacketBuffer *>::iterator it;
diff --git a/src/device-manager/WeaveDataManagementClient.h b/src/device-manager/WeaveDataManagementClient.h
index 8b96878..1cea9b8 100644
--- a/src/device-manager/WeaveDataManagementClient.h
+++ b/src/device-manager/WeaveDataManagementClient.h
@@ -137,10 +137,6 @@
void * mpAppState;
private:
- union
- {
- DMCompleteFunct General;
- } mOnComplete;
DMErrorFunct mOnError;
template <class T>
diff --git a/src/device-manager/WeaveDeviceManager.h b/src/device-manager/WeaveDeviceManager.h
index 99c23cc..95d97e4 100644
--- a/src/device-manager/WeaveDeviceManager.h
+++ b/src/device-manager/WeaveDeviceManager.h
@@ -136,11 +136,11 @@
WEAVE_ERROR PassiveRendezvousDevice(const uint8_t *accessToken, uint32_t accessTokenLen, void *appReqState, CompleteFunct onComplete, ErrorFunct onError);
#if CONFIG_NETWORK_LAYER_BLE
WEAVE_ERROR ConnectBle(BLE_CONNECTION_OBJECT connObj,
- void *appReqState, CompleteFunct onComplete, ErrorFunct onError, bool autoClose = false);
+ void *appReqState, CompleteFunct onComplete, ErrorFunct onError, bool autoClose = true);
WEAVE_ERROR ConnectBle(BLE_CONNECTION_OBJECT connObj, const char *pairingCode,
- void *appReqState, CompleteFunct onComplete, ErrorFunct onError, bool autoClose = false);
+ void *appReqState, CompleteFunct onComplete, ErrorFunct onError, bool autoClose = true);
WEAVE_ERROR ConnectBle(BLE_CONNECTION_OBJECT connObj, const uint8_t *accessToken, uint32_t accessTokenLen,
- void *appReqState, CompleteFunct onComplete, ErrorFunct onError, bool autoClose = false);
+ void *appReqState, CompleteFunct onComplete, ErrorFunct onError, bool autoClose = true);
#endif // CONFIG_NETWORK_LAYER_BLE
// ----- Remote Passive Rendezvous -----
diff --git a/src/device-manager/cocoa/Makefile.am b/src/device-manager/cocoa/Makefile.am
index 0f2c976..5a1cd7f 100644
--- a/src/device-manager/cocoa/Makefile.am
+++ b/src/device-manager/cocoa/Makefile.am
@@ -63,6 +63,7 @@
NLWeavePasscodeEncryptionSupport.h \
NLWeaveKeyExportClient.h \
NLWeaveKeyExportSupport.h \
+ NLWeaveLogging.h \
NLWdmClient.h \
NLGenericTraitUpdatableDataSink.h \
NLResourceIdentifier.h \
diff --git a/src/device-manager/cocoa/NLIdentifyDeviceCriteria_Protected.h b/src/device-manager/cocoa/NLIdentifyDeviceCriteria_Protected.h
index 9288d8d..f1e3e23 100644
--- a/src/device-manager/cocoa/NLIdentifyDeviceCriteria_Protected.h
+++ b/src/device-manager/cocoa/NLIdentifyDeviceCriteria_Protected.h
@@ -26,6 +26,7 @@
#include "WeaveDeviceManager.h"
#include <Weave/Profiles/device-description/DeviceDescription.h>
+#import "NLIdentifyDeviceCriteria.h"
using nl::Weave::Profiles::DeviceDescription::IdentifyDeviceCriteria;
diff --git a/src/device-manager/cocoa/NLWeaveDeviceManager.h b/src/device-manager/cocoa/NLWeaveDeviceManager.h
index fc9d54e..c992591 100644
--- a/src/device-manager/cocoa/NLWeaveDeviceManager.h
+++ b/src/device-manager/cocoa/NLWeaveDeviceManager.h
@@ -180,7 +180,7 @@
- (BOOL)isConnected;
-- (BOOL)isValidPairingCode:(NSString *)pairingCode;
++ (BOOL)isValidPairingCode:(NSString *)pairingCode;
- (void)getCameraAuthData:(NSString *)nonce completion:(WDMCompletionBlock)completionBlock failure:(WDMFailureBlock)failureBlock;
diff --git a/src/device-manager/cocoa/NLWeaveDeviceManager.mm b/src/device-manager/cocoa/NLWeaveDeviceManager.mm
index 6f1d3ac..8190e88 100644
--- a/src/device-manager/cocoa/NLWeaveDeviceManager.mm
+++ b/src/device-manager/cocoa/NLWeaveDeviceManager.mm
@@ -308,11 +308,11 @@
// Note that we're already in Weave work queue, which means all callbacks for the previous or current request
// has either happened/completed or would be canceled by this call to Close. Therefore, it should be safe
// to wipe out request context variables like _mRequestName and _mCompletionHandler.
-
_mWeaveCppDM->Close();
if (_blePeripheral) {
[[[NLWeaveStack sharedStack] BleDelegate] forceBleDisconnect_Sync:_blePeripheral];
+
// autoclose is disabled when running weave connect ble, close ble after woble stack is
// destroyed
// release reference to the CBPeripheral
@@ -347,11 +347,11 @@
return result ? YES : NO;
}
-- (BOOL)isValidPairingCode:(NSString *)pairingCode;
++ (BOOL)isValidPairingCode:(NSString *)pairingCode;
{
__block bool result = false;
- WDM_LOG_METHOD_SIG();
+ WDM_LOG_DEBUG(@"isValidPairingCode");
if ([pairingCode length] != 0) {
// note we're not executing in any specific queue, as this subroutine is supposed to be 'static'
@@ -939,7 +939,7 @@
_BleConnectionPreparationCompleteHandler = ^(NLWeaveDeviceManager * dm, WEAVE_ERROR err) {
if (WEAVE_NO_ERROR == err) {
err = _mWeaveCppDM->ConnectBle(
- (__bridge void *) _blePeripheral, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError);
+ (__bridge void *) _blePeripheral, (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError, false);
}
if (WEAVE_NO_ERROR != err) {
[dm DispatchAsyncDefaultFailureBlockWithCode:err];
@@ -979,7 +979,7 @@
const char * pairingCodeStr = [pairingCode UTF8String];
err = _mWeaveCppDM->ConnectBle((__bridge void *) _blePeripheral, pairingCodeStr, (__bridge void *) self,
- HandleSimpleOperationComplete, onWeaveError);
+ HandleSimpleOperationComplete, onWeaveError, false);
}
if (WEAVE_NO_ERROR != err) {
[dm DispatchAsyncDefaultFailureBlockWithCode:err];
@@ -1073,7 +1073,7 @@
uint8_t * pAccessToken = (uint8_t *) [accessTokenData bytes];
err = _mWeaveCppDM->ConnectBle((__bridge void *) _blePeripheral, pAccessToken, accessTokenLen,
- (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError);
+ (__bridge void *) self, HandleSimpleOperationComplete, onWeaveError, false);
}
if (WEAVE_NO_ERROR != err) {
diff --git a/src/device-manager/cocoa/NLWeaveDeviceManagerTypes.h b/src/device-manager/cocoa/NLWeaveDeviceManagerTypes.h
index fafd39c..5251865 100644
--- a/src/device-manager/cocoa/NLWeaveDeviceManagerTypes.h
+++ b/src/device-manager/cocoa/NLWeaveDeviceManagerTypes.h
@@ -23,6 +23,7 @@
*/
#import <Foundation/Foundation.h>
+#import "NLWeaveErrorCodes.h"
#ifndef __NLWEAVEDEVICEMANAGERTYPES_H__
#define __NLWEAVEDEVICEMANAGERTYPES_H__
diff --git a/src/device-manager/cocoa/NLWeaveLogging.h b/src/device-manager/cocoa/NLWeaveLogging.h
index 00289c3..3eac928 100644
--- a/src/device-manager/cocoa/NLWeaveLogging.h
+++ b/src/device-manager/cocoa/NLWeaveLogging.h
@@ -96,7 +96,7 @@
*/
@interface NLWeaveLogging : NSObject
-#pragma Logging Configuration
+#pragma mark Logging Configuration
/**
* Sets the shared @c NLWeaveLogWriter to start receiving Weave logs.
@@ -108,7 +108,7 @@
*/
+ (void)setSharedLogWriter:(nullable id<NLWeaveLogWriter>)logWriter;
-#pragma Log Methods
+#pragma mark Log Methods
/**
* Internal handler method for logging a message to the console and notifying the shared log writer.
diff --git a/src/device-manager/cocoa/NLWeaveStack.mm b/src/device-manager/cocoa/NLWeaveStack.mm
index e9345b2..c647eb9 100644
--- a/src/device-manager/cocoa/NLWeaveStack.mm
+++ b/src/device-manager/cocoa/NLWeaveStack.mm
@@ -37,6 +37,8 @@
#include <Weave/Profiles/data-management/Current/WdmManagedNamespace.h>
#include <Weave/Profiles/data-management/DataManagement.h>
+#include <array>
+
using namespace nl::Weave::Profiles;
using namespace nl::Weave::Profiles::DataManagement;
@@ -60,12 +62,6 @@
nl::Ble::BleLayer _mBleLayer;
NLWeaveBleDelegate * _mBleDelegate;
#endif // #if CONFIG_NETWORK_LAYER_BLE
- /*
- int selectRes;
- int MaxNumberedFdPlusOne;
- struct timeval sleepTime;
- fd_set readFDs, writeFDs, exceptFDs;
- */
}
- (WEAVE_ERROR)InitStack_internal:(NSString *)listenAddr bleDelegate:(NLWeaveBleDelegate *)bleDelegate;
@@ -332,18 +328,20 @@
WDM_LOG_DEBUG(@"Shutdown Weave System Layer\n");
_mSystemLayer.Shutdown();
- WDM_LOG_DEBUG(@"Shutdown completed\n");
-
- self.currentState = kWeaveStack_QueueInitialized;
if (WEAVE_NO_ERROR != err) {
WDM_LOG_ERROR(@"Error in ShutdownStack_Stage2 : (%d) %@\n", err, [NSString stringWithUTF8String:nl::ErrorStr(err)]);
}
- // inform application layer about the completion, if so desired
- if (block) {
- block(err);
- }
+ NSTimeInterval delay = 2.0;
+ WDM_LOG_DEBUG(@"Waiting %f seconds for rx/tx buffers to flush.\n", delay);
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), _mWorkQueue, ^(void) {
+ WDM_LOG_DEBUG(@"Shutdown completed\n");
+ self.currentState = kWeaveStack_QueueInitialized;
+ if (block) {
+ block(err);
+ }
+ });
}
/**
@@ -382,8 +380,10 @@
exit:
if (WEAVE_NO_ERROR != err) {
WDM_LOG_ERROR(@"Error in ShutdownStack_Stage1 : (%d) %@\n", err, [NSString stringWithUTF8String:nl::ErrorStr(err)]);
-
- _mShutdownCompletionBlock(err);
+ if (_mShutdownCompletionBlock) {
+ _mShutdownCompletionBlock(err);
+ _mShutdownCompletionBlock = nil;
+ }
}
}
@@ -418,25 +418,19 @@
*/
- (void)TryProcessNetworkEvents
{
- __block struct timeval sleepTime;
- __block fd_set readFDs, writeFDs, exceptFDs;
- int MaxNumberedFdPlusOne = 0;
WEAVE_ERROR err = WEAVE_NO_ERROR;
// WDM_LOG_METHOD_SIG();
+ int sleepTime = 10000;
+ __block std::array<struct pollfd, WEAVE_CONFIG_MAX_POLL_FDS> pollFDs;
+ int numPollFDs = 0;
+
VerifyOrExit(kWeaveStack_FullyInitialized == self.currentState, err = WEAVE_ERROR_INCORRECT_STATE);
- FD_ZERO(&readFDs);
- FD_ZERO(&writeFDs);
- FD_ZERO(&exceptFDs);
-
- sleepTime.tv_sec = 10;
- sleepTime.tv_usec = 0;
-
// Collect the currently active file descriptors.
- _mSystemLayer.PrepareSelect(MaxNumberedFdPlusOne, &readFDs, &writeFDs, &exceptFDs, sleepTime);
- _mInetLayer.PrepareSelect(MaxNumberedFdPlusOne, &readFDs, &writeFDs, &exceptFDs, sleepTime);
+ _mSystemLayer.PrepareSelect(pollFDs.data(), numPollFDs, sleepTime);
+ _mInetLayer.PrepareSelect(pollFDs.data(), numPollFDs, sleepTime);
// WDM_LOG_DEBUG(@"Sleeping for %f sec.\n", sleepTime.tv_sec + (sleepTime.tv_usec / 1000000.0));
@@ -447,7 +441,7 @@
dispatch_async(_mSelectQueue, ^(void) {
// Wait for for I/O or for the next timer to expire.
// Note that this is not a good practice to use with GCD, but it's
- int selectRes = select(MaxNumberedFdPlusOne, &readFDs, &writeFDs, &exceptFDs, &sleepTime);
+ int pollRes = poll(pollFDs.data(), numPollFDs, sleepTime);
dispatch_async(_mWorkQueue, ^(void) {
_mIsWaitingOnSelect = false;
@@ -459,8 +453,8 @@
[self ShutdownStack_Stage2];
} else if (kWeaveStack_FullyInitialized == self.currentState) {
// Perform I/O and/or dispatch timers.
- _mSystemLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
- _mInetLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
+ _mSystemLayer.HandleSelectResult(pollFDs.data(), numPollFDs);
+ _mInetLayer.HandleSelectResult(pollFDs.data(), numPollFDs);
// It's wierd that with iOS 9 SDK, we have to use disaptch_after here,
// instead of directly calling TryProcessNetworkEvents nor dispatch_async.
@@ -558,7 +552,7 @@
{
return;
}
-
+
} // Platform
} // WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current)
diff --git a/src/device-manager/java/WeaveDeviceManager-JNI.cpp b/src/device-manager/java/WeaveDeviceManager-JNI.cpp
index 3491723..65908ed 100644
--- a/src/device-manager/java/WeaveDeviceManager-JNI.cpp
+++ b/src/device-manager/java/WeaveDeviceManager-JNI.cpp
@@ -24,6 +24,7 @@
*
*/
+#include <array>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -1910,9 +1911,6 @@
{
JNIEnv *env;
JavaVMAttachArgs attachArgs;
- struct timeval sleepTime;
- fd_set readFDs, writeFDs, exceptFDs;
- int numFDs = 0;
// Attach the IO thread to the JVM as a daemon thread. This allows the JVM to shutdown
// without waiting for this thread to exit.
@@ -1933,23 +1931,24 @@
// Loop until we told to exit.
while (true)
{
- numFDs = 0;
- FD_ZERO(&readFDs);
- FD_ZERO(&writeFDs);
- FD_ZERO(&exceptFDs);
-
- sleepTime.tv_sec = 10;
- sleepTime.tv_usec = 0;
+ int sleepTime = 10000;
+ struct pollfd pollFDs[WEAVE_CONFIG_MAX_POLL_FDS];
+ int numPollFDs = 0;
// Collect the currently active file descriptors.
- sSystemLayer.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, sleepTime);
- sInet.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, sleepTime);
+ sSystemLayer.PrepareSelect(pollFDs, numPollFDs, sleepTime);
+ sInet.PrepareSelect(pollFDs, numPollFDs, sleepTime);
// Unlock the stack so that Java threads can make API calls.
pthread_mutex_unlock(&sStackLock);
// Wait for for I/O or for the next timer to expire.
- int selectRes = select(numFDs, &readFDs, &writeFDs, &exceptFDs, &sleepTime);
+ int pollRes = poll(pollFDs, numPollFDs, sleepTime);
+ if (pollRes < 0)
+ {
+ printf("poll failed: %s\n", nl::ErrorStr(System::MapErrorPOSIX(errno)));
+ continue;
+ }
// Break the loop if requested to shutdown.
if (sShutdown)
@@ -1959,8 +1958,8 @@
pthread_mutex_lock(&sStackLock);
// Perform I/O and/or dispatch timers.
- sSystemLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
- sInet.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
+ sSystemLayer.HandleSelectResult(pollFDs, numPollFDs);
+ sInet.HandleSelectResult(pollFDs, numPollFDs);
}
// Detach the thread from the JVM.
diff --git a/src/device-manager/python/WeaveDeviceManager-ScriptBinding.cpp b/src/device-manager/python/WeaveDeviceManager-ScriptBinding.cpp
index 7119252..4db957f 100644
--- a/src/device-manager/python/WeaveDeviceManager-ScriptBinding.cpp
+++ b/src/device-manager/python/WeaveDeviceManager-ScriptBinding.cpp
@@ -349,9 +349,10 @@
ExitNow(err = WEAVE_ERROR_NOT_IMPLEMENTED);
#else /* WEAVE_SYSTEM_CONFIG_USE_SOCKETS */
- struct timeval sleepTime;
- fd_set readFDs, writeFDs, exceptFDs;
- int maxFDs = 0;
+ int sleepTime = sleepTimeMS;
+ struct pollfd pollFDs[WEAVE_CONFIG_MAX_POLL_FDS];
+ int numPollFDs = 0;
+ int blePollFD = -1;
#if CONFIG_NETWORK_LAYER_BLE
uint8_t bleWakeByte;
bool result = false;
@@ -367,33 +368,30 @@
} evu;
#endif /* CONFIG_NETWORK_LAYER_BLE */
- FD_ZERO(&readFDs);
- FD_ZERO(&writeFDs);
- FD_ZERO(&exceptFDs);
-
- sleepTime.tv_sec = sleepTimeMS / 1000;
- sleepTime.tv_usec = (sleepTimeMS % 1000) * 1000;
-
if (sSystemLayer.State() == System::kLayerState_Initialized)
- sSystemLayer.PrepareSelect(maxFDs, &readFDs, &writeFDs, &exceptFDs, sleepTime);
+ sSystemLayer.PrepareSelect(pollFDs, numPollFDs, sleepTime);
if (Inet.State == InetLayer::kState_Initialized)
- Inet.PrepareSelect(maxFDs, &readFDs, &writeFDs, &exceptFDs, sleepTime);
+ Inet.PrepareSelect(pollFDs, numPollFDs, sleepTime);
#if CONFIG_NETWORK_LAYER_BLE
// Add read end of BLE wake pipe to readFDs.
- FD_SET(BleWakePipe[0], &readFDs);
-
- if (BleWakePipe[0] + 1 > maxFDs)
- maxFDs = BleWakePipe[0] + 1;
+ {
+ struct pollfd event;
+ event.fd = BleWakePipe[0];
+ event.events = POLLIN;
+ event.revents = 0;
+ blePollFD = numPollFDs;
+ pollFDs[numPollFDs++] = event;
+ }
#endif /* CONFIG_NETWORK_LAYER_BLE */
- int selectRes = select(maxFDs, &readFDs, &writeFDs, &exceptFDs, &sleepTime);
- VerifyOrExit(selectRes >= 0, err = System::MapErrorPOSIX(errno));
+ int pollRes = poll(pollFDs, numPollFDs, sleepTime);
+ VerifyOrExit(pollRes >= 0, err = System::MapErrorPOSIX(errno));
#if CONFIG_NETWORK_LAYER_BLE
// Drive IO to InetLayer and/or BleLayer.
- if (FD_ISSET(BleWakePipe[0], &readFDs))
+ if (pollFDs[blePollFD].revents != 0)
{
while (true)
{
@@ -498,17 +496,14 @@
}
}
}
-
- // Don't bother InetLayer if we only got BLE IO.
- selectRes--;
}
#endif /* CONFIG_NETWORK_LAYER_BLE */
if (sSystemLayer.State() == System::kLayerState_Initialized)
- sSystemLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
+ sSystemLayer.HandleSelectResult(pollFDs, numPollFDs);
if (Inet.State == InetLayer::kState_Initialized)
- Inet.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
+ Inet.HandleSelectResult(pollFDs, numPollFDs);
#endif /* WEAVE_SYSTEM_CONFIG_USE_SOCKETS */
@@ -1373,7 +1368,7 @@
case nl::Weave::Binding::kEvent_DefaultCheck:
WeaveLogDetail(DeviceManager, "kEvent_DefaultCheck");
- // fall through
+ [[fallthrough]];
default:
nl::Weave::Binding::DefaultEventHandler(apAppState, aEvent, aInParam, aOutParam);
}
diff --git a/src/device-manager/python/weave-device-mgr.py b/src/device-manager/python/weave-device-mgr.py
index 809e08a..3c943a9 100755
--- a/src/device-manager/python/weave-device-mgr.py
+++ b/src/device-manager/python/weave-device-mgr.py
@@ -41,8 +41,8 @@
from copy import copy
from cmd import Cmd
-from Cryptodome.Hash import CMAC
-from Cryptodome.Cipher import AES
+from cryptography.hazmat.primitives import cmac
+from cryptography.hazmat.primitives.ciphers import algorithms
from six.moves import range
from six.moves import zip
@@ -148,9 +148,9 @@
def aes_cmac(key, message):
- cipher = CMAC.new(key, ciphermod=AES)
+ cipher = cmac.CMAC.new(algorithms.AES(key))
cipher.update(message)
- return cipher.digest()
+ return cipher.finalize()
#see RFC-4615
@@ -2602,3 +2602,4 @@
if __name__ == "__main__":
main()
+
diff --git a/src/examples/weave-app-common.cpp b/src/examples/weave-app-common.cpp
index d27c2bb..9f6b759 100644
--- a/src/examples/weave-app-common.cpp
+++ b/src/examples/weave-app-common.cpp
@@ -122,40 +122,31 @@
void DriveIO(void)
{
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
- struct timeval sleepTime;
- fd_set readFDs, writeFDs, exceptFDs;
- int numFDs = 0;
- int selectRes;
-
- // Use a sleep value of 100 milliseconds
- sleepTime.tv_sec = 0;
- sleepTime.tv_usec = NETWORK_SLEEP_TIME_MSECS;
-
- FD_ZERO(&readFDs);
- FD_ZERO(&writeFDs);
- FD_ZERO(&exceptFDs);
+ int sleepTime = NETWORK_SLEEP_TIME_MSECS;
+ struct pollfd pollFDs[WEAVE_CONFIG_MAX_POLL_FDS];
+ int numPollFDs = 0;
if (SystemLayer.State() == System::kLayerState_Initialized)
- SystemLayer.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, sleepTime);
+ SystemLayer.PrepareSelect(pollFDs, numPollFDs, sleepTime);
if (Inet.State == InetLayer::kState_Initialized)
- Inet.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, sleepTime);
+ Inet.PrepareSelect(pollFDs, numPollFDs, sleepTime);
- selectRes = select(numFDs, &readFDs, &writeFDs, &exceptFDs, &sleepTime);
- if (selectRes < 0)
+ int pollRes = poll(pollFDs, numPollFDs, sleepTime);
+ if (pollRes < 0)
{
- printf("select failed: %s\n", nl::ErrorStr(System::MapErrorPOSIX(errno)));
+ printf("poll failed: %s\n", nl::ErrorStr(System::MapErrorPOSIX(errno)));
return;
}
if (SystemLayer.State() == System::kLayerState_Initialized)
{
- SystemLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
+ SystemLayer.HandleSelectResult(pollFDs, numPollFDs);
}
if (Inet.State == InetLayer::kState_Initialized)
{
- Inet.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
+ Inet.HandleSelectResult(pollFDs, numPollFDs);
}
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
}
diff --git a/src/inet/IPAddress.cpp b/src/inet/IPAddress.cpp
index c78a857..246f238 100644
--- a/src/inet/IPAddress.cpp
+++ b/src/inet/IPAddress.cpp
@@ -53,19 +53,6 @@
return Addr[0] != other.Addr[0] || Addr[1] != other.Addr[1] || Addr[2] != other.Addr[2] || Addr[3] != other.Addr[3];
}
-IPAddress & IPAddress::operator=(const IPAddress& other)
-{
- if (this != &other)
- {
- Addr[0] = other.Addr[0];
- Addr[1] = other.Addr[1];
- Addr[2] = other.Addr[2];
- Addr[3] = other.Addr[3];
- }
-
- return *this;
-}
-
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
#if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
diff --git a/src/inet/IPAddress.h b/src/inet/IPAddress.h
index c50d2f1..2379985 100644
--- a/src/inet/IPAddress.h
+++ b/src/inet/IPAddress.h
@@ -289,15 +289,6 @@
bool operator !=(const IPAddress& other) const;
/**
- * @brief Conventional assignment operator.
- *
- * @param[in] other The address to copy.
- *
- * @return A reference to this object.
- */
- IPAddress& operator =(const IPAddress& other);
-
- /**
* @brief Emit the IP address in conventional text presentation format.
*
* @param[out] buf The address of the emitted text.
diff --git a/src/inet/IPPrefix.cpp b/src/inet/IPPrefix.cpp
index 492f336..94abd72 100644
--- a/src/inet/IPPrefix.cpp
+++ b/src/inet/IPPrefix.cpp
@@ -53,17 +53,6 @@
return IPAddr != other.IPAddr || Length != other.Length;
}
-IPPrefix & IPPrefix::operator=(const IPPrefix& other)
-{
- if (this != &other)
- {
- IPAddr = other.IPAddr;
- Length = other.Length;
- }
-
- return *this;
-}
-
bool IPPrefix::MatchAddress(const IPAddress& addr) const
{
uint8_t l = (Length <= 128) ? Length : 128;
diff --git a/src/inet/IPPrefix.h b/src/inet/IPPrefix.h
index 0d6e950..d8f19d6 100644
--- a/src/inet/IPPrefix.h
+++ b/src/inet/IPPrefix.h
@@ -100,15 +100,6 @@
bool operator !=(const IPPrefix& other) const;
/**
- * @brief Conventional assignment operator.
- *
- * @param[in] other the prefix to copy.
- *
- * @return a reference to this object.
- */
- IPPrefix& operator =(const IPPrefix& other);
-
- /**
* @brief Test if an address matches the prefix.
*
* @param[in] addr the address to test.
diff --git a/src/inet/InetLayer.cpp b/src/inet/InetLayer.cpp
index b0a4ad6..8638638 100644
--- a/src/inet/InetLayer.cpp
+++ b/src/inet/InetLayer.cpp
@@ -1411,20 +1411,12 @@
/**
* Prepare the sets of file descriptors for @p select() to work with.
*
- * @param[out] nfds The range of file descriptors in the file
- * descriptor set.
- *
- * @param[in] readfds A pointer to the set of readable file descriptors.
- *
- * @param[in] writefds A pointer to the set of writable file descriptors.
- *
- * @param[in] exceptfds A pointer to the set of file descriptors with errors.
- *
- * @param[in] sleepTimeTV A pointer to a structure specifying how long the select should sleep
+ * @param[in,out] pollFDs The fd set which is going to be polled
+ * @param[in,out] numPollFDs The number of fds in the fd set
+ * @param[in] timeoutMS A reference to the maximum sleep time.
*
*/
-void InetLayer::PrepareSelect(int& nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
- struct timeval& sleepTimeTV)
+void InetLayer::PrepareSelect(struct pollfd * pollFDs, int& numPollFDs, int& timeoutMS)
{
if (State != kState_Initialized)
return;
@@ -1434,7 +1426,7 @@
{
RawEndPoint* lEndPoint = RawEndPoint::sPool.Get(*mSystemLayer, i);
if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this))
- lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, nfds, readfds, writefds, exceptfds);
+ lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, pollFDs, numPollFDs);
}
#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT
@@ -1443,7 +1435,7 @@
{
TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*mSystemLayer, i);
if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this))
- lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, nfds, readfds, writefds, exceptfds);
+ lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, pollFDs, numPollFDs);
}
#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
@@ -1452,7 +1444,7 @@
{
UDPEndPoint* lEndPoint = UDPEndPoint::sPool.Get(*mSystemLayer, i);
if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this))
- lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, nfds, readfds, writefds, exceptfds);
+ lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, pollFDs, numPollFDs);
}
#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT
@@ -1461,14 +1453,14 @@
{
TunEndPoint* lEndPoint = TunEndPoint::sPool.Get(*mSystemLayer, i);
if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this))
- lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, nfds, readfds, writefds, exceptfds);
+ lEndPoint->PrepareIO().SetFDs(lEndPoint->mSocket, pollFDs, numPollFDs);
}
#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT
#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES
if (mSystemLayer == &mImplicitSystemLayer)
{
- mSystemLayer->PrepareSelect(nfds, readfds, writefds, exceptfds, sleepTimeTV);
+ mSystemLayer->PrepareSelect(pollFDs, numPollFDs, timeoutMS);
}
#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES
}
@@ -1490,26 +1482,14 @@
* on it allows the endpoint code to clear the I/O flags in the event
* of a close, thus avoiding any confusion.
*
- * @param[in] selectRes The return value of the select call.
- *
- * @param[in] readfds A pointer to the set of read file descriptors.
- *
- * @param[in] writefds A pointer to the set of write file descriptors.
- *
- * @param[in] exceptfds A pointer to the set of file descriptors with
- * errors.
- *
+ * @param[in] pollFDs The result of polled FDs
+ * @param[in] numPollFDs The number of fds in the fd set
*/
-void InetLayer::HandleSelectResult(int selectRes, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
+void InetLayer::HandleSelectResult(const struct pollfd * pollFDs, int numPollFDs)
{
if (State != kState_Initialized)
return;
- if (selectRes < 0)
- return;
-
- if (selectRes > 0)
- {
// Set the pending I/O field for each active endpoint based on the value returned by select.
#if INET_CONFIG_ENABLE_RAW_ENDPOINT
for (size_t i = 0; i < RawEndPoint::sPool.Size(); i++)
@@ -1517,7 +1497,7 @@
RawEndPoint* lEndPoint = RawEndPoint::sPool.Get(*mSystemLayer, i);
if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this))
{
- lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, readfds, writefds, exceptfds);
+ lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, pollFDs, numPollFDs);
}
}
#endif // INET_CONFIG_ENABLE_RAW_ENDPOINT
@@ -1528,7 +1508,7 @@
TCPEndPoint* lEndPoint = TCPEndPoint::sPool.Get(*mSystemLayer, i);
if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this))
{
- lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, readfds, writefds, exceptfds);
+ lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, pollFDs, numPollFDs);
}
}
#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
@@ -1539,7 +1519,7 @@
UDPEndPoint* lEndPoint = UDPEndPoint::sPool.Get(*mSystemLayer, i);
if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this))
{
- lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, readfds, writefds, exceptfds);
+ lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, pollFDs, numPollFDs);
}
}
#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT
@@ -1550,7 +1530,7 @@
TunEndPoint* lEndPoint = TunEndPoint::sPool.Get(*mSystemLayer, i);
if ((lEndPoint != NULL) && lEndPoint->IsCreatedByInetLayer(*this))
{
- lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, readfds, writefds, exceptfds);
+ lEndPoint->mPendingIO = SocketEvents::FromFDs(lEndPoint->mSocket, pollFDs, numPollFDs);
}
}
#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT
@@ -1599,12 +1579,11 @@
}
}
#endif // INET_CONFIG_ENABLE_TUN_ENDPOINT
- }
#if INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES
if (mSystemLayer == &mImplicitSystemLayer)
{
- mSystemLayer->HandleSelectResult(selectRes, readfds, writefds, exceptfds);
+ mSystemLayer->HandleSelectResult(pollFDs, numPollFDs);
}
#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES
}
diff --git a/src/inet/InetLayer.h b/src/inet/InetLayer.h
index 678e997..a4e8ddd 100644
--- a/src/inet/InetLayer.h
+++ b/src/inet/InetLayer.h
@@ -284,8 +284,8 @@
#endif // INET_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
- void PrepareSelect(int& nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval& sleepTime);
- void HandleSelectResult(int selectRes, fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
+ void PrepareSelect(struct pollfd * pollFDs, int& numPollFDs, int& timeoutMS);
+ void HandleSelectResult(const struct pollfd * pollFDs, int numPollFDs);
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
static void UpdateSnapshot(nl::Weave::System::Stats::Snapshot &aSnapshot);
diff --git a/src/inet/InetLayerBasis.cpp b/src/inet/InetLayerBasis.cpp
index 8db5fc2..3895fc0 100644
--- a/src/inet/InetLayerBasis.cpp
+++ b/src/inet/InetLayerBasis.cpp
@@ -32,29 +32,24 @@
/**
* Sets the bit for the specified file descriptor in the given sets of file descriptors.
*
- * @param[in] socket The file descriptor for which the bit is being set.
- *
- * @param[out] nfds A reference to the range of file descriptors in the set.
- *
- * @param[in] readfds A pointer to the set of readable file descriptors.
- *
- * @param[in] writefds A pointer to the set of writable file descriptors.
- *
- * @param[in] exceptfds A pointer to the set of file descriptors with errors.
- *
+ * @param[in] socket The file descriptor for which the bit is being set.
+ * @param[in,out] pollFDs The fd set which is going to be polled
+ * @param[in,out] numPollFDs The number of fds in the fd set
*/
-void SocketEvents::SetFDs(int socket, int& nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
+void SocketEvents::SetFDs(int socket, struct pollfd * pollFDs, int& numPollFDs)
{
if (socket != INET_INVALID_SOCKET_FD)
{
+ struct pollfd & event = pollFDs[numPollFDs];
+ event.fd = socket;
+ event.events = 0;
+ event.revents = 0;
if (IsReadable())
- FD_SET(socket, readfds);
+ event.events |= POLLIN;
if (IsWriteable())
- FD_SET(socket, writefds);
- if (IsError())
- FD_SET(socket, exceptfds);
- if (IsSet() && (socket + 1) > nfds)
- nfds = socket + 1;
+ event.events |= POLLOUT;
+ if (event.events != 0)
+ numPollFDs++;
}
}
@@ -62,27 +57,29 @@
* Set the read, write or exception bit flags for the specified socket based on its status in
* the corresponding file descriptor sets.
*
- * @param[in] socket The file descriptor for which the bit flags are being set.
- *
- * @param[in] readfds A pointer to the set of readable file descriptors.
- *
- * @param[in] writefds A pointer to the set of writable file descriptors.
- *
- * @param[in] exceptfds A pointer to the set of file descriptors with errors.
- *
+ * @param[in] socket The file descriptor for which the bit flags are being set.
+ * @param[in] pollFDs The result of polled FDs
+ * @param[in] numPollFDs The number of fds in the fd set
*/
-SocketEvents SocketEvents::FromFDs(int socket, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
+SocketEvents SocketEvents::FromFDs(int socket, const struct pollfd * pollFDs, int numPollFDs)
{
SocketEvents res;
if (socket != INET_INVALID_SOCKET_FD)
{
- if (FD_ISSET(socket, readfds))
- res.SetRead();
- if (FD_ISSET(socket, writefds))
- res.SetWrite();
- if (FD_ISSET(socket, exceptfds))
- res.SetError();
+ for (int i = 0; i < numPollFDs; ++i)
+ {
+ const struct pollfd & event = pollFDs[i];
+ if (event.fd == socket)
+ {
+ if ((event.revents & (POLLIN | POLLHUP)) != 0)
+ res.SetRead();
+ if ((event.revents & POLLOUT) != 0)
+ res.SetWrite();
+ if ((event.revents & POLLERR) != 0)
+ res.SetError();
+ }
+ }
}
return res;
diff --git a/src/inet/InetLayerBasis.h b/src/inet/InetLayerBasis.h
index 297e30f..fa2c6ba 100644
--- a/src/inet/InetLayerBasis.h
+++ b/src/inet/InetLayerBasis.h
@@ -33,7 +33,7 @@
#include <stdint.h>
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
-#include <sys/select.h>
+#include <poll.h>
#endif
namespace nl {
@@ -204,8 +204,8 @@
*/
void ClearError() { Value &= ~kError; }
- void SetFDs(int socket, int& nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
- static SocketEvents FromFDs(int socket, fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
+ void SetFDs(int socket, struct pollfd * pollFDs, int& numPollFDs);
+ static SocketEvents FromFDs(int socket, const struct pollfd * pollFDs, int numPollFDs);
};
/**
diff --git a/src/inet/RawEndPoint.cpp b/src/inet/RawEndPoint.cpp
index c53a504..2c0def5 100644
--- a/src/inet/RawEndPoint.cpp
+++ b/src/inet/RawEndPoint.cpp
@@ -46,7 +46,7 @@
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
-#include <sys/select.h>
+#include <poll.h>
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif // HAVE_SYS_SOCKET_H
diff --git a/src/inet/TCPEndPoint.cpp b/src/inet/TCPEndPoint.cpp
index 3ac8722..61cab5f 100644
--- a/src/inet/TCPEndPoint.cpp
+++ b/src/inet/TCPEndPoint.cpp
@@ -51,7 +51,7 @@
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
#include <sys/socket.h>
-#include <sys/select.h>
+#include <poll.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
diff --git a/src/inet/UDPEndPoint.cpp b/src/inet/UDPEndPoint.cpp
index 432aa18..d741842 100644
--- a/src/inet/UDPEndPoint.cpp
+++ b/src/inet/UDPEndPoint.cpp
@@ -46,7 +46,7 @@
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
-#include <sys/select.h>
+#include <poll.h>
#if HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif // HAVE_SYS_SOCKET_H
diff --git a/src/lib/core/ExchangeContext.cpp b/src/lib/core/ExchangeContext.cpp
index 8cb0299..08abd02 100644
--- a/src/lib/core/ExchangeContext.cpp
+++ b/src/lib/core/ExchangeContext.cpp
@@ -66,6 +66,7 @@
kFlagAutoReleaseKey = 0x0100, /// Automatically release the message encryption key when the exchange context is freed.
kFlagAutoReleaseConnection = 0x0200, /// Automatically release the associated WeaveConnection when the exchange context is freed.
kFlagUseEphemeralUDPPort = 0x0400, /// When set, use the local ephemeral UDP port as the source port for outbound messages.
+ kFlagCaptureSentMessage = 0x0800, /// Capture the sent message after encoded with Weave headers.
};
/**
@@ -314,6 +315,18 @@
SetFlag(mFlags, static_cast<uint16_t>(kFlagAutoReleaseConnection), autoReleaseCon);
}
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+void ExchangeContext::SetCaptureSentMessage(bool inCaptureSentMessage)
+{
+ SetFlag(mFlags, static_cast<uint16_t>(kFlagCaptureSentMessage), inCaptureSentMessage);
+}
+
+bool ExchangeContext::ShouldCaptureSentMessage() const
+{
+ return GetFlag(mFlags, static_cast<uint16_t>(kFlagCaptureSentMessage));
+}
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
/**
* @fn bool ExchangeContext::UseEphemeralUDPPort(void) const
*
@@ -563,6 +576,15 @@
SetFlag(msgInfo->Flags, kWeaveMessageFlag_ViaEphemeralUDPPort, UseEphemeralUDPPort());
#endif // WEAVE_CONFIG_ENABLE_EPHEMERAL_UDP_PORT
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ // Set flag for capture in MessageInfo if ExchangeContext is marked for
+ // capture.
+ if (ShouldCaptureSentMessage())
+ {
+ msgInfo->Flags |= kWeaveMessageFlag_CaptureTxMessage;
+ }
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
// Send the message via UDP or TCP/BLE based on the presence of a connection.
if (Con != NULL)
{
diff --git a/src/lib/core/HostPortList.cpp b/src/lib/core/HostPortList.cpp
index 5cbbcb9..41191d6 100644
--- a/src/lib/core/HostPortList.cpp
+++ b/src/lib/core/HostPortList.cpp
@@ -35,15 +35,6 @@
using namespace nl::Weave::Encoding;
/**
- * Class default (void) constructor.
- *
- */
-HostPortList::HostPortList(void)
-{
- Clear();
-}
-
-/**
* Reset the list to empty.
*
*/
diff --git a/src/lib/core/HostPortList.h b/src/lib/core/HostPortList.h
index 7151b54..42cf120 100644
--- a/src/lib/core/HostPortList.h
+++ b/src/lib/core/HostPortList.h
@@ -46,7 +46,7 @@
class HostPortList
{
public:
- HostPortList(void);
+ HostPortList(void) = default;
inline HostPortList(const uint8_t *hostPortList, uint8_t hostPortCount, const uint8_t *suffixList, const uint8_t suffixCount)
{
mElements = hostPortList;
diff --git a/src/lib/core/WeaveBinding.cpp b/src/lib/core/WeaveBinding.cpp
index 87c0629..01079c5 100644
--- a/src/lib/core/WeaveBinding.cpp
+++ b/src/lib/core/WeaveBinding.cpp
@@ -1374,6 +1374,14 @@
appExchangeContext->SetAutoReleaseKey(true);
}
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ // If message is marked for capture set flag in Exchange Context
+ if (GetFlag(kFlag_CaptureTxMessage))
+ {
+ appExchangeContext->SetCaptureSentMessage(true);
+ }
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
err = AdjustResponseTimeout(appExchangeContext);
SuccessOrExit(err);
@@ -1930,6 +1938,19 @@
return *this;
}
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+/**
+ * Set the flag for capturing sent messages
+ *
+ * @return A reference to the Binding object.
+ */
+Binding::Configuration& Binding::Configuration::CaptureTxMessage(void)
+{
+ mBinding.SetFlag(kFlag_CaptureTxMessage);
+ return *this;
+}
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
/**
* Configure the binding to allow communication with the sender of a received message.
*
diff --git a/src/lib/core/WeaveBinding.h b/src/lib/core/WeaveBinding.h
index 0d78186..1c12e2b 100644
--- a/src/lib/core/WeaveBinding.h
+++ b/src/lib/core/WeaveBinding.h
@@ -268,6 +268,7 @@
{
kFlag_KeyReserved = 0x1,
kFlag_ConnectionReferenced = 0x2,
+ kFlag_CaptureTxMessage = 0x4,
};
WeaveExchangeManager * mExchangeManager;
@@ -389,6 +390,10 @@
Configuration& Security_EncryptionType(uint8_t aEncType);
Configuration& Security_AuthenticationMode(WeaveAuthMode aAuthMode);
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ Configuration& CaptureTxMessage(void);
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
Configuration& ConfigureFromMessage(const WeaveMessageInfo *aMsgInfo, const Inet::IPPacketInfo *aPacketInfo);
WEAVE_ERROR PrepareBinding(void);
diff --git a/src/lib/core/WeaveConfig.h b/src/lib/core/WeaveConfig.h
index acf5067..3bd4d2a 100644
--- a/src/lib/core/WeaveConfig.h
+++ b/src/lib/core/WeaveConfig.h
@@ -2403,6 +2403,22 @@
#endif // WEAVE_CONFIG_TCP_CONN_REPAIR_SUPPORTED
/**
+ * @def WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ *
+ * @brief
+ * When this option is enabled, transmitted Weave messages can be captured
+ * back at the WeaveMessageLayer after being fully encoded with the Weave
+ * Exchange and Message layer headers.
+ * In orderr to capture messages, the application can configure a WeaveBinding
+ * object to vend an ExchangeContext that is tagged for capture. Thereafter,
+ * all transmitted messages on that ExchangeContext would be captured.
+ *
+ */
+#ifndef WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+#define WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE 0
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
+/**
* @def WEAVE_NON_PRODUCTION_MARKER
*
* @brief Defines the name of a mark symbol whose presence signals that the Weave code
@@ -2422,6 +2438,15 @@
extern const char WEAVE_NON_PRODUCTION_MARKER[];
#endif
+/**
+ * @def WEAVE_CONFIG_MAX_POLL_FDS
+ *
+ * @brief Max number of select/poll fds.
+ */
+#ifndef WEAVE_CONFIG_MAX_POLL_FDS
+#define WEAVE_CONFIG_MAX_POLL_FDS 16
+#endif // WEAVE_CONFIG_MAX_POLL_FDS
+
// clang-format on
#endif /* WEAVE_CONFIG_H_ */
diff --git a/src/lib/core/WeaveConnection.cpp b/src/lib/core/WeaveConnection.cpp
index be05b1c..7ffd9c6 100644
--- a/src/lib/core/WeaveConnection.cpp
+++ b/src/lib/core/WeaveConnection.cpp
@@ -661,6 +661,7 @@
{
msgInfo->Flags |= kWeaveMessageFlag_DestNodeId;
}
+
// Encode the Weave message. NOTE that this results in the payload buffer containing the entire encoded message.
// If the encoded message would have exceeded the sent limit, return WEAVE_ERROR_SENDING_BLOCKED to the caller.
res = MessageLayer->EncodeMessageWithLength(msgInfo, msgBuf, this, UINT16_MAX);
@@ -672,6 +673,18 @@
// Copy msg to a right-sized buffer if applicable
msgBuf = PacketBuffer::RightSize(msgBuf);
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ if (GetFlag(msgInfo->Flags, kWeaveMessageFlag_CaptureTxMessage))
+ {
+ WeaveLogDetail(MessageLayer, "Message tagged for capture over Con %04X ", LogId());
+ if (MessageLayer->OnMessageCapture)
+ {
+ MessageLayer->OnMessageCapture(msgBuf->Start(), msgBuf->DataLength(), msgInfo);
+ }
+ ExitNow(res);
+ }
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
#if CONFIG_NETWORK_LAYER_BLE
if (mBleEndPoint != NULL)
{
@@ -1117,7 +1130,8 @@
MessageLayer->ExchangeMgr->HandleConnectionClosed(this, err);
// Call the Fabric state object to alert it of the connection close.
- MessageLayer->FabricState->HandleConnectionClosed(this);
+ if (MessageLayer->FabricState != NULL)
+ MessageLayer->FabricState->HandleConnectionClosed(this);
// Call the appropriate app callback if allowed.
if ((flags & kDoCloseFlag_SuppressCallback) == 0)
diff --git a/src/lib/core/WeaveExchangeMgr.cpp b/src/lib/core/WeaveExchangeMgr.cpp
index 845861b..dba2c36 100644
--- a/src/lib/core/WeaveExchangeMgr.cpp
+++ b/src/lib/core/WeaveExchangeMgr.cpp
@@ -666,7 +666,7 @@
WeaveLogRetain(ExchangeManager, "Msg %s %08" PRIX32 ":%d %d %016" PRIX64 " %04" PRIX16 " %04" PRIX16 " %ld MsgId:%08" PRIX32,
"rcvd", exchangeHeader.ProfileId, exchangeHeader.MessageType,
- (int)msgBuf->DataLength(), msgInfo->SourceNodeId, msgCon->LogId(), exchangeHeader.ExchangeId,
+ (int)msgBuf->DataLength(), msgInfo->SourceNodeId, ((msgCon == NULL) ? -1 : msgCon->LogId()), exchangeHeader.ExchangeId,
(long)err, msgInfo->MessageId);
#if WEAVE_CONFIG_USE_APP_GROUP_KEYS_FOR_MSG_ENC
@@ -1556,7 +1556,7 @@
WEAVE_ERROR WeaveExchangeManager::SendFromRetransTable(RetransTableEntry *entry)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
- uint16_t msgSendFlags = 0;
+ uint32_t msgSendFlags = 0;
uint8_t *p = NULL;
uint32_t len = 0;
ExchangeContext *ec = entry->exchContext;
@@ -1573,6 +1573,12 @@
if (ec)
{
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ if (ec->ShouldCaptureSentMessage())
+ {
+ SetFlag(msgSendFlags, kWeaveMessageFlag_CaptureTxMessage);
+ }
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
SetFlag(msgSendFlags, kWeaveMessageFlag_RetainBuffer);
#if WEAVE_CONFIG_ENABLE_EPHEMERAL_UDP_PORT
diff --git a/src/lib/core/WeaveExchangeMgr.h b/src/lib/core/WeaveExchangeMgr.h
index 957d6c0..fb638a8 100644
--- a/src/lib/core/WeaveExchangeMgr.h
+++ b/src/lib/core/WeaveExchangeMgr.h
@@ -159,6 +159,8 @@
kSendFlag_RequestAck = 0x0400, /**< Used to send a WRM message requesting an acknowledgment. */
kSendFlag_NoAutoRequestAck = 0x0800, /**< Suppress the auto-request acknowledgment feature when sending a message. */
+ kSendFlag_CaptureSentMessage = 0x1000, /**< Capture the sent message after encoded with Weave headers */
+
kSendFlag_MulticastFromLinkLocal = kSendFlag_DefaultMulticastSourceAddress,
/**< Deprecated alias for \c kSendFlag_DefaultMulticastSourceAddress */
};
@@ -192,6 +194,11 @@
void SetUseEphemeralUDPPort(bool val);
#endif
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ void SetCaptureSentMessage(bool inCaptureSentMessage);
+ bool ShouldCaptureSentMessage() const;
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
WEAVE_ERROR SendMessage(uint32_t profileId, uint8_t msgType, PacketBuffer *msgPayload, uint16_t sendFlags = 0, void *msgCtxt = 0);
WEAVE_ERROR SendMessage(uint32_t profileId, uint8_t msgType, PacketBuffer *msgBuf, uint16_t sendFlags, WeaveMessageInfo * msgInfo, void *msgCtxt = 0);
WEAVE_ERROR SendCommonNullMessage(void);
diff --git a/src/lib/core/WeaveMessageLayer.cpp b/src/lib/core/WeaveMessageLayer.cpp
index 5393077..a7b9717 100644
--- a/src/lib/core/WeaveMessageLayer.cpp
+++ b/src/lib/core/WeaveMessageLayer.cpp
@@ -153,6 +153,9 @@
SecurityMgr = NULL;
IsListening = context->listenTCP || context->listenUDP;
IncomingConIdleTimeout = WEAVE_CONFIG_DEFAULT_INCOMING_CONNECTION_IDLE_TIMEOUT;
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ OnMessageCapture = NULL;
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
//Internal and for Debug Only; When set, Message Layer drops message and returns.
mDropMessage = false;
@@ -250,6 +253,9 @@
ExchangeMgr = NULL;
AppState = NULL;
mFlags = 0;
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ OnMessageCapture = NULL;
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
return WEAVE_NO_ERROR;
}
@@ -547,7 +553,7 @@
* @retval errors generated from the lower Inet layer UDP endpoint during sending.
*
*/
-WEAVE_ERROR WeaveMessageLayer::SendMessage(const IPAddress & destAddr, uint16_t destPort, InterfaceId sendIntfId,
+WEAVE_ERROR WeaveMessageLayer::SendMessage(IPAddress & destAddr, uint16_t destPort, InterfaceId sendIntfId,
PacketBuffer * payload, uint32_t msgFlags)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
@@ -561,6 +567,21 @@
} sendAction;
uint16_t udpSendFlags;
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ // Check the destination address to check if the message is meant to be sent
+ // to the Service Cloud subnet. In that case, replace the subnetID to the
+ // CaptureSubnet if it is tagged for capture.
+
+ if (GetFlag(msgFlags, kWeaveMessageFlag_CaptureTxMessage) && destAddr.Subnet() == kWeaveSubnetId_Service)
+ {
+ char ipAddrStr[64];
+ destAddr = IPAddress::MakeULA(FabricState->FabricId, kWeaveSubnetId_TunneledCapture, destAddr.InterfaceId());
+ ClearFlag(msgFlags, kWeaveMessageFlag_CaptureTxMessage);
+ destAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
+ WeaveLogDetail(ExchangeManager, "Setting Capture Subnet in DestAddr %s", ipAddrStr);
+ }
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
IPPacketInfo pktInfo;
pktInfo.Clear();
pktInfo.DestAddress = destAddr;
@@ -625,6 +646,23 @@
sendAction = kMulticast_AllInterfaces;
}
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ // Capture the message if it is tagged for capture in the message flags
+ if (GetFlag(msgFlags, kWeaveMessageFlag_CaptureTxMessage))
+ {
+ WeaveMessageInfo msgInfo;
+ memset(&msgInfo, 0, sizeof(msgInfo));
+ msgInfo.Flags = msgFlags;
+
+ if (OnMessageCapture)
+ {
+ OnMessageCapture(payload->Start(), payload->DataLength(), &msgInfo);
+ }
+
+ ExitNow(err);
+ }
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
// Send the message...
switch (sendAction)
{
@@ -645,7 +683,10 @@
// Send the message over each local interface that supports multicast.
for (InterfaceIterator intfIter; intfIter.HasCurrent(); intfIter.Next())
{
- if (intfIter.SupportsMulticast())
+ bool isBroadcastSupported = intfIter.SupportsMulticast() &&
+ intfIter.HasBroadcastAddress() &&
+ intfIter.IsUp();
+ if (isBroadcastSupported)
{
pktInfo.Interface = intfIter.GetInterface();
WEAVE_ERROR sendErr = ep->SendMsg(&pktInfo, payload, UDPEndPoint::kSendFlag_RetainBuffer);
@@ -668,7 +709,10 @@
{
pktInfo.SrcAddress = addrIter.GetAddress();
pktInfo.Interface = addrIter.GetInterface();
- if (addrIter.SupportsMulticast() &&
+ bool isBroadcastSupported = addrIter.SupportsMulticast() &&
+ addrIter.HasBroadcastAddress() &&
+ addrIter.IsUp();
+ if (isBroadcastSupported &&
FabricState->IsLocalFabricAddress(pktInfo.SrcAddress) &&
(sendIntfId == INET_NULL_INTERFACEID || pktInfo.Interface == sendIntfId))
{
@@ -2406,6 +2450,22 @@
OnMessageLayerActivityChange = messageLayerActivityChangeHandler;
}
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+/**
+ * Set an application handler that would get called to receive the captured
+ * message.
+ *
+ * @param[in] messageLayerPktCaptureHandler A pointer to a function to be
+ * called when a message is captured by the WeaveMessageLayer.
+ *
+ * @retval None.
+ */
+void WeaveMessageLayer::SetMessageLayerPktCaptureHandler(MessageLayerPktCaptureHandlerFunct messageLayerPktCaptureHandler)
+{
+ OnMessageCapture = messageLayerPktCaptureHandler;
+}
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
bool WeaveMessageLayer::IsMessageLayerActive(void)
{
return (ExchangeMgr->mContextsInUse != 0)
diff --git a/src/lib/core/WeaveMessageLayer.h b/src/lib/core/WeaveMessageLayer.h
index 44cb6c1..1bf664f 100644
--- a/src/lib/core/WeaveMessageLayer.h
+++ b/src/lib/core/WeaveMessageLayer.h
@@ -137,10 +137,11 @@
kWeaveMessageFlag_PeerRequestedAck = 0x00004000, /**< Indicates that the sender of the message requested an acknowledgment. */
kWeaveMessageFlag_DuplicateMessage = 0x00008000, /**< Indicates that the message is a duplicate of a previously received message. */
kWeaveMessageFlag_PeerGroupMsgIdNotSynchronized = 0x00010000, /**< Indicates that the peer's group key message counter is not synchronized. */
- kWeaveMessageFlag_FromInitiator = 0x00020000, /**< Indicates that the source of the message is the initiator of the
- Weave exchange. */
+ kWeaveMessageFlag_FromInitiator = 0x00020000, /**< Indicates that the source of the message is the initiator of the Weave exchange. */
kWeaveMessageFlag_ViaEphemeralUDPPort = 0x00040000, /**< Indicates that message is being sent/received via the local ephemeral UDP port. */
+ kWeaveMessageFlag_CaptureTxMessage = 0x00080000, /**< Indicates that the outgoing message needs to be captured. */
+
kWeaveMessageFlag_MulticastFromLinkLocal = kWeaveMessageFlag_DefaultMulticastSourceAddress,
/**< Deprecated alias for \c kWeaveMessageFlag_DefaultMulticastSourceAddress */
@@ -745,6 +746,27 @@
void SetSignalMessageLayerActivityChanged(MessageLayerActivityChangeHandlerFunct messageLayerActivityChangeHandler);
bool IsMessageLayerActive(void);
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ /**
+ * This function is the callback for capturing a sent Weave message and
+ * passing it to the application. The Weave message encoded all the way to
+ * the MessageLayer is captured and handed over via this API.
+ *
+ * @param[in] msgBuf A pointer to the Weave message being captured.
+ *
+ * @param[in] msgLen Length of the encoded message in the buffer.
+ *
+ * @param[in] msgInfo A pointer to the WeaveMessageInfo object
+ * pertaining to this captured message.
+ *
+ * @note
+ * All pointer parameters passed via this API may be freed once the callback returns and it is the responsibility
+ * of the callee to copy their contents if need be.
+ */
+ typedef void (*MessageLayerPktCaptureHandlerFunct)(uint8_t *msgBuf, uint16_t msgLen, WeaveMessageInfo *msgInfo);
+ void SetMessageLayerPktCaptureHandler(MessageLayerPktCaptureHandlerFunct messageLayerPktCaptureHandler);
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
static uint32_t GetMaxWeavePayloadSize(const PacketBuffer *msgBuf, bool isUDP, uint32_t udpMTU);
static void GetPeerDescription(char *buf, size_t bufSize, uint64_t nodeId, const IPAddress *addr, uint16_t port, InterfaceId interfaceId, const WeaveConnection *con);
@@ -795,6 +817,10 @@
void *UnsecuredConnectionReceivedAppState;
MessageLayerActivityChangeHandlerFunct OnMessageLayerActivityChange;
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ MessageLayerPktCaptureHandlerFunct OnMessageCapture;
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
WEAVE_ERROR EnableUnsecuredListen(void);
WEAVE_ERROR DisableUnsecuredListen(void);
@@ -805,7 +831,7 @@
WEAVE_ERROR RefreshEndpoint(TCPEndPoint *& endPoint, bool enable, const char * name, IPAddressType addrType, IPAddress addr, uint16_t port);
WEAVE_ERROR RefreshEndpoint(UDPEndPoint *& endPoint, bool enable, const char * name, IPAddressType addrType, IPAddress addr, uint16_t port, InterfaceId intfId);
- WEAVE_ERROR SendMessage(const IPAddress &destAddr, uint16_t destPort, InterfaceId sendIntfId, PacketBuffer *payload, uint32_t msgFlags);
+ WEAVE_ERROR SendMessage(IPAddress &destAddr, uint16_t destPort, InterfaceId sendIntfId, PacketBuffer *payload, uint32_t msgFlags);
WEAVE_ERROR SelectOutboundUDPEndPoint(const IPAddress & destAddr, uint32_t msgFlags, UDPEndPoint *& ep);
WEAVE_ERROR SelectDestNodeIdAndAddress(uint64_t& destNodeId, IPAddress& destAddr);
WEAVE_ERROR DecodeMessage(PacketBuffer *msgBuf, uint64_t sourceNodeId, WeaveConnection *con,
@@ -1086,6 +1112,7 @@
kWeaveSubnetId_MobileDevice = 4, /**< The subnet identifier for all Mobile devices. */
kWeaveSubnetId_Service = 5, /**< The subnet identifier for the Nest Service endpoints. */
kWeaveSubnetId_ThreadMesh = 6, /**< The Thread mesh radio interface subnet identifier. */
+ kWeaveSubnetId_TunneledCapture = 32, /**< A Subnet identifier for marking a tunneled packet for capture. */
} WeaveSubnetId;
#define WEAVE_MAX_NODE_ADDR_STR_LENGTH (nl::Weave::kWeavePeerDescription_MaxLength)
diff --git a/src/lib/core/WeaveTLVDebug.cpp b/src/lib/core/WeaveTLVDebug.cpp
index bd66a7d..8d6cf46 100644
--- a/src/lib/core/WeaveTLVDebug.cpp
+++ b/src/lib/core/WeaveTLVDebug.cpp
@@ -154,7 +154,10 @@
err = temp.GetDataPtr(strbuf);
VerifyOrExit(err == WEAVE_NO_ERROR, aWriter("Error in kTLVType_ByteString"));
}
- aWriter("%p\n", strbuf);
+ for (int i = 0; i < len; i++) {
+ aWriter("%02x ", strbuf[i]);
+ }
+ aWriter("\n");
break;
case kTLVType_Null:
diff --git a/src/lib/core/WeaveTLVReader.cpp b/src/lib/core/WeaveTLVReader.cpp
index ae48bf9..e6e198b 100644
--- a/src/lib/core/WeaveTLVReader.cpp
+++ b/src/lib/core/WeaveTLVReader.cpp
@@ -541,6 +541,45 @@
return WEAVE_NO_ERROR;
}
+namespace {
+float BitCastToFloat(const uint64_t elemLenOrVal)
+{
+ float f;
+ auto u32 = static_cast<uint32_t>(elemLenOrVal);
+ memcpy(&f, &u32, sizeof(f));
+ return f;
+}
+} // namespace
+
+// Note: Unlike the integer Get functions, this code avoids doing conversions
+// between float and double wherever possible, because these conversions are
+// relatively expensive on platforms that use soft-float instruction sets.
+
+/**
+ * Get the value of the current element as a single-precision floating point number.
+ *
+ * @param[out] v Receives the value associated with current TLV element.
+ *
+ * @retval #WEAVE_NO_ERROR If the method succeeded.
+ * @retval #WEAVE_ERROR_WRONG_TLV_TYPE If the current element is not a TLV floating point type, or
+ * the reader is not positioned on an element.
+ *
+ */
+WEAVE_ERROR TLVReader::Get(float & v)
+{
+ switch (ElementType())
+ {
+ case kTLVElementType_FloatingPointNumber32:
+ {
+ v = BitCastToFloat(mElemLenOrVal);
+ break;
+ }
+ default:
+ return WEAVE_ERROR_WRONG_TLV_TYPE;
+ }
+ return WEAVE_NO_ERROR;
+}
+
/**
* Get the value of the current element as a double-precision floating point number.
*
@@ -557,24 +596,14 @@
{
case kTLVElementType_FloatingPointNumber32:
{
- union
- {
- uint32_t u32;
- float f;
- } cvt;
- cvt.u32 = (uint32_t)mElemLenOrVal;
- v = cvt.f;
+ v = BitCastToFloat(mElemLenOrVal);
break;
}
case kTLVElementType_FloatingPointNumber64:
{
- union
- {
- uint64_t u64;
- double d;
- } cvt;
- cvt.u64 = mElemLenOrVal;
- v = cvt.d;
+ double d;
+ memcpy(&d, &mElemLenOrVal, sizeof(d));
+ v = d;
break;
}
default:
diff --git a/src/lib/profiles/data-management/Current/Command.h b/src/lib/profiles/data-management/Current/Command.h
index 6cb07b7..58155fd 100644
--- a/src/lib/profiles/data-management/Current/Command.h
+++ b/src/lib/profiles/data-management/Current/Command.h
@@ -77,18 +77,6 @@
class NL_DLL_EXPORT Command
{
public:
- /**
- * @brief
- * The Command flag bits.
- */
- typedef enum CommandFlags
- {
- kCommandFlag_MustBeVersionValid = 0x0001, /**< Set when the version field is valid */
- kCommandFlag_InitiationTimeValid = 0x0002, /**< Set when the init time is valid */
- kCommandFlag_ActionTimeValid = 0x0004, /**< Set when the action time is valid */
- kCommandFlag_ExpiryTimeValid = 0x0008, /**< Set when the expiry time is valid */
- kCommandFlag_IsOneWay = 0x0010, /**< Set when the command is one-way */
- } CommandFlags;
uint64_t commandType;
uint64_t mustBeVersion;
diff --git a/src/lib/profiles/data-management/Current/CommandSender.cpp b/src/lib/profiles/data-management/Current/CommandSender.cpp
index a5e9f39..27c3bf8 100644
--- a/src/lib/profiles/data-management/Current/CommandSender.cpp
+++ b/src/lib/profiles/data-management/Current/CommandSender.cpp
@@ -209,9 +209,7 @@
WEAVE_ERROR CommandSender::SendCommand(nl::Weave::PacketBuffer *aPayload, nl::Weave::Binding *aBinding, ResourceIdentifier &aResourceId, uint32_t aProfileId, uint32_t aCommandType)
{
- SendParams sendParams;
-
- memset(&sendParams, 0, sizeof(sendParams));
+ SendParams sendParams = SendParams();
sendParams.ResourceId = aResourceId;
sendParams.ProfileId = aProfileId;
@@ -431,12 +429,11 @@
void CommandSender::OnResponseTimeout(ExchangeContext *aEC)
{
- WEAVE_ERROR err = WEAVE_NO_ERROR;
CommandSender *_this = static_cast<CommandSender *>(aEC->AppState);
InEventParam inEventParam;
OutEventParam outEventParam;
- VerifyOrExit(_this, err = WEAVE_ERROR_INVALID_ARGUMENT);
+ VerifyOrExit(_this, );
inEventParam.CommunicationError.error = WEAVE_ERROR_TIMEOUT;
_this->mEventCallback(_this->mAppState, kEvent_CommunicationError, inEventParam, outEventParam);
diff --git a/src/lib/profiles/data-management/Current/LoggingManagement.cpp b/src/lib/profiles/data-management/Current/LoggingManagement.cpp
index ff32a7a..df2f09a 100644
--- a/src/lib/profiles/data-management/Current/LoggingManagement.cpp
+++ b/src/lib/profiles/data-management/Current/LoggingManagement.cpp
@@ -2276,9 +2276,9 @@
size_t bufLen = mBuffer.GetQueueSize();
size_t initLen = inBufLen;
- if (initLen > bufStart + bufLen - inBufStart)
+ if (initLen > ((size_t) ((bufStart - inBufStart) + bufLen)))
{
- initLen = bufStart + bufLen - inBufStart;
+ initLen = (size_t) ((bufStart - inBufStart) + bufLen);
}
err = writer.StartContainer(AnonymousTag, kTLVType_Structure, container);
diff --git a/src/lib/profiles/data-management/Current/NotificationEngine.cpp b/src/lib/profiles/data-management/Current/NotificationEngine.cpp
index f26df90..573da3a 100644
--- a/src/lib/profiles/data-management/Current/NotificationEngine.cpp
+++ b/src/lib/profiles/data-management/Current/NotificationEngine.cpp
@@ -1033,6 +1033,7 @@
mCurSubscriptionHandlerIdx = 0;
mCurTraitInstanceIdx = 0;
mNumNotifiesInFlight = 0;
+ mNotifyTxEnabled = true;
return WEAVE_NO_ERROR;
}
@@ -1761,6 +1762,10 @@
bool isClean = true;
bool isLocked = false;
+
+ VerifyOrExit(mNotifyTxEnabled, WeaveLogProgress(DataManagement, "Notify Transmission disabled. Enable to send Notifies");
+ err = WEAVE_NO_ERROR);
+
// Lock before attempting to modify any of the shared data structures.
err = subEngine->Lock();
SuccessOrExit(err);
@@ -1850,3 +1855,23 @@
return;
}
+
+WEAVE_ERROR NotificationEngine::EnableNotifications(void)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ WeaveLogDetail(DataManagement, "<NE> Enabling notifications!");
+ mNotifyTxEnabled = true;
+
+ return err;
+}
+
+WEAVE_ERROR NotificationEngine::DisableNotifications(void)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ WeaveLogDetail(DataManagement, "<NE> Disabling notifications!");
+ mNotifyTxEnabled = false;
+
+ return err;
+}
diff --git a/src/lib/profiles/data-management/Current/NotificationEngine.h b/src/lib/profiles/data-management/Current/NotificationEngine.h
index 22cfad7..b0c666c 100644
--- a/src/lib/profiles/data-management/Current/NotificationEngine.h
+++ b/src/lib/profiles/data-management/Current/NotificationEngine.h
@@ -128,6 +128,16 @@
void ScheduleRun(void);
/**
+ * Enable sending WDM notifications.
+ */
+ WEAVE_ERROR EnableNotifications(void);
+
+ /**
+ * Disable sending WDM notifications.
+ */
+ WEAVE_ERROR DisableNotifications(void);
+
+ /**
* Marks a handle associated with a data source as being dirty.
*
* @retval #WEAVE_NO_ERROR On success.
@@ -416,6 +426,7 @@
uint32_t mCurSubscriptionHandlerIdx;
uint32_t mCurTraitInstanceIdx;
uint32_t mNumNotifiesInFlight;
+ bool mNotifyTxEnabled;
nl::Weave::TLV::TLVType mOuterContainerType;
WEAVE_CONFIG_WDM_PUBLISHER_GRAPH_SOLVER mGraphSolver;
};
diff --git a/src/lib/profiles/data-management/Current/SubscriptionClient.cpp b/src/lib/profiles/data-management/Current/SubscriptionClient.cpp
index a4319f1..f4dee8f 100644
--- a/src/lib/profiles/data-management/Current/SubscriptionClient.cpp
+++ b/src/lib/profiles/data-management/Current/SubscriptionClient.cpp
@@ -576,6 +576,9 @@
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
+ // Make double sure the protocol callback is set on the binding object
+ mBinding->SetProtocolLayerCallback(BindingEventCallback, this);
+
WeaveLogDetail(DataManagement, "Client[%u] [%5.5s] %s Ref(%d)", SubscriptionEngine::GetInstance()->GetClientId(this),
GetStateStr(), __func__, mRefCount);
_AddRef();
diff --git a/src/lib/profiles/data-management/Current/SubscriptionHandler.cpp b/src/lib/profiles/data-management/Current/SubscriptionHandler.cpp
index 273f372..a4ec1bc 100644
--- a/src/lib/profiles/data-management/Current/SubscriptionHandler.cpp
+++ b/src/lib/profiles/data-management/Current/SubscriptionHandler.cpp
@@ -509,14 +509,27 @@
(static_cast<uint32_t>(importance) >= static_cast<uint32_t>(kImportanceType_First)) &&
(static_cast<uint32_t>(importance) <= static_cast<uint32_t>(kImportanceType_Last)))
{
- // We add one to the observed event ID because
- // mSelfVendedEvents should point to the next event ID that
- // we publish. Otherwise, we would publish an event that
- // the subscriber already received.
uint32_t i = static_cast<uint32_t>(importance) - static_cast<uint32_t>(kImportanceType_First);
- WeaveLogProgress(DataManagement, "Update mSelfVendedEvents[%d] from %d to %d using service data",
- i, mSelfVendedEvents[i], eventId + 1);
- mSelfVendedEvents[i] = static_cast<event_id_t>(eventId + 1);
+#if WEAVE_CONFIG_PERSIST_SUBSCRIPTION_STATE
+ if (DeliveredEventsExist((ImportanceType) importance))
+ {
+ WeaveLogProgress(DataManagement, "Update mSelfVendedEvents[%d] from %d to %d using device data",
+ i, mSelfVendedEvents[i], 1 + mDeliveredEvents[i]);
+ mSelfVendedEvents[i] = 1 + mDeliveredEvents[i];
+ }
+ else
+ {
+#endif // WEAVE_CONFIG_PERSIST_SUBSCRIPTION_STATE
+ // We add one to the observed event ID because
+ // mSelfVendedEvents should point to the next event ID that
+ // we publish. Otherwise, we would publish an event that
+ // the subscriber already received.
+ WeaveLogProgress(DataManagement, "Update mSelfVendedEvents[%d] from %d to %d using service data",
+ i, mSelfVendedEvents[i], eventId + 1);
+ mSelfVendedEvents[i] = static_cast<event_id_t>(eventId + 1);
+#if WEAVE_CONFIG_PERSIST_SUBSCRIPTION_STATE
+ }
+#endif // WEAVE_CONFIG_PERSIST_SUBSCRIPTION_STATE
}
else
{
@@ -643,8 +656,18 @@
#if WEAVE_CONFIG_PERSIST_SUBSCRIPTION_STATE
void SubscriptionHandler::UpdateDeliveredEvents(ImportanceType importance)
{
- uint32_t i = static_cast<uint32_t>(importance) - static_cast<uint32_t>(kImportanceType_First);
- mDeliveredEvents[i] = mSelfVendedEvents[i] - 1;
+ uint32_t i = static_cast<uint32_t>(importance) - static_cast<uint32_t>(kImportanceType_First);
+ mDeliveredEvents[i] = mSelfVendedEvents[i] - 1;
+}
+
+bool SubscriptionHandler::DeliveredEventsExist(ImportanceType importance)
+{
+ uint32_t i = static_cast<uint32_t>(importance) - static_cast<uint32_t>(kImportanceType_First);
+ if (mDeliveredEvents[i] != 0)
+ {
+ return true;
+ }
+ return false;
}
#endif // WEAVE_CONFIG_PERSIST_SUBSCRIPTION_STATE
@@ -1785,7 +1808,6 @@
// Capture the binding and arrange to receive event callbacks.
mBinding->AddRef();
- mBinding->SetProtocolLayerCallback(BindingEventCallback, this);
mBytesOffloaded = 0;
@@ -1964,14 +1986,6 @@
// mNumTraitInstanceList has already be incremented
mTraitInstanceList = traitInstance;
}
-
- // TODO (didis) Check if data source is persisted, set to dirty if trait data changed from persisted data
- WeaveLogDetail(DataManagement, "Handler[%u] Syncing is requested for trait[%u].path[%u]",
- SubscriptionEngine::GetInstance()->GetHandlerId(this), traitDataHandle, kRootPropertyPathHandle);
- err = SubscriptionEngine::GetInstance()->mPublisherCatalog->Locate(traitDataHandle, &dataSource);
- SuccessOrExit(err);
- dataSource->SetRootDirty();
- traitInstance->SetDirty();
}
if (err != WEAVE_END_OF_TLV)
diff --git a/src/lib/profiles/data-management/Current/SubscriptionHandler.h b/src/lib/profiles/data-management/Current/SubscriptionHandler.h
index 90fdd72..85ff081 100644
--- a/src/lib/profiles/data-management/Current/SubscriptionHandler.h
+++ b/src/lib/profiles/data-management/Current/SubscriptionHandler.h
@@ -351,6 +351,7 @@
#if WEAVE_CONFIG_PERSIST_SUBSCRIPTION_STATE
void UpdateDeliveredEvents(ImportanceType importance);
+ bool DeliveredEventsExist(ImportanceType importance);
#endif // WEAVE_CONFIG_PERSIST_SUBSCRIPTION_STATE
static void BindingEventCallback(void * const apAppState, const Binding::EventType aEvent,
diff --git a/src/lib/profiles/data-management/Current/UpdateClient.h b/src/lib/profiles/data-management/Current/UpdateClient.h
index 387ebe5..d017191 100644
--- a/src/lib/profiles/data-management/Current/UpdateClient.h
+++ b/src/lib/profiles/data-management/Current/UpdateClient.h
@@ -83,7 +83,6 @@
EventCallback mEventCallback;
nl::Weave::ExchangeContext * mEC;
UpdateClientState mState;
- utc_timestamp_t mExpiryTimeMicroSecond;
static void OnSendError(ExchangeContext * aEC, WEAVE_ERROR aErrorCode, void * aMsgSpecificContext);
static void OnResponseTimeout(nl::Weave::ExchangeContext * aEC);
diff --git a/src/lib/profiles/data-management/Current/UpdateEncoder.h b/src/lib/profiles/data-management/Current/UpdateEncoder.h
index 6ca95f4..874fa89 100644
--- a/src/lib/profiles/data-management/Current/UpdateEncoder.h
+++ b/src/lib/profiles/data-management/Current/UpdateEncoder.h
@@ -138,7 +138,13 @@
*/
struct DataElementDataContext
{
- DataElementDataContext() { memset(this, 0, sizeof(*this)); }
+ DataElementDataContext() :
+ mTraitPath(0, 0),
+ mUpdateRequiredVersion(0),
+ mForceMerge(false),
+ mDataSink(nullptr),
+ mSchemaEngine(nullptr),
+ mNextDictionaryElementPathHandle(0) { }
TraitPath mTraitPath; /**< The TraitPath to encode. */
DataVersion mUpdateRequiredVersion; /**< If the update is conditional, the version the update is based off. */
diff --git a/src/lib/profiles/security/WeaveKeyExportClient.cpp b/src/lib/profiles/security/WeaveKeyExportClient.cpp
index 72757df..e45d1bc 100644
--- a/src/lib/profiles/security/WeaveKeyExportClient.cpp
+++ b/src/lib/profiles/security/WeaveKeyExportClient.cpp
@@ -504,10 +504,7 @@
kDecodeFlag_GenerateTBSHash, cert);
SuccessOrExit(err);
-// we need debug in order to get key export functionality working in mobile-ios
-#if DEBUG
-
- // If DEBUG is enabled and mTrustPreProdDevices == true, arrange to accept key export responses
+ // If mTrustPreProdDevices == true, arrange to accept key export responses
// from pre-production devices built with Nest development certificates.
if (mAllowNestDevDevices)
@@ -529,8 +526,6 @@
SuccessOrExit(err);
}
-#endif //DEBUG
-
exit:
if (err != WEAVE_NO_ERROR && certSetInitialized)
{
diff --git a/src/lib/profiles/weave-tunneling/WeaveTunnelAgent.cpp b/src/lib/profiles/weave-tunneling/WeaveTunnelAgent.cpp
index f1c5a2e..548ecb1 100644
--- a/src/lib/profiles/weave-tunneling/WeaveTunnelAgent.cpp
+++ b/src/lib/profiles/weave-tunneling/WeaveTunnelAgent.cpp
@@ -40,15 +40,20 @@
#include <Weave/Support/WeaveFaultInjection.h>
#include <Weave/Profiles/weave-tunneling/WeaveTunnelCommon.h>
#include <Weave/Profiles/weave-tunneling/WeaveTunnelControl.h>
+#include <Weave/Support/logging/DecodedIPPacket.h>
+#include <Weave/Core/WeaveEncoding.h>
#if WEAVE_CONFIG_ENABLE_TUNNELING
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
#include "lwip/ip6.h"
#include "lwip/ip6_addr.h"
+#include "lwip/sockets.h"
+#include "lwip/udp.h"
#else
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <netinet/udp.h>
#include <netinet/ip6.h>
#endif
@@ -934,6 +939,150 @@
#endif // !WEAVE_SYSTEM_CONFIG_USE_LWIP
}
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
+struct PseudoHeader {
+ uint16_t PayloadLength;
+ uint16_t Protocol;
+ uint8_t SrcAddr[16];
+ uint8_t DstAddr[16];
+};
+
+uint32_t WeaveTunnelAgent::Checksum(uint16_t *buf, uint16_t len)
+{
+ uint32_t sum = 0;
+ uint16_t result = 0;
+
+ while (len > 1)
+ {
+ sum += *buf++;
+ len -= 2;
+ }
+
+ if (len == 1)
+ {
+ *(uint8_t *)(&result) = *(uint8_t *)buf;
+ sum += result;
+ }
+
+ return sum;
+}
+
+WEAVE_ERROR WeaveTunnelAgent::ComputeUDPChecksumForIPv6Pkt(PacketBuffer *inMsg, const IPAddress &srcAddr, const IPAddress &destAddr)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ uint8_t *p = NULL;
+ uint16_t *q = NULL;
+ PseudoHeader payloadWithPseudoHdr;
+ uint16_t udpPktLen = 0;
+ uint32_t sum = 0;
+ uint16_t *currCSumPtr = 0;
+ uint16_t cSumDataLen = 0;
+
+ // The beginning of the IPv6 packet
+ p = inMsg->Start() + TUN_HDR_SIZE_IN_BYTES;
+
+ // The paylload of the IPv6 packet
+ q = (uint16_t *)(p + sizeof(struct ip6_hdr));
+
+#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
+ struct udphdr *udpHdr = (struct udphdr *)(q);
+
+ // Initialize checksum to 0
+ udpHdr->check = 0;
+#else // !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
+ struct udp_hdr *udpHdr = (struct udp_hdr *)(q);
+
+ // Initialize checksum to 0
+ udpHdr->chksum = 0;
+#endif // !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
+
+ struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p;
+
+ // Get the UDP length or the IPv6 payload length
+ udpPktLen = inMsg->DataLength() - TUN_HDR_SIZE_IN_BYTES - sizeof(struct ip6_hdr);
+
+ //Fill up IPv6 fields belonging to the pseudo header necessary to calculate the checksum.
+ payloadWithPseudoHdr.PayloadLength = nl::Weave::Encoding::BigEndian::HostSwap16(udpPktLen);
+ payloadWithPseudoHdr.Protocol = nl::Weave::Encoding::BigEndian::HostSwap16(NL_PROTO_TYPE_UDP);
+ memcpy(payloadWithPseudoHdr.SrcAddr, &srcAddr, sizeof(payloadWithPseudoHdr.SrcAddr));
+ memcpy(payloadWithPseudoHdr.DstAddr, &destAddr, sizeof(payloadWithPseudoHdr.DstAddr));
+
+ // Calculate checksum for the pseudo header
+ sum = Checksum((uint16_t*)&payloadWithPseudoHdr, sizeof(PseudoHeader));
+ // Calculate the UDP Datagram checksum and add to the sum.
+ sum += Checksum(q, udpPktLen);
+
+ // Adjust for carryover
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+ sum = ~sum;
+
+#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
+ // Set the new computed checksum result
+ udpHdr->check = ((uint16_t)sum == 0x0000) ? 0xFFFF : (uint16_t)sum;
+ WeaveLogDetail(WeaveTunnel, "New checksum = %x", udpHdr->check);
+#else // !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
+ // Set the new computed checksum result
+ udpHdr->chksum = ((uint16_t)sum == 0x0000) ? 0xFFFF : (uint16_t)sum;
+ WeaveLogDetail(WeaveTunnel, "New checksum = %x", udpHdr->chksum);
+#endif // !WEAVE_SYSTEM_CONFIG_USE_SOCKETS
+
+ return err;
+}
+
+WEAVE_ERROR WeaveTunnelAgent::ReplaceDestSubnetInAddress(PacketBuffer *inMsg, const uint16_t subnetId)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ uint8_t *p = NULL;
+ struct ip6_hdr *ip6hdr = NULL;
+ IPAddress inDest, srcAddr, replacedDestAddr;
+#if WEAVE_SYSTEM_CONFIG_USE_LWIP
+ ip6_addr_t ipv6Addr;
+#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
+
+#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
+ struct in6_addr ipv6Addr;
+#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
+
+ // Extract the IPv6 header to look at the destination address
+
+ p = inMsg->Start() + TUN_HDR_SIZE_IN_BYTES;
+
+ ip6hdr = (struct ip6_hdr *)p;
+
+ // Fetch destination address from header
+#if WEAVE_SYSTEM_CONFIG_USE_LWIP
+ ip6_addr_copy(ipv6Addr, ip6hdr->dest);
+ inDest = IPAddress::FromIPv6(ipv6Addr);
+
+ ip6_addr_copy(ipv6Addr, ip6hdr->src);
+ srcAddr = IPAddress::FromIPv6(ipv6Addr);
+#else // !WEAVE_SYSTEM_CONFIG_USE_LWIP
+ inDest = IPAddress::FromIPv6(ip6hdr->ip6_dst);
+ srcAddr = IPAddress::FromIPv6(ip6hdr->ip6_src);
+#endif // !WEAVE_SYSTEM_CONFIG_USE_LWIP
+
+ replacedDestAddr = IPAddress::MakeULA(inDest.GlobalId(), subnetId, inDest.InterfaceId());
+
+ // Set correct destination address
+
+#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
+ ip6hdr->ip6_dst = replacedDestAddr.ToIPv6();
+#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
+
+#if WEAVE_SYSTEM_CONFIG_USE_LWIP
+ ipv6Addr = replacedDestAddr.ToIPv6();
+ ip6_addr_copy(ip6hdr->dest, ipv6Addr);
+#endif // !WEAVE_SYSTEM_CONFIG_USE_LWIP
+
+ // Recompute UDP checksum to account for the destination address change
+ err = ComputeUDPChecksumForIPv6Pkt(inMsg, srcAddr, replacedDestAddr);
+
+ return err;
+}
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
/**
* Handler to receive IPv6 packets from the Tunnel EndPoint interface and forward, either to the Service
* via the Service TCP connection after encapsulating IPv6 packet inside the tunnel header or to the Mobile
@@ -958,6 +1107,7 @@
SuccessOrExit(err);
nodeId = destIP6Addr.InterfaceId();
+
if (destIP6Addr.Subnet() == kWeaveSubnetId_Service)
{
// Destined for Service
@@ -993,6 +1143,18 @@
SuccessOrExit(err);
}
}
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ else if (destIP6Addr.Subnet() == kWeaveSubnetId_TunneledCapture)
+ {
+ WeaveLogDetail(WeaveTunnel, "Tunneled message received with Capture subnet. Replacing with Service Subnet\n");
+ err = tAgent->ReplaceDestSubnetInAddress(msg, kWeaveSubnetId_Service);
+ SuccessOrExit(err);
+
+ err = tAgent->HandleSendingToService(msg, true);
+ msg = NULL;
+ SuccessOrExit(err);
+ }
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
exit:
if (msg != NULL)
@@ -1164,8 +1326,6 @@
void WeaveTunnelAgent::PopulateTunnelMsgHeader(WeaveMessageInfo *msgInfo,
const WeaveTunnelConnectionMgr *connMgr)
{
- msgInfo->Clear();
-
// Set to no-encryption when not using a tunnel to the Service
if (!connMgr)
@@ -1262,10 +1422,13 @@
/**
* Prepare message and send to Service via Remote tunnel.
*/
-WEAVE_ERROR WeaveTunnelAgent::HandleSendingToService(PacketBuffer *msg)
+WEAVE_ERROR WeaveTunnelAgent::HandleSendingToService(PacketBuffer *msg, const bool shouldCapture)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
bool dropPacket = false;
+ WeaveMessageInfo msgInfo;
+
+ msgInfo.Clear();
if (mPrimaryTunConnMgr.mConnectionState != WeaveTunnelConnectionMgr::kState_TunnelOpen
#if WEAVE_CONFIG_TUNNEL_FAILOVER_SUPPORTED
@@ -1286,12 +1449,18 @@
ExitNow();
}
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ if (shouldCapture)
+ {
+ WeaveLogDetail(WeaveTunnel, "Tagging Tunneled message for capture\n");
+ msgInfo.Flags |= kWeaveMessageFlag_CaptureTxMessage;
+ }
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
// Send on primary tunnel if open; else send over backup tunnel
if (mPrimaryTunConnMgr.mConnectionState == WeaveTunnelConnectionMgr::kState_TunnelOpen)
{
- WeaveMessageInfo msgInfo;
-
PopulateTunnelMsgHeader(&msgInfo, &mPrimaryTunConnMgr);
err = SendMessageUponPktTransitAnalysis(&mPrimaryTunConnMgr, kDir_Outbound, kType_TunnelPrimary,
@@ -1300,8 +1469,6 @@
#if WEAVE_CONFIG_TUNNEL_FAILOVER_SUPPORTED
else if (mBackupTunConnMgr.mConnectionState == WeaveTunnelConnectionMgr::kState_TunnelOpen)
{
- WeaveMessageInfo msgInfo;
-
PopulateTunnelMsgHeader(&msgInfo, &mBackupTunConnMgr);
err = SendMessageUponPktTransitAnalysis(&mBackupTunConnMgr, kDir_Outbound, kType_TunnelBackup,
diff --git a/src/lib/profiles/weave-tunneling/WeaveTunnelAgent.h b/src/lib/profiles/weave-tunneling/WeaveTunnelAgent.h
index bd3455c..01d1fa9 100644
--- a/src/lib/profiles/weave-tunneling/WeaveTunnelAgent.h
+++ b/src/lib/profiles/weave-tunneling/WeaveTunnelAgent.h
@@ -654,7 +654,7 @@
// Message encapsulating/decapsulating functions for sending between Tunnel and other interfaces
WEAVE_ERROR AddTunnelHdrToMsg(PacketBuffer *msg);
- WEAVE_ERROR HandleSendingToService(PacketBuffer *msg);
+ WEAVE_ERROR HandleSendingToService(PacketBuffer *msg, const bool shouldCapture = false);
WEAVE_ERROR HandleTunneledReceive(PacketBuffer *msg, TunnelType tunType);
/// Decide based on lookup of nexthop table and send locally
@@ -718,6 +718,13 @@
void WeaveTunnelNotifyTCPSendIdleStateChange(const TunnelType tunType, const bool isIdle);
#endif // WEAVE_CONFIG_TUNNEL_ENABLE_TCP_IDLE_CALLBACK
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ WEAVE_ERROR ReplaceDestSubnetInAddress(PacketBuffer *inMsg, const uint16_t subnetId);
+
+ WEAVE_ERROR ComputeUDPChecksumForIPv6Pkt(PacketBuffer *inMsg, const IPAddress &srcAddr, const IPAddress &destAddr);
+ uint32_t Checksum(uint16_t *buf, uint16_t len);
+
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
};
diff --git a/src/lib/support/StatusReportStr.cpp b/src/lib/support/StatusReportStr.cpp
index c52251a..fcb0f18 100644
--- a/src/lib/support/StatusReportStr.cpp
+++ b/src/lib/support/StatusReportStr.cpp
@@ -101,238 +101,254 @@
NL_DLL_EXPORT const char *StatusReportStr(uint32_t profileId, uint16_t statusCode)
{
- const char *fmt = NULL;
+ const char *fmt = "[ %s(%08" PRIX32 "):%" PRIu16 " ] %s";
+ const char *profileName = NULL;
+ const char *errorMsg = "";
switch (profileId)
{
case kWeaveProfile_BDX:
+ profileName = "BDX";
switch (statusCode)
{
#if WEAVE_CONFIG_BDX_NAMESPACE == kWeaveManagedNamespace_Development
- case BulkDataTransfer::kStatus_Overflow : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Overflow"; break;
- case BulkDataTransfer::kStatus_LengthTooShort : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Length too short"; break;
- case BulkDataTransfer::kStatus_XferFailedUnknownErr : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Transfer failed for unknown reason"; break;
- case BulkDataTransfer::kStatus_XferMethodNotSupported : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Transfer method not supported"; break;
- case BulkDataTransfer::kStatus_UnknownFile : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Unknown file"; break;
- case BulkDataTransfer::kStatus_StartOffsetNotSupported : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Start offset not support"; break;
- case BulkDataTransfer::kStatus_Unknown : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Unknown error"; break;
+ case BulkDataTransfer::kStatus_Overflow : errorMsg = "Overflow"; break;
+ case BulkDataTransfer::kStatus_LengthTooShort : errorMsg = "Length too short"; break;
+ case BulkDataTransfer::kStatus_XferFailedUnknownErr : errorMsg = "Transfer failed for unknown reason"; break;
+ case BulkDataTransfer::kStatus_XferMethodNotSupported : errorMsg = "Transfer method not supported"; break;
+ case BulkDataTransfer::kStatus_UnknownFile : errorMsg = "Unknown file"; break;
+ case BulkDataTransfer::kStatus_StartOffsetNotSupported : errorMsg = "Start offset not support"; break;
+ case BulkDataTransfer::kStatus_Unknown : errorMsg = "Unknown error"; break;
#else
- case BulkDataTransfer::kStatus_Overflow : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Overflow"; break;
- case BulkDataTransfer::kStatus_LengthTooLarge : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Length too long"; break;
- case BulkDataTransfer::kStatus_LengthTooShort : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Length too short"; break;
- case BulkDataTransfer::kStatus_LengthMismatch : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Length mismatch"; break;
- case BulkDataTransfer::kStatus_LengthRequired : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Length required"; break;
- case BulkDataTransfer::kStatus_BadMessageContents : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Bad message contents"; break;
- case BulkDataTransfer::kStatus_BadBlockCounter : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Bad block counter"; break;
- case BulkDataTransfer::kStatus_XferFailedUnknownErr : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Transfer failed for unknown reason"; break;
- case BulkDataTransfer::kStatus_ServerBadState : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Server is in incorrect state"; break;
- case BulkDataTransfer::kStatus_FailureToSend : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Failure to send"; break;
- case BulkDataTransfer::kStatus_XferMethodNotSupported : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Transfer method not supported"; break;
- case BulkDataTransfer::kStatus_UnknownFile : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Unknown file"; break;
- case BulkDataTransfer::kStatus_StartOffsetNotSupported : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Start offset not support"; break;
- case BulkDataTransfer::kStatus_VersionNotSupported : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Protocol version not supported"; break;
- case BulkDataTransfer::kStatus_Unknown : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ] Unknown error"; break;
+ case BulkDataTransfer::kStatus_Overflow : errorMsg = "Overflow"; break;
+ case BulkDataTransfer::kStatus_LengthTooLarge : errorMsg = "Length too long"; break;
+ case BulkDataTransfer::kStatus_LengthTooShort : errorMsg = "Length too short"; break;
+ case BulkDataTransfer::kStatus_LengthMismatch : errorMsg = "Length mismatch"; break;
+ case BulkDataTransfer::kStatus_LengthRequired : errorMsg = "Length required"; break;
+ case BulkDataTransfer::kStatus_BadMessageContents : errorMsg = "Bad message contents"; break;
+ case BulkDataTransfer::kStatus_BadBlockCounter : errorMsg = "Bad block counter"; break;
+ case BulkDataTransfer::kStatus_XferFailedUnknownErr : errorMsg = "Transfer failed for unknown reason"; break;
+ case BulkDataTransfer::kStatus_ServerBadState : errorMsg = "Server is in incorrect state"; break;
+ case BulkDataTransfer::kStatus_FailureToSend : errorMsg = "Failure to send"; break;
+ case BulkDataTransfer::kStatus_XferMethodNotSupported : errorMsg = "Transfer method not supported"; break;
+ case BulkDataTransfer::kStatus_UnknownFile : errorMsg = "Unknown file"; break;
+ case BulkDataTransfer::kStatus_StartOffsetNotSupported : errorMsg = "Start offset not support"; break;
+ case BulkDataTransfer::kStatus_VersionNotSupported : errorMsg = "Protocol version not supported"; break;
+ case BulkDataTransfer::kStatus_Unknown : errorMsg = "Unknown error"; break;
#endif // WEAVE_CONFIG_BDX_NAMESPACE == kWeaveManagedNamespace_Development
- default : fmt = "[ BDX(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ default : errorMsg = ""; break;
}
break;
case kWeaveProfile_Common:
+ profileName = "Common";
switch (statusCode)
{
- case nl::Weave::Profiles::Common::kStatus_Success : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Success"; break;
- case nl::Weave::Profiles::Common::kStatus_Canceled : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Canceled"; break;
- case nl::Weave::Profiles::Common::kStatus_BadRequest : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Bad/malformed request"; break;
- case nl::Weave::Profiles::Common::kStatus_UnsupportedMessage : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Unrecognized/unsupported message"; break;
- case nl::Weave::Profiles::Common::kStatus_UnexpectedMessage : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Unexpected message"; break;
- case nl::Weave::Profiles::Common::kStatus_AuthenticationRequired : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Authentication required"; break;
- case nl::Weave::Profiles::Common::kStatus_AccessDenied : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Access denied"; break;
- case nl::Weave::Profiles::Common::kStatus_OutOfMemory : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Out of memory"; break;
- case nl::Weave::Profiles::Common::kStatus_NotAvailable : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Not available"; break;
- case nl::Weave::Profiles::Common::kStatus_LocalSetupRequired : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Local setup required"; break;
- case nl::Weave::Profiles::Common::kStatus_Relocated : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Relocated"; break;
- case nl::Weave::Profiles::Common::kStatus_Busy : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Sender busy"; break;
- case nl::Weave::Profiles::Common::kStatus_Timeout : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Timeout"; break;
- case nl::Weave::Profiles::Common::kStatus_InternalError : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Internal error"; break;
- case nl::Weave::Profiles::Common::kStatus_Continue : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ] Continue"; break;
- default : fmt = "[ Common(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ case nl::Weave::Profiles::Common::kStatus_Success : errorMsg = "Success"; break;
+ case nl::Weave::Profiles::Common::kStatus_Canceled : errorMsg = "Canceled"; break;
+ case nl::Weave::Profiles::Common::kStatus_BadRequest : errorMsg = "Bad/malformed request"; break;
+ case nl::Weave::Profiles::Common::kStatus_UnsupportedMessage : errorMsg = "Unrecognized/unsupported message"; break;
+ case nl::Weave::Profiles::Common::kStatus_UnexpectedMessage : errorMsg = "Unexpected message"; break;
+ case nl::Weave::Profiles::Common::kStatus_AuthenticationRequired : errorMsg = "Authentication required"; break;
+ case nl::Weave::Profiles::Common::kStatus_AccessDenied : errorMsg = "Access denied"; break;
+ case nl::Weave::Profiles::Common::kStatus_OutOfMemory : errorMsg = "Out of memory"; break;
+ case nl::Weave::Profiles::Common::kStatus_NotAvailable : errorMsg = "Not available"; break;
+ case nl::Weave::Profiles::Common::kStatus_LocalSetupRequired : errorMsg = "Local setup required"; break;
+ case nl::Weave::Profiles::Common::kStatus_Relocated : errorMsg = "Relocated"; break;
+ case nl::Weave::Profiles::Common::kStatus_Busy : errorMsg = "Sender busy"; break;
+ case nl::Weave::Profiles::Common::kStatus_Timeout : errorMsg = "Timeout"; break;
+ case nl::Weave::Profiles::Common::kStatus_InternalError : errorMsg = "Internal error"; break;
+ case nl::Weave::Profiles::Common::kStatus_Continue : errorMsg = "Continue"; break;
+ default : errorMsg = ""; break;
}
break;
case kWeaveProfile_WDM:
+ profileName = "WDM";
switch (statusCode)
{
- case DataManagement_Legacy::kStatus_CancelSuccess : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Subscription canceled"; break;
- case DataManagement_Legacy::kStatus_InvalidPath : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Invalid path"; break;
- case DataManagement_Legacy::kStatus_UnknownTopic : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Unknown topic"; break;
- case DataManagement_Legacy::kStatus_IllegalReadRequest : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Illegal read request"; break;
- case DataManagement_Legacy::kStatus_IllegalWriteRequest : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Illegal write request"; break;
- case DataManagement_Legacy::kStatus_InvalidVersion : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Invalid version"; break;
- case DataManagement_Legacy::kStatus_UnsupportedSubscriptionMode : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Unsupported subscription mode"; break;
+ case DataManagement_Legacy::kStatus_CancelSuccess : errorMsg = "Subscription canceled"; break;
+ case DataManagement_Legacy::kStatus_InvalidPath : errorMsg = "Invalid path"; break;
+ case DataManagement_Legacy::kStatus_UnknownTopic : errorMsg = "Unknown topic"; break;
+ case DataManagement_Legacy::kStatus_IllegalReadRequest : errorMsg = "Illegal read request"; break;
+ case DataManagement_Legacy::kStatus_IllegalWriteRequest : errorMsg = "Illegal write request"; break;
+ case DataManagement_Legacy::kStatus_InvalidVersion : errorMsg = "Invalid version"; break;
+ case DataManagement_Legacy::kStatus_UnsupportedSubscriptionMode : errorMsg = "Unsupported subscription mode"; break;
- case DataManagement_Current::kStatus_InvalidValueInNotification : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Invalid value in notification"; break;
- case DataManagement_Current::kStatus_InvalidPath : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Invalid path"; break;
- case DataManagement_Current::kStatus_ExpiryTimeNotSupported : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Expiry time not supported"; break;
- case DataManagement_Current::kStatus_NotTimeSyncedYet : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Not time-synced yet"; break;
- case DataManagement_Current::kStatus_RequestExpiredInTime : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Request expired in time"; break;
- case DataManagement_Current::kStatus_VersionMismatch : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Version mismatch"; break;
- case DataManagement_Current::kStatus_GeneralProtocolError : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] General protocol error"; break;
- case DataManagement_Current::kStatus_SecurityError : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Security error"; break;
- case DataManagement_Current::kStatus_InvalidSubscriptionID : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Invalid subscription ID"; break;
- case DataManagement_Current::kStatus_GeneralSchemaViolation : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] General schema violation"; break;
- case DataManagement_Current::kStatus_UnpairedDeviceRejected : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Unpaired device rejected"; break;
- case DataManagement_Current::kStatus_IncompatibleDataSchemaVersion : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Incompatible data schema violation"; break;
- case DataManagement_Current::kStatus_MultipleFailures : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Multiple failures"; break;
- case DataManagement_Current::kStatus_UpdateOutOfSequence : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ] Update out of sequence"; break;
- default : fmt = "[ WDM(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ case DataManagement_Current::kStatus_InvalidValueInNotification : errorMsg = "Invalid value in notification"; break;
+ case DataManagement_Current::kStatus_InvalidPath : errorMsg = "Invalid path"; break;
+ case DataManagement_Current::kStatus_ExpiryTimeNotSupported : errorMsg = "Expiry time not supported"; break;
+ case DataManagement_Current::kStatus_NotTimeSyncedYet : errorMsg = "Not time-synced yet"; break;
+ case DataManagement_Current::kStatus_RequestExpiredInTime : errorMsg = "Request expired in time"; break;
+ case DataManagement_Current::kStatus_VersionMismatch : errorMsg = "Version mismatch"; break;
+ case DataManagement_Current::kStatus_GeneralProtocolError : errorMsg = "General protocol error"; break;
+ case DataManagement_Current::kStatus_SecurityError : errorMsg = "Security error"; break;
+ case DataManagement_Current::kStatus_InvalidSubscriptionID : errorMsg = "Invalid subscription ID"; break;
+ case DataManagement_Current::kStatus_GeneralSchemaViolation : errorMsg = "General schema violation"; break;
+ case DataManagement_Current::kStatus_UnpairedDeviceRejected : errorMsg = "Unpaired device rejected"; break;
+ case DataManagement_Current::kStatus_IncompatibleDataSchemaVersion : errorMsg = "Incompatible data schema violation"; break;
+ case DataManagement_Current::kStatus_MultipleFailures : errorMsg = "Multiple failures"; break;
+ case DataManagement_Current::kStatus_UpdateOutOfSequence : errorMsg = "Update out of sequence"; break;
+ default : errorMsg = ""; break;
}
break;
case kWeaveProfile_DeviceControl:
+ profileName = "DeviceControl";
switch (statusCode)
{
- case DeviceControl::kStatusCode_FailSafeAlreadyActive : fmt = "[ DeviceControl(%08" PRIX32 "):%" PRIu16 " ] Fail-safe already active"; break;
- case DeviceControl::kStatusCode_NoFailSafeActive : fmt = "[ DeviceControl(%08" PRIX32 "):%" PRIu16 " ] No fail-safe active"; break;
- case DeviceControl::kStatusCode_NoMatchingFailSafeActive : fmt = "[ DeviceControl(%08" PRIX32 "):%" PRIu16 " ] No matching fail-safe active"; break;
- case DeviceControl::kStatusCode_UnsupportedFailSafeMode : fmt = "[ DeviceControl(%08" PRIX32 "):%" PRIu16 " ] Unsupported fail-safe mode"; break;
- case DeviceControl::kStatusCode_RemotePassiveRendezvousTimedOut : fmt = "[ DeviceControl(%08" PRIX32 "):%" PRIu16 " ] Remote Passive Rendezvous timed out"; break;
- case DeviceControl::kStatusCode_UnsecuredListenPreempted : fmt = "[ DeviceControl(%08" PRIX32 "):%" PRIu16 " ] Unsecured Listen pre-empted"; break;
- case DeviceControl::kStatusCode_ResetSuccessCloseCon : fmt = "[ DeviceControl(%08" PRIX32 "):%" PRIu16 " ] ResetConfig will succeed after connection close"; break;
- case DeviceControl::kStatusCode_ResetNotAllowed : fmt = "[ DeviceControl(%08" PRIX32 "):%" PRIu16 " ] Reset not allowed"; break;
- case DeviceControl::kStatusCode_NoSystemTestDelegate : fmt = "[ DeviceControl(%08" PRIX32 "):%" PRIu16 " ] System test cannot run without a delegate"; break;
- default : fmt = "[ DeviceControl(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ case DeviceControl::kStatusCode_FailSafeAlreadyActive : errorMsg = "Fail-safe already active"; break;
+ case DeviceControl::kStatusCode_NoFailSafeActive : errorMsg = "No fail-safe active"; break;
+ case DeviceControl::kStatusCode_NoMatchingFailSafeActive : errorMsg = "No matching fail-safe active"; break;
+ case DeviceControl::kStatusCode_UnsupportedFailSafeMode : errorMsg = "Unsupported fail-safe mode"; break;
+ case DeviceControl::kStatusCode_RemotePassiveRendezvousTimedOut : errorMsg = "Remote Passive Rendezvous timed out"; break;
+ case DeviceControl::kStatusCode_UnsecuredListenPreempted : errorMsg = "Unsecured Listen pre-empted"; break;
+ case DeviceControl::kStatusCode_ResetSuccessCloseCon : errorMsg = "ResetConfig will succeed after connection close"; break;
+ case DeviceControl::kStatusCode_ResetNotAllowed : errorMsg = "Reset not allowed"; break;
+ case DeviceControl::kStatusCode_NoSystemTestDelegate : errorMsg = "System test cannot run without a delegate"; break;
+ default : errorMsg = ""; break;
}
break;
case kWeaveProfile_DeviceDescription:
+ profileName = "DeviceDescription";
switch (statusCode)
{
- default : fmt = "[ DeviceDescription(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ default : errorMsg = ""; break;
}
break;
case kWeaveProfile_Echo:
+ profileName = "Echo";
switch (statusCode)
{
- default : fmt = "[ Echo(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ default : errorMsg = ""; break;
}
break;
case kWeaveProfile_FabricProvisioning:
+ profileName = "FabricProvisioning";
switch (statusCode)
{
- case FabricProvisioning::kStatusCode_AlreadyMemberOfFabric : fmt = "[ FabricProvisioning(%08" PRIX32 "):%" PRIu16 " ] Already member of fabric"; break;
- case FabricProvisioning::kStatusCode_NotMemberOfFabric : fmt = "[ FabricProvisioning(%08" PRIX32 "):%" PRIu16 " ] Not member of fabric"; break;
- case FabricProvisioning::kStatusCode_InvalidFabricConfig : fmt = "[ FabricProvisioning(%08" PRIX32 "):%" PRIu16 " ] Invalid fabric config"; break;
- default : fmt = "[ FabricProvisioning(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ case FabricProvisioning::kStatusCode_AlreadyMemberOfFabric : errorMsg = "Already member of fabric"; break;
+ case FabricProvisioning::kStatusCode_NotMemberOfFabric : errorMsg = "Not member of fabric"; break;
+ case FabricProvisioning::kStatusCode_InvalidFabricConfig : errorMsg = "Invalid fabric config"; break;
+ default : errorMsg = ""; break;
}
break;
case kWeaveProfile_NetworkProvisioning:
+ profileName = "NetworkProvisioning";
switch (statusCode)
{
- case NetworkProvisioning::kStatusCode_UnknownNetwork : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] Unknown network"; break;
- case NetworkProvisioning::kStatusCode_TooManyNetworks : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] Too many networks"; break;
- case NetworkProvisioning::kStatusCode_InvalidNetworkConfiguration : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] Invalid network configuration"; break;
- case NetworkProvisioning::kStatusCode_UnsupportedNetworkType : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] Unsupported network configuration"; break;
- case NetworkProvisioning::kStatusCode_UnsupportedWiFiMode : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] Unsupported WiFi mode"; break;
- case NetworkProvisioning::kStatusCode_UnsupportedWiFiRole : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] Unsupported WiFi role"; break;
- case NetworkProvisioning::kStatusCode_UnsupportedWiFiSecurityType : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] Unsupported WiFi security type"; break;
- case NetworkProvisioning::kStatusCode_InvalidState : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] Invalid state"; break;
- case NetworkProvisioning::kStatusCode_TestNetworkFailed : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] Test network failed"; break;
- case NetworkProvisioning::kStatusCode_NetworkConnectFailed : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] Network connect failed"; break;
- case NetworkProvisioning::kStatusCode_NoRouterAvailable : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] No router available"; break;
- case NetworkProvisioning::kStatusCode_UnsupportedRegulatoryDomain : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] Unsupported wireless regulatory domain"; break;
- case NetworkProvisioning::kStatusCode_UnsupportedOperatingLocation : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ] Unsupported wireless operating location"; break;
- default : fmt = "[ NetworkProvisioning(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ case NetworkProvisioning::kStatusCode_UnknownNetwork : errorMsg = "Unknown network"; break;
+ case NetworkProvisioning::kStatusCode_TooManyNetworks : errorMsg = "Too many networks"; break;
+ case NetworkProvisioning::kStatusCode_InvalidNetworkConfiguration : errorMsg = "Invalid network configuration"; break;
+ case NetworkProvisioning::kStatusCode_UnsupportedNetworkType : errorMsg = "Unsupported network configuration"; break;
+ case NetworkProvisioning::kStatusCode_UnsupportedWiFiMode : errorMsg = "Unsupported WiFi mode"; break;
+ case NetworkProvisioning::kStatusCode_UnsupportedWiFiRole : errorMsg = "Unsupported WiFi role"; break;
+ case NetworkProvisioning::kStatusCode_UnsupportedWiFiSecurityType : errorMsg = "Unsupported WiFi security type"; break;
+ case NetworkProvisioning::kStatusCode_InvalidState : errorMsg = "Invalid state"; break;
+ case NetworkProvisioning::kStatusCode_TestNetworkFailed : errorMsg = "Test network failed"; break;
+ case NetworkProvisioning::kStatusCode_NetworkConnectFailed : errorMsg = "Network connect failed"; break;
+ case NetworkProvisioning::kStatusCode_NoRouterAvailable : errorMsg = "No router available"; break;
+ case NetworkProvisioning::kStatusCode_UnsupportedRegulatoryDomain : errorMsg = "Unsupported wireless regulatory domain"; break;
+ case NetworkProvisioning::kStatusCode_UnsupportedOperatingLocation : errorMsg = "Unsupported wireless operating location"; break;
+ default : errorMsg = ""; break;
}
break;
case kWeaveProfile_Security:
+ profileName = "Security";
switch (statusCode)
{
- case Security::kStatusCode_SessionAborted : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Session aborted"; break;
- case Security::kStatusCode_PASESupportsOnlyConfig1 : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] PASE Engine only supports Config1"; break;
- case Security::kStatusCode_UnsupportedEncryptionType : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Unsupported encryption type"; break;
- case Security::kStatusCode_InvalidKeyId : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Invalid key id"; break;
- case Security::kStatusCode_DuplicateKeyId : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Duplicate key id"; break;
- case Security::kStatusCode_KeyConfirmationFailed : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Key confirmation failed"; break;
- case Security::kStatusCode_InternalError : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Internal error"; break;
- case Security::kStatusCode_AuthenticationFailed : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Authentication failed"; break;
- case Security::kStatusCode_UnsupportedCASEConfiguration : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Unsupported CASE configuration"; break;
- case Security::kStatusCode_UnsupportedCertificate : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Unsupported certificate"; break;
- case Security::kStatusCode_NoCommonPASEConfigurations : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] No supported PASE configurations in common"; break;
- case Security::kStatusCode_KeyNotFound : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Key not found"; break;
- case Security::kStatusCode_WrongEncryptionType : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Wrong encryption type"; break;
- case Security::kStatusCode_UnknownKeyType : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Unknown key type"; break;
- case Security::kStatusCode_InvalidUseOfSessionKey : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Invalid use of session key"; break;
- case Security::kStatusCode_InternalKeyError : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Internal key error"; break;
- case Security::kStatusCode_NoCommonKeyExportConfiguration : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] No common key export configuration"; break;
- case Security::kStatusCode_UnauthorizedKeyExportRequest : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Unauthorized key export request"; break;
- case Security::kStatusCode_NoNewOperationalCertRequired : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] No new operational certificate required"; break;
- case Security::kStatusCode_OperationalNodeIdInUse : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Operational node Id collision"; break;
- case Security::kStatusCode_InvalidOperationalNodeId : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Invalid operational node Id"; break;
- case Security::kStatusCode_InvalidOperationalCertificate : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ] Invalid operational certificate"; break;
- default : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ case Security::kStatusCode_SessionAborted : errorMsg = "Session aborted"; break;
+ case Security::kStatusCode_PASESupportsOnlyConfig1 : errorMsg = "PASE Engine only supports Config1"; break;
+ case Security::kStatusCode_UnsupportedEncryptionType : errorMsg = "Unsupported encryption type"; break;
+ case Security::kStatusCode_InvalidKeyId : errorMsg = "Invalid key id"; break;
+ case Security::kStatusCode_DuplicateKeyId : errorMsg = "Duplicate key id"; break;
+ case Security::kStatusCode_KeyConfirmationFailed : errorMsg = "Key confirmation failed"; break;
+ case Security::kStatusCode_InternalError : errorMsg = "Internal error"; break;
+ case Security::kStatusCode_AuthenticationFailed : errorMsg = "Authentication failed"; break;
+ case Security::kStatusCode_UnsupportedCASEConfiguration : errorMsg = "Unsupported CASE configuration"; break;
+ case Security::kStatusCode_UnsupportedCertificate : errorMsg = "Unsupported certificate"; break;
+ case Security::kStatusCode_NoCommonPASEConfigurations : errorMsg = "No supported PASE configurations in common"; break;
+ case Security::kStatusCode_KeyNotFound : errorMsg = "Key not found"; break;
+ case Security::kStatusCode_WrongEncryptionType : errorMsg = "Wrong encryption type"; break;
+ case Security::kStatusCode_UnknownKeyType : errorMsg = "Unknown key type"; break;
+ case Security::kStatusCode_InvalidUseOfSessionKey : errorMsg = "Invalid use of session key"; break;
+ case Security::kStatusCode_InternalKeyError : errorMsg = "Internal key error"; break;
+ case Security::kStatusCode_NoCommonKeyExportConfiguration : errorMsg = "No common key export configuration"; break;
+ case Security::kStatusCode_UnauthorizedKeyExportRequest : errorMsg = "Unauthorized key export request"; break;
+ case Security::kStatusCode_NoNewOperationalCertRequired : errorMsg = "No new operational certificate required"; break;
+ case Security::kStatusCode_OperationalNodeIdInUse : errorMsg = "Operational node Id collision"; break;
+ case Security::kStatusCode_InvalidOperationalNodeId : errorMsg = "Invalid operational node Id"; break;
+ case Security::kStatusCode_InvalidOperationalCertificate : errorMsg = "Invalid operational certificate"; break;
+ default : errorMsg = ""; break;
}
break;
#if WEAVE_CONFIG_ENABLE_SERVICE_DIRECTORY
case kWeaveProfile_ServiceDirectory:
+ profileName = "ServiceDirectory";
switch (statusCode)
{
- case ServiceDirectory::kStatus_DirectoryUnavailable : fmt = "[ ServiceDirectory(%08" PRIX32 "):%" PRIu16 " ] Service directory unavailable"; break;
- default : fmt = "[ ServiceDirectory(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ case ServiceDirectory::kStatus_DirectoryUnavailable : errorMsg = "Service directory unavailable"; break;
+ default : errorMsg = ""; break;
}
break;
#endif
case kWeaveProfile_ServiceProvisioning:
+ profileName = "ServiceProvisioning";
switch (statusCode)
{
- case ServiceProvisioning::kStatusCode_TooManyServices : fmt = "[ ServiceProvisioning(%08" PRIX32 "):%" PRIu16 " ] Too many services"; break;
- case ServiceProvisioning::kStatusCode_ServiceAlreadyRegistered : fmt = "[ ServiceProvisioning(%08" PRIX32 "):%" PRIu16 " ] Service already registered"; break;
- case ServiceProvisioning::kStatusCode_InvalidServiceConfig : fmt = "[ ServiceProvisioning(%08" PRIX32 "):%" PRIu16 " ] Invalid service configuration"; break;
- case ServiceProvisioning::kStatusCode_NoSuchService : fmt = "[ ServiceProvisioning(%08" PRIX32 "):%" PRIu16 " ] No such service"; break;
- case ServiceProvisioning::kStatusCode_PairingServerError : fmt = "[ ServiceProvisioning(%08" PRIX32 "):%" PRIu16 " ] Error talking to pairing server"; break;
- case ServiceProvisioning::kStatusCode_InvalidPairingToken : fmt = "[ ServiceProvisioning(%08" PRIX32 "):%" PRIu16 " ] Invalid pairing token"; break;
- case ServiceProvisioning::kStatusCode_PairingTokenOld : fmt = "[ ServiceProvisioning(%08" PRIX32 "):%" PRIu16 " ] Pairing token no longer valid"; break;
- case ServiceProvisioning::kStatusCode_ServiceCommunicationError : fmt = "[ ServiceProvisioning(%08" PRIX32 "):%" PRIu16 " ] Service communication error"; break;
- case ServiceProvisioning::kStatusCode_ServiceConfigTooLarge : fmt = "[ ServiceProvisioning(%08" PRIX32 "):%" PRIu16 " ] Service configuration too large"; break;
- case ServiceProvisioning::kStatusCode_WrongFabric : fmt = "[ ServiceProvisioning(%08" PRIX32 "):%" PRIu16 " ] Wrong fabric"; break;
- case ServiceProvisioning::kStatusCode_TooManyFabrics : fmt = "[ ServiceProvisioning(%08" PRIX32 "):%" PRIu16 " ] Too many fabrics"; break;
- default : fmt = "[ ServiceProvisioning(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ case ServiceProvisioning::kStatusCode_TooManyServices : errorMsg = "Too many services"; break;
+ case ServiceProvisioning::kStatusCode_ServiceAlreadyRegistered : errorMsg = "Service already registered"; break;
+ case ServiceProvisioning::kStatusCode_InvalidServiceConfig : errorMsg = "Invalid service configuration"; break;
+ case ServiceProvisioning::kStatusCode_NoSuchService : errorMsg = "No such service"; break;
+ case ServiceProvisioning::kStatusCode_PairingServerError : errorMsg = "Error talking to pairing server"; break;
+ case ServiceProvisioning::kStatusCode_InvalidPairingToken : errorMsg = "Invalid pairing token"; break;
+ case ServiceProvisioning::kStatusCode_PairingTokenOld : errorMsg = "Pairing token no longer valid"; break;
+ case ServiceProvisioning::kStatusCode_ServiceCommunicationError : errorMsg = "Service communication error"; break;
+ case ServiceProvisioning::kStatusCode_ServiceConfigTooLarge : errorMsg = "Service configuration too large"; break;
+ case ServiceProvisioning::kStatusCode_WrongFabric : errorMsg = "Wrong fabric"; break;
+ case ServiceProvisioning::kStatusCode_TooManyFabrics : errorMsg = "Too many fabrics"; break;
+ default : errorMsg = ""; break;
}
break;
case kWeaveProfile_SWU:
+ profileName = "SWU";
switch (statusCode)
{
- case SoftwareUpdate::kStatus_NoUpdateAvailable : fmt = "[ SWU(%08" PRIX32 "):%" PRIu16 " ] No software update available"; break;
- case SoftwareUpdate::kStatus_UpdateFailed : fmt = "[ SWU(%08" PRIX32 "):%" PRIu16 " ] Software update failed"; break;
- case SoftwareUpdate::kStatus_InvalidInstructions : fmt = "[ SWU(%08" PRIX32 "):%" PRIu16 " ] Invalid software image download instructions"; break;
- case SoftwareUpdate::kStatus_DownloadFailed : fmt = "[ SWU(%08" PRIX32 "):%" PRIu16 " ] Software image download failed"; break;
- case SoftwareUpdate::kStatus_IntegrityCheckFailed : fmt = "[ SWU(%08" PRIX32 "):%" PRIu16 " ] Software image integrity check failed"; break;
- case SoftwareUpdate::kStatus_Abort : fmt = "[ SWU(%08" PRIX32 "):%" PRIu16 " ] Software image query aborted"; break;
- case SoftwareUpdate::kStatus_Retry : fmt = "[ SWU(%08" PRIX32 "):%" PRIu16 " ] Retry software image query"; break;
- default : fmt = "[ SWU(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ case SoftwareUpdate::kStatus_NoUpdateAvailable : errorMsg = "No software update available"; break;
+ case SoftwareUpdate::kStatus_UpdateFailed : errorMsg = "Software update failed"; break;
+ case SoftwareUpdate::kStatus_InvalidInstructions : errorMsg = "Invalid software image download instructions"; break;
+ case SoftwareUpdate::kStatus_DownloadFailed : errorMsg = "Software image download failed"; break;
+ case SoftwareUpdate::kStatus_IntegrityCheckFailed : errorMsg = "Software image integrity check failed"; break;
+ case SoftwareUpdate::kStatus_Abort : errorMsg = "Software image query aborted"; break;
+ case SoftwareUpdate::kStatus_Retry : errorMsg = "Retry software image query"; break;
+ default : errorMsg = ""; break;
}
break;
case kWeaveProfile_Tunneling:
+ profileName = "WeaveTunnel";
switch (statusCode)
{
#if WEAVE_CONFIG_ENABLE_TUNNELING
- case WeaveTunnel::kStatusCode_TunnelOpenFail : fmt = "[ WeaveTunnel(%08" PRIX32 "):%" PRIu16 " ] Tunnel open failed"; break;
- case WeaveTunnel::kStatusCode_TunnelCloseFail : fmt = "[ WeaveTunnel(%08" PRIX32 "):%" PRIu16 " ] Tunnel close failed"; break;
- case WeaveTunnel::kStatusCode_TunnelRouteUpdateFail : fmt = "[ WeaveTunnel(%08" PRIX32 "):%" PRIu16 " ] Tunnel route update failed"; break;
- case WeaveTunnel::kStatusCode_TunnelReconnectFail : fmt = "[ WeaveTunnel(%08" PRIX32 "):%" PRIu16 " ] Tunnel reconnect failed"; break;
+ case WeaveTunnel::kStatusCode_TunnelOpenFail : errorMsg = "Tunnel open failed"; break;
+ case WeaveTunnel::kStatusCode_TunnelCloseFail : errorMsg = "Tunnel close failed"; break;
+ case WeaveTunnel::kStatusCode_TunnelRouteUpdateFail : errorMsg = "Tunnel route update failed"; break;
+ case WeaveTunnel::kStatusCode_TunnelReconnectFail : errorMsg = "Tunnel reconnect failed"; break;
#endif
- default : fmt = "[ WeaveTunnel(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ default : errorMsg = ""; break;
}
break;
case kWeaveProfile_StatusReport_Deprecated:
+ profileName = "Security";
switch (statusCode)
{
- default : fmt = "[ Security(%08" PRIX32 "):%" PRIu16 " ]"; break;
+ default : errorMsg = ""; break;
}
break;
@@ -342,10 +358,18 @@
}
- if (fmt == NULL)
- fmt = "[ %08" PRIX32 ":%" PRIu16 " ]";
+ if (profileName != NULL)
+ {
+ snprintf(sErrorStr, sizeof(sErrorStr) - 2, fmt, profileName, profileId, statusCode, errorMsg);
+ }
+ else
+ {
+ if (fmt == NULL)
+ fmt = "[ %08" PRIX32 ":%" PRIu16 " ]";
- snprintf(sErrorStr, sizeof(sErrorStr) - 2, fmt, profileId, statusCode);
+ snprintf(sErrorStr, sizeof(sErrorStr) - 2, fmt, profileId, statusCode);
+ }
+
sErrorStr[sizeof(sErrorStr) - 1] = 0;
return sErrorStr;
}
diff --git a/src/lib/support/crypto/CTRMode.cpp b/src/lib/support/crypto/CTRMode.cpp
index 120503b..e93b1ef 100644
--- a/src/lib/support/crypto/CTRMode.cpp
+++ b/src/lib/support/crypto/CTRMode.cpp
@@ -38,9 +38,11 @@
namespace Crypto {
template <class BlockCipher>
-CTRMode<BlockCipher>::CTRMode()
+CTRMode<BlockCipher>::CTRMode() : mBlockCipher()
{
- memset(this, 0, sizeof(*this));
+ mMsgIndex = 0;
+ memset(Counter, 0, sizeof(Counter));
+ ClearSecretData(mEncryptedCounter, sizeof(mEncryptedCounter));
}
template <class BlockCipher>
diff --git a/src/lib/support/crypto/DRBG.cpp b/src/lib/support/crypto/DRBG.cpp
index 05b2b15..f0346dc 100644
--- a/src/lib/support/crypto/DRBG.cpp
+++ b/src/lib/support/crypto/DRBG.cpp
@@ -36,9 +36,12 @@
namespace Crypto {
template <class BlockCipher>
-CTR_DRBG<BlockCipher>::CTR_DRBG()
+CTR_DRBG<BlockCipher>::CTR_DRBG() : mBlockCipher()
{
- memset(this, 0, sizeof(*this));
+ mEntropyFunct = NULL;
+ mReseedCounter = 0;
+ mEntropyFunct = 0;
+ memset(mCounter, 0, kBlockLength);
}
template <class BlockCipher>
diff --git a/src/system/SystemLayer.cpp b/src/system/SystemLayer.cpp
index 8b40038..a7b67eb 100644
--- a/src/system/SystemLayer.cpp
+++ b/src/system/SystemLayer.cpp
@@ -555,24 +555,22 @@
/**
* Prepare the sets of file descriptors for @p select() to work with.
*
- * @param[out] aSetSize The range of file descriptors in the file descriptor set.
- * @param[in] aReadSet A pointer to the set of readable file descriptors.
- * @param[in] aWriteSet A pointer to the set of writable file descriptors.
- * @param[in] aExceptionSet A pointer to the set of file descriptors with errors.
- * @param[in] aSleepTime A reference to the maximum sleep time.
+ * @param[in,out] pollFDs The fd set which is going to be polled
+ * @param[in,out] numPollFDs The number of fds in the fd set
+ * @param[in] timeoutMS A reference to the maximum sleep time.
*/
-void Layer::PrepareSelect(int& aSetSize, fd_set* aReadSet, fd_set* aWriteSet, fd_set* aExceptionSet, struct timeval& aSleepTime)
+void Layer::PrepareSelect(struct pollfd * pollFDs, int& numPollFDs, int& timeoutMS)
{
if (this->State() != kLayerState_Initialized)
return;
- if (this->mWakePipeIn + 1 > aSetSize)
- aSetSize = this->mWakePipeIn + 1;
-
- FD_SET(this->mWakePipeIn, aReadSet);
+ struct pollfd & event = pollFDs[numPollFDs++];
+ event.fd = this->mWakePipeIn;
+ event.events = POLLIN;
+ event.revents = 0;
const Timer::Epoch kCurrentEpoch = Timer::GetCurrentEpoch();
- Timer::Epoch lAwakenEpoch = kCurrentEpoch + static_cast<Timer::Epoch>(aSleepTime.tv_sec) * 1000 + aSleepTime.tv_usec / 1000;
+ Timer::Epoch lAwakenEpoch = kCurrentEpoch + timeoutMS;
for (size_t i = 0; i < Timer::sPool.Size(); i++)
{
@@ -592,8 +590,7 @@
}
const Timer::Epoch kSleepTime = lAwakenEpoch - kCurrentEpoch;
- aSleepTime.tv_sec = kSleepTime / 1000;
- aSleepTime.tv_usec = (kSleepTime % 1000) * 1000;
+ timeoutMS = kSleepTime;
}
/**
@@ -607,30 +604,25 @@
* I/O related to the old incarnation of the endpoint, not the current one. Saving the pending I/O state in each endpoint before
* acting on it allows the endpoint code to clear the I/O flags in the event of a close, thus avoiding any confusion.
*
- * @param[in] aSetSize The return value of the select call.
- * @param[in] aReadSet A pointer to the set of read file descriptors.
- * @param[in] aWriteSet A pointer to the set of write file descriptors.
- * @param[in] aExceptionSet A pointer to the set of file descriptors with errors.
- *
+ * @param[in] pollFDs The result of polled FDs
+ * @param[in] numPollFDs The number of fds in the fd set
*/
-void Layer::HandleSelectResult(int aSetSize, fd_set* aReadSet, fd_set* aWriteSet, fd_set* aExceptionSet)
+void Layer::HandleSelectResult(const struct pollfd * pollFDs, int numPollFDs)
{
pthread_t lThreadSelf;
if (this->State() != kLayerState_Initialized)
return;
- if (aSetSize < 0)
- return;
-
#if WEAVE_SYSTEM_CONFIG_POSIX_LOCKING
lThreadSelf = pthread_self();
#endif // WEAVE_SYSTEM_CONFIG_POSIX_LOCKING
- if (aSetSize > 0)
+ for (int i = 0; i < numPollFDs; ++i)
{
+ const struct pollfd & event = pollFDs[i];
// If we woke because of someone writing to the wake pipe, clear the contents of the pipe before returning.
- if (FD_ISSET(this->mWakePipeIn, aReadSet))
+ if (event.fd == this->mWakePipeIn && event.revents != 0)
{
while (true)
{
diff --git a/src/system/SystemLayer.h b/src/system/SystemLayer.h
index 148ed5e..668fec6 100644
--- a/src/system/SystemLayer.h
+++ b/src/system/SystemLayer.h
@@ -31,7 +31,7 @@
// Include dependent headers
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
-#include <sys/select.h>
+#include <poll.h>
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
#if WEAVE_SYSTEM_CONFIG_POSIX_LOCKING
@@ -156,8 +156,8 @@
Error ScheduleWork(TimerCompleteFunct aComplete, void* aAppState);
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
- void PrepareSelect(int& aSetSize, fd_set* aReadSet, fd_set* aWriteSet, fd_set* aExceptionSet, struct timeval& aSleepTime);
- void HandleSelectResult(int aSetSize, fd_set* aReadSet, fd_set* aWriteSet, fd_set* aExceptionSet);
+ void PrepareSelect(struct pollfd * pollFDs, int& numPollFDs, int& timeoutMS);
+ void HandleSelectResult(const struct pollfd * pollFDs, int numPollFDs);
void WakeSelect(void);
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
diff --git a/src/system/SystemPacketBuffer.cpp b/src/system/SystemPacketBuffer.cpp
index c50d49b..afca4ef 100644
--- a/src/system/SystemPacketBuffer.cpp
+++ b/src/system/SystemPacketBuffer.cpp
@@ -251,12 +251,12 @@
*/
PacketBuffer* PacketBuffer::DetachTail()
{
- PacketBuffer& lReturn = *static_cast<PacketBuffer*>(this->next);
+ PacketBuffer* lReturn = static_cast<PacketBuffer*>(this->next);
this->next = NULL;
this->tot_len = this->len;
- return &lReturn;
+ return lReturn;
}
/**
diff --git a/src/test-apps/AndroidTest.cpp b/src/test-apps/AndroidTest.cpp
index f021753..bd714e7 100644
--- a/src/test-apps/AndroidTest.cpp
+++ b/src/test-apps/AndroidTest.cpp
@@ -253,22 +253,21 @@
void ServiceNetwork(struct timeval sleepTime)
{
- fd_set readFDs, writeFDs, exceptFDs;
- int numFDs = 0;
-
- FD_ZERO(&readFDs);
- FD_ZERO(&writeFDs);
- FD_ZERO(&exceptFDs);
+ int sleepTime = aSleepTime.tv_usec / 1000 + aSleepTime.tv_sec * 1000;
+ struct pollfd pollFDs[WEAVE_CONFIG_MAX_POLL_FDS];
+ int numPollFDs = 0;
if (Inet.State == InetLayer::kState_Initialized)
- Inet.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs);
+ Inet.PrepareSelect(pollFDs, numPollFDs, sleepTime);
- int selectRes = select(numFDs, &readFDs, &writeFDs, &exceptFDs, &sleepTime);
- if (selectRes < 0)
- printf("select failed: %ld\n", (long)(errno));
+ int pollRes = poll(pollFDs, numPollFDs, sleepTime);
+ if (pollRes < 0)
+ {
+ printf("poll failed: %s\n", ErrorStr(MapErrorPOSIX(errno)));
+ }
- if (selectRes > 0 && Inet.State == InetLayer::kState_Initialized)
- Inet.HandleIO(&readFDs, &writeFDs, &exceptFDs);
+ if (pollRes > 0 && Inet.State == InetLayer::kState_Initialized)
+ Inet.HandleSelectResult(pollFDs, numPollFDs);
}
uint64_t Now()
diff --git a/src/test-apps/Makefile.am b/src/test-apps/Makefile.am
index 7623112..6bdf850 100644
--- a/src/test-apps/Makefile.am
+++ b/src/test-apps/Makefile.am
@@ -1041,6 +1041,7 @@
happy/tests/standalone/wdmNext/test_weave_wdm_next_update_03.py \
happy/tests/standalone/wdmNext/test_weave_wdm_next_update_04.py \
happy/tests/standalone/wdmNext/test_weave_wdm_next_update_05.py \
+ happy/tests/standalone/wdmNext/test_weave_wdm_next_disable_notify_01.py \
$(NULL)
endif # WEAVE_RUN_HAPPY_WDM
diff --git a/src/test-apps/MockSourceTraits.h b/src/test-apps/MockSourceTraits.h
index 6b401f3..d722fcf 100644
--- a/src/test-apps/MockSourceTraits.h
+++ b/src/test-apps/MockSourceTraits.h
@@ -156,7 +156,7 @@
uint32_t tae[10];
// weave.common.StringRef is implemented as a union
- char *tag_string = "stringreftest";
+ char tag_string[20] = "stringreftest";
uint16_t tag_ref;
bool tag_use_ref;
uint32_t tai_stageditem;
@@ -186,7 +186,7 @@
uint32_t tat;
int32_t tau;
bool tav;
- char *taw = "boxedstring";
+ char taw[20] = "boxedstring";
// boxed float
int16_t tax;
diff --git a/src/test-apps/MockWdmSubscriptionInitiator.cpp b/src/test-apps/MockWdmSubscriptionInitiator.cpp
index 77d311c..8ed495d 100644
--- a/src/test-apps/MockWdmSubscriptionInitiator.cpp
+++ b/src/test-apps/MockWdmSubscriptionInitiator.cpp
@@ -252,6 +252,8 @@
kTestCase_IncompatibleVersionedCommandRequest = 9,
kTestCase_TestUpdatableTraits = 10,
+
+ kTestCase_TestDisableSendingNotifies = 11,
};
enum
@@ -481,6 +483,10 @@
case kTestCase_TestUpdatableTraits:
WeaveLogDetail(DataManagement, "kTestCase_TestUpdatableTraits");
break;
+
+ case kTestCase_TestDisableSendingNotifies:
+ WeaveLogDetail(DataManagement, "kTestCase_TestDisableSendingNotifies");
+ break;
default:
mTestCaseId = kTestCase_TestTrait;
WeaveLogDetail(DataManagement, "kTestCase_TestTrait");
@@ -565,6 +571,7 @@
{
case kTestCase_IntegrationTrait:
case kTestCase_RejectIncomingSubscribeRequest:
+ case kTestCase_TestDisableSendingNotifies:
mTraitPaths[0].mTraitDataHandle = mTraitHandleSet[kLocaleSettingsSinkIndex];
mTraitPaths[0].mPropertyPathHandle = kRootPropertyPathHandle;
@@ -1061,6 +1068,7 @@
{
case kTestCase_IntegrationTrait:
case kTestCase_RejectIncomingSubscribeRequest:
+ case kTestCase_TestDisableSendingNotifies:
initiator->AddNewVersion(initiator->kLocaleSettingsSinkIndex);
initiator->AddNewVersion(initiator->kApplicationKeysTraitSinkIndex);
break;
@@ -1515,6 +1523,11 @@
initiator->mLocaleCapabilitiesDataSource.Mutate();
SubscriptionEngine::GetInstance()->GetNotificationEngine()->Run();
break;
+ case kTestCase_TestDisableSendingNotifies:
+ initiator->mLocaleCapabilitiesDataSource.Mutate();
+ SubscriptionEngine::GetInstance()->GetNotificationEngine()->DisableNotifications();
+ SubscriptionEngine::GetInstance()->GetNotificationEngine()->Run();
+ break;
case kTestCase_TestTrait:
initiator->mTestATraitDataSource0.Mutate();
initiator->mTestATraitDataSource1.Mutate();
diff --git a/src/test-apps/MockWdmSubscriptionResponder.cpp b/src/test-apps/MockWdmSubscriptionResponder.cpp
index df682aa..5b85853 100644
--- a/src/test-apps/MockWdmSubscriptionResponder.cpp
+++ b/src/test-apps/MockWdmSubscriptionResponder.cpp
@@ -79,24 +79,6 @@
static bool gCleanStatus = true;
static nl::Weave::WRMPConfig gWRMPConfig = { kWRMPInitialRetransTimeoutMsec, kWRMPActiveRetransTimeoutMsec, kWRMPAckTimeoutMsec, kWRMPMaxRetrans };
-
-static void TLVPrettyPrinter(const char *aFormat, ...)
-{
- va_list args;
-
- va_start(args, aFormat);
-
- // There is no proper Weave logging routine for us to use here
- vprintf(aFormat, args);
-
- va_end(args);
-}
-
-static WEAVE_ERROR DebugPrettyPrint(nl::Weave::TLV::TLVReader & aReader)
-{
- return nl::Weave::TLV::Debug::Dump(aReader, TLVPrettyPrinter);
-}
-
nl::Weave::Profiles::DataManagement::SubscriptionEngine * nl::Weave::Profiles::DataManagement::SubscriptionEngine::GetInstance()
{
static nl::Weave::Profiles::DataManagement::SubscriptionEngine gWdmSubscriptionEngine;
@@ -1082,9 +1064,7 @@
{
uint64_t nowMicroSecs, deadline;
- CommandSender::SendParams sendParams;
-
- memset(&sendParams, 0, sizeof(sendParams));
+ CommandSender::SendParams sendParams = CommandSender::SendParams();
if (mTestCaseId == kTestCase_ForwardCompatibleVersionedRequest) {
sendParams.VersionRange.mMaxVersion = 4;
diff --git a/src/test-apps/TestSystemObject.cpp b/src/test-apps/TestSystemObject.cpp
index 3f87f57..16e913d 100644
--- a/src/test-apps/TestSystemObject.cpp
+++ b/src/test-apps/TestSystemObject.cpp
@@ -295,7 +295,7 @@
void* TestObject::CheckHighWatermarkThread(void* aContext)
{
TestContext& lContext = *static_cast<TestContext*>(aContext);
- unsigned int i;
+ int i;
nl::Weave::System::Stats::count_t lNumInUse;
nl::Weave::System::Stats::count_t lHighWatermark;
@@ -359,11 +359,11 @@
{
memset(&sPool, 0, sizeof(sPool));
- const unsigned int kNumObjects = kPoolSize;
+ const int kNumObjects = kPoolSize;
TestObject* lObject = NULL;
TestContext& lContext = *static_cast<TestContext*>(aContext);
Layer lLayer;
- unsigned int i;
+ int i;
nl::Weave::System::Stats::count_t lNumInUse;
nl::Weave::System::Stats::count_t lHighWatermark;
diff --git a/src/test-apps/TestSystemTimer.cpp b/src/test-apps/TestSystemTimer.cpp
index 7e51ffb..9221847 100644
--- a/src/test-apps/TestSystemTimer.cpp
+++ b/src/test-apps/TestSystemTimer.cpp
@@ -40,7 +40,7 @@
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
-#include <sys/select.h>
+#include <poll.h>
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
#include <SystemLayer/SystemError.h>
@@ -57,20 +57,17 @@
static void ServiceEvents(Layer& aLayer, ::timeval& aSleepTime)
{
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
- fd_set readFDs, writeFDs, exceptFDs;
- int numFDs = 0;
-
- FD_ZERO(&readFDs);
- FD_ZERO(&writeFDs);
- FD_ZERO(&exceptFDs);
+ int sleepTime = aSleepTime.tv_usec / 1000 + aSleepTime.tv_sec * 1000;
+ struct pollfd pollFDs[WEAVE_CONFIG_MAX_POLL_FDS];
+ int numPollFDs = 0;
if (aLayer.State() == kLayerState_Initialized)
- aLayer.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, aSleepTime);
+ aLayer.PrepareSelect(pollFDs, numPollFDs, sleepTime);
- int selectRes = select(numFDs, &readFDs, &writeFDs, &exceptFDs, &aSleepTime);
- if (selectRes < 0)
+ int pollRes = poll(pollFDs, numPollFDs, sleepTime);
+ if (pollRes < 0)
{
- printf("select failed: %s\n", ErrorStr(MapErrorPOSIX(errno)));
+ printf("poll failed: %s\n", ErrorStr(MapErrorPOSIX(errno)));
return;
}
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
@@ -78,7 +75,7 @@
if (aLayer.State() == kLayerState_Initialized)
{
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
- aLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
+ aLayer.HandleSelectResult(pollFDs, numPollFDs);
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
diff --git a/src/test-apps/TestTLV.cpp b/src/test-apps/TestTLV.cpp
index ff280ad..9a4431a 100644
--- a/src/test-apps/TestTLV.cpp
+++ b/src/test-apps/TestTLV.cpp
@@ -580,11 +580,12 @@
TestNext<TLVReader>(inSuite, reader2);
- TestGet<TLVReader, double>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535), (float)17.9);
+ TestGet<TLVReader, float>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535), 17.9f);
+ TestGet<TLVReader, double>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535), 17.9f);
TestNext<TLVReader>(inSuite, reader2);
- TestGet<TLVReader, double>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65536), (double)17.9);
+ TestGet<TLVReader, double>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65536), 17.9);
TestEndAndCloseContainer(inSuite, reader, reader2);
}
@@ -2946,11 +2947,12 @@
TestNext<TLVReader>(inSuite, reader2);
- TestGet<TLVReader, double>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535), (float)17.9);
+ TestGet<TLVReader, float>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535), 17.9f);
+ TestGet<TLVReader, double>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535), 17.9f);
TestNext<TLVReader>(inSuite, reader2);
- TestGet<TLVReader, double>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65536), (double)17.9);
+ TestGet<TLVReader, double>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65536), 17.9);
TestEndAndCloseContainer(inSuite, reader, reader2);
}
@@ -2974,6 +2976,11 @@
err = reader.Get(val);
NL_TEST_ASSERT(inSuite, err == WEAVE_ERROR_WRONG_TLV_TYPE);
+ // Get(float&)
+ float numF;
+ err = reader.Get(numF);
+ NL_TEST_ASSERT(inSuite, err == WEAVE_ERROR_WRONG_TLV_TYPE);
+
// Get(double&)
double numD;
err = reader.Get(numD);
@@ -3020,6 +3027,38 @@
NL_TEST_ASSERT(inSuite, err == WEAVE_ERROR_WRONG_TLV_TYPE);
free((void *)data);
}
+
+/**
+ * Test that Weave TLV reader returns an error when a read is requested that
+ * would truncate the output.
+ */
+void TestWeaveTLVReaderTruncatedReads(nlTestSuite * inSuite)
+{
+ uint8_t buf[2048];
+ TLVWriter writer;
+ TLVReader reader;
+
+ WEAVE_ERROR err;
+ float outF;
+
+ // Setup: Write some values into the buffer
+ writer.Init(buf, sizeof(buf));
+ writer.ImplicitProfileId = TestProfile_2;
+
+ err = writer.Put(AnonymousTag, double(12.5));
+ NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR);
+
+ // Test reading values from the buffer
+ reader.Init(buf, sizeof(buf));
+
+ TestNext<TLVReader>(inSuite, reader);
+
+ TestGet<TLVReader, double>(inSuite, reader, kTLVType_FloatingPointNumber, AnonymousTag, 12.5);
+
+ err = reader.Get(outF);
+ NL_TEST_ASSERT(inSuite, err == WEAVE_ERROR_WRONG_TLV_TYPE);
+}
+
/**
* Test Weave TLV Reader in a use case
*/
@@ -3046,7 +3085,7 @@
TestNext<TLVReader>(inSuite, reader);
- TestGet<TLVReader, double>(inSuite, reader, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_1, 4000000000ULL), (float) 1.0);
+ TestGet<TLVReader, float>(inSuite, reader, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_1, 4000000000ULL), (float) 1.0);
}
void TestWeaveTLVReader_NextOverContainer_ProcessElement(nlTestSuite *inSuite, TLVReader& reader, void *context)
@@ -3147,6 +3186,8 @@
TestWeaveTLVReaderErrorHandling(inSuite);
+ TestWeaveTLVReaderTruncatedReads(inSuite);
+
TestWeaveTLVReaderInPractice(inSuite);
TestWeaveTLVReader_NextOverContainer(inSuite);
diff --git a/src/test-apps/TestWdmUpdateServer.cpp b/src/test-apps/TestWdmUpdateServer.cpp
index eddb2de..1e45ca3 100644
--- a/src/test-apps/TestWdmUpdateServer.cpp
+++ b/src/test-apps/TestWdmUpdateServer.cpp
@@ -265,7 +265,6 @@
PacketBuffer * pBuf = NULL;
UpdateRequest::Parser update;
Weave::TLV::TLVReader reader;
- bool isDataListPresent = false;
bool existFailure = false;
uint32_t numDataElements = 0;
uint32_t maxPayloadSize = 0;
@@ -297,14 +296,9 @@
{
DataList::Parser dataList;
err = update.GetDataList(&dataList);
- if (WEAVE_NO_ERROR == err)
+ if (WEAVE_END_OF_TLV == err)
{
- isDataListPresent = true;
- }
- else if (WEAVE_END_OF_TLV == err)
- {
- isDataListPresent = false;
- err = WEAVE_NO_ERROR;
+ err = WEAVE_NO_ERROR;
}
SuccessOrExit(err);
diff --git a/src/test-apps/TestWeaveTunnel.h b/src/test-apps/TestWeaveTunnel.h
index 23b2fb6..1e8880b 100644
--- a/src/test-apps/TestWeaveTunnel.h
+++ b/src/test-apps/TestWeaveTunnel.h
@@ -83,6 +83,7 @@
kTestNum_TestTunnelRestrictedRoutingOnStandaloneTunnelOpen = 27,
kTestNum_TestTunnelTCPIdle = 28,
kTestNum_TestTunnelPersistCASESession = 29,
+ kTestNum_TestTunneledPacketCapture = 30,
};
#endif // WEAVE_CONFIG_ENABLE_TUNNELING
diff --git a/src/test-apps/TestWeaveTunnelBR.cpp b/src/test-apps/TestWeaveTunnelBR.cpp
index 8a8486e..1432bdb 100644
--- a/src/test-apps/TestWeaveTunnelBR.cpp
+++ b/src/test-apps/TestWeaveTunnelBR.cpp
@@ -57,6 +57,12 @@
#define NL_PATH_PROCNET_IPV6_ROUTE "/proc/net/ipv6_route"
#endif /* NL_PATH_PROCNET_IPV6_ROUTE */
+const nl::Weave::ExchangeContext::Timeout kResponseTimeoutMsec = 10000;
+const nl::Weave::ExchangeContext::Timeout kWRMPActiveRetransTimeoutMsec = 3000;
+const nl::Weave::ExchangeContext::Timeout kWRMPInitialRetransTimeoutMsec = 3000;
+const uint16_t kWRMPMaxRetrans = 3;
+const uint16_t kWRMPAckTimeoutMsec = 200;
+
static bool HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg);
static bool HandleNonOptionArgs(const char *progName, int argc, char *argv[]);
static void
@@ -79,6 +85,14 @@
uint8_t msgType, PacketBuffer *payload);
static void ResetReconnectTimeout(System::Layer* aSystemLayer, void* aAppState, System::Error aError);
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+static void MessageLayerPacketCaptureHandler(uint8_t *msgBuf, uint16_t msgLen, WeaveMessageInfo *msgInfo);
+
+static WEAVE_ERROR SendMessageForCapture(nl::Weave::Binding* binding);
+static void BindingEventCallback (void * const apAppState, const nl::Weave::Binding::EventType aEvent,
+ const nl::Weave::Binding::InEventParam & aInParam, nl::Weave::Binding::OutEventParam & aOutParam);
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
static int AddDeleteIPv4Address(InterfaceId intf, const char *ipAddr, bool isAdd);
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
@@ -104,6 +118,8 @@
uint64_t gReconnectResetArmTime = 0;
bool gtestDataSent = false;
+static nl::Weave::WRMPConfig gWRMPConfig = { kWRMPInitialRetransTimeoutMsec, kWRMPActiveRetransTimeoutMsec, kWRMPAckTimeoutMsec, kWRMPMaxRetrans };
+
#if WEAVE_CONFIG_ENABLE_SERVICE_DIRECTORY
bool gUseServiceDir = false;
ServiceDirectory::WeaveServiceManager gServiceMgr;
@@ -2726,6 +2742,91 @@
}
#endif // WEAVE_CONFIG_TUNNEL_ENABLE_TCP_IDLE_CALLBACK
+
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+/**
+ * Test to capture a sent Tunneled Weave message.
+ * Binding API used to indicate intent to capture.
+ * Message Capture Handler receives captured message from WeaveMessageLayer.
+ */
+
+static void TestTunneledPacketCapture(nlTestSuite *inSuite, void *inContext)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ Done = false;
+ gTestSucceeded = false;
+ // Set a longer duration for the queueing test. 3 times the default test
+ // duration(~15 seconds) is sufficient for the completion of this test with
+ // close to 100% confidence.
+ gMaxTestDurationMillisecs = (DEFAULT_TEST_DURATION_MILLISECS * 3);
+ gCurrTestNum = kTestNum_TestTunneledPacketCapture;
+ gTestStartTime = Now();
+
+#if WEAVE_CONFIG_ENABLE_SERVICE_DIRECTORY
+ if (gUseServiceDir)
+ {
+ err = gTunAgent.Init(&Inet, &ExchangeMgr, gDestNodeId,
+ gAuthMode, &gServiceMgr);
+ }
+ else
+#endif
+ {
+ err = gTunAgent.Init(&Inet, &ExchangeMgr, gDestNodeId, gDestAddr,
+ gAuthMode);
+ }
+
+
+ gTunAgent.OnServiceTunStatusNotify = WeaveTunnelOnStatusNotifyHandlerCB;
+
+ SuccessOrExit(err);
+
+ ExchangeMgr.MessageLayer->SetMessageLayerPktCaptureHandler(MessageLayerPacketCaptureHandler);
+
+ err = gTunAgent.StartServiceTunnel();
+ SuccessOrExit(err);
+
+ while (!Done)
+ {
+ struct timeval sleepTime;
+ sleepTime.tv_sec = TEST_SLEEP_TIME_WITHIN_LOOP_SECS;
+ sleepTime.tv_usec = TEST_SLEEP_TIME_WITHIN_LOOP_MICROSECS;
+
+ ServiceNetwork(sleepTime);
+
+ if (Now() < gTestStartTime + gMaxTestDurationMillisecs * System::kTimerFactor_micro_per_milli)
+ {
+ if (gTestSucceeded)
+ {
+ Done = true;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ else // Time's up
+ {
+ gTestSucceeded = false;
+ Done = true;
+ }
+
+ if (Done)
+ {
+
+ gTunAgent.StopServiceTunnel(WEAVE_NO_ERROR);
+ }
+ }
+
+exit:
+
+ NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR);
+ NL_TEST_ASSERT(inSuite, gTestSucceeded == true);
+
+ gTunAgent.Shutdown();
+}
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
void HandleTunnelTestResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo,
const WeaveMessageInfo *msgInfo, uint32_t profileId,
uint8_t msgType, PacketBuffer *payload)
@@ -2840,6 +2941,74 @@
}
#endif // WEAVE_CONFIG_TUNNEL_ENABLE_TCP_IDLE_CALLBACK
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+WEAVE_ERROR SendMessageForCapture(nl::Weave::Binding* binding)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ nl::Weave::ExchangeContext* ec = NULL;
+
+ err = binding->NewExchangeContext(ec);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(WeaveTunnel, "Sending Echo Message for Capture\n");
+ err = SendTunnelTestMessage(ec, kWeaveProfile_Echo,
+ kEchoMessageType_EchoRequest,
+ 0);
+ SuccessOrExit(err);
+
+exit:
+ return err;
+
+}
+
+void MessageLayerPacketCaptureHandler(uint8_t *msgBuf, uint16_t msgLen, WeaveMessageInfo *msgInfo)
+{
+ WeaveLogDetail(WeaveTunnel, "Tunneled packet received by capture handler\n");
+
+ gTestSucceeded = true;
+}
+
+void
+BindingEventCallback(
+ void* const apAppState,
+ const nl::Weave::Binding::EventType aEventType,
+ const nl::Weave::Binding::InEventParam& aInParam,
+ nl::Weave::Binding::OutEventParam& aOutParam)
+{
+
+ nl::Weave::Binding* binding = aInParam.Source;
+
+ // TODO: Failure events need correct handling when they occur
+ switch (aEventType)
+ {
+ case nl::Weave::Binding::kEvent_PrepareRequested:
+ {
+ // Nothing to do here, since the binding preperation is done in
+ // Addbinding
+ break;
+ }
+ case nl::Weave::Binding::kEvent_BindingReady:
+ {
+ WeaveLogDetail(WeaveTunnel, "Binding Ready: Send for Capture\n");
+ /* Send the message for the binding that is ready
+ * in the un-cached binding model */
+ (void)SendMessageForCapture(binding);
+ break;
+ }
+ case nl::Weave::Binding::kEvent_PrepareFailed:
+ case nl::Weave::Binding::kEvent_BindingFailed:
+ {
+ break;
+ }
+ default:
+ // All unhandled events must be delivered to the binding's default
+ // event handler.
+ nl::Weave::Binding::DefaultEventHandler(
+ apAppState, aEventType, aInParam, aOutParam);
+ }
+}
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+
void
WeaveTunnelOnStatusNotifyHandlerCB(WeaveTunnelConnectionMgr::TunnelConnNotifyReasons reason,
WEAVE_ERROR aErr, void *appCtxt)
@@ -3233,6 +3402,36 @@
}
break;
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ case kTestNum_TestTunneledPacketCapture:
+ if (reason == WeaveTunnelConnectionMgr::kStatus_TunPrimaryUp)
+ {
+ // Tunnel established; Formulate a message for capture and send it.
+
+ WeaveLogDetail(WeaveTunnel, "Tunnel Up for sending Capture message\n");
+ nl::Weave::Binding *newBinding = ExchangeMgr.NewBinding(BindingEventCallback, NULL);
+ VerifyOrExit(NULL != newBinding, err = WEAVE_ERROR_NO_MEMORY);
+
+ {
+ Binding::Configuration bindingConfig = newBinding->BeginConfiguration()
+ .Target_NodeId(gDestNodeId)
+ .TargetAddress_WeaveFabric(kWeaveSubnetId_Service)
+ .Transport_UDP_WRM()
+ //.Transport_UDP()
+ .Transport_DefaultWRMPConfig(gWRMPConfig)
+ .Exchange_ResponseTimeoutMsec(kResponseTimeoutMsec)
+ .Security_None();
+
+ WeaveLogDetail(WeaveTunnel, "Set Binding flag for Capture\n");
+ bindingConfig.CaptureTxMessage();
+
+ err = bindingConfig.PrepareBinding();
+ SuccessOrExit(err);
+ }
+ }
+
+ break;
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
default:
@@ -3285,6 +3484,9 @@
NL_TEST_DEF("TestTunnelResetReconnectBackoffImmediately", TestTunnelResetReconnectBackoffImmediately),
NL_TEST_DEF("TestTunnelResetReconnectBackoffRandomized", TestTunnelResetReconnectBackoffRandomized),
NL_TEST_DEF("TestTunnelNoStatusReportResetReconnectBackoff", TestTunnelNoStatusReportResetReconnectBackoff),
+#if WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
+ NL_TEST_DEF("TestTunneledPacketCapture", TestTunneledPacketCapture),
+#endif // WEAVE_CONFIG_ENABLE_MESSAGE_CAPTURE
#if WEAVE_CONFIG_TUNNEL_ENABLE_TCP_IDLE_CALLBACK
NL_TEST_DEF("TestTunnelTCPIdle", TestTunnelTCPIdle),
#endif // WEAVE_CONFIG_TUNNEL_ENABLE_TCP_IDLE_CALLBACK
diff --git a/src/test-apps/TestWeaveTunnelCASEPersistClient.cpp b/src/test-apps/TestWeaveTunnelCASEPersistClient.cpp
index a38735b..1f45199 100644
--- a/src/test-apps/TestWeaveTunnelCASEPersistClient.cpp
+++ b/src/test-apps/TestWeaveTunnelCASEPersistClient.cpp
@@ -62,12 +62,14 @@
static bool HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg);
static bool HandleNonOptionArgs(const char *progName, int argc, char *argv[]);
+#if WEAVE_CONFIG_PERSIST_CONNECTED_SESSION
static void HandleLoadPersistedTunnelCASESession(nl::Weave::WeaveConnection *con);
-static void HandleSessionPersistOnTunnelClosure(nl::Weave::WeaveConnection *con);
-static WEAVE_ERROR RestorePersistedTunnelCASESession(nl::Weave::WeaveConnection *con);
-static WEAVE_ERROR SuspendAndPersistTunnelCASESession(nl::Weave::WeaveConnection *con);
static bool IsPersistentTunnelSessionPresent(uint64_t peerNodeId);
+static WEAVE_ERROR RestorePersistedTunnelCASESession(nl::Weave::WeaveConnection *con);
+#endif
+static void HandleSessionPersistOnTunnelClosure(nl::Weave::WeaveConnection *con);
+static WEAVE_ERROR SuspendAndPersistTunnelCASESession(nl::Weave::WeaveConnection *con);
static void
WeaveTunnelOnStatusNotifyHandlerCB(WeaveTunnelConnectionMgr::TunnelConnNotifyReasons reason,
WEAVE_ERROR aErr, void *appCtxt);
@@ -326,6 +328,7 @@
return err;
}
+#if WEAVE_CONFIG_PERSIST_CONNECTED_SESSION
WEAVE_ERROR
RestorePersistedTunnelCASESession(nl::Weave::WeaveConnection *con)
{
@@ -397,6 +400,14 @@
}
}
+bool IsPersistentTunnelSessionPresent(uint64_t peerNodeId)
+{
+ const char * persistentTunnelSessionPath = PERSISTENT_TUNNEL_SESSION_PATH;
+
+ return (access(persistentTunnelSessionPath, F_OK) != -1);
+}
+#endif // WEAVE_CONFIG_PERSIST_CONNECTED_SESSION
+
void HandleSessionPersistOnTunnelClosure(nl::Weave::WeaveConnection *con)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
@@ -408,13 +419,6 @@
printf("Suspending and persisting Tunnel CASE Session failed with Weave error: %d\n", err);
}
}
-
-bool IsPersistentTunnelSessionPresent(uint64_t peerNodeId)
-{
- const char * persistentTunnelSessionPath = PERSISTENT_TUNNEL_SESSION_PATH;
-
- return (access(persistentTunnelSessionPath, F_OK) != -1);
-}
#endif // WEAVE_CONFIG_ENABLE_TUNNELING
int main(int argc, char *argv[])
diff --git a/src/test-apps/ToolCommon.cpp b/src/test-apps/ToolCommon.cpp
index bc9aa69..31fefe3 100644
--- a/src/test-apps/ToolCommon.cpp
+++ b/src/test-apps/ToolCommon.cpp
@@ -92,7 +92,7 @@
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
#include <arpa/inet.h>
-#include <sys/select.h>
+#include <poll.h>
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
@@ -1013,29 +1013,27 @@
}
}
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
- fd_set readFDs, writeFDs, exceptFDs;
- int numFDs = 0;
-
- FD_ZERO(&readFDs);
- FD_ZERO(&writeFDs);
- FD_ZERO(&exceptFDs);
+ int sleepTime = aSleepTime.tv_usec / 1000 + aSleepTime.tv_sec * 1000;
+ struct pollfd pollFDs[WEAVE_CONFIG_MAX_POLL_FDS];
+ int numPollFDs = 0;
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
if (SystemLayer.State() == System::kLayerState_Initialized)
- SystemLayer.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, aSleepTime);
+ SystemLayer.PrepareSelect(pollFDs, numPollFDs, sleepTime);
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
if (Inet.State == InetLayer::kState_Initialized)
- Inet.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, aSleepTime);
+ Inet.PrepareSelect(pollFDs, numPollFDs, sleepTime);
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
- int selectRes = select(numFDs, &readFDs, &writeFDs, &exceptFDs, &aSleepTime);
- if (selectRes < 0)
+ int pollRes = poll(pollFDs, numPollFDs, sleepTime);
+ if (pollRes < 0)
{
- printf("select failed: %s\n", ErrorStr(System::MapErrorPOSIX(errno)));
+ printf("poll failed: %s\n", ErrorStr(System::MapErrorPOSIX(errno)));
return;
}
+
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
if (SystemLayer.State() == System::kLayerState_Initialized)
@@ -1046,7 +1044,7 @@
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
- SystemLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
+ SystemLayer.HandleSelectResult(pollFDs, numPollFDs);
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
@@ -1083,7 +1081,7 @@
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
- Inet.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
+ Inet.HandleSelectResult(pollFDs, numPollFDs);
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
diff --git a/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_disable_notify_01.py b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_disable_notify_01.py
new file mode 100755
index 0000000..19f1c43
--- /dev/null
+++ b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_disable_notify_01.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+
+
+#
+# Copyright (c) 2021 Google, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# @file
+# Calls Weave WDM mutual subscribe between nodes.
+# F16: Mutual Subscribe: Root path. Null Version. Mutate data in initiator and responder. Publisher in initiator aborts
+# M20: Stress Mutual Subscribe: Root path. Null Version. Mutate data in initiator and responder. Publisher in initiator aborts
+#
+
+from __future__ import absolute_import
+from __future__ import print_function
+import unittest
+import set_test_path
+from weave_wdm_next_test_base import weave_wdm_next_test_base
+import WeaveUtilities
+
+
+class test_weave_wdm_next_disable_notify_01(weave_wdm_next_test_base):
+
+ def test_weave_wdm_next_disable_notify_01(self):
+ wdm_next_args = {}
+
+ wdm_next_args['wdm_option'] = "mutual_subscribe"
+
+ wdm_next_args['total_client_count'] = 1
+ wdm_next_args['final_client_status'] = 3
+ wdm_next_args['timer_client_period'] = 5000
+ wdm_next_args['test_client_iterations'] = 1
+ wdm_next_args['test_client_delay'] = 25000
+ wdm_next_args['enable_client_flip'] = 1
+ wdm_next_args['test_client_case'] = 11 # kTestCase_TestDisableSendingNotifies
+
+ wdm_next_args['total_server_count'] = 1
+ wdm_next_args['final_server_status'] = 4
+ wdm_next_args['timer_server_period'] = 4000
+ wdm_next_args['enable_server_flip'] = 0
+ wdm_next_args['test_server_case'] = 11 # kTestCase_TestDisableSendingNotifies
+
+ wdm_next_args['client_clear_state_between_iterations'] = True
+ wdm_next_args['server_clear_state_between_iterations'] = True
+
+ wdm_next_args['client_log_check'] = [('Client\[0\] \[(ALIVE|CONFM)\] bound mutual subscription is going away', wdm_next_args['test_client_iterations']),
+ ('Client->kEvent_OnNotificationProcessed', wdm_next_args['test_client_iterations'] * (wdm_next_args['total_server_count'])),
+ ('Handler\[0\] \[(ALIVE|CONFM)\] AbortSubscription Ref\(\d+\)', wdm_next_args['test_client_iterations']),
+ ('Client\[0\] moving to \[ FREE\] Ref\(0\)', wdm_next_args['test_client_iterations']),
+ ('Disabling notifications', wdm_next_args['test_client_iterations']),
+ ('Notify Transmission disabled', wdm_next_args['test_client_iterations']),
+ ('Handler\[0\] Moving to \[ FREE\] Ref\(0\)', wdm_next_args['test_client_iterations'])]
+ wdm_next_args['server_log_check'] = [('TimerEventHandler Ref\(\d+\) Timeout', wdm_next_args['test_client_iterations']),
+ ('bound mutual subscription is going away', wdm_next_args['test_client_iterations']),
+ ('Client\[0\] \[(ALIVE|CONFM)\] TerminateSubscription ', wdm_next_args['test_client_iterations']),
+ ('Client\[0\] moving to \[ FREE\] Ref\(0\)', wdm_next_args['test_client_iterations']),
+ ('Handler\[0\] Moving to \[ FREE\] Ref\(0\)', wdm_next_args['test_client_iterations'])]
+ wdm_next_args['test_tag'] = self.__class__.__name__[19:].upper()
+ wdm_next_args['test_case_name'] = ['DisableNotify 01: Disable Notify on Mutual Subscribe: Root path. Null Version. Mutate data in initiator and responder. Publisher in initiator aborts']
+ print('test file: ' + self.__class__.__name__)
+ print("weave-wdm-next DisableNotify test")
+ super(test_weave_wdm_next_disable_notify_01, self).weave_wdm_next_test_base(wdm_next_args)
+
+
+
+if __name__ == "__main__":
+ WeaveUtilities.run_unittest()
+
diff --git a/src/tools/weave/Cmd_PrintAccessToken.cpp b/src/tools/weave/Cmd_PrintAccessToken.cpp
new file mode 100644
index 0000000..08d6e39
--- /dev/null
+++ b/src/tools/weave/Cmd_PrintAccessToken.cpp
@@ -0,0 +1,196 @@
+/*
+ *
+ * Copyright (c) 2022 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * This file implements the command handler for the 'weave' tool
+ * that decodes and prints the contents of a Weave access token certificate.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "weave-tool.h"
+#include <Weave/Support/ASN1OID.h>
+#include <Weave/Profiles/security/WeaveSecurityDebug.h>
+#include <Weave/Profiles/security/WeaveAccessToken.h>
+#include <Weave/Support/Base64.h>
+
+using namespace nl::Weave::ASN1;
+using namespace nl::Weave::Profiles::Security;
+
+#define CMD_NAME "weave print-access-token"
+
+static bool HandleNonOptionArgs(const char *progName, int argc, char *argv[]);
+static bool HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg);
+
+static OptionDef gCmdOptionDefs[] =
+{
+ { "base64", kNoArgument, 'b' },
+ { }
+};
+
+static const char *const gCmdOptionHelp =
+ " -b, --base64\n"
+ "\n"
+ " The file containing the TLV should be parsed as base64.\n"
+ "\n"
+ ;
+
+static OptionSet gCmdOptions =
+{
+ HandleOption,
+ gCmdOptionDefs,
+ "COMMAND OPTIONS",
+ gCmdOptionHelp
+};
+static HelpOptions gHelpOptions(
+ CMD_NAME,
+ "Usage: " CMD_NAME " [<options...>] <access-token>\n",
+ WEAVE_VERSION_STRING "\n" COPYRIGHT_STRING,
+ "Print a Weave Access Token certificate.\n"
+ "\n"
+ "ARGUMENTS\n"
+ "\n"
+ " <access-token>\n"
+ "\n"
+ " A file containing a Weave Access Token either in raw TLV format (default)\n"
+ " or in base-64 format with -b option.\n"
+ "\n"
+);
+
+static OptionSet *gCmdOptionSets[] =
+{
+ &gCmdOptions,
+ &gHelpOptions,
+ NULL
+};
+
+static const char *gCertFileName = NULL;
+static bool gUseBase64Decoding = false;
+enum {
+ kNumCerts = 1,
+ kCertBufSize = 1024,
+};
+
+bool Cmd_PrintAccessToken(int argc, char *argv[])
+{
+ bool res = true;
+ WEAVE_ERROR err;
+ WeaveCertificateData *certData;
+ WeaveCertificateSet certSet;
+ uint8_t * accessToken = NULL;
+ uint32_t accessTokenLen = 0;
+ TLVReader reader;
+
+ if (argc == 1)
+ {
+ gHelpOptions.PrintBriefUsage(stderr);
+ ExitNow(res = true);
+ }
+
+ if (!ParseArgs(CMD_NAME, argc, argv, gCmdOptionSets, HandleNonOptionArgs))
+ {
+ ExitNow(res = false);
+ }
+
+ if (!ReadFileIntoMem(gCertFileName, accessToken, accessTokenLen))
+ {
+ ExitNow(res = false);
+ }
+
+ if (gUseBase64Decoding)
+ {
+ uint32_t b64len = accessTokenLen;
+ uint8_t * b64 = accessToken;
+ accessToken = (uint8_t *)malloc(accessTokenLen);
+ if (accessToken == NULL)
+ {
+ fprintf(stderr, "Memory allocation error\n");
+ free(b64);
+ ExitNow(res = false);
+ }
+ accessTokenLen = nl::Base64Decode((const char *)b64, b64len, accessToken);
+ free(b64);
+ }
+
+ reader.Init(accessToken, accessTokenLen);
+ certSet.Init(kNumCerts, kCertBufSize);
+ err = LoadAccessTokenCerts(reader, certSet, 0, certData);
+
+ if (err != WEAVE_NO_ERROR)
+ {
+ fprintf(stderr, "Error reading cert info: %s.\n", nl::ErrorStr(err));
+ ExitNow(res = false);
+ }
+
+ printf("Weave Access Token:\n");
+
+ printf("Weave Certificate:\n");
+
+ PrintCert(stdout, *certData, NULL, 2, true);
+
+ printf("Access Token Private Key omitted\n");
+
+ res = (err == WEAVE_NO_ERROR);
+
+exit:
+ if (accessToken != NULL)
+ free(accessToken);
+ return res;
+}
+
+bool HandleNonOptionArgs(const char *progName, int argc, char *argv[])
+{
+ if (argc == 0)
+ {
+ PrintArgError("%s: Please specify the name of the certificate to be printed.\n", progName);
+ return false;
+ }
+
+ if (argc > 1)
+ {
+ PrintArgError("%s: Unexpected argument: %s\n", progName, argv[1]);
+ return false;
+ }
+
+ gCertFileName = argv[0];
+
+ return true;
+}
+
+bool HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg)
+{
+ switch (id)
+ {
+ case 'b':
+ gUseBase64Decoding = true;
+ break;
+
+ default:
+ PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", progName, name);
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/tools/weave/Cmd_PrintServiceConfig.cpp b/src/tools/weave/Cmd_PrintServiceConfig.cpp
new file mode 100644
index 0000000..e553ea6
--- /dev/null
+++ b/src/tools/weave/Cmd_PrintServiceConfig.cpp
@@ -0,0 +1,284 @@
+/*
+ *
+ * Copyright (c) 2022 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * This file implements the command handler for the 'weave' tool
+ * that decodes and prints the contents of a service config object.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "weave-tool.h"
+#include <Weave/Support/ASN1OID.h>
+#include <Weave/Profiles/security/WeaveSecurityDebug.h>
+#include <Weave/Profiles/security/WeaveAccessToken.h>
+#include <Weave/Profiles/service-provisioning/ServiceProvisioning.h>
+#include <Weave/Profiles/service-directory/ServiceDirectory.h>
+#include <Weave/Support/Base64.h>
+
+using namespace nl::Weave::ASN1;
+using namespace nl::Weave::Profiles::Security;
+using namespace nl::Weave::TLV;
+using namespace nl::Weave::Profiles::ServiceProvisioning;
+using namespace nl::Weave::Profiles;
+
+#define CMD_NAME "weave print-service-config"
+
+static WEAVE_ERROR PrintServiceHostname(TLVReader &reader);
+static bool HandleNonOptionArgs(const char *progName, int argc, char *argv[]);
+static bool HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg);
+
+static OptionDef gCmdOptionDefs[] =
+{
+ { "base64", kNoArgument, 'b' },
+ { }
+};
+
+static const char *const gCmdOptionHelp =
+ " -b, --base64\n"
+ "\n"
+ " The file containing the TLV should be parsed as base64.\n"
+ "\n"
+ ;
+
+static OptionSet gCmdOptions =
+{
+ HandleOption,
+ gCmdOptionDefs,
+ "COMMAND OPTIONS",
+ gCmdOptionHelp
+};
+static HelpOptions gHelpOptions(
+ CMD_NAME,
+ "Usage: " CMD_NAME " [<options...>] <service-config-file>\n",
+ WEAVE_VERSION_STRING "\n" COPYRIGHT_STRING,
+ "Print a service config object.\n"
+ "\n"
+ "ARGUMENTS\n"
+ "\n"
+ " <service-config-file>\n"
+ "\n"
+ " A file containing a service config object either in binary (default) or in base-64 format\n"
+ "\n"
+);
+
+static OptionSet *gCmdOptionSets[] =
+{
+ &gCmdOptions,
+ &gHelpOptions,
+ NULL
+};
+
+static const char *gCertFileName = NULL;
+static bool gUseBase64Decoding = false;
+enum {
+ kNumCerts = 3,
+ kCertBufSize = 1024,
+};
+
+bool Cmd_PrintServiceConfig(int argc, char *argv[])
+{
+ bool res = true;
+ WEAVE_ERROR err;
+ WeaveCertificateSet certSet;
+ uint8_t * serviceConfig = NULL;
+ uint32_t serviceConfigLen = 0;
+ TLVReader reader;
+ uint64_t serviceEndpoint;
+ TLVType serviceConfigContainer, serviceEndpointContainer, serviceDirectoryContainer;
+
+ if (argc == 1)
+ {
+ gHelpOptions.PrintBriefUsage(stderr);
+ ExitNow(res = true);
+ }
+
+ if (!ParseArgs(CMD_NAME, argc, argv, gCmdOptionSets, HandleNonOptionArgs))
+ {
+ ExitNow(res = false);
+ }
+
+ if (!ReadFileIntoMem(gCertFileName, serviceConfig, serviceConfigLen))
+ {
+ ExitNow(res = false);
+ }
+
+ if (gUseBase64Decoding)
+ {
+ uint32_t b64len = serviceConfigLen;
+ uint8_t * b64 = serviceConfig;
+ serviceConfig = (uint8_t *)malloc(serviceConfigLen);
+ if (serviceConfig == NULL)
+ {
+ fprintf(stderr, "Memory allocation error\n");
+ free(b64);
+ ExitNow(res = false);
+ }
+ serviceConfigLen = nl::Base64Decode((const char *)b64, b64len, serviceConfig);
+ free(b64);
+ }
+
+ reader.Init(serviceConfig, serviceConfigLen);
+ certSet.Init(kNumCerts, kCertBufSize);
+
+ err = reader.Next(kTLVType_Structure, ProfileTag(kWeaveProfile_ServiceProvisioning, kTag_ServiceConfig));
+ SuccessOrExit(err);
+
+ err = reader.EnterContainer(serviceConfigContainer);
+ SuccessOrExit(err);
+
+ err = reader.Next(kTLVType_Array, ContextTag(kTag_ServiceConfig_CACerts));
+ SuccessOrExit(err);
+
+ err = certSet.LoadCerts(reader, 0);
+ SuccessOrExit(err);
+
+ printf("Weave Service Config:\n\n");
+ printf("Trusted certificates:\n");
+ for (int i = 0; i < certSet.CertCount; i++)
+ {
+ printf("Certificate %d\n", i + 1);
+ PrintCert(stdout, certSet.Certs[i], NULL, 2, true);
+ }
+
+ err = reader.Next(kTLVType_Structure, ContextTag(kTag_ServiceEndPoint));
+ SuccessOrExit(err);
+
+ err = reader.EnterContainer(serviceEndpointContainer);
+ SuccessOrExit(err);
+
+ err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_ServiceEndPoint_Id));
+ SuccessOrExit(err);
+
+ err = reader.Get(serviceEndpoint);
+ SuccessOrExit(err);
+
+ printf("Service Endpoint ID: %016" PRIX64 "\n", serviceEndpoint);
+
+ err = reader.Next(kTLVType_Array, ContextTag(kTag_ServiceEndPoint_Addresses));
+ SuccessOrExit(err);
+
+ err = reader.EnterContainer(serviceDirectoryContainer);
+ SuccessOrExit(err);
+
+ while (err == WEAVE_NO_ERROR)
+ {
+ err = PrintServiceHostname(reader);
+ }
+ if (err == WEAVE_END_OF_TLV)
+ {
+ err = WEAVE_NO_ERROR;
+ }
+
+exit:
+ res = (err == WEAVE_NO_ERROR);
+
+ if (serviceConfig != NULL)
+ {
+ free(serviceConfig);
+ }
+ return res;
+}
+
+bool HandleNonOptionArgs(const char *progName, int argc, char *argv[])
+{
+ if (argc == 0)
+ {
+ PrintArgError("%s: Please specify the name of the certificate to be printed.\n", progName);
+ return false;
+ }
+
+ if (argc > 1)
+ {
+ PrintArgError("%s: Unexpected argument: %s\n", progName, argv[1]);
+ return false;
+ }
+
+ gCertFileName = argv[0];
+
+ return true;
+}
+
+bool HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg)
+{
+ switch (id)
+ {
+ case 'b':
+ gUseBase64Decoding = true;
+ break;
+
+ default:
+ PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", progName, name);
+ return false;
+ }
+
+ return true;
+}
+
+WEAVE_ERROR PrintServiceHostname(TLVReader &reader)
+{
+ WEAVE_ERROR err;
+ TLVType container;
+ uint32_t len;
+ const uint8_t * strbuf = NULL;
+ uint16_t port;
+ err = reader.Next();
+ SuccessOrExit(err);
+
+ err = reader.EnterContainer(container);
+ SuccessOrExit(err);
+
+ while ((err = reader.Next()) == WEAVE_NO_ERROR)
+ {
+ uint64_t tag = reader.GetTag();
+ uint8_t tagNum;
+ if (!IsContextTag(tag))
+ {
+ continue;
+ }
+
+ tagNum = TagNumFromTag(tag);
+
+ switch (tagNum)
+ {
+ case kTag_ServiceEndPointAddress_HostName:
+ reader.GetDataPtr(strbuf);
+ len = reader.GetLength();
+ printf("Hostname: %-.*s ", (int)len, strbuf);
+ break;
+ case kTag_ServiceEndPointAddress_Port:
+ reader.Get(port);
+ printf("Port: %d ", port);
+ break;
+
+ default:
+ printf("Unknown tag num %d", tagNum);
+ }
+ }
+ printf("\n");
+ reader.ExitContainer(container);
+exit:
+ return err;
+}
diff --git a/src/tools/weave/Cmd_PrintTLV.cpp b/src/tools/weave/Cmd_PrintTLV.cpp
index d010974..d413456 100644
--- a/src/tools/weave/Cmd_PrintTLV.cpp
+++ b/src/tools/weave/Cmd_PrintTLV.cpp
@@ -48,6 +48,7 @@
static OptionDef gCmdOptionDefs[] =
{
{ "base64", kNoArgument, 'b' },
+ { "profile", kArgumentRequired, 'p' },
{ }
};
@@ -56,6 +57,10 @@
"\n"
" The file containing the TLV should be parsed as base64.\n"
"\n"
+ " -p, --profile <profileNumber>\n"
+ "\n"
+ " The profile number to be used for decoding implicit tags\n"
+ "\n"
;
static OptionSet gCmdOptions =
@@ -90,6 +95,7 @@
static const char *gFileName = NULL;
static bool gUseBase64Decoding = false;
+static uint32_t gImplicitProfileID = kProfileIdNotSpecified;
bool Cmd_PrintTLV(int argc, char *argv[])
{
@@ -98,6 +104,7 @@
uint8_t *raw = NULL;
int fd;
struct stat st;
+ WEAVE_ERROR err;
TLVReader reader;
uint32_t len;
@@ -145,8 +152,12 @@
printf("TLV length is %d bytes\n", len);
reader.Init(raw, len);
- nl::Weave::TLV::Debug::Dump(reader, _DumpWriter);
-
+ reader.ImplicitProfileId = gImplicitProfileID;
+ err = nl::Weave::TLV::Debug::Dump(reader, _DumpWriter);
+ if (err == WEAVE_ERROR_UNKNOWN_IMPLICIT_TLV_TAG)
+ {
+ printf("Data contains unknown implicit TLV encoding, for correct decode, please specify the correct implicit profile\n");
+ }
exit:
if (raw != NULL && raw != map)
{
@@ -199,6 +210,13 @@
gUseBase64Decoding = true;
break;
+ case 'p':
+ if (!ParseInt(arg, gImplicitProfileID))
+ {
+ PrintArgError("s: Invalid value specified for the profile ID, \"%s\" must be an integer\n", progName, arg);
+ return false;
+ }
+ break;
default:
PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", progName, name);
return false;
diff --git a/src/tools/weave/Makefile.am b/src/tools/weave/Makefile.am
index 2a77be5..5bdc985 100644
--- a/src/tools/weave/Makefile.am
+++ b/src/tools/weave/Makefile.am
@@ -74,6 +74,8 @@
Cmd_GenServiceEndpointCert.cpp \
Cmd_MakeAccessToken.cpp \
Cmd_MakeServiceConfig.cpp \
+ Cmd_PrintAccessToken.cpp \
+ Cmd_PrintServiceConfig.cpp \
Cmd_PrintCert.cpp \
Cmd_PrintSig.cpp \
Cmd_PrintTLV.cpp \
diff --git a/src/tools/weave/weave-tool.cpp b/src/tools/weave/weave-tool.cpp
index b10258a..14e26a3 100644
--- a/src/tools/weave/weave-tool.cpp
+++ b/src/tools/weave/weave-tool.cpp
@@ -59,8 +59,14 @@
"\n"
" make-service-config -- Make a service config object.\n"
"\n"
+ " make-access-token -- Make a Weave Access Token.\n"
+ "\n"
" validate-cert -- Validate a Weave certificate chain.\n"
"\n"
+ " print-access-token -- Print a Weave Access Token.\n"
+ "\n"
+ " print-service-config -- Print a service config object\n"
+ "\n"
" print-cert -- Print a Weave certificate.\n"
"\n"
" print-sig -- Print a Weave signature.\n"
@@ -137,6 +143,12 @@
else if (strcasecmp(argv[1], "validate-cert") == 0 || strcasecmp(argv[1], "validatecert") == 0)
res = Cmd_ValidateCert(argc - 1, argv + 1);
+ else if (strcasecmp(argv[1], "print-access-token") == 0 || strcasecmp(argv[1], "printaccesstoken") == 0)
+ res = Cmd_PrintAccessToken(argc - 1, argv + 1);
+
+ else if (strcasecmp(argv[1], "print-service-config") == 0 || strcasecmp(argv[1], "printserviceconfig") == 0)
+ res = Cmd_PrintServiceConfig(argc - 1, argv + 1);
+
else if (strcasecmp(argv[1], "print-cert") == 0 || strcasecmp(argv[1], "printcert") == 0)
res = Cmd_PrintCert(argc - 1, argv + 1);
diff --git a/src/tools/weave/weave-tool.h b/src/tools/weave/weave-tool.h
index e112966..33de037 100644
--- a/src/tools/weave/weave-tool.h
+++ b/src/tools/weave/weave-tool.h
@@ -92,6 +92,8 @@
extern bool Cmd_MakeAccessToken(int argc, char *argv[]);
extern bool Cmd_GenProvisioningData(int argc, char *argv[]);
extern bool Cmd_ValidateCert(int argc, char *argv[]);
+extern bool Cmd_PrintAccessToken(int argc, char *argv[]);
+extern bool Cmd_PrintServiceConfig(int argc, char *argv[]);
extern bool Cmd_PrintCert(int argc, char *argv[]);
extern bool Cmd_PrintSig(int argc, char *argv[]);
extern bool Cmd_PrintTLV(int argc, char *argv[]);