#ifndef RTC_IMPL_PEER_CONNECTION_H
#define RTC_IMPL_PEER_CONNECTION_H
#include "common.hpp"
#include "datachannel.hpp"
#include "dtlstransport.hpp"
#include "icetransport.hpp"
#include "init.hpp"
#include "processor.hpp"
#include "sctptransport.hpp"
#include "track.hpp"
#include "rtc/peerconnection.hpp"
#include <mutex>
#include <shared_mutex>
#include <unordered_map>
#include <vector>
namespace rtc::impl {
struct PeerConnection : std::enable_shared_from_this<PeerConnection> {
using State = rtc::PeerConnection::State;
using IceState = rtc::PeerConnection::IceState;
using GatheringState = rtc::PeerConnection::GatheringState;
using SignalingState = rtc::PeerConnection::SignalingState;
PeerConnection(Configuration config_);
~PeerConnection();
void close();
void remoteClose();
optional<Description> localDescription() const;
optional<Description> remoteDescription() const;
size_t remoteMaxMessageSize() const;
shared_ptr<IceTransport> initIceTransport();
shared_ptr<DtlsTransport> initDtlsTransport();
shared_ptr<SctpTransport> initSctpTransport();
shared_ptr<IceTransport> getIceTransport() const;
shared_ptr<DtlsTransport> getDtlsTransport() const;
shared_ptr<SctpTransport> getSctpTransport() const;
void closeTransports();
void endLocalCandidates();
void rollbackLocalDescription();
bool checkFingerprint(const std::string &fingerprint);
void forwardMessage(message_ptr message);
void forwardMedia(message_ptr message);
void forwardBufferedAmount(uint16_t stream, size_t amount);
shared_ptr<DataChannel> emplaceDataChannel(string label, DataChannelInit init);
std::pair<shared_ptr<DataChannel>, bool> findDataChannel(uint16_t stream);
bool removeDataChannel(uint16_t stream);
uint16_t maxDataChannelStream() const;
void assignDataChannels();
void iterateDataChannels(std::function<void(shared_ptr<DataChannel> channel)> func);
void openDataChannels();
void closeDataChannels();
void remoteCloseDataChannels();
shared_ptr<Track> emplaceTrack(Description::Media description);
void iterateTracks(std::function<void(shared_ptr<Track> track)> func);
void iterateRemoteTracks(std::function<void(shared_ptr<Track> track)> func);
void openTracks();
void closeTracks();
void validateRemoteDescription(const Description &description);
void populateLocalDescription(Description &description) const;
void processLocalDescription(Description description);
void processLocalCandidate(Candidate candidate);
void processRemoteDescription(Description description);
void processRemoteCandidate(Candidate candidate);
string localBundleMid() const;
bool negotiationNeeded() const;
void setMediaHandler(shared_ptr<MediaHandler> handler);
shared_ptr<MediaHandler> getMediaHandler() const;
void triggerDataChannel(weak_ptr<DataChannel> weakDataChannel);
void triggerTrack(weak_ptr<Track> weakTrack);
void triggerPendingDataChannels();
void triggerPendingTracks();
void flushPendingDataChannels();
void flushPendingTracks();
bool changeState(State newState);
bool changeIceState(IceState newState);
bool changeGatheringState(GatheringState newState);
bool changeSignalingState(SignalingState newState);
void resetCallbacks();
CertificateFingerprint remoteFingerprint();
template <typename... Args> void trigger(synchronized_callback<Args...> *cb, Args... args) {
try {
(*cb)(std::move(args...));
} catch (const std::exception &e) {
PLOG_WARNING << "Uncaught exception in callback: " << e.what();
}
}
const Configuration config;
std::atomic<State> state = State::New;
std::atomic<IceState> iceState = IceState::New;
std::atomic<GatheringState> gatheringState = GatheringState::New;
std::atomic<SignalingState> signalingState = SignalingState::Stable;
std::atomic<bool> closing = false;
std::mutex signalingMutex;
synchronized_callback<shared_ptr<rtc::DataChannel>> dataChannelCallback;
synchronized_callback<Description> localDescriptionCallback;
synchronized_callback<Candidate> localCandidateCallback;
synchronized_callback<State> stateChangeCallback;
synchronized_callback<IceState> iceStateChangeCallback;
synchronized_callback<GatheringState> gatheringStateChangeCallback;
synchronized_callback<SignalingState> signalingStateChangeCallback;
synchronized_callback<shared_ptr<rtc::Track>> trackCallback;
private:
void dispatchMedia(message_ptr message);
void updateTrackSsrcCache(const Description &description);
const init_token mInitToken = Init::Instance().token();
future_certificate_ptr mCertificate;
Processor mProcessor;
optional<Description> mLocalDescription;
optional<Description> mCurrentLocalDescription;
mutable std::mutex mLocalDescriptionMutex;
optional<Description> mRemoteDescription;
CertificateFingerprint::Algorithm mRemoteFingerprintAlgorithm = CertificateFingerprint::Algorithm::Sha256;
optional<string> mRemoteFingerprint;
mutable std::mutex mRemoteDescriptionMutex;
shared_ptr<MediaHandler> mMediaHandler;
mutable std::shared_mutex mMediaHandlerMutex;
shared_ptr<IceTransport> mIceTransport;
shared_ptr<DtlsTransport> mDtlsTransport;
shared_ptr<SctpTransport> mSctpTransport;
std::unordered_map<uint16_t, weak_ptr<DataChannel>> mDataChannels; std::vector<weak_ptr<DataChannel>> mUnassignedDataChannels;
mutable std::shared_mutex mDataChannelsMutex;
std::unordered_map<string, weak_ptr<Track>> mTracks; std::unordered_map<uint32_t, weak_ptr<Track>> mTracksBySsrc; std::vector<weak_ptr<Track>> mTrackLines; mutable std::shared_mutex mTracksMutex;
Queue<shared_ptr<DataChannel>> mPendingDataChannels;
Queue<shared_ptr<Track>> mPendingTracks;
};
}
#endif