diff --git a/go.mod b/go.mod index cf982eec5..4f07c6bca 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/gorilla/websocket v1.4.2 github.com/hashicorp/go-version v1.6.0 github.com/hashicorp/golang-lru v0.5.4 - github.com/livekit/protocol v0.13.5-0.20220801175011-ae34dc3ec45d + github.com/livekit/protocol v0.13.5-0.20220805160532-dc99a5ad3ce2 github.com/livekit/rtcscore-go v0.0.0-20220524203225-dfd1ba40744a github.com/mackerelio/go-osstat v0.2.1 github.com/magefile/mage v1.13.0 diff --git a/go.sum b/go.sum index d9051edc1..810debff7 100644 --- a/go.sum +++ b/go.sum @@ -237,14 +237,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8= github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts= -github.com/livekit/protocol v0.13.5-0.20220726184153-ad9c55ddef52 h1:E0trQ3RLu2b9hjSiJG1+1hyK/8v57NPJznA7/lKj0qY= -github.com/livekit/protocol v0.13.5-0.20220726184153-ad9c55ddef52/go.mod h1:Qd/Dn4BkJfZQy/IjtEeUOGXARrR7l09WDkg5SY8thkw= -github.com/livekit/protocol v0.13.5-0.20220727215941-ac26418a52e9 h1:e12j1EyiiTG56Ag44fwpVtnYQ6MVgLv4bYYI0nTgxZY= -github.com/livekit/protocol v0.13.5-0.20220727215941-ac26418a52e9/go.mod h1:Qd/Dn4BkJfZQy/IjtEeUOGXARrR7l09WDkg5SY8thkw= -github.com/livekit/protocol v0.13.5-0.20220801175011-ae34dc3ec45d h1:9VHZG4Tu723DA/jsg0APEmnk5blWRif9indB/nkdeFY= -github.com/livekit/protocol v0.13.5-0.20220801175011-ae34dc3ec45d/go.mod h1:vGQzKUaSYC92o5y7EbnhosgpoLWK9a3PneyYkGOGL0o= -github.com/livekit/protocol v0.13.5-0.20220728214908-67539ebcab2a h1:tRioM9WNDjxGryt03ROYa8zq17J0MqHftCLr8Ex4dM0= -github.com/livekit/protocol v0.13.5-0.20220728214908-67539ebcab2a/go.mod h1:vGQzKUaSYC92o5y7EbnhosgpoLWK9a3PneyYkGOGL0o= +github.com/livekit/protocol v0.13.5-0.20220805160532-dc99a5ad3ce2 h1:PFZfzLm1gNjX4Z3jOlKcSDMMSt1bIbqZ7av2399uoO0= +github.com/livekit/protocol v0.13.5-0.20220805160532-dc99a5ad3ce2/go.mod h1:vGQzKUaSYC92o5y7EbnhosgpoLWK9a3PneyYkGOGL0o= github.com/livekit/rtcscore-go v0.0.0-20220524203225-dfd1ba40744a h1:cENjhGfslLSDV07gt8ASy47Wd12Q0kBS7hsdunyQ62I= github.com/livekit/rtcscore-go v0.0.0-20220524203225-dfd1ba40744a/go.mod h1:116ych8UaEs9vfIE8n6iZCZ30iagUFTls0vRmC+Ix5U= github.com/mackerelio/go-osstat v0.2.1 h1:5AeAcBEutEErAOlDz6WCkEvm6AKYgHTUQrfwm5RbeQc= @@ -763,8 +757,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/pkg/rtc/participant_signal.go b/pkg/rtc/participant_signal.go index 971e52a14..670b96012 100644 --- a/pkg/rtc/participant_signal.go +++ b/pkg/rtc/participant_signal.go @@ -54,6 +54,9 @@ func (p *ParticipantImpl) SendJoinResponse( // indicates both server and client support subscriber as primary SubscriberPrimary: p.SubscriberAsPrimary(), ClientConfiguration: p.params.ClientConf, + // sane defaults for ping interval & timeout + PingInterval: 10, + PingTimeout: 20, }, }, }) diff --git a/pkg/service/rtcservice.go b/pkg/service/rtcservice.go index d1151f09a..f7f484dfa 100644 --- a/pkg/service/rtcservice.go +++ b/pkg/service/rtcservice.go @@ -256,6 +256,14 @@ func (s *RTCService) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } } + if _, ok := req.Message.(*livekit.SignalRequest_Ping); ok { + _ = sigConn.WriteResponse(&livekit.SignalResponse{ + Message: &livekit.SignalResponse_Pong{ + Pong: 1, + }, + }) + continue + } if err := reqSink.WriteMessage(req); err != nil { pLogger.Warnw("error writing to request sink", err, "connID", connId) diff --git a/test/client/client.go b/test/client/client.go index eebd76b10..086f90654 100644 --- a/test/client/client.go +++ b/test/client/client.go @@ -55,6 +55,7 @@ type RTCClient struct { lossyDCSub *webrtc.DataChannel publisherConnected atomic.Bool publisherNegotiated atomic.Bool + pongReceivedAt atomic.Int64 // tracks waiting to be acked, cid => trackInfo pendingPublishedTracks map[string]*livekit.TrackInfo @@ -347,6 +348,8 @@ func (c *RTCClient) Run() error { delete(c.trackSenders, sid) delete(c.localTracks, sid) c.lock.Unlock() + case *livekit.SignalResponse_Pong: + c.pongReceivedAt.Store(msg.Pong) } } } @@ -441,6 +444,18 @@ func (c *RTCClient) RefreshToken() string { return c.refreshToken } +func (c *RTCClient) PongReceivedAt() int64 { + return c.pongReceivedAt.Load() +} + +func (c *RTCClient) SendPing() error { + return c.SendRequest(&livekit.SignalRequest{ + Message: &livekit.SignalRequest_Ping{ + Ping: time.Now().UnixNano(), + }, + }) +} + func (c *RTCClient) SendRequest(msg *livekit.SignalRequest) error { payload, err := proto.Marshal(msg) if err != nil { diff --git a/test/singlenode_test.go b/test/singlenode_test.go index b0a8e9fb4..5af6602e0 100644 --- a/test/singlenode_test.go +++ b/test/singlenode_test.go @@ -328,6 +328,23 @@ func TestSingleNodeCORS(t *testing.T) { require.Equal(t, "testhost.com", res.Header.Get("Access-Control-Allow-Origin")) } +func TestPingPong(t *testing.T) { + if testing.Short() { + t.SkipNow() + return + } + _, finish := setupSingleNodeTest("TestPingPong") + defer finish() + + c1 := createRTCClient("c1", defaultServerPort, nil) + waitUntilConnected(t, c1) + + require.NoError(t, c1.SendPing()) + require.Eventually(t, func() bool { + return c1.PongReceivedAt() > 0 + }, time.Second, 10*time.Millisecond) +} + func TestSingleNodeJoinAfterClose(t *testing.T) { if testing.Short() { t.SkipNow()