PeerConnection used the public OnConnectionStateChange to track the
status of the ICETransport. This was incorrect because a user can
override this value at anytime.
Add a new internalOnConnectionStateChangeHandler that is set directly by
the PeerConnection and not accessible to the user.
When creating answer, check ICE role while determining DTLS role.
ORTC thread on how roles are set
https://github.com/w3c/ortc/issues/167#issuecomment-69409953
When remote is ice-lite and there is no answering role set,
the answer uses the default which is DTLS client. So 'setup'
is set as 'active' and answer sent.
But, when DTLS transport is started, it checks the ICE role
and sets itself as DTLS server (because remote is lite
and hence local agent becomes controlling ICE agent).
So, both sides end up being DTLS server and nobody sends
client hello.
If the SRTP Stream hasn't been opened yet we would attempt to process
(and fail) RTP traffic. This change causes us to not even attempt to
read.
No behavior change from this, but will cause less useless logging.
Do the set up of RTP receivers synchronously so that they
are ready to receive media as soon as signalling to remote
side is sent. Once signalling to remote side is sent, the
remote can send media at any time and receiver has to be ready.
Like the bug mentions, a negotiation quickly followed by
a renegotiation left the RTP receivers of the tracks in the
second offer not set up. If the tracks in the renegotiation
happen to be simulcast tracks, they are missed as browsers
send RID only in the first few packets.
The problem can be reproduced by introducing a 1 second
delay in Downstream direction in Network Link Conditioner
and using a modified version of LiveKit JS SDK sample app to
force a double negotiation spaced closely.
With this change, onTrack fires, but the unhandled warning
from RTCP for the highest layer still happens. But, the
track fires almost immediately following that warning
(less than 5 ms later). So, all the simulcast layers
are available.
Resolves#2054
in some case like session migration from one sfu node
to another, we need manual set mid of transceiver instead of
auto generate, to make mid consistent between to sfu node.
If SetRemoteDescription is called with offer SDP which
has a=invalid, PeerConnection sets its transceiver direction
as recvonly. Fix direction recvonly to invalid.
Resolves#2050
rfc8839#section-5.1 specifies that a WebRTC Agent MUST
ignore any name/value pairs it doesn't understand. When
we parse a candidate and it fails because we don't understand
the type we now log and continue.
Resolvespion/webrtc#1949
rfc8839#section-5.1 specifies that a WebRTC Agent MUST
ignore any name/value pairs it doesn't understand. When
we parse a candidate and it fails because we don't understand
the type we now log and continue.
Resolvespion/webrtc#1949
If a transceiver is created by remote sdp, then set
prefer codec same as offer peer.
For pion's codec match, it will use exact match
first, and then partial match. If patial match
only, the partial match codecs will become
negotiated codes. So it will be set prefer codec
when only exist partial match. And has same payload.
Add test cast for this.
refer to https://www.w3.org/TR/webrtc/#bib-rfc8829
A race existed with Negotiated DataChannels before this. Before
the remote could sends us a DataChannel message before the
datachannel was negotiated locally. We would then discard the
message and print an error.
This PR moves the processing of remote datachannel messages after
we have registered all local ones. It also informs
datachannel.Accept of existing datachannels in order to prevent
any initialization logic from proceeding incorrectly.
When filtering SSRCes we were running the filter operation on the source
slice and not the filtered slice. Causing us to ignore all the filter
operations that had been previously run.
Problem:
--------
In the following negotiation sequence, the Simulcast track is lost.
1. Remote Offer with Simulcast tracks with rids
2. A new track added to Remote Offer with tracks using SSRCs
When the updated `offer` is received, the Simulcast transceiver's
receiver gets overwritten because the tracks from SDP is compared
against current transceivers. The current transceiver for the
Simulcast track already had SSRCs set as media has been received.
But, tracks read from the SDP only has `rid`. So, no current
transceiver matches and hence a new receiver is created which
clobeers the good Simulcast receiver.
Fix:
----
- Prioritize search by `rid`.
- Also found a case of a loop where the index was missing entries
in the loop. Fix it.
Testing:
--------
- The above case works
This reverts commit 6c3620093d.
This commit would cause sender.ReadRTCP() to never return
even when pc associated with this sender was closed.
The aftermath is leaked goroutines that will never stop.
Interceptors are being accidentally misused by users.
The issue is that an Interceptor can be re-used between
multiple PeerConnections. Interceptors were designed to only be
single PeerConnection aware, so state is being corrupted.
Instead we are now going to provide InterceptorFactories. The default
API of pion/webrtc will now be safe to use between PeerConnections.
Resolves webrtc#1956
Read + Discard packets from the Simulcast repair stream. When a
Simulcast stream is enabled the remote will send packets via the repair
stream for probing. We can't ignore these packets anymore because it
will cause gaps in the feedback reports
Resolves#1957
Add an accessor to make getting value easy. Also add
TestPeerConnection_SkipStoppedTransceiver. This commit also cleans
up RTPTransceiver creation. We used a helper function, when we should
have just used the provide constructor
Before we wouldn't start the undeclaredMediaProcessor until SCTP had
finished. If SCTP never finishes an inbound RTP packet with an unknown
SSRC would cause all RTP processing to hang.
If we have a media section with no SSRC we would fire an OnTrack. This
code now properly ignores a MediaSection that has a rid attribute.
Resolves#1808
This gives an option to raise the receive MTU as SettingEngine option.
If SettingEngine has not been set the MTU, then default value is used
instead, 1460
Resolves#1925
It isn't possible to send media if a MediaEngine has no codecs. This
catches a common misconfiguration issues that users find themselves in.
Resolves#1702
Previously we could have situations where during
first condition like `transceiver.Sender() != nil`
there would be another condition like
`transceiver.Sender().isNegotiated()` where
`.Sender()` could become nil if changed in
a different goroutine.
In some rare cases during ice connection stage
change may result in deadlock. This fix makes
iceConnectionState and connectionState atomic
which should prevent deadlock.
now proctected by lock:
- CreateOffer
- CreateAnswer
- AddTransceiverFromKind
- AddTransceiverFromTrack
newRTPTransceiver is no longer a PeerConnection method;
pc.addRTPTransceiver would fire onNegotiationNeeded;
pc.AddTrack, pc.RemoveTrack now hold lock for the entire function;
Fixes TestNegotiationNeededStressOneSided() by waiting til all
tracks added to pcA and the negotiation completed
CurrentRemoteDescription and PendingRemoteDescription both access
members of the PeerConnection that should be protected by a lock.
Co-authored-by: Markus Tzoe <chou.marcus@gmail.com>
in CurrentLocalDescription() or PendingLocalDescription():
when gathering local candidates in populateLocalCandidates(),
agent would try submitting a task via run():
a.chanTask <- task
the chanTask is consumed by a bg routine using taskLoop():
for {
select {
case <-a.done:
return
case t := <-a.chanTask:
t.fn(a.context(), a)
close(t.done)
after()
}
}
while there're other routines using the agent, e.g. calling
`agent.updateConnectionState()`
a.afterRun(func(ctx context.Context) {
a.chanState <- newState
})
and the submitted task would be run by the `after()` func in
`taskLoop()`, where the `a.chanState` is handled by
`agent.startOnConnectionStateChangeRoutine()`
this `after()` task may block the bg routine when there's ongoing
event handler `agent.onConnectionStateChange()`, which would
eventually call PeerConnection's onICEConnectionStateChange():
pc.mu.Lock()
pc.iceConnectionState = cs
handler := pc.onICEConnectionStateChangeHandler
pc.mu.Unlock()
which would try to hold the PeerConnection lock, causing deadlock
Use fine granularity rw-mutex to protect rtpTransceivers and for
exclusively accessing AddTrack and RemoveTrack
Fixes `shouldAddCandidates` typo in sdp.go
Which were previously unable to:
1. have a sending track set to them, or
2. receive a track after renegotiation.
I'm not 100% sure if this covers all cases where a track is added and
removed and then added again. BUT IIRC there was a change that did not
allow transceiver reuse after a track was removed from it. Again, not
100% sure.
Fixes#1722.
When a local peer connection has a single transceiver with a sendrecv
direction, and the remote has a transceiver with a recvonly direction,
the local peer connection must change the transceiver direction to
sendonly.
When a local peer connection has a single transceiver with a recvonly
direction, and the remote has a transceiver with a recvonly direction,
the local peer connection must create another transceiver with a
sendonly direction.
A unit test is added to cover all possible cases.
If an API is shared between PeerConnections they would use the same
MediaEngine. A MediaEngine contains negotiated PayloadTypes so if the
PeerConnections were answering you would end up in invalid states.
Add DisableMediaEngineCopy to SettingEngine in case user needs old
behavior.
Resolves#1662