Skip to content

[Darwin][Network.framework] Add src/platform/Darwin/system/SystemLaye… #38912

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ jobs:
--known-failure platform/DeviceSafeQueue.h \
--known-failure platform/GLibTypeDeleter.h \
--known-failure platform/SingletonConfigurationManager.cpp \
--known-failure system/SystemLayerImplDispatch.h \
"
# These ARE actually orphaned but due to dynamic-server we have code paths
# for them. Keeping them as a list as they still need review ...
Expand Down
8 changes: 7 additions & 1 deletion src/inet/tests/TestInetCommonPosix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,16 +358,22 @@ void ServiceEvents(uint32_t aSleepTimeMilliseconds)
}
}

#if !CHIP_SYSTEM_CONFIG_USE_DISPATCH
// Start a timer (with a no-op callback) to ensure that WaitForEvents() does not block longer than aSleepTimeMilliseconds.
gSystemLayer.StartTimer(
System::Clock::Milliseconds32(aSleepTimeMilliseconds), [](System::Layer *, void *) -> void {}, nullptr);
#endif

#if CHIP_SYSTEM_CONFIG_USE_SOCKETS
#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && !CHIP_SYSTEM_CONFIG_USE_DISPATCH
gSystemLayer.PrepareEvents();
gSystemLayer.WaitForEvents();
gSystemLayer.HandleEvents();
#endif

#if CHIP_SYSTEM_CONFIG_USE_DISPATCH
gSystemLayer.HandleDispatchQueueEvents(System::Clock::Milliseconds32(aSleepTimeMilliseconds));
#endif

#if CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
if (gSystemLayer.IsInitialized())
{
Expand Down
7 changes: 7 additions & 0 deletions src/platform/Darwin/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import("//build_overrides/chip.gni")
import("//build_overrides/nlassert.gni")

import("${chip_root}/src/platform/device.gni")
import("${chip_root}/src/system/system.gni")

assert(chip_device_platform == "darwin")

Expand Down Expand Up @@ -79,8 +80,14 @@ static_library("Darwin") {
"UserDefaults.mm",
"inet/InterfacesMonitor.h",
"inet/InterfacesMonitor.mm",
"system/SystemLayerImplDispatch.h",
"system/SystemLayerImplDispatch.mm",
]

if (chip_system_config_use_sockets) {
sources += [ "system/SystemLayerImplDispatchSockets.mm" ]
}

if (chip_enable_wifi) {
sources += [
"WiFi/ConfigurationManagerImplWiFi.cpp",
Expand Down
2 changes: 1 addition & 1 deletion src/platform/Darwin/PlatformManagerImpl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@

#if CHIP_SYSTEM_CONFIG_USE_DISPATCH
// Ensure there is a dispatch queue available
static_cast<System::LayerSocketsLoop &>(DeviceLayer::SystemLayer()).SetDispatchQueue(GetWorkQueue());
static_cast<System::LayerDispatch &>(DeviceLayer::SystemLayer()).SetDispatchQueue(GetWorkQueue());
#endif

// Call _InitChipStack() on the generic implementation base class
Expand Down
134 changes: 134 additions & 0 deletions src/platform/Darwin/system/SystemLayerImplDispatch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
*
* Copyright (c) 2025 Project CHIP Authors
*
* 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 declares an implementation of System::Layer using dispatch.
*/

#pragma once

#include "system/SystemConfig.h"

#include <lib/support/ObjectLifeCycle.h>
#include <system/SystemLayer.h>
#include <system/SystemTimer.h>

namespace chip {
namespace System {

class LayerImplDispatch : public LayerDispatch
{
public:
LayerImplDispatch() = default;
~LayerImplDispatch() override { VerifyOrDie(mLayerState.Destroy()); }

// Layer overrides.
CHIP_ERROR Init() override;
void Shutdown() override;
bool IsInitialized() const override { return mLayerState.IsInitialized(); }
CHIP_ERROR StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override;
CHIP_ERROR ExtendTimerTo(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override;
bool IsTimerActive(TimerCompleteCallback onComplete, void * appState) override;
Clock::Timeout GetRemainingTime(TimerCompleteCallback onComplete, void * appState) override;
void CancelTimer(TimerCompleteCallback onComplete, void * appState) override;
CHIP_ERROR ScheduleWork(TimerCompleteCallback onComplete, void * appState) override;

// LayerDispatch overrides.
void SetDispatchQueue(dispatch_queue_t dispatchQueue) override { mDispatchQueue = dispatchQueue; };
dispatch_queue_t GetDispatchQueue() override { return mDispatchQueue; };
void HandleDispatchQueueEvents(Clock::Timeout timeout) override;
CHIP_ERROR ScheduleWorkWithBlock(dispatch_block_t block) override;

#if CHIP_SYSTEM_CONFIG_USE_SOCKETS
// LayerSocket overrides.
CHIP_ERROR StartWatchingSocket(int fd, SocketWatchToken * tokenOut) override;
CHIP_ERROR SetCallback(SocketWatchToken token, SocketWatchCallback callback, intptr_t data) override;
CHIP_ERROR RequestCallbackOnPendingRead(SocketWatchToken token) override;
CHIP_ERROR RequestCallbackOnPendingWrite(SocketWatchToken token) override;
CHIP_ERROR ClearCallbackOnPendingRead(SocketWatchToken token) override;
CHIP_ERROR ClearCallbackOnPendingWrite(SocketWatchToken token) override;
CHIP_ERROR StopWatchingSocket(SocketWatchToken * tokenInOut) override;
SocketWatchToken InvalidSocketWatchToken() override { return reinterpret_cast<SocketWatchToken>(nullptr); }
#endif

protected:
#if CHIP_SYSTEM_CONFIG_USE_SOCKETS
struct SelectSets
{
fd_set mReadSet;
fd_set mWriteSet;
fd_set mErrorSet;
};

struct SocketWatch
{
int mFD;
SocketEvents mPendingIO;
SocketWatchCallback mCallback;
intptr_t mCallbackData;

dispatch_source_t mRdSource = nullptr;
dispatch_source_t mWrSource = nullptr;

bool IsActive() const { return mFD != kInvalidFd; }
void PrepareEvents(SelectSets & sets, int & maxFd) const;
void HandleEvents(const SelectSets & sets) const;
void Clear();
};

class SocketWatchPool
{
public:
CHIP_ERROR Allocate(int fd, SocketWatch *& outWatch);
CHIP_ERROR Release(SocketWatch * watch);
void Clear();

bool PrepareEvents(SelectSets & sets, timeval timeout) const;
void HandleEvents(const SelectSets & sets) const;

private:
static constexpr int kSocketWatchMax = (INET_CONFIG_ENABLE_TCP_ENDPOINT ? INET_CONFIG_NUM_TCP_ENDPOINTS : 0) +
(INET_CONFIG_ENABLE_UDP_ENDPOINT ? INET_CONFIG_NUM_UDP_ENDPOINTS : 0);
SocketWatch mPool[kSocketWatchMax];
};

SocketWatchPool mSocketWatchPool;
void HandleSocketsAndTimerEvents(Clock::Timeout timeout);
CHIP_ERROR RequestCallback(SocketWatchToken token, SocketEventFlags flag);
CHIP_ERROR ClearCallback(SocketWatchToken token, SocketEventFlags flag);
#endif

TimerPool<TimerList::Node> mTimerPool;
TimerList mTimerList;
// List of expired timers being processed right now. Stored in a member so
// we can cancel them.
TimerList mExpiredTimers;
void EnableTimer(const char * source, TimerList::Node *);
void DisableTimer(const char * source, TimerList::Node *);
CHIP_ERROR StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState, bool shouldCancel);
void HandleTimerEvents(Clock::Timeout timeout);

ObjectLifeCycle mLayerState;

dispatch_queue_t mDispatchQueue = nullptr;
};

using LayerImpl = LayerImplDispatch;

} // namespace System
} // namespace chip
Loading
Loading