blob: e854db7092e9ebb7a7eaae69fae51e822b104e41 [file] [log] [blame]
/**
*
* Copyright (c) 2020-2022 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.
*/
#import "CastingServerBridge.h"
#import "CastingServer.h"
#import "DiscoveredNodeDataConverter.hpp"
#import "OnboardingPayload.h"
#include <credentials/DeviceAttestationCredsProvider.h>
#include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h>
#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>
#include <lib/support/CHIPMem.h>
#include <platform/PlatformManager.h>
#include <platform/TestOnlyCommissionableDataProvider.h>
@interface CastingServerBridge ()
// queue used to serialize all work performed by the CastingServerBridge
@property (atomic, readonly) dispatch_queue_t chipWorkQueue;
@end
@implementation CastingServerBridge
+ (CastingServerBridge * _Nullable)getSharedInstance
{
static CastingServerBridge * instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (instancetype)init
{
if (self = [super init]) {
CHIP_ERROR err = chip::Platform::MemoryInit();
if (err != CHIP_NO_ERROR) {
ChipLogError(AppServer, "MemoryInit failed: %s", ErrorStr(err));
return nil;
}
err = chip::DeviceLayer::PlatformMgr().InitChipStack();
if (err != CHIP_NO_ERROR) {
ChipLogError(AppServer, "InitChipStack failed: %s", ErrorStr(err));
return nil;
}
chip::DeviceLayer::TestOnlyCommissionableDataProvider TestOnlyCommissionableDataProvider;
uint32_t defaultTestPasscode = 0;
VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupPasscode(defaultTestPasscode) == CHIP_NO_ERROR);
uint16_t defaultTestSetupDiscriminator = 0;
VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupDiscriminator(defaultTestSetupDiscriminator) == CHIP_NO_ERROR);
_onboardingPayload = [[OnboardingPayload alloc] initWithSetupPasscode:defaultTestPasscode
setupDiscriminator:defaultTestSetupDiscriminator];
// Initialize device attestation config
SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider());
// Initialize device attestation verifier from a constant version
{
// TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore();
SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore));
}
// init app Server
static chip::CommonCaseDeviceServerInitParams initParams;
err = initParams.InitializeStaticResourcesBeforeServerInit();
if (err != CHIP_NO_ERROR) {
ChipLogError(AppServer, "InitializeStaticResourcesBeforeServerInit failed: %s", ErrorStr(err));
return nil;
}
err = chip::Server::GetInstance().Init(initParams);
if (err != CHIP_NO_ERROR) {
ChipLogError(AppServer, "chip::Server init failed: %s", ErrorStr(err));
return nil;
}
_chipWorkQueue = chip::DeviceLayer::PlatformMgrImpl().GetWorkQueue();
chip::DeviceLayer::PlatformMgrImpl().StartEventLoopTask();
CastingServer::GetInstance()->Init();
}
return self;
}
- (void)discoverCommissioners:(dispatch_queue_t _Nonnull)clientQueue
discoveryRequestSentHandler:(nullable void (^)(bool))discoveryRequestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().discoverCommissioners() called");
dispatch_async(_chipWorkQueue, ^{
bool discoveryRequestStatus = true;
CHIP_ERROR err = CastingServer::GetInstance()->DiscoverCommissioners();
if (err != CHIP_NO_ERROR) {
ChipLogError(AppServer, "CastingServerBridge().discoverCommissioners() failed: %" CHIP_ERROR_FORMAT, err.Format());
discoveryRequestStatus = false;
}
dispatch_async(clientQueue, ^{
discoveryRequestSentHandler(discoveryRequestStatus);
});
});
}
- (void)getDiscoveredCommissioner:(int)index
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData * _Nullable))discoveredCommissionerHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().getDiscoveredCommissioner() called");
dispatch_async(_chipWorkQueue, ^{
DiscoveredNodeData * commissioner = nil;
const chip::Dnssd::DiscoveredNodeData * chipDiscoveredNodeData
= CastingServer::GetInstance()->GetDiscoveredCommissioner(index);
if (chipDiscoveredNodeData != nullptr) {
commissioner = [DiscoveredNodeDataConverter convertToObjC:chipDiscoveredNodeData];
}
dispatch_async(clientQueue, ^{
discoveredCommissionerHandler(commissioner);
});
});
}
- (void)sendUserDirectedCommissioningRequest:(NSString * _Nonnull)commissionerIpAddress
commissionerPort:(uint16_t)commissionerPort
platformInterface:(unsigned int)platformInterface
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
udcRequestSentHandler:(nullable void (^)(bool))udcRequestSentHandler
{
ChipLogProgress(AppServer,
"CastingServerBridge().sendUserDirectedCommissioningRequest() called with IP %s port %d platformInterface %d",
[commissionerIpAddress UTF8String], commissionerPort, platformInterface);
dispatch_async(_chipWorkQueue, ^{
bool udcRequestStatus;
chip::Inet::IPAddress commissionerAddrInet;
if (chip::Inet::IPAddress::FromString([commissionerIpAddress UTF8String], commissionerAddrInet) == false) {
ChipLogError(AppServer, "CastingServerBridge().sendUserDirectedCommissioningRequest() failed to parse IP address");
udcRequestStatus = false;
} else {
chip::Inet::InterfaceId interfaceId = chip::Inet::InterfaceId(platformInterface);
chip::Transport::PeerAddress commissionerPeerAddress
= chip::Transport::PeerAddress::UDP(commissionerAddrInet, commissionerPort, interfaceId);
CHIP_ERROR err = CastingServer::GetInstance()->SendUserDirectedCommissioningRequest(commissionerPeerAddress);
if (err != CHIP_NO_ERROR) {
ChipLogError(AppServer, "CastingServerBridge().sendUserDirectedCommissioningRequest() failed: %" CHIP_ERROR_FORMAT,
err.Format());
udcRequestStatus = false;
} else {
udcRequestStatus = true;
}
}
dispatch_async(clientQueue, ^{
udcRequestSentHandler(udcRequestStatus);
});
});
}
- (OnboardingPayload *)getOnboardingPaylod
{
return _onboardingPayload;
}
- (void)openBasicCommissioningWindow:(void (^_Nonnull)(bool))commissioningCompleteCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
commissioningWindowRequestedHandler:(void (^_Nonnull)(bool))commissioningWindowRequestedHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().openBasicCommissioningWindow() called");
_commissioningCompleteCallback = commissioningCompleteCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->OpenBasicCommissioningWindow(
[](CHIP_ERROR err) { [CastingServerBridge getSharedInstance].commissioningCompleteCallback(CHIP_NO_ERROR == err); });
dispatch_async(clientQueue, ^{
commissioningWindowRequestedHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)contentLauncher_launchUrl:(NSString * _Nonnull)contentUrl
contentDisplayStr:(NSString * _Nonnull)contentDisplayStr
responseCallback:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().contentLauncher_launchUrl() called");
_contentLauncher_launchUrlResponseCallback = responseCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->ContentLauncherLaunchURL(
[contentUrl UTF8String], [contentDisplayStr UTF8String], [](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].contentLauncher_launchUrlResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)levelControl_step:(uint8_t)stepMode
stepSize:(uint8_t)stepSize
transitionTime:(uint16_t)transitionTime
optionMask:(uint8_t)optionMask
optionOverride:(uint8_t)optionOverride
responseCallback:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().levelControl_step() called");
_levelControl_stepResponseCallback = responseCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err
= CastingServer::GetInstance()->LevelControl_Step(static_cast<chip::app::Clusters::LevelControl::StepMode>(stepMode),
stepSize, transitionTime, optionMask, optionOverride, [](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].levelControl_stepResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)levelControl_moveToLevel:(uint8_t)level
transitionTime:(uint16_t)transitionTime
optionMask:(uint8_t)optionMask
optionOverride:(uint8_t)optionOverride
responseCallback:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().levelControl_moveToLevel() called");
_levelControl_moveToLevelResponseCallback = responseCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->LevelControl_MoveToLevel(
level, transitionTime, optionMask, optionOverride, [](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].levelControl_moveToLevelResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)mediaPlayback_play:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_play() called");
_mediaPlayback_playResponseCallback = responseCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_Play([](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].mediaPlayback_playResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)mediaPlayback_pause:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_pause() called");
_mediaPlayback_pauseResponseCallback = responseCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_Pause([](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].mediaPlayback_pauseResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)mediaPlayback_stopPlayback:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_stopPlayback() called");
_mediaPlayback_pauseResponseCallback = responseCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_Pause([](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].mediaPlayback_stopPlaybackResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)mediaPlayback_next:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_next() called");
_mediaPlayback_nextResponseCallback = responseCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_Next([](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].mediaPlayback_nextResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)mediaPlayback_seek:(uint8_t)position
responseCallback:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_seek() called");
_mediaPlayback_seekResponseCallback = responseCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_Seek(position, [](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].mediaPlayback_seekResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)mediaPlayback_skipForward:(uint64_t)deltaPositionMilliseconds
responseCallback:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_skipForward() called");
_mediaPlayback_skipForwardResponseCallback = responseCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_SkipForward(deltaPositionMilliseconds, [](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].mediaPlayback_skipForwardResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)mediaPlayback_skipBackward:(uint64_t)deltaPositionMilliseconds
responseCallback:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_skipBackward() called");
_mediaPlayback_skipBackwardResponseCallback = responseCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_SkipBackward(deltaPositionMilliseconds, [](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].mediaPlayback_skipBackwardResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)applicationLauncher_launchApp:(uint16_t)catalogVendorId
applicationId:(NSString * _Nonnull)applicationId
data:(NSData * _Nullable)data
responseCallback:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().applicationLauncher_launchApp() called");
_applicationLauncher_launchAppResponseCallback = responseCallback;
chip::app::Clusters::ApplicationLauncher::Structs::Application::Type application;
application.catalogVendorId = catalogVendorId;
application.applicationId = chip::CharSpan::fromCharString([applicationId UTF8String]);
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->ApplicationLauncher_LaunchApp(application,
chip::MakeOptional(chip::ByteSpan(static_cast<const uint8_t *>(data.bytes), data.length)), [](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].applicationLauncher_launchAppResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)applicationLauncher_stopApp:(uint16_t)catalogVendorId
applicationId:(NSString * _Nonnull)applicationId
responseCallback:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().applicationLauncher_stopApp() called");
_applicationLauncher_stopAppResponseCallback = responseCallback;
chip::app::Clusters::ApplicationLauncher::Structs::Application::Type application;
application.catalogVendorId = catalogVendorId;
application.applicationId = chip::CharSpan::fromCharString([applicationId UTF8String]);
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->ApplicationLauncher_StopApp(application, [](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].applicationLauncher_stopAppResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)applicationLauncher_hideApp:(uint16_t)catalogVendorId
applicationId:(NSString * _Nonnull)applicationId
responseCallback:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().applicationLauncher_hideApp() called");
_applicationLauncher_hideAppResponseCallback = responseCallback;
chip::app::Clusters::ApplicationLauncher::Structs::Application::Type application;
application.catalogVendorId = catalogVendorId;
application.applicationId = chip::CharSpan::fromCharString([applicationId UTF8String]);
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->ApplicationLauncher_HideApp(application, [](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].applicationLauncher_hideAppResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)targetNavigator_navigateTarget:(uint8_t)target
data:(NSString * _Nullable)data
responseCallback:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().targetNavigator_navigateTarget() called");
_targetNavigator_navigateTargetResponseCallback = responseCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->TargetNavigator_NavigateTarget(
target, chip::MakeOptional(chip::CharSpan::fromCharString([data UTF8String])), [](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].targetNavigator_navigateTargetResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
- (void)keypadInput_sendKey:(uint8_t)keyCode
responseCallback:(void (^_Nonnull)(bool))responseCallback
clientQueue:(dispatch_queue_t _Nonnull)clientQueue
requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().keypadInput_sendKey() called");
_keypadInput_sendKeyResponseCallback = responseCallback;
dispatch_async(_chipWorkQueue, ^{
CHIP_ERROR err = CastingServer::GetInstance()->KeypadInput_SendKey(
static_cast<chip::app::Clusters::KeypadInput::CecKeyCode>(keyCode), [](CHIP_ERROR err) {
[CastingServerBridge getSharedInstance].keypadInput_sendKeyResponseCallback(CHIP_NO_ERROR == err);
});
dispatch_async(clientQueue, ^{
requestSentHandler(CHIP_NO_ERROR == err);
});
});
}
@end