ZaStoGram/TMessagesProj/jni/voip/tgcalls/v2wasm/CallCoreHost.h
2026-09-24 16:17:30 +04:00

176 lines
7.8 KiB
C++

#ifndef TGCALLS_V2WASM_CALL_CORE_HOST_H
#define TGCALLS_V2WASM_CALL_CORE_HOST_H
#include <deque>
#include <map>
#include <memory>
#include <set>
#include "Instance.h"
#include "StaticThreads.h"
#include "third-party/json11.hpp"
#include "api/peer_connection_interface.h"
#include "rtc_base/network_monitor_factory.h"
#include "p2p/base/basic_packet_socket_factory.h"
#include "p2p/client/relay_port_factory_interface.h"
#include "v2wasm/CallCoreABI.h"
#include "v2wasm/CallCoreBackend.h"
namespace tgcalls {
class EncryptedConnection;
class SignalingConnection;
class VideoCaptureInterface;
namespace v2wasm_detail {
class PeerConnectionDelegateAdapter;
class DataChannelObserverImpl;
} // namespace v2wasm_detail
// Fixed harness for the pump boundary: owns PeerConnection, ADM, signaling
// crypto/transport, timers and stats; executes core commands and forwards
// platform callbacks to the core as events. Lives on the media thread.
class CallCoreHost final : public std::enable_shared_from_this<CallCoreHost> {
public:
CallCoreHost(Descriptor &&descriptor, std::shared_ptr<Threads> threads);
~CallCoreHost();
void start();
void receiveSignalingData(const std::vector<uint8_t> &data);
void setVideoCapture(std::shared_ptr<VideoCaptureInterface> videoCapture);
void setMuteMicrophone(bool mute);
void setIsLowBatteryLevel(bool low);
void setIncomingVideoOutput(std::weak_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink);
void setAudioInputDevice(std::string id);
void setAudioOutputDevice(std::string id);
void stop(std::function<void(FinalState)> completion);
private:
friend class v2wasm_detail::PeerConnectionDelegateAdapter;
void deliverEvent(json11::Json::object &&event);
void deliverEventNow(json11::Json::object &&event);
void processPendingCommands();
void executeCommand(json11::Json const &command);
void emitErrorEvent(std::string const &message, std::string const &commandType);
void disableCoreWithFailure(std::string const &reason);
void executePcCreate(json11::Json const &command);
void applyAudioProcessingConfig(json11::Json const &config, std::string const &commandName);
void executeSetConfiguration(json11::Json const &command);
void executeCreateDescription(bool isOffer);
void executeSetLocalDescription(json11::Json const &command);
void executeSetRemoteDescription(json11::Json const &command);
void executeAddIceCandidate(json11::Json const &command);
void executeAddTransceiver(json11::Json const &command);
void executeSetParameters(json11::Json const &command);
void executeSetTrackEnabled(json11::Json const &command);
void executeRemoveTrack(json11::Json const &command);
void executeSetIncomingSink(json11::Json const &command);
void executeCreateDataChannel(json11::Json const &command);
void executeSignalingSendPacket(json11::Json const &command);
void executeGetStats();
void executeClose();
void attachDataChannel(std::string const &label, webrtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel);
void onDataChannelStateUpdated(std::string const &label);
void onDataChannelBufferedAmountChanged(std::string const &label);
void executeDcSend(json11::Json const &command);
void onSignalingData(const std::vector<uint8_t> &data);
void connectIncomingVideoSink(webrtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver);
void disconnectIncomingVideoSink(webrtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver);
void disconnectAllIncomingVideoSinks();
webrtc::scoped_refptr<webrtc::AudioDeviceModule> createAudioDeviceModule();
std::shared_ptr<Threads> _threads;
// descriptor
std::string _version;
std::vector<RtcServer> _rtcServers;
bool _enableP2P = false;
EncryptionKey _encryptionKey;
std::string _customParameters;
std::map<std::string, json11::Json> _parsedCustomParameters;
std::function<void(State)> _stateUpdated;
std::function<void(int)> _signalBarsUpdated;
std::function<void(bool)> _remoteBatteryLevelIsLowUpdated;
std::function<void(AudioState, VideoState)> _remoteMediaStateUpdated;
std::function<void(const std::vector<uint8_t> &)> _signalingDataEmitted;
std::function<webrtc::scoped_refptr<webrtc::AudioDeviceModule>(webrtc::TaskQueueFactory *)> _createAudioDeviceModule;
std::function<webrtc::scoped_refptr<WrappedAudioDeviceModule>(webrtc::TaskQueueFactory *)> _createWrappedAudioDeviceModule;
FilePath _statsLogPath;
// core + pump
std::unique_ptr<CallCoreBackend> _core;
std::deque<json11::Json> _pendingCommands;
bool _isProcessingCommands = false;
bool _isDeliveringEvent = false;
bool _isCoreDisabled = false;
// signaling
std::unique_ptr<SignalingConnection> _signalingConnection;
std::unique_ptr<EncryptedConnection> _signalingEncryptedConnection;
// Signaling transport routing only — the framing (gzip, acks, resends,
// service packets) is core-owned since Phase 2.6.
bool _useSctpSignalingTransport = false;
// Host-enforced strict monotonicity of the core-chosen packet counter
// (low 30 bits of the seq) — preserves AEAD IV freshness.
uint32_t _lastSentSignalingCounter = 0;
// webrtc
std::unique_ptr<webrtc::TaskQueueFactory> _taskQueueFactory;
std::unique_ptr<rtc::NetworkMonitorFactory> _networkMonitorFactory;
std::unique_ptr<rtc::BasicPacketSocketFactory> _socketFactory;
std::unique_ptr<rtc::BasicNetworkManager> _networkManager;
std::unique_ptr<cricket::RelayPortFactoryInterface> _relayPortFactory;
webrtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> _peerConnectionFactory;
std::unique_ptr<webrtc::PeerConnectionObserver> _peerConnectionObserver;
webrtc::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection;
webrtc::scoped_refptr<webrtc::AudioDeviceModule> _audioDeviceModule;
webrtc::scoped_refptr<webrtc::AudioProcessing> _audioProcessing;
// Core-managed transceivers/tracks, keyed by the core-chosen id from
// pc_add_transceiver. Incoming (remote) transceivers stay keyed by mid in
// _incomingVideoTransceivers.
std::map<std::string, webrtc::scoped_refptr<webrtc::RtpTransceiverInterface>> _coreTransceivers;
std::map<std::string, webrtc::scoped_refptr<webrtc::MediaStreamTrackInterface>> _coreTracks;
// Incoming mids the core asked to bind the app video sink to.
std::set<std::string> _requestedSinkMids;
std::map<std::string, webrtc::scoped_refptr<webrtc::RtpTransceiverInterface>> _incomingVideoTransceivers;
std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> _currentStrongSink;
// Exactly the tracks we called AddOrUpdateSink on. RemoveSink DCHECKs when the
// sink was never added, and attachment is asymmetric (a transceiver added while
// no sink is set is never attached), so removal must be driven by this set, not
// by the transceiver map.
std::set<webrtc::VideoTrackInterface*> _attachedSinkTracks;
std::shared_ptr<VideoCaptureInterface> _videoCapture;
struct HostDataChannel {
webrtc::scoped_refptr<webrtc::DataChannelInterface> channel;
std::unique_ptr<v2wasm_detail::DataChannelObserverImpl> observer;
bool isOpen = false;
uint64_t lastBufferedAmount = 0;
};
std::map<std::string, HostDataChannel> _dataChannels;
// stop flow
std::function<void(FinalState)> _stopCompletion;
std::string _pendingStatsLogJson;
std::atomic<bool> _isStopped{false};
// stats delta state (media thread only): cumulative byte counters from
// the previous pc_get_stats, for host-computed bitrate deltas.
int64_t _lastStatsTimestampMs = 0;
uint64_t _lastAudioBytesSent = 0;
uint64_t _lastVideoBytesSent = 0;
uint64_t _lastAudioBytesReceived = 0;
uint64_t _lastVideoBytesReceived = 0;
};
} // namespace tgcalls
#endif