Bladeren bron

Added ICE state to PeerConnection

Paul-Louis Ageneau 1 jaar geleden
bovenliggende
commit
ca1dade1b6
6 gewijzigde bestanden met toevoegingen van 113 en 1 verwijderingen
  1. 13 0
      include/rtc/peerconnection.hpp
  2. 12 0
      include/rtc/rtc.h
  3. 14 0
      src/capi.cpp
  4. 30 1
      src/impl/peerconnection.cpp
  5. 4 0
      src/impl/peerconnection.hpp
  6. 40 0
      src/peerconnection.cpp

+ 13 - 0
include/rtc/peerconnection.hpp

@@ -46,6 +46,16 @@ public:
 		Closed = RTC_CLOSED
 	};
 
+	enum class IceState : int {
+		New = RTC_ICE_NEW,
+		Checking = RTC_ICE_CHECKING,
+		Connected = RTC_ICE_CONNECTED,
+		Completed = RTC_ICE_COMPLETED,
+		Failed = RTC_ICE_FAILED,
+		Disconnected = RTC_ICE_DISCONNECTED,
+		Closed = RTC_ICE_CLOSED
+	};
+
 	enum class GatheringState : int {
 		New = RTC_GATHERING_NEW,
 		InProgress = RTC_GATHERING_INPROGRESS,
@@ -68,6 +78,7 @@ public:
 
 	const Configuration *config() const;
 	State state() const;
+	IceState iceState() const;
 	GatheringState gatheringState() const;
 	SignalingState signalingState() const;
 	bool hasMedia() const;
@@ -94,6 +105,7 @@ public:
 	void onLocalDescription(std::function<void(Description description)> callback);
 	void onLocalCandidate(std::function<void(Candidate candidate)> callback);
 	void onStateChange(std::function<void(State state)> callback);
+	void onIceStateChange(std::function<void(IceState state)> callback);
 	void onGatheringStateChange(std::function<void(GatheringState state)> callback);
 	void onSignalingStateChange(std::function<void(SignalingState state)> callback);
 
@@ -109,6 +121,7 @@ public:
 } // namespace rtc
 
 RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, rtc::PeerConnection::State state);
+RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, rtc::PeerConnection::IceState state);
 RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out,
                                         rtc::PeerConnection::GatheringState state);
 RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out,

+ 12 - 0
include/rtc/rtc.h

@@ -67,6 +67,16 @@ typedef enum {
 	RTC_CLOSED = 5
 } rtcState;
 
+typedef enum {
+	RTC_ICE_NEW = 0,
+	RTC_ICE_CHECKING = 1,
+	RTC_ICE_CONNECTED = 2,
+	RTC_ICE_COMPLETED = 3,
+	RTC_ICE_FAILED = 4,
+	RTC_ICE_DISCONNECTED = 5,
+	RTC_ICE_CLOSED = 6
+} rtcIceState;
+
 typedef enum {
 	RTC_GATHERING_NEW = 0,
 	RTC_GATHERING_INPROGRESS = 1,
@@ -131,6 +141,7 @@ typedef void(RTC_API *rtcDescriptionCallbackFunc)(int pc, const char *sdp, const
 typedef void(RTC_API *rtcCandidateCallbackFunc)(int pc, const char *cand, const char *mid,
                                                 void *ptr);
 typedef void(RTC_API *rtcStateChangeCallbackFunc)(int pc, rtcState state, void *ptr);
+typedef void(RTC_API *rtcIceStateChangeCallbackFunc)(int pc, rtcIceState state, void *ptr);
 typedef void(RTC_API *rtcGatheringStateCallbackFunc)(int pc, rtcGatheringState state, void *ptr);
 typedef void(RTC_API *rtcSignalingStateCallbackFunc)(int pc, rtcSignalingState state, void *ptr);
 typedef void(RTC_API *rtcDataChannelCallbackFunc)(int pc, int dc, void *ptr);
@@ -179,6 +190,7 @@ RTC_C_EXPORT int rtcDeletePeerConnection(int pc);
 RTC_C_EXPORT int rtcSetLocalDescriptionCallback(int pc, rtcDescriptionCallbackFunc cb);
 RTC_C_EXPORT int rtcSetLocalCandidateCallback(int pc, rtcCandidateCallbackFunc cb);
 RTC_C_EXPORT int rtcSetStateChangeCallback(int pc, rtcStateChangeCallbackFunc cb);
+RTC_C_EXPORT int rtcSetIceStateChangeCallback(int pc, rtcIceStateChangeCallbackFunc cb);
 RTC_C_EXPORT int rtcSetGatheringStateChangeCallback(int pc, rtcGatheringStateCallbackFunc cb);
 RTC_C_EXPORT int rtcSetSignalingStateChangeCallback(int pc, rtcSignalingStateCallbackFunc cb);
 

+ 14 - 0
src/capi.cpp

@@ -494,6 +494,20 @@ int rtcSetStateChangeCallback(int pc, rtcStateChangeCallbackFunc cb) {
 	});
 }
 
+int rtcSetIceStateChangeCallback(int pc, rtcIceStateChangeCallbackFunc cb) {
+	return wrap([&] {
+		auto peerConnection = getPeerConnection(pc);
+		if (cb)
+			peerConnection->onIceStateChange([pc, cb](PeerConnection::IceState state) {
+				if (auto ptr = getUserPointer(pc))
+					cb(pc, static_cast<rtcIceState>(state), *ptr);
+			});
+		else
+			peerConnection->onIceStateChange(nullptr);
+		return RTC_ERR_SUCCESS;
+	});
+}
+
 int rtcSetGatheringStateChangeCallback(int pc, rtcGatheringStateCallbackFunc cb) {
 	return wrap([&] {
 		auto peerConnection = getPeerConnection(pc);

+ 30 - 1
src/impl/peerconnection.cpp

@@ -152,16 +152,23 @@ shared_ptr<IceTransport> PeerConnection::initIceTransport() {
 				    return;
 			    switch (transportState) {
 			    case IceTransport::State::Connecting:
+				    changeIceState(IceState::Checking);
 				    changeState(State::Connecting);
 				    break;
 			    case IceTransport::State::Connected:
+				    changeIceState(IceState::Connected);
 				    initDtlsTransport();
 				    break;
+			    case IceTransport::State::Completed:
+				    changeIceState(IceState::Completed);
+				    break;
 			    case IceTransport::State::Failed:
+				    changeIceState(IceState::Failed);
 				    changeState(State::Failed);
 				    mProcessor.enqueue(&PeerConnection::remoteClose, shared_from_this());
 				    break;
 			    case IceTransport::State::Disconnected:
+				    changeIceState(IceState::Disconnected);
 				    changeState(State::Disconnected);
 				    mProcessor.enqueue(&PeerConnection::remoteClose, shared_from_this());
 				    break;
@@ -345,11 +352,14 @@ shared_ptr<SctpTransport> PeerConnection::getSctpTransport() const {
 void PeerConnection::closeTransports() {
 	PLOG_VERBOSE << "Closing transports";
 
+	// Change ICE state to sink state Closed
+	changeIceState(IceState::Closed);
+
 	// Change state to sink state Closed
 	if (!changeState(State::Closed))
 		return; // already closed
 
-	// Reset intercceptor and callbacks now that state is changed
+	// Reset interceptor and callbacks now that state is changed
 	setMediaHandler(nullptr);
 	resetCallbacks();
 
@@ -1175,6 +1185,24 @@ bool PeerConnection::changeState(State newState) {
 	return true;
 }
 
+bool PeerConnection::changeIceState(IceState newState) {
+	if (iceState.exchange(newState) == newState)
+		return false;
+
+	std::ostringstream s;
+	s << newState;
+	PLOG_INFO << "Changed ICE state to " << s.str();
+
+	if (newState == IceState::Closed) {
+		auto callback = std::move(iceStateChangeCallback); // steal the callback
+		callback(IceState::Closed);                        // call it synchronously
+	} else {
+		mProcessor.enqueue(&PeerConnection::trigger<IceState>, shared_from_this(),
+		                   &iceStateChangeCallback, newState);
+	}
+	return true;
+}
+
 bool PeerConnection::changeGatheringState(GatheringState newState) {
 	if (gatheringState.exchange(newState) == newState)
 		return false;
@@ -1207,6 +1235,7 @@ void PeerConnection::resetCallbacks() {
 	localDescriptionCallback = nullptr;
 	localCandidateCallback = nullptr;
 	stateChangeCallback = nullptr;
+	iceStateChangeCallback = nullptr;
 	gatheringStateChangeCallback = nullptr;
 	signalingStateChangeCallback = nullptr;
 	trackCallback = nullptr;

+ 4 - 0
src/impl/peerconnection.hpp

@@ -29,6 +29,7 @@ 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;
 
@@ -92,6 +93,7 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {
 	void flushPendingTracks();
 
 	bool changeState(State newState);
+	bool changeIceState(IceState newState);
 	bool changeGatheringState(GatheringState newState);
 	bool changeSignalingState(SignalingState newState);
 
@@ -108,6 +110,7 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {
 
 	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> negotiationNeeded = false;
@@ -118,6 +121,7 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {
 	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;

+ 40 - 0
src/peerconnection.cpp

@@ -51,6 +51,10 @@ const Configuration *PeerConnection::config() const { return &impl()->config; }
 
 PeerConnection::State PeerConnection::state() const { return impl()->state; }
 
+PeerConnection::IceState PeerConnection::iceState() const {
+	return impl()->iceState;
+}
+
 PeerConnection::GatheringState PeerConnection::gatheringState() const {
 	return impl()->gatheringState;
 }
@@ -311,6 +315,10 @@ void PeerConnection::onStateChange(std::function<void(State state)> callback) {
 	impl()->stateChangeCallback = callback;
 }
 
+void PeerConnection::onIceStateChange(std::function<void(IceState state)> callback) {
+	impl()->iceStateChangeCallback = callback;
+}
+
 void PeerConnection::onGatheringStateChange(std::function<void(GatheringState state)> callback) {
 	impl()->gatheringStateChangeCallback = callback;
 }
@@ -377,6 +385,38 @@ std::ostream &operator<<(std::ostream &out, rtc::PeerConnection::State state) {
 	return out << str;
 }
 
+std::ostream &operator<<(std::ostream &out, rtc::PeerConnection::IceState state) {
+	using IceState = rtc::PeerConnection::IceState;
+	const char *str;
+	switch (state) {
+	case IceState::New:
+		str = "new";
+		break;
+	case IceState::Checking:
+		str = "checking";
+		break;
+	case IceState::Connected:
+		str = "connected";
+		break;
+	case IceState::Completed:
+		str = "completed";
+		break;
+	case IceState::Failed:
+		str = "failed";
+		break;
+	case IceState::Disconnected:
+		str = "disconnected";
+		break;
+	case IceState::Closed:
+		str = "closed";
+		break;
+	default:
+		str = "unknown";
+		break;
+	}
+	return out << str;
+}
+
 std::ostream &operator<<(std::ostream &out, rtc::PeerConnection::GatheringState state) {
 	using GatheringState = rtc::PeerConnection::GatheringState;
 	const char *str;