| /* |
| * |
| * 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. |
| */ |
| |
| #include "WebRTC.h" |
| #include <WebRTCClient.h> |
| |
| #include <memory> |
| #include <thread> |
| #include <unistd.h> |
| |
| #include <rtc/description.hpp> |
| #include <rtc/rtc.h> |
| #include <rtc/rtc.hpp> |
| |
| #include <lib/support/logging/CHIPLogging.h> |
| |
| namespace chip { |
| namespace webrtc { |
| |
| static std::mutex g_mutex; |
| static std::map<WebRTCClientHandle, std::shared_ptr<WebRTCClient>> g_clients; |
| static std::map<WebRTCClientHandle, std::unique_ptr<WebRTCTransportProviderClient>> g_provider_clients; |
| |
| WebRTCClientHandle webrtc_client_create() |
| { |
| auto client = std::make_shared<WebRTCClient>(); |
| WebRTCClientHandle handle = reinterpret_cast<WebRTCClientHandle>(client.get()); |
| std::lock_guard<std::mutex> lock(g_mutex); |
| g_clients[handle] = client; |
| return handle; |
| } |
| |
| void webrtc_client_destroy(WebRTCClientHandle handle) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| g_clients.erase(handle); |
| } |
| |
| PyChipError webrtc_client_create_peer_connection(WebRTCClientHandle handle, const char * stun_url) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_clients.find(handle); |
| if (it != g_clients.end()) |
| { |
| CHIP_ERROR err = it->second->CreatePeerConnection(stun_url); |
| return ToPyChipError(err); |
| } |
| |
| return ToPyChipError(CHIP_NO_ERROR); |
| } |
| |
| void webrtc_client_create_offer(WebRTCClientHandle handle) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_clients.find(handle); |
| if (it != g_clients.end()) |
| { |
| it->second->CreateOffer(); |
| } |
| } |
| |
| void webrtc_client_create_answer(WebRTCClientHandle handle) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_clients.find(handle); |
| if (it != g_clients.end()) |
| { |
| it->second->CreateAnswer(); |
| } |
| } |
| |
| void webrtc_client_set_remote_description(WebRTCClientHandle handle, const char * sdp, const char * type) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_clients.find(handle); |
| if (it != g_clients.end()) |
| { |
| it->second->SetRemoteDescription(sdp, type); |
| } |
| } |
| |
| void webrtc_client_add_ice_candidate(WebRTCClientHandle handle, const char * candidate, const char * mid) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_clients.find(handle); |
| if (it != g_clients.end()) |
| { |
| it->second->AddIceCandidate(candidate, mid); |
| } |
| } |
| |
| void webrtc_client_set_local_description_callback(WebRTCClientHandle handle, LocalDescriptionCallback cb, void * user_data) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_clients.find(handle); |
| if (it != g_clients.end()) |
| { |
| it->second->OnLocalDescription( |
| [cb, user_data](const std::string & sdp, const std::string & type) { cb(sdp.c_str(), type.c_str(), user_data); }); |
| } |
| } |
| |
| void webrtc_client_set_ice_candidate_callback(WebRTCClientHandle handle, IceCandidateCallback cb, void * user_data) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_clients.find(handle); |
| if (it != g_clients.end()) |
| { |
| it->second->OnIceCandidate([cb, user_data](const std::string & candidate, const std::string & mid) { |
| cb(candidate.c_str(), mid.c_str(), user_data); |
| }); |
| } |
| } |
| |
| const char * webrtc_get_local_description(WebRTCClientHandle handle) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_clients.find(handle); |
| if (it != g_clients.end()) |
| { |
| return it->second->GetLocalSessionDescriptionInternal(); |
| } |
| return ""; |
| } |
| |
| const char * webrtc_get_peer_connection_state(WebRTCClientHandle handle) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_clients.find(handle); |
| if (it != g_clients.end()) |
| { |
| return it->second->GetPeerConnectionState(); |
| } |
| return "Invalid"; |
| } |
| |
| void webrtc_client_set_gathering_complete_callback(WebRTCClientHandle handle, GatheringCompleteCallback cb) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_clients.find(handle); |
| if (it != g_clients.end()) |
| { |
| it->second->OnGatheringComplete(cb); |
| } |
| } |
| |
| void webrtc_client_set_state_change_callback(WebRTCClientHandle handle, OnStateChangeCallback cb) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_clients.find(handle); |
| if (it != g_clients.end()) |
| { |
| it->second->OnStateChange(cb); |
| } |
| } |
| |
| WebRTCClientHandle webrtc_provider_client_create() |
| { |
| auto client = std::make_unique<WebRTCTransportProviderClient>(); |
| WebRTCClientHandle handle = reinterpret_cast<WebRTCClientHandle>(client.get()); |
| std::lock_guard<std::mutex> lock(g_mutex); |
| g_provider_clients[handle] = std::move(client); |
| return handle; |
| } |
| |
| void webrtc_provider_client_destroy(WebRTCClientHandle handle) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| g_provider_clients.erase(handle); |
| } |
| |
| void webrtc_provider_client_init(WebRTCClientHandle handle, uint64_t nodeId, uint8_t fabricIndex, uint16_t endpoint) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_provider_clients.find(handle); |
| if (it != g_provider_clients.end()) |
| { |
| it->second->Init(nodeId, fabricIndex, endpoint); |
| } |
| } |
| |
| void webrtc_provider_client_init_commandsender_callbacks(WebRTCClientHandle handle, |
| OnCommandSenderResponseCallback onCommandSenderResponseCallback, |
| OnCommandSenderErrorCallback onCommandSenderErrorCallback, |
| OnCommandSenderDoneCallback onCommandSenderDoneCallback) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_provider_clients.find(handle); |
| if (it != g_provider_clients.end()) |
| { |
| it->second->InitCallbacks(onCommandSenderResponseCallback, onCommandSenderErrorCallback, onCommandSenderDoneCallback); |
| } |
| } |
| |
| PyChipError webrtc_provider_client_send_command(WebRTCClientHandle handle, void * appContext, uint16_t endpointId, |
| uint32_t clusterId, uint32_t commandId, const uint8_t * payload, size_t length) |
| { |
| std::lock_guard<std::mutex> lock(g_mutex); |
| auto it = g_provider_clients.find(handle); |
| if (it != g_provider_clients.end()) |
| { |
| return it->second->SendCommand(appContext, endpointId, clusterId, commandId, payload, length); |
| } |
| return ToPyChipError(CHIP_ERROR_INTERNAL); |
| } |
| |
| } // namespace webrtc |
| } // namespace chip |