1// +build !js
2
3package webrtc
4
5import (
6	"github.com/pion/ice"
7	"github.com/pion/webrtc/v2/pkg/rtcerr"
8)
9
10// ICEServer describes a single STUN and TURN server that can be used by
11// the ICEAgent to establish a connection with a peer.
12type ICEServer struct {
13	URLs           []string
14	Username       string
15	Credential     interface{}
16	CredentialType ICECredentialType
17}
18
19func (s ICEServer) parseURL(i int) (*ice.URL, error) {
20	return ice.ParseURL(s.URLs[i])
21}
22
23func (s ICEServer) validate() error {
24	_, err := s.urls()
25	return err
26}
27
28func (s ICEServer) urls() ([]*ice.URL, error) {
29	urls := []*ice.URL{}
30
31	for i := range s.URLs {
32		url, err := s.parseURL(i)
33		if err != nil {
34			return nil, err
35		}
36
37		if url.Scheme == ice.SchemeTypeTURN || url.Scheme == ice.SchemeTypeTURNS {
38			// https://www.w3.org/TR/webrtc/#set-the-configuration (step #11.3.2)
39			if s.Username == "" || s.Credential == nil {
40				return nil, &rtcerr.InvalidAccessError{Err: ErrNoTurnCredentials}
41			}
42			url.Username = s.Username
43
44			switch s.CredentialType {
45			case ICECredentialTypePassword:
46				// https://www.w3.org/TR/webrtc/#set-the-configuration (step #11.3.3)
47				password, ok := s.Credential.(string)
48				if !ok {
49					return nil, &rtcerr.InvalidAccessError{Err: ErrTurnCredentials}
50				}
51				url.Password = password
52
53			case ICECredentialTypeOauth:
54				// https://www.w3.org/TR/webrtc/#set-the-configuration (step #11.3.4)
55				if _, ok := s.Credential.(OAuthCredential); !ok {
56					return nil, &rtcerr.InvalidAccessError{Err: ErrTurnCredentials}
57				}
58
59			default:
60				return nil, &rtcerr.InvalidAccessError{Err: ErrTurnCredentials}
61			}
62		}
63
64		urls = append(urls, url)
65	}
66
67	return urls, nil
68}
69