package api //nolint:revive import ( "fmt" "net/http" "testing" "time" "github.com/bluenviron/mediamtx/internal/conf" "github.com/bluenviron/mediamtx/internal/defs" "github.com/bluenviron/mediamtx/internal/servers/webrtc" "github.com/bluenviron/mediamtx/internal/test" "github.com/google/uuid" "github.com/stretchr/testify/require" ) type testWebRTCServer struct { sessions map[uuid.UUID]*defs.APIWebRTCSession } func (s *testWebRTCServer) APISessionsList() (*defs.APIWebRTCSessionList, error) { items := make([]*defs.APIWebRTCSession, 0, len(s.sessions)) for _, session := range s.sessions { items = append(items, session) } return &defs.APIWebRTCSessionList{Items: items}, nil } func (s *testWebRTCServer) APISessionsGet(id uuid.UUID) (*defs.APIWebRTCSession, error) { session, ok := s.sessions[id] if !ok { return nil, webrtc.ErrSessionNotFound } return session, nil } func (s *testWebRTCServer) APISessionsKick(id uuid.UUID) error { _, ok := s.sessions[id] if !ok { return webrtc.ErrSessionNotFound } return nil } func TestWebRTCSessionsList(t *testing.T) { id1 := uuid.New() id2 := uuid.New() now := time.Now() webrtcServer := &testWebRTCServer{ sessions: map[uuid.UUID]*defs.APIWebRTCSession{ id1: { ID: id1, Created: now, RemoteAddr: "192.168.1.1:5000", PeerConnectionEstablished: true, LocalCandidate: "192.168.1.100:8000", RemoteCandidate: "192.168.1.1:5000", State: defs.APIWebRTCSessionStatePublish, Path: "stream1", Query: "token=abc", BytesReceived: 1000, BytesSent: 2000, RTPPacketsReceived: 100, RTPPacketsSent: 200, RTPPacketsLost: 5, RTPPacketsJitter: 0.5, RTCPPacketsReceived: 10, RTCPPacketsSent: 15, }, id2: { ID: id2, Created: now.Add(time.Minute), RemoteAddr: "192.168.1.2:5001", PeerConnectionEstablished: true, LocalCandidate: "192.168.1.100:8001", RemoteCandidate: "192.168.1.2:5001", State: defs.APIWebRTCSessionStateRead, Path: "stream2", Query: "", BytesReceived: 500, BytesSent: 1500, RTPPacketsReceived: 50, RTPPacketsSent: 150, RTPPacketsLost: 0, RTPPacketsJitter: 0.1, RTCPPacketsReceived: 5, RTCPPacketsSent: 10, }, }, } api := API{ Address: "localhost:9997", ReadTimeout: conf.Duration(10 * time.Second), WriteTimeout: conf.Duration(10 * time.Second), AuthManager: test.NilAuthManager, WebRTCServer: webrtcServer, Parent: &testParent{}, } err := api.Initialize() require.NoError(t, err) defer api.Close() tr := &http.Transport{} defer tr.CloseIdleConnections() hc := &http.Client{Transport: tr} var out defs.APIWebRTCSessionList httpRequest(t, hc, http.MethodGet, "http://localhost:9997/v3/webrtcsessions/list", nil, &out) require.Equal(t, 2, out.ItemCount) require.Equal(t, 1, out.PageCount) require.Len(t, out.Items, 2) } func TestWebRTCSessionsGet(t *testing.T) { id := uuid.New() now := time.Now() webrtcServer := &testWebRTCServer{ sessions: map[uuid.UUID]*defs.APIWebRTCSession{ id: { ID: id, Created: now, RemoteAddr: "192.168.1.100:5000", PeerConnectionEstablished: true, LocalCandidate: "192.168.1.200:8000", RemoteCandidate: "192.168.1.100:5000", State: defs.APIWebRTCSessionStatePublish, Path: "mystream", Query: "key=value", BytesReceived: 999999, BytesSent: 888888, RTPPacketsReceived: 10000, RTPPacketsSent: 20000, RTPPacketsLost: 50, RTPPacketsJitter: 1.5, RTCPPacketsReceived: 100, RTCPPacketsSent: 200, }, }, } api := API{ Address: "localhost:9997", ReadTimeout: conf.Duration(10 * time.Second), WriteTimeout: conf.Duration(10 * time.Second), AuthManager: test.NilAuthManager, WebRTCServer: webrtcServer, Parent: &testParent{}, } err := api.Initialize() require.NoError(t, err) defer api.Close() tr := &http.Transport{} defer tr.CloseIdleConnections() hc := &http.Client{Transport: tr} var out defs.APIWebRTCSession httpRequest(t, hc, http.MethodGet, fmt.Sprintf("http://localhost:9997/v3/webrtcsessions/get/%s", id), nil, &out) require.Equal(t, id, out.ID) require.Equal(t, "192.168.1.100:5000", out.RemoteAddr) require.Equal(t, defs.APIWebRTCSessionStatePublish, out.State) require.Equal(t, "mystream", out.Path) require.True(t, out.PeerConnectionEstablished) require.Equal(t, "192.168.1.200:8000", out.LocalCandidate) require.Equal(t, "192.168.1.100:5000", out.RemoteCandidate) require.Equal(t, uint64(999999), out.BytesReceived) require.Equal(t, uint64(888888), out.BytesSent) require.Equal(t, uint64(10000), out.RTPPacketsReceived) require.Equal(t, uint64(20000), out.RTPPacketsSent) require.Equal(t, uint64(50), out.RTPPacketsLost) require.Equal(t, 1.5, out.RTPPacketsJitter) } func TestWebRTCSessionsKick(t *testing.T) { id := uuid.New() now := time.Now() webrtcServer := &testWebRTCServer{ sessions: map[uuid.UUID]*defs.APIWebRTCSession{ id: { ID: id, Created: now, RemoteAddr: "192.168.1.100:5000", PeerConnectionEstablished: true, LocalCandidate: "192.168.1.200:8000", RemoteCandidate: "192.168.1.100:5000", State: defs.APIWebRTCSessionStatePublish, Path: "mystream", Query: "", BytesReceived: 1000, BytesSent: 2000, RTPPacketsReceived: 100, RTPPacketsSent: 200, RTPPacketsLost: 0, RTPPacketsJitter: 0.5, RTCPPacketsReceived: 10, RTCPPacketsSent: 15, }, }, } api := API{ Address: "localhost:9997", ReadTimeout: conf.Duration(10 * time.Second), WriteTimeout: conf.Duration(10 * time.Second), AuthManager: test.NilAuthManager, WebRTCServer: webrtcServer, Parent: &testParent{}, } err := api.Initialize() require.NoError(t, err) defer api.Close() tr := &http.Transport{} defer tr.CloseIdleConnections() hc := &http.Client{Transport: tr} httpRequest(t, hc, http.MethodPost, fmt.Sprintf("http://localhost:9997/v3/webrtcsessions/kick/%s", id), nil, nil) }