Skip to content

Commit

Permalink
Merge branch 'master' into no_large_enums
Browse files Browse the repository at this point in the history
  • Loading branch information
andy31415 committed Dec 13, 2023
2 parents 32f1042 + b6e465a commit 062810d
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 27 deletions.
2 changes: 1 addition & 1 deletion examples/lighting-app/esp32/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

#if CONFIG_ENABLE_ESP_INSIGHTS_SYSTEM_STATS
#include <tracing/esp32_trace/insights_sys_stats.h>
#define START_TIMEOUT_MS 600000
#define START_TIMEOUT_MS 60000
#endif

#if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER
Expand Down
2 changes: 1 addition & 1 deletion scripts/setup/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ portpicker==1.5.2
# via
# -r requirements.all.txt
# mobly
prompt-toolkit==3.0.38
prompt-toolkit==3.0.43
# via ipython
protobuf==4.24.4
# via
Expand Down
17 changes: 9 additions & 8 deletions src/controller/python/ChipDeviceController-ScriptBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ using namespace chip::DeviceLayer;
extern "C" {
typedef void (*ConstructBytesArrayFunct)(const uint8_t * dataBuf, uint32_t dataLen);
typedef void (*LogMessageFunct)(uint64_t time, uint64_t timeUS, const char * moduleName, uint8_t category, const char * msg);
typedef void (*DeviceAvailableFunc)(DeviceProxy * device, PyChipError err);
typedef void (*DeviceAvailableFunc)(chip::Controller::Python::PyObject * context, DeviceProxy * device, PyChipError err);
typedef void (*ChipThreadTaskRunnerFunct)(intptr_t context);
typedef void (*DeviceUnpairingCompleteFunct)(uint64_t nodeId, PyChipError error);
}
Expand Down Expand Up @@ -207,7 +207,7 @@ const char * pychip_Stack_StatusReportToString(uint32_t profileId, uint16_t stat
void pychip_Stack_SetLogFunct(LogMessageFunct logFunct);

PyChipError pychip_GetConnectedDeviceByNodeId(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId nodeId,
DeviceAvailableFunc callback);
chip::Controller::Python::PyObject * context, DeviceAvailableFunc callback);
PyChipError pychip_FreeOperationalDeviceProxy(chip::OperationalDeviceProxy * deviceProxy);
PyChipError pychip_GetLocalSessionId(chip::OperationalDeviceProxy * deviceProxy, uint16_t * localSessionId);
PyChipError pychip_GetNumSessionsToPeer(chip::OperationalDeviceProxy * deviceProxy, uint32_t * numSessions);
Expand Down Expand Up @@ -737,36 +737,37 @@ namespace {

struct GetDeviceCallbacks
{
GetDeviceCallbacks(DeviceAvailableFunc callback) :
mOnSuccess(OnDeviceConnectedFn, this), mOnFailure(OnConnectionFailureFn, this), mCallback(callback)
GetDeviceCallbacks(chip::Controller::Python::PyObject * context, DeviceAvailableFunc callback) :
mOnSuccess(OnDeviceConnectedFn, this), mOnFailure(OnConnectionFailureFn, this), mContext(context), mCallback(callback)
{}

static void OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle)
{
auto * self = static_cast<GetDeviceCallbacks *>(context);
auto * operationalDeviceProxy = new OperationalDeviceProxy(&exchangeMgr, sessionHandle);
self->mCallback(operationalDeviceProxy, ToPyChipError(CHIP_NO_ERROR));
self->mCallback(self->mContext, operationalDeviceProxy, ToPyChipError(CHIP_NO_ERROR));
delete self;
}

static void OnConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
{
auto * self = static_cast<GetDeviceCallbacks *>(context);
self->mCallback(nullptr, ToPyChipError(error));
self->mCallback(self->mContext, nullptr, ToPyChipError(error));
delete self;
}

Callback::Callback<OnDeviceConnected> mOnSuccess;
Callback::Callback<OnDeviceConnectionFailure> mOnFailure;
chip::Controller::Python::PyObject * const mContext;
DeviceAvailableFunc mCallback;
};
} // anonymous namespace

PyChipError pychip_GetConnectedDeviceByNodeId(chip::Controller::DeviceCommissioner * devCtrl, chip::NodeId nodeId,
DeviceAvailableFunc callback)
chip::Controller::Python::PyObject * context, DeviceAvailableFunc callback)
{
VerifyOrReturnError(devCtrl != nullptr, ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT));
auto * callbacks = new GetDeviceCallbacks(callback);
auto * callbacks = new GetDeviceCallbacks(context, callback);
return ToPyChipError(devCtrl->GetConnectedDevice(nodeId, &callbacks->mOnSuccess, &callbacks->mOnFailure));
}

Expand Down
35 changes: 22 additions & 13 deletions src/controller/python/chip/ChipDeviceCtrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
#
# CHIP_ERROR is actually signed, so using c_uint32 is weird, but everything
# else seems to do it.
_DeviceAvailableFunct = CFUNCTYPE(None, c_void_p, PyChipError)
_DeviceAvailableCallbackFunct = CFUNCTYPE(None, py_object, c_void_p, PyChipError)

_IssueNOCChainCallbackPythonCallbackFunct = CFUNCTYPE(
None, py_object, PyChipError, c_void_p, c_size_t, c_void_p, c_size_t, c_void_p, c_size_t, c_void_p, c_size_t, c_uint64)
Expand All @@ -100,6 +100,11 @@ class NOCChain:
adminSubject: int


@_DeviceAvailableCallbackFunct
def _DeviceAvailableCallback(closure, device, err):
closure.deviceAvailable(device, err)


@_IssueNOCChainCallbackPythonCallbackFunct
def _IssueNOCChainCallbackPythonCallback(devCtrl, status: PyChipError, noc: c_void_p, nocLen: int, icac: c_void_p,
icacLen: int, rcac: c_void_p, rcacLen: int, ipk: c_void_p, ipkLen: int, adminSubject: int):
Expand Down Expand Up @@ -759,25 +764,29 @@ def GetConnectedDeviceSync(self, nodeid, allowPASE=True, timeoutMs: int = None):
returnErr = None
deviceAvailableCV = threading.Condition()

@_DeviceAvailableFunct
def DeviceAvailableCallback(device, err):
nonlocal returnDevice
nonlocal returnErr
nonlocal deviceAvailableCV
with deviceAvailableCV:
returnDevice = c_void_p(device)
returnErr = err
deviceAvailableCV.notify_all()

if allowPASE:
res = self._ChipStack.Call(lambda: self._dmLib.pychip_GetDeviceBeingCommissioned(
self.devCtrl, nodeid, byref(returnDevice)), timeoutMs)
if res.is_success:
print('Using PASE connection')
return DeviceProxyWrapper(returnDevice)

class DeviceAvailableClosure():
def deviceAvailable(self, device, err):
nonlocal returnDevice
nonlocal returnErr
nonlocal deviceAvailableCV
with deviceAvailableCV:
returnDevice = c_void_p(device)
returnErr = err
deviceAvailableCV.notify_all()
ctypes.pythonapi.Py_DecRef(ctypes.py_object(self))

closure = DeviceAvailableClosure()
ctypes.pythonapi.Py_IncRef(ctypes.py_object(closure))
self._ChipStack.Call(lambda: self._dmLib.pychip_GetConnectedDeviceByNodeId(
self.devCtrl, nodeid, DeviceAvailableCallback), timeoutMs).raise_on_error()
self.devCtrl, nodeid, ctypes.py_object(closure), _DeviceAvailableCallback),
timeoutMs).raise_on_error()

# The callback might have been received synchronously (during self._ChipStack.Call()).
# Check if the device is already set before waiting for the callback.
Expand Down Expand Up @@ -1568,7 +1577,7 @@ def _InitLib(self):
self._dmLib.pychip_ScriptDevicePairingDelegate_SetFabricCheckCallback.restype = PyChipError

self._dmLib.pychip_GetConnectedDeviceByNodeId.argtypes = [
c_void_p, c_uint64, _DeviceAvailableFunct]
c_void_p, c_uint64, py_object, _DeviceAvailableCallbackFunct]
self._dmLib.pychip_GetConnectedDeviceByNodeId.restype = PyChipError

self._dmLib.pychip_FreeOperationalDeviceProxy.argtypes = [
Expand Down
1 change: 1 addition & 0 deletions src/platform/Linux/SystemPlatformConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ struct ChipDeviceEvent;
#define CHIP_SYSTEM_CONFIG_POOL_USE_HEAP 1

// ========== Platform-specific Configuration Overrides =========
#define CHIP_CONFIG_MDNS_RESOLVE_LOOKUP_RESULTS 5
115 changes: 112 additions & 3 deletions src/tracing/esp32_trace/esp32_tracing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

#include "esp32_tracing.h"
#include <algorithm>
#include <esp_heap_caps.h>
#include <esp_insights.h>
#include <esp_log.h>
Expand All @@ -26,6 +27,107 @@
namespace chip {
namespace Tracing {
namespace Insights {
namespace {

constexpr size_t kPermitListMaxSize = 10;
using HashValue = uint32_t;

// Implements a murmurhash with 0 seed.
uint32_t MurmurHash(const void * key)
{
const uint32_t kMultiplier = 0x5bd1e995;
const uint32_t kShift = 24;
const unsigned char * data = (const unsigned char *) key;
uint32_t hash = 0;

while (*data)
{
uint32_t value = *data++;
value *= kMultiplier;
value ^= value >> kShift;
value *= kMultiplier;
hash *= kMultiplier;
hash ^= value;
}

hash ^= hash >> 13;
hash *= kMultiplier;
hash ^= hash >> 15;

if (hash == 0)
{
ESP_LOGW("Tracing", "MurmurHash resulted in a hash value of 0");
}

return hash;
}

/* PASESession,CASESession,NetworkCommissioning,GeneralCommissioning,OperationalCredentials
* are well known permitted entries.
*/

HashValue gPermitList[kPermitListMaxSize] = {
MurmurHash("PASESession"),
MurmurHash("CASESession"),
MurmurHash("NetworkCommissioning"),
MurmurHash("GeneralCommissioning"),
MurmurHash("OperationalCredentials"),
};

bool IsPermitted(HashValue hashValue)
{
for (HashValue permitted : gPermitList)
{
if (permitted == 0)
{
break;
}
if (hashValue == permitted)
{
return true;
}
}
return false;
}

} // namespace

namespace ESP32Filter {

CHIP_ERROR AddHashToPermitlist(const char * str)
{
HashValue hashValue = MurmurHash(str);
if (hashValue == 0)
{
ESP_LOGW("TRC", "Hash value for '%s' is 0", str);
return CHIP_ERROR_INCORRECT_STATE;
}

for (HashValue & permitted : gPermitList)
{
if (permitted == 0)
{
permitted = hashValue;
return CHIP_NO_ERROR;
}
if (hashValue == permitted)
{
ESP_LOGW("TRC", "Hash value for '%s' is colliding with an existing entry", str);
return CHIP_ERROR_DUPLICATE_KEY_ID;
}
}
return CHIP_ERROR_NO_MEMORY;
}

void RemoveHashFromPermitlist(const char * str)
{
HashValue hashValue = MurmurHash(str);

auto * end = gPermitList + kPermitListMaxSize;
std::fill(std::remove(gPermitList, end, hashValue), end, 0);
}

} // namespace ESP32Filter

#define LOG_HEAP_INFO(label, group, entry_exit) \
do \
Expand All @@ -48,12 +150,20 @@ void ESP32Backend::LogNodeDiscoveryFailed(NodeDiscoveryFailedInfo & info) {}

void ESP32Backend::TraceBegin(const char * label, const char * group)
{
LOG_HEAP_INFO(label, group, "Entry");
HashValue hashValue = MurmurHash(group);
if (IsPermitted(hashValue))
{
LOG_HEAP_INFO(label, group, "Entry");
}
}

void ESP32Backend::TraceEnd(const char * label, const char * group)
{
LOG_HEAP_INFO(label, group, "Exit");
HashValue hashValue = MurmurHash(group);
if (IsPermitted(hashValue))
{
LOG_HEAP_INFO(label, group, "Exit");
}
}

void ESP32Backend::TraceInstant(const char * label, const char * group)
Expand All @@ -63,4 +173,3 @@ void ESP32Backend::TraceInstant(const char * label, const char * group)
} // namespace Insights
} // namespace Tracing
} // namespace chip
// namespace chip
9 changes: 8 additions & 1 deletion src/tracing/esp32_trace/esp32_tracing.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
#include <lib/core/CHIPError.h>
#include <tracing/backend.h>

#include <memory>

namespace chip {
namespace Tracing {
namespace Insights {

// Provide the user the ability to add/remove trace filters.
namespace ESP32Filter {

CHIP_ERROR AddHashToPermitlist(const char * alabel);
void RemoveHashFromPermitlist(const char * alabel);
} // namespace ESP32Filter

/// A Backend that outputs data to chip logging.
///
/// Structured data is formatted as json strings.
Expand Down

0 comments on commit 062810d

Please sign in to comment.