1package webrtc
2
3import (
4	"github.com/pion/sdp/v3"
5)
6
7// DTLSRole indicates the role of the DTLS transport.
8type DTLSRole byte
9
10const (
11	// DTLSRoleAuto defines the DTLS role is determined based on
12	// the resolved ICE role: the ICE controlled role acts as the DTLS
13	// client and the ICE controlling role acts as the DTLS server.
14	DTLSRoleAuto DTLSRole = iota + 1
15
16	// DTLSRoleClient defines the DTLS client role.
17	DTLSRoleClient
18
19	// DTLSRoleServer defines the DTLS server role.
20	DTLSRoleServer
21)
22
23const (
24	// https://tools.ietf.org/html/rfc5763
25	/*
26		The answerer MUST use either a
27		setup attribute value of setup:active or setup:passive.  Note that
28		if the answerer uses setup:passive, then the DTLS handshake will
29		not begin until the answerer is received, which adds additional
30		latency. setup:active allows the answer and the DTLS handshake to
31		occur in parallel.  Thus, setup:active is RECOMMENDED.
32	*/
33	defaultDtlsRoleAnswer = DTLSRoleClient
34	/*
35		The endpoint that is the offerer MUST use the setup attribute
36		value of setup:actpass and be prepared to receive a client_hello
37		before it receives the answer.
38	*/
39	defaultDtlsRoleOffer = DTLSRoleAuto
40)
41
42func (r DTLSRole) String() string {
43	switch r {
44	case DTLSRoleAuto:
45		return "auto"
46	case DTLSRoleClient:
47		return "client"
48	case DTLSRoleServer:
49		return "server"
50	default:
51		return unknownStr
52	}
53}
54
55// Iterate a SessionDescription from a remote to determine if an explicit
56// role can been determined from it. The decision is made from the first role we we parse.
57// If no role can be found we return DTLSRoleAuto
58func dtlsRoleFromRemoteSDP(sessionDescription *sdp.SessionDescription) DTLSRole {
59	if sessionDescription == nil {
60		return DTLSRoleAuto
61	}
62
63	for _, mediaSection := range sessionDescription.MediaDescriptions {
64		for _, attribute := range mediaSection.Attributes {
65			if attribute.Key == "setup" {
66				switch attribute.Value {
67				case sdp.ConnectionRoleActive.String():
68					return DTLSRoleClient
69				case sdp.ConnectionRolePassive.String():
70					return DTLSRoleServer
71				default:
72					return DTLSRoleAuto
73				}
74			}
75		}
76	}
77
78	return DTLSRoleAuto
79}
80
81func connectionRoleFromDtlsRole(d DTLSRole) sdp.ConnectionRole {
82	switch d {
83	case DTLSRoleClient:
84		return sdp.ConnectionRoleActive
85	case DTLSRoleServer:
86		return sdp.ConnectionRolePassive
87	case DTLSRoleAuto:
88		return sdp.ConnectionRoleActpass
89	default:
90		return sdp.ConnectionRole(0)
91	}
92}
93