-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
feat: delete rejected transceiver #3007
base: master
Are you sure you want to change the base?
Conversation
1932439
to
0ea417e
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #3007 +/- ##
==========================================
+ Coverage 77.96% 79.66% +1.70%
==========================================
Files 89 78 -11
Lines 10578 9728 -850
==========================================
- Hits 8247 7750 -497
+ Misses 1840 1533 -307
+ Partials 491 445 -46
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Thank you so much @o-u-p Would you be able to write a test for this? If you could have a static answer and then just show that disabling works. |
Correct me if I'm wrong, but shouldn't this be handled in setLocalDescription rather than in createAnswer? |
@joeturki you are right! Actual changes/committing sound only happen in |
ee016ad
to
4e29ef2
Compare
you're right, I have update the code and add example page. the unit test may not be easy, since the signal state will be have-remote-offer->SetRemote(offer)->have-remote-offer |
4e29ef2
to
b0bca58
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about the side effects of automatically deleting transceivers like this, Also I'm not sure if this follows the spec on this, It would help us to have few tests for this behavior:
If any RtpTransceiver has been added, and there exists an m= section with a zero port in the current local description or the current remote description, that m= section MUST be recycled by generating an m= section for the added RtpTransceiver as if the m= section were being added to the session description (including a new MID value), and placing it at the same index as the m= section with a zero port.
If an RtpTransceiver is stopped and is not associated with an m= section, an m= section MUST NOT be generated for it. This prevents adding back RtpTransceivers whose m= sections were recycled and used for a new RtpTransceiver in a previous offer/ answer exchange, as described above.
If an RtpTransceiver has been stopped and is associated with an m= section, and the m= section is not being recycled as described above, an m= section MUST be generated for it with the port set to zero and all "a=msid" lines removed.
https://rtcweb-wg.github.io/jsep/#sec.subsequent-offers
Thank you for your work, let me know if you need help writing tests :)
(Sorry for the long review)
@@ -0,0 +1,18 @@ | |||
# delete-transceiver |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we can add an example for this, At least in this PR!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I add the example to clarify the usage, please let me know if you have any concern
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if adding a standalone example for a spec behavior change is appropriate. Also, "delete transceivers" means something different from handling of "rejected transceivers." Perhaps just adding a few unit tests would be sufficient?
That said, I'm open to hearing other opinions on this, and maybe wait for others!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I try to add unit test, I cannot set multiple times of remote or local description in the unit test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wdym, like renegotiation? there are few unit tests you can base of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, maybe hard to write
@@ -1007,14 +1006,18 @@ func (pc *PeerConnection) SetLocalDescription(desc SessionDescription) error { | |||
weAnswer := desc.Type == SDPTypeAnswer | |||
remoteDesc := pc.RemoteDescription() | |||
if weAnswer && remoteDesc != nil { | |||
_ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, false) | |||
rejected := []string{} | |||
_ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, false, &rejected) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do this without using a pointer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I add pointer here to make the logic concise. 1. the first offer/answer doesn't need this, so when renegotiate the rejected
would not be nil; 2. I want to get the rejected mid value but keep original func return just error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry but this style isn't idiomatic, and it makes the code harder to maintain in the future, also I'm not sure why don't just delete rejected transceivers is there a reason why you extract the mids first?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it may be more efficient
@@ -1184,14 +1187,18 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { | |||
|
|||
if isRenegotiation { | |||
if weOffer { | |||
_ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, true) | |||
rejected := []string{} | |||
_ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, true, &rejected) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do this without using a pointer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
@@ -1214,7 +1221,7 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { | |||
// Start the networking in a new routine since it will block until | |||
// the connection is actually established. | |||
if weOffer { | |||
_ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, true) | |||
_ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, true, nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same above
peerconnection.go
Outdated
needDelete := false | ||
for _, mid := range mids { | ||
if transceiver.Mid() == mid { | ||
transceiver.Stop() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should log this error!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
// removeRTPTransceiver remove inactive | ||
// and fires onNegotiationNeeded; | ||
// caller of this method should hold `pc.mu` lock | ||
func (pc *PeerConnection) removeRTPTransceiver(mids []string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we handle the recycling in single loop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can use a map to make the time complexity to o(n)
n++ | ||
} | ||
} | ||
pc.rtpTransceivers = pc.rtpTransceivers[:n] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we delete a transceiver from the middle of the slice? Can you add a unit test for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
peerconnection.go
Outdated
} | ||
} | ||
pc.rtpTransceivers = pc.rtpTransceivers[:n] | ||
pc.onNegotiationNeeded() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the spec for calling onNegotiationNeeded() here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
transceiver modify or restart ice, etc need to call onNegotiationNeeded, but this func is not export outside, I will remove it for unnecessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't trigger onNegotiationNeeded() from setLocalDescription.
If an RtpTransceiver has been stopped and is associated with an m= section, and the m= section is not being recycled as described above, an m= section MUST be generated for it with the port set to zero and all "a=msid" lines removed.
|
||
// reject transceiver if it is inactive | ||
if rejected != nil && media.MediaName.Port.Value == 0 && direction == RTPTransceiverDirectionInactive { | ||
*rejected = append(*rejected, midValue) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do this without using a pointer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see above
b0bca58
to
bd02493
Compare
see SdpOfferAnswerHandler::RemoveStoppedTransceivers in c++ RTC_DCHECK_RUN_ON(signaling_thread()); |
I'm talking about side effects from deleting transceivers this way in Pion, we should make sure that.
I believe the snippet you referenced is from libwebrtc, and I'm confident libwebrtc implements behavior. |
bd02493
to
ea155fa
Compare
|
when port = 0 and direction = inactive indicates that the media stream is not wanted, so we need delete transceiver, sync the logic with c++ implement
https://www.ietf.org/rfc/rfc3264.txt#:~:text=A%20port%20number%20of%20zero,rejected%20stream%20(Section%206).