Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix IceServer crash when client uses ICE renomination #1182

Merged
merged 9 commits into from
Oct 23, 2023
Merged

Conversation

ibc
Copy link
Member

@ibc ibc commented Oct 18, 2023

Fixes #1176

Details

Fixes #1176

### Details

- Problem was in this PR 756 that added support for ICE nomination.
- Before that PR, we always assumed that if there is a tuple then we are in 'connected' or 'completed' state, so there is a selected ICE tuple.
- That's no longer true when client uses ICE nomination stuff.
@ibc ibc added this to the v3 updates milestone Oct 18, 2023
@ibc ibc requested a review from jmillan October 18, 2023 17:46
@ibc
Copy link
Member Author

ibc commented Oct 18, 2023

@penguinol could you please take a look to this?

@ibc ibc mentioned this pull request Oct 18, 2023
@ibc ibc changed the title Fix IceServer crash when client uses ICE nomination Fix IceServer crash when client uses ICE renomination Oct 18, 2023
@penguinol
Copy link
Contributor

Maybe we do not need to remove MS_ASSERT in IceState::NEW and IceState::DISCONNECTED, just reset this->remoteNomination = 0 when state change to IceState::DISCONNECTED is enough.

@ibc
Copy link
Member Author

ibc commented Oct 19, 2023

Maybe we do not need to remove MS_ASSERT in IceState::NEW and IceState::DISCONNECTED, just reset this->remoteNomination = 0 when state change to IceState::DISCONNECTED is enough.

I don't think so. In the original code, when HandleTuple() is called, we first assert that tuple is empty and later we check nomination, but the assertion already happened and there were tuples so it aborted the process.

The thing here is that, before introducing renomination stuff, IceServer logic assumed that if there is any tuple then state was connected or completed and there was a selectedTuple. This is no longer true. With renomination it can happen that the first time we call to HandleTuple() the tuple is added to the list of tuples but selectedTuple remains unset and state remains new (or disconnected).

So I have a question. Scenario:

  • State is new with no tuples.
  • HandleTuple() is called for first time with a candidate with nomination 0.
  • In that case the tuple is added to the tuple list but it doesn't become selectedTuple and state remains NEW.

Is this correct? Or should state change to connected and the tuple become the selectedTuple?

Copy link
Member

@jmillan jmillan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good 👍

worker/include/RTC/IceServer.hpp Outdated Show resolved Hide resolved
worker/src/RTC/WebRtcTransport.cpp Outdated Show resolved Hide resolved
worker/src/RTC/WebRtcTransport.cpp Outdated Show resolved Hide resolved
@penguinol
Copy link
Contributor

Maybe we do not need to remove MS_ASSERT in IceState::NEW and IceState::DISCONNECTED, just reset this->remoteNomination = 0 when state change to IceState::DISCONNECTED is enough.

I don't think so. In the original code, when HandleTuple() is called, we first assert that tuple is empty and later we check nomination, but the assertion already happened and there were tuples so it aborted the process.

The thing here is that, before introducing renomination stuff, IceServer logic assumed that if there is any tuple then state was connected or completed and there was a selectedTuple. This is no longer true. With renomination it can happen that the first time we call to HandleTuple() the tuple is added to the list of tuples but selectedTuple remains unset and state remains new (or disconnected).

So I have a question. Scenario:

  • State is new with no tuples.
  • HandleTuple() is called for first time with a candidate with nomination 0.
  • In that case the tuple is added to the tuple list but it doesn't become selectedTuple and state remains NEW.

Is this correct? Or should state change to connected and the tuple become the selectedTuple?

According to https://webrtc.googlesource.com/src/+/refs/heads/main/p2p/base/connection.cc#1037
Nomination will not be 0

@ibc
Copy link
Member Author

ibc commented Oct 19, 2023

According to https://webrtc.googlesource.com/src/+/refs/heads/main/p2p/base/connection.cc#1037
Nomination will not be 0

Yes, but we cannot crash if client sends a STUN binding request with nomination 0.

@ibc
Copy link
Member Author

ibc commented Oct 19, 2023

@jmillan commented in #756 (review) about those conditions in HandleTuple(). My response here:

Those conditions are basically like this:

case IceState::NEW:
{
	if (!hasUseCandidate && !hasNomination)
	{
		// Store the tuple.
		auto* storedTuple = AddTuple(tuple);

		// Mark it as selected tuple.
		SetSelectedTuple(storedTuple);

		// Update state.
		this->state = IceState::CONNECTED;

		// Notify the listener.
		this->listener->OnIceServerConnected(this);
	}
	else
	{
		// Store the tuple.
		auto* storedTuple = AddTuple(tuple);

		if ((hasNomination && nomination > this->remoteNomination) || !hasNomination)
		{

			// Mark it as selected tuple.
			SetSelectedTuple(storedTuple);

			// Update state.
			this->state = IceState::COMPLETED;

			// Update nomination.
			if (hasNomination && nomination > this->remoteNomination)
			{
				this->remoteNomination = nomination;
			}

			// Notify the listener.
			this->listener->OnIceServerCompleted(this);
		}
	}

	break;
}

@jmillan said:

The condition previous to this else block assures that here hasUseCandidate is true and hasNominamtion is also true, so checking that again here is not needed, and makes it harder to read. I had to go to the previous block to make sure this conditions were repeated.

But that's not true:

  • The fist condition is if (!hasUseCandidate && !hasNomination).
  • So if we are in the else block it means that hasUseCandidate OR hasNomination is true (or both).

@jmillan
Copy link
Member

jmillan commented Oct 19, 2023

The fist condition is if (!hasUseCandidate && !hasNomination).
So if we are in the else blockit means thathasUseCandidateORhasNomination` is true (or both).

Totally true 👍

@ibc ibc merged commit b66673c into v3 Oct 23, 2023
33 checks passed
@ibc ibc deleted the fix-ice-server-crash branch October 23, 2023 07:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Worker Crash SIGABRT
3 participants