Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions internal/mux/mux.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package mux

import (
"fmt"
"net"
"sync"

"github.com/pions/webrtc/pkg/logging"
)

var muxLog = logging.NewScopedLogger("mux")

// Mux allows multiplexing
type Mux struct {
lock sync.RWMutex
Expand Down Expand Up @@ -100,7 +103,7 @@ func (m *Mux) dispatch(buf []byte) {
m.lock.Unlock()

if endpoint == nil {
fmt.Printf("Warning: mux: no endpoint for packet starting with %d\n", buf[0])
muxLog.Warnf("Warning: mux: no endpoint for packet starting with %d\n", buf[0])
Copy link
Member Author

Choose a reason for hiding this comment

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

Just moving everything off of fmt.

return
}

Expand Down
10 changes: 4 additions & 6 deletions peerconnection.go
Original file line number Diff line number Diff line change
Expand Up @@ -1334,8 +1334,8 @@ func (pc *PeerConnection) Close() error {
// Conn if one of the endpoints is closed down. To
// continue the chain the Mux has to be closed.

for _, t := range pc.rtpTransceivers {
if err := t.Stop(); err != nil {
if pc.iceTransport != nil {
if err := pc.iceTransport.Stop(); err != nil {
closeErrs = append(closeErrs, err)
}
}
Expand All @@ -1350,10 +1350,8 @@ func (pc *PeerConnection) Close() error {
}
}

// TODO: Close DTLS?

if pc.iceTransport != nil {
if err := pc.iceTransport.Stop(); err != nil {
for _, t := range pc.rtpTransceivers {
if err := t.Stop(); err != nil {
closeErrs = append(closeErrs, err)
}
}
Expand Down
6 changes: 2 additions & 4 deletions peerconnection_media_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,8 @@ func TestPeerConnection_Media_Sender_Transports_OnSelectedCandidatePairChange(t

pcAnswer.OnICEConnectionStateChange(func(iceState ICEConnectionState) {
if iceState == ICEConnectionStateConnected {
go func() {
time.Sleep(3 * time.Second) // TODO PeerConnection.Close() doesn't block for all subsystems
close(iceComplete)
}()
time.Sleep(3 * time.Second) // TODO PeerConnection.Close() doesn't block for all subsystems
Copy link
Member Author

Choose a reason for hiding this comment

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

This is fired in a goroutine already, I don't want users to see this and assume they need the same.

close(iceComplete)
}
})

Expand Down
49 changes: 49 additions & 0 deletions peerconnection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (
"testing"
"time"

"github.com/pions/transport/test"
"github.com/pions/webrtc/internal/ice"
"github.com/pions/webrtc/internal/mux"

"github.com/pions/webrtc/pkg/rtcerr"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -478,3 +480,50 @@ func TestPeerConnection_EventHandlers(t *testing.T) {
<-onDataChannelCalled,
}))
}

// This test asserts that nothing deadlocks we try to shutdown when DTLS is in flight
// We ensure that DTLS is in flight by removing the mux func for it, so all inbound DTLS is lost
func TestPeerConnection_ShutdownNoDTLS(t *testing.T) {
dtlsMatchFunc := mux.MatchDTLS
defer func() {
mux.MatchDTLS = dtlsMatchFunc
}()

// Drop all incoming DTLS traffic
mux.MatchDTLS = func([]byte) bool {
return false
}

lim := test.TimeOut(time.Second * 10)
defer lim.Stop()

api := NewAPI()
offerPC, answerPC, err := api.newPair()
if err != nil {
t.Fatal(err)
}

if err = signalPair(offerPC, answerPC); err != nil {
t.Fatal(err)
}

iceComplete := make(chan interface{})
answerPC.OnICEConnectionStateChange(func(iceState ICEConnectionState) {
if iceState == ICEConnectionStateConnected {
time.Sleep(time.Second) // Give time for DTLS to start

select {
case <-iceComplete:
default:
close(iceComplete)
}
}
})

<-iceComplete
if err = offerPC.Close(); err != nil {
t.Fatal(err)
} else if err = answerPC.Close(); err != nil {
t.Fatal(err)
}
}