#ifndef MS_RTC_ICE_ICE_SERVER_HPP
#define MS_RTC_ICE_ICE_SERVER_HPP
#include "common.hpp"
#include "FBS/webRtcTransport.h"
#include "handles/TimerHandleInterface.hpp"
#include "RTC/ICE/StunPacket.hpp"
#include "RTC/TransportTuple.hpp"
#include "SharedInterface.hpp"
#include <ankerl/unordered_dense.h>
#include <list>
#include <string>
namespace RTC
{
namespace ICE
{
class IceServer : public TimerHandleInterface::Listener
{
public:
enum class IceState : uint8_t
{
NEW = 1,
CONNECTED,
COMPLETED,
DISCONNECTED,
};
public:
class Listener
{
public:
virtual ~Listener() = default;
public:
virtual void OnIceServerSendStunPacket(
const RTC::ICE::IceServer* iceServer,
const RTC::ICE::StunPacket* packet,
RTC::TransportTuple* tuple) = 0;
virtual void OnIceServerLocalUsernameFragmentAdded(
const RTC::ICE::IceServer* iceServer, const std::string& usernameFragment) = 0;
virtual void OnIceServerLocalUsernameFragmentRemoved(
const RTC::ICE::IceServer* iceServer, const std::string& usernameFragment) = 0;
virtual void OnIceServerTupleAdded(
const RTC::ICE::IceServer* iceServer, RTC::TransportTuple* tuple) = 0;
virtual void OnIceServerTupleRemoved(
const RTC::ICE::IceServer* iceServer, RTC::TransportTuple* tuple) = 0;
virtual void OnIceServerSelectedTuple(
const RTC::ICE::IceServer* iceServer, RTC::TransportTuple* tuple) = 0;
virtual void OnIceServerConnected(const RTC::ICE::IceServer* iceServer) = 0;
virtual void OnIceServerCompleted(const RTC::ICE::IceServer* iceServer) = 0;
virtual void OnIceServerDisconnected(const RTC::ICE::IceServer* iceServer) = 0;
};
public:
static const std::string& IceStateToString(IceState iceState);
static FBS::WebRtcTransport::IceState IceStateToFbs(IceState state);
private:
static ankerl::unordered_dense::map<IceState, std::string> iceStateToString;
public:
IceServer(
Listener* listener,
SharedInterface* shared,
const std::string& usernameFragment,
const std::string& password,
uint8_t consentTimeoutSec);
~IceServer() override;
public:
void Dump(int indentation = 0) const;
void ProcessStunPacket(const RTC::ICE::StunPacket* packet, RTC::TransportTuple* tuple);
const std::string& GetUsernameFragment() const
{
return this->usernameFragment;
}
const std::string& GetPassword() const
{
return this->password;
}
IceState GetState() const
{
return this->state;
}
RTC::TransportTuple* GetSelectedTuple() const
{
return this->selectedTuple;
}
void RestartIce(const std::string& usernameFragment, const std::string& password);
bool IsValidTuple(const RTC::TransportTuple* tuple) const;
void RemoveTuple(RTC::TransportTuple* tuple);
void MayForceSelectedTuple(const RTC::TransportTuple* tuple);
private:
void ProcessStunRequest(const RTC::ICE::StunPacket* request, RTC::TransportTuple* tuple);
void ProcessStunIndication(const RTC::ICE::StunPacket* indication);
void ProcessStunResponse(const RTC::ICE::StunPacket* response);
void HandleTuple(
RTC::TransportTuple* tuple, bool hasUseCandidate, bool hasNomination, uint32_t nomination);
RTC::TransportTuple* AddTuple(RTC::TransportTuple* tuple);
RTC::TransportTuple* HasTuple(const RTC::TransportTuple* tuple) const;
void SetSelectedTuple(RTC::TransportTuple* storedTuple);
bool IsConsentCheckSupported() const
{
return this->consentTimeoutMs != 0u;
}
bool IsConsentCheckRunning() const
{
return (this->consentCheckTimer && this->consentCheckTimer->IsActive());
}
void StartConsentCheck();
void RestartConsentCheck();
void StopConsentCheck();
public:
void OnTimer(TimerHandleInterface* timer) override;
private:
Listener* listener{ nullptr };
SharedInterface* shared{ nullptr };
std::string usernameFragment;
std::string password;
uint16_t consentTimeoutMs{ 30000u };
std::string oldUsernameFragment;
std::string oldPassword;
IceState state{ IceState::NEW };
uint32_t remoteNomination{ 0u };
std::list<RTC::TransportTuple> tuples;
RTC::TransportTuple* selectedTuple{ nullptr };
TimerHandleInterface* consentCheckTimer{ nullptr };
bool isRemovingTuples{ false };
};
} }
#endif