Make new path for signalling v1.5 support. (#4180)

* Make new path for signalling v1.5 support.

To be able to support newer clients to interact with older servers, move
signalling v1.5 to new path (`/rtc1`). On the new path, `join_request`
is required and single peer connection is used.

With the existing path `/rtc`, single peer connection is still supported
if `join_request` is used.

Newer clients connecting to old server should follow
1. Try new path WebSocket
2. If that fails, try new path validate at `/rtc1/validate`.
3. If the above gets a 404 which will happen with older server, revert
   back to old path and signalling 1.0.

Open to suggestions on path name.

* test on both paths

* change path from /rtc1 -> /rtc/v1

* test all rtc service path combinations
This commit is contained in:
Raja Subramanian authored and GitHub committed 2025-12-20 01:02:22 +05:30
1 parent 32cd0370c7
commit cd99fec2e7
10 files changed
+249 -160

No files matched your search

+27 -27
View File
@@ -44,11 +44,11 @@ func TestMultiNodeRouting(t *testing.T) {
})
require.NoError(t, err)
for _, useSinglePeerConnection := range []bool{false, true} {
t.Run(fmt.Sprintf("singlePeerConnection=%+v", useSinglePeerConnection), func(t *testing.T) {
for _, testRTCServicePath := range testRTCServicePaths {
t.Run(fmt.Sprintf("testRTCServicePath=%s", testRTCServicePath.String()), func(t *testing.T) {
// one node connecting to node 1, and another connecting to node 2
c1 := createRTCClient("c1", defaultServerPort, useSinglePeerConnection, nil)
c2 := createRTCClient("c2", secondServerPort, useSinglePeerConnection, nil)
c1 := createRTCClient("c1", defaultServerPort, testRTCServicePath, nil)
c2 := createRTCClient("c2", secondServerPort, testRTCServicePath, nil)
waitUntilConnected(t, c1, c2)
defer stopClients(c1, c2)
@@ -88,9 +88,9 @@ func TestConnectWithoutCreation(t *testing.T) {
_, _, finish := setupMultiNodeTest("TestConnectWithoutCreation")
defer finish()
for _, useSinglePeerConnection := range []bool{false, true} {
t.Run(fmt.Sprintf("singlePeerConnection=%+v", useSinglePeerConnection), func(t *testing.T) {
c1 := createRTCClient("c1", defaultServerPort, useSinglePeerConnection, nil)
for _, testRTCServicePath := range testRTCServicePaths {
t.Run(fmt.Sprintf("testRTCServicePath=%s", testRTCServicePath.String()), func(t *testing.T) {
c1 := createRTCClient("c1", defaultServerPort, testRTCServicePath, nil)
waitUntilConnected(t, c1)
c1.Stop()
@@ -127,8 +127,8 @@ func TestMultinodeReconnectAfterNodeShutdown(t *testing.T) {
return
}
for _, useSinglePeerConnection := range []bool{false, true} {
t.Run(fmt.Sprintf("singlePeerConnection=%+v", useSinglePeerConnection), func(t *testing.T) {
for _, testRTCServicePath := range testRTCServicePaths {
t.Run(fmt.Sprintf("testRTCServicePath=%s", testRTCServicePath.String()), func(t *testing.T) {
_, s2, finish := setupMultiNodeTest("TestMultinodeReconnectAfterNodeShutdown")
defer finish()
@@ -140,8 +140,8 @@ func TestMultinodeReconnectAfterNodeShutdown(t *testing.T) {
require.NoError(t, err)
// one node connecting to node 1, and another connecting to node 2
c1 := createRTCClient("c1", defaultServerPort, useSinglePeerConnection, nil)
c2 := createRTCClient("c2", secondServerPort, useSinglePeerConnection, nil)
c1 := createRTCClient("c1", defaultServerPort, testRTCServicePath, nil)
c2 := createRTCClient("c2", secondServerPort, testRTCServicePath, nil)
waitUntilConnected(t, c1, c2)
stopClients(c1, c2)
@@ -151,7 +151,7 @@ func TestMultinodeReconnectAfterNodeShutdown(t *testing.T) {
time.Sleep(syncDelay)
c3 := createRTCClient("c3", defaultServerPort, useSinglePeerConnection, nil)
c3 := createRTCClient("c3", defaultServerPort, testRTCServicePath, nil)
waitUntilConnected(t, c3)
})
}
@@ -200,10 +200,10 @@ func TestMultiNodeRefreshToken(t *testing.T) {
_, _, finish := setupMultiNodeTest("TestMultiNodeJoinAfterClose")
defer finish()
for _, useSinglePeerConnection := range []bool{false, true} {
t.Run(fmt.Sprintf("singlePeerConnection=%+v", useSinglePeerConnection), func(t *testing.T) {
for _, testRTCServicePath := range testRTCServicePaths {
t.Run(fmt.Sprintf("testRTCServicePath=%s", testRTCServicePath.String()), func(t *testing.T) {
// a participant joining with full permissions
c1 := createRTCClient("c1", defaultServerPort, useSinglePeerConnection, nil)
c1 := createRTCClient("c1", defaultServerPort, testRTCServicePath, nil)
waitUntilConnected(t, c1)
// update permissions and metadata
@@ -258,16 +258,16 @@ func TestMultiNodeUpdateAttributes(t *testing.T) {
_, _, finish := setupMultiNodeTest("TestMultiNodeUpdateAttributes")
defer finish()
for _, useSinglePeerConnection := range []bool{false, true} {
t.Run(fmt.Sprintf("singlePeerConnection=%+v", useSinglePeerConnection), func(t *testing.T) {
c1 := createRTCClient("au1", defaultServerPort, useSinglePeerConnection, &client.Options{
for _, testRTCServicePath := range testRTCServicePaths {
t.Run(fmt.Sprintf("testRTCServicePath=%s", testRTCServicePath.String()), func(t *testing.T) {
c1 := createRTCClient("au1", defaultServerPort, testRTCServicePath, &client.Options{
TokenCustomizer: func(token *auth.AccessToken, grants *auth.VideoGrant) {
token.SetAttributes(map[string]string{
"mykey": "au1",
})
},
})
c2 := createRTCClient("au2", secondServerPort, useSinglePeerConnection, &client.Options{
c2 := createRTCClient("au2", secondServerPort, testRTCServicePath, &client.Options{
TokenCustomizer: func(token *auth.AccessToken, grants *auth.VideoGrant) {
token.SetAttributes(map[string]string{
"mykey": "au2",
@@ -331,10 +331,10 @@ func TestMultiNodeRevokePublishPermission(t *testing.T) {
_, _, finish := setupMultiNodeTest("TestMultiNodeRevokePublishPermission")
defer finish()
for _, useSinglePeerConnection := range []bool{false, true} {
t.Run(fmt.Sprintf("singlePeerConnection=%+v", useSinglePeerConnection), func(t *testing.T) {
c1 := createRTCClient("c1", defaultServerPort, useSinglePeerConnection, nil)
c2 := createRTCClient("c2", secondServerPort, useSinglePeerConnection, nil)
for _, testRTCServicePath := range testRTCServicePaths {
t.Run(fmt.Sprintf("testRTCServicePath=%s", testRTCServicePath.String()), func(t *testing.T) {
c1 := createRTCClient("c1", defaultServerPort, testRTCServicePath, nil)
c2 := createRTCClient("c2", secondServerPort, testRTCServicePath, nil)
waitUntilConnected(t, c1, c2)
// c1 publishes a track for c2
@@ -383,12 +383,12 @@ func TestCloseDisconnectedParticipantOnSignalClose(t *testing.T) {
_, _, finish := setupMultiNodeTest("TestCloseDisconnectedParticipantOnSignalClose")
defer finish()
for _, useSinglePeerConnection := range []bool{false, true} {
t.Run(fmt.Sprintf("singlePeerConnection=%+v", useSinglePeerConnection), func(t *testing.T) {
c1 := createRTCClient("c1", secondServerPort, useSinglePeerConnection, nil)
for _, testRTCServicePath := range testRTCServicePaths {
t.Run(fmt.Sprintf("testRTCServicePath=%s", testRTCServicePath.String()), func(t *testing.T) {
c1 := createRTCClient("c1", secondServerPort, testRTCServicePath, nil)
waitUntilConnected(t, c1)
c2 := createRTCClient("c2", defaultServerPort, useSinglePeerConnection, &client.Options{
c2 := createRTCClient("c2", defaultServerPort, testRTCServicePath, &client.Options{
SignalRequestInterceptor: func(msg *livekit.SignalRequest, next client.SignalRequestHandler) error {
switch msg.Message.(type) {
case *livekit.SignalRequest_Offer, *livekit.SignalRequest_Answer, *livekit.SignalRequest_Leave: