1
0
Fork 0
forked from External/mediamtx

Add option for ICE servers to be client only (#3164)

* Add option for ICE servers to be client only

* add clientOnly to configuration file and API docs

---------

Co-authored-by: aler9 <46489434+aler9@users.noreply.github.com>
This commit is contained in:
Dan Bason 2024-04-07 04:32:53 +12:00 committed by GitHub
parent 60e7d77e41
commit 87c0535823
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 80 additions and 27 deletions

View file

@ -1879,6 +1879,16 @@ webrtcICEServers2:
where secret is the secret of the TURN server. MediaMTX will generate a set of credentials by using the secret, and credentials will be sent to clients before the WebRTC/ICE connection is established.
In some cases you may want the browser to connect using TURN servers but have mediamtx not using TURN (for example if the TURN server is on the same network as mediamtx). To allow this you can configure the TURN server to be client only:
```yml
webrtcICEServers2:
- url: turn:host:port
username: user
password: password
clientOnly: true
```
### RTSP-specific features
#### Transport protocols

View file

@ -190,6 +190,8 @@ components:
type: string
password:
type: string
clientOnly:
type: boolean
# SRT server
srt:

View file

@ -5,4 +5,5 @@ type WebRTCICEServer struct {
URL string `json:"url"`
Username string `json:"username"`
Password string `json:"password"`
ClientOnly bool `json:"clientOnly"`
}

View file

@ -151,7 +151,7 @@ func (s *httpServer) onWHIPOptions(ctx *gin.Context, path string, publish bool)
return
}
servers, err := s.parent.generateICEServers()
servers, err := s.parent.generateICEServers(true)
if err != nil {
writeError(ctx, http.StatusInternalServerError, err)
return
@ -191,7 +191,7 @@ func (s *httpServer) onWHIPPost(ctx *gin.Context, path string, publish bool) {
return
}
servers, err := s.parent.generateICEServers()
servers, err := s.parent.generateICEServers(true)
if err != nil {
writeError(ctx, http.StatusInternalServerError, err)
return

View file

@ -429,10 +429,11 @@ func (s *Server) findSessionByUUID(uuid uuid.UUID) *session {
return nil
}
func (s *Server) generateICEServers() ([]pwebrtc.ICEServer, error) {
ret := make([]pwebrtc.ICEServer, len(s.ICEServers))
func (s *Server) generateICEServers(clientConfig bool) ([]pwebrtc.ICEServer, error) {
ret := make([]pwebrtc.ICEServer, 0, len(s.ICEServers))
for i, server := range s.ICEServers {
for _, server := range s.ICEServers {
if !server.ClientOnly || clientConfig {
if server.Username == "AUTH_SECRET" {
expireDate := time.Now().Add(webrtcTurnSecretExpiration).Unix()
@ -449,10 +450,11 @@ func (s *Server) generateICEServers() ([]pwebrtc.ICEServer, error) {
server.Password = base64.StdEncoding.EncodeToString(h.Sum(nil))
}
ret[i] = pwebrtc.ICEServer{
ret = append(ret, pwebrtc.ICEServer{
URLs: []string{server.URL},
Username: server.Username,
Credential: server.Password,
})
}
}

View file

@ -408,3 +408,40 @@ func TestServerReadNotFound(t *testing.T) {
require.Equal(t, http.StatusNotFound, res.StatusCode)
}
func TestICEServerNoClientOnly(t *testing.T) {
s := &Server{
ICEServers: []conf.WebRTCICEServer{
{
URL: "turn:turn.example.com:1234",
Username: "user",
Password: "passwrd",
},
},
}
clientICEServers, err := s.generateICEServers(true)
require.NoError(t, err)
require.Equal(t, len(s.ICEServers), len(clientICEServers))
serverICEServers, err := s.generateICEServers(false)
require.NoError(t, err)
require.Equal(t, len(s.ICEServers), len(serverICEServers))
}
func TestICEServerClientOnly(t *testing.T) {
s := &Server{
ICEServers: []conf.WebRTCICEServer{
{
URL: "turn:turn.example.com:1234",
Username: "user",
Password: "passwrd",
ClientOnly: true,
},
},
}
clientICEServers, err := s.generateICEServers(true)
require.NoError(t, err)
require.Equal(t, len(s.ICEServers), len(clientICEServers))
serverICEServers, err := s.generateICEServers(false)
require.NoError(t, err)
require.Equal(t, 0, len(serverICEServers))
}

View file

@ -393,7 +393,7 @@ func (s *session) runPublish() (int, error) {
defer path.RemovePublisher(defs.PathRemovePublisherReq{Author: s})
iceServers, err := s.parent.generateICEServers()
iceServers, err := s.parent.generateICEServers(false)
if err != nil {
return http.StatusInternalServerError, err
}
@ -528,7 +528,7 @@ func (s *session) runRead() (int, error) {
defer path.RemoveReader(defs.PathRemoveReaderReq{Author: s})
iceServers, err := s.parent.generateICEServers()
iceServers, err := s.parent.generateICEServers(false)
if err != nil {
return http.StatusInternalServerError, err
}

View file

@ -311,6 +311,7 @@ webrtcICEServers2: []
# the secret must be inserted into the password field.
# username: ''
# password: ''
# clientOnly: false
###############################################
# Global settings -> SRT server