mirror of
https://github.com/pion/webrtc.git
synced 2025-10-05 15:16:52 +08:00
Support running ICE lite locally and on a remote
* Parse ice-lite property from remote SessionDescription * Add option to SettingEngine that allows the local ICEAgent to run in lite mode
This commit is contained in:

committed by
Sean DuBois

parent
c178b8ef97
commit
e0aab79044
@@ -20,6 +20,7 @@ func (api *API) NewICEGatherer(opts ICEGatherOptions) (*ICEGatherer, error) {
|
|||||||
api.settingEngine.timeout.ICERelayAcceptanceMinWait,
|
api.settingEngine.timeout.ICERelayAcceptanceMinWait,
|
||||||
api.settingEngine.LoggerFactory,
|
api.settingEngine.LoggerFactory,
|
||||||
api.settingEngine.candidates.ICETrickle,
|
api.settingEngine.candidates.ICETrickle,
|
||||||
|
api.settingEngine.candidates.ICELite,
|
||||||
api.settingEngine.candidates.ICENetworkTypes,
|
api.settingEngine.candidates.ICENetworkTypes,
|
||||||
opts,
|
opts,
|
||||||
)
|
)
|
||||||
|
@@ -21,6 +21,7 @@ type ICEGatherer struct {
|
|||||||
validatedServers []*ice.URL
|
validatedServers []*ice.URL
|
||||||
|
|
||||||
agentIsTrickle bool
|
agentIsTrickle bool
|
||||||
|
lite bool
|
||||||
agent *ice.Agent
|
agent *ice.Agent
|
||||||
|
|
||||||
portMin uint16
|
portMin uint16
|
||||||
@@ -54,6 +55,7 @@ func NewICEGatherer(
|
|||||||
relayAcceptanceMinWait *time.Duration,
|
relayAcceptanceMinWait *time.Duration,
|
||||||
loggerFactory logging.LoggerFactory,
|
loggerFactory logging.LoggerFactory,
|
||||||
agentIsTrickle bool,
|
agentIsTrickle bool,
|
||||||
|
lite bool,
|
||||||
networkTypes []NetworkType,
|
networkTypes []NetworkType,
|
||||||
opts ICEGatherOptions,
|
opts ICEGatherOptions,
|
||||||
) (*ICEGatherer, error) {
|
) (*ICEGatherer, error) {
|
||||||
@@ -69,7 +71,9 @@ func NewICEGatherer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
candidateTypes := []ice.CandidateType{}
|
candidateTypes := []ice.CandidateType{}
|
||||||
if opts.ICEGatherPolicy == ICETransportPolicyRelay {
|
if lite {
|
||||||
|
candidateTypes = append(candidateTypes, ice.CandidateTypeHost)
|
||||||
|
} else if opts.ICEGatherPolicy == ICETransportPolicyRelay {
|
||||||
candidateTypes = append(candidateTypes, ice.CandidateTypeRelay)
|
candidateTypes = append(candidateTypes, ice.CandidateTypeRelay)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +87,7 @@ func NewICEGatherer(
|
|||||||
loggerFactory: loggerFactory,
|
loggerFactory: loggerFactory,
|
||||||
log: loggerFactory.NewLogger("ice"),
|
log: loggerFactory.NewLogger("ice"),
|
||||||
agentIsTrickle: agentIsTrickle,
|
agentIsTrickle: agentIsTrickle,
|
||||||
|
lite: lite,
|
||||||
networkTypes: networkTypes,
|
networkTypes: networkTypes,
|
||||||
candidateTypes: candidateTypes,
|
candidateTypes: candidateTypes,
|
||||||
candidateSelectionTimeout: candidateSelectionTimeout,
|
candidateSelectionTimeout: candidateSelectionTimeout,
|
||||||
@@ -103,6 +108,7 @@ func (g *ICEGatherer) createAgent() error {
|
|||||||
|
|
||||||
config := &ice.AgentConfig{
|
config := &ice.AgentConfig{
|
||||||
Trickle: g.agentIsTrickle,
|
Trickle: g.agentIsTrickle,
|
||||||
|
Lite: g.lite,
|
||||||
Urls: g.validatedServers,
|
Urls: g.validatedServers,
|
||||||
PortMin: g.portMin,
|
PortMin: g.portMin,
|
||||||
PortMax: g.portMax,
|
PortMax: g.portMax,
|
||||||
|
@@ -22,7 +22,7 @@ func TestNewICEGatherer_Success(t *testing.T) {
|
|||||||
ICEServers: []ICEServer{{URLs: []string{"stun:stun.l.google.com:19302"}}},
|
ICEServers: []ICEServer{{URLs: []string{"stun:stun.l.google.com:19302"}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
gatherer, err := NewICEGatherer(0, 0, nil, nil, nil, nil, nil, nil, nil, logging.NewDefaultLoggerFactory(), false, nil, opts)
|
gatherer, err := NewICEGatherer(0, 0, nil, nil, nil, nil, nil, nil, nil, logging.NewDefaultLoggerFactory(), false, false, nil, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ func TestICEGather_LocalCandidateOrder(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
to := time.Second
|
to := time.Second
|
||||||
gatherer, err := NewICEGatherer(10000, 10010, &to, &to, &to, &to, &to, &to, &to, logging.NewDefaultLoggerFactory(), false, []NetworkType{NetworkTypeUDP4}, opts)
|
gatherer, err := NewICEGatherer(10000, 10010, &to, &to, &to, &to, &to, &to, &to, logging.NewDefaultLoggerFactory(), false, false, []NetworkType{NetworkTypeUDP4}, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
@@ -460,6 +460,11 @@ func (pc *PeerConnection) CreateOffer(options *OfferOptions) (SessionDescription
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pc.iceGatherer.lite {
|
||||||
|
// RFC 5245 S15.3
|
||||||
|
d = d.WithValueAttribute(sdp.AttrKeyICELite, sdp.AttrKeyICELite)
|
||||||
|
}
|
||||||
|
|
||||||
midValue := strconv.Itoa(bundleCount)
|
midValue := strconv.Itoa(bundleCount)
|
||||||
if pc.configuration.SDPSemantics == SDPSemanticsPlanB {
|
if pc.configuration.SDPSemantics == SDPSemanticsPlanB {
|
||||||
midValue = "data"
|
midValue = "data"
|
||||||
@@ -869,6 +874,10 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error {
|
|||||||
if desc.Type == SDPTypeOffer {
|
if desc.Type == SDPTypeOffer {
|
||||||
weOffer = false
|
weOffer = false
|
||||||
}
|
}
|
||||||
|
remoteIsLite := false
|
||||||
|
if liteValue, haveRemoteIs := desc.parsed.Attribute(sdp.AttrKeyICELite); haveRemoteIs && liteValue == sdp.AttrKeyICELite {
|
||||||
|
remoteIsLite = true
|
||||||
|
}
|
||||||
|
|
||||||
fingerprint, haveFingerprint := desc.parsed.Attribute("fingerprint")
|
fingerprint, haveFingerprint := desc.parsed.Attribute("fingerprint")
|
||||||
for _, m := range pc.RemoteDescription().parsed.MediaDescriptions {
|
for _, m := range pc.RemoteDescription().parsed.MediaDescriptions {
|
||||||
@@ -940,7 +949,10 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error {
|
|||||||
|
|
||||||
// Start the ice transport
|
// Start the ice transport
|
||||||
iceRole := ICERoleControlled
|
iceRole := ICERoleControlled
|
||||||
if weOffer {
|
// If one of the agents is lite and the other one is not, the lite agent must be the controlling agent.
|
||||||
|
// If both or neither agents are lite the offering agent is controlling.
|
||||||
|
// RFC 8445 S6.1.1
|
||||||
|
if (weOffer && remoteIsLite == pc.iceGatherer.lite) || (remoteIsLite && !pc.iceGatherer.lite) {
|
||||||
iceRole = ICERoleControlling
|
iceRole = ICERoleControlling
|
||||||
}
|
}
|
||||||
err := pc.iceTransport.Start(
|
err := pc.iceTransport.Start(
|
||||||
|
@@ -556,3 +556,75 @@ func TestGatherOnSetLocalDescription(t *testing.T) {
|
|||||||
|
|
||||||
<-pcAnswerGathered
|
<-pcAnswerGathered
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPeerConnection_OfferingLite(t *testing.T) {
|
||||||
|
s := SettingEngine{}
|
||||||
|
s.SetLite(true)
|
||||||
|
offerPC, err := NewAPI(WithSettingEngine(s)).NewPeerConnection(Configuration{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
answerPC, err := NewAPI().NewPeerConnection(Configuration{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = signalPair(offerPC, answerPC); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
iceComplete := make(chan interface{})
|
||||||
|
answerPC.OnICEConnectionStateChange(func(iceState ICEConnectionState) {
|
||||||
|
if iceState == ICEConnectionStateConnected {
|
||||||
|
select {
|
||||||
|
case <-iceComplete:
|
||||||
|
default:
|
||||||
|
close(iceComplete)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
<-iceComplete
|
||||||
|
if err = offerPC.Close(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if err = answerPC.Close(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPeerConnection_AnsweringLite(t *testing.T) {
|
||||||
|
offerPC, err := NewAPI().NewPeerConnection(Configuration{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := SettingEngine{}
|
||||||
|
s.SetLite(true)
|
||||||
|
answerPC, err := NewAPI(WithSettingEngine(s)).NewPeerConnection(Configuration{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = signalPair(offerPC, answerPC); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
iceComplete := make(chan interface{})
|
||||||
|
answerPC.OnICEConnectionStateChange(func(iceState ICEConnectionState) {
|
||||||
|
if iceState == ICEConnectionStateConnected {
|
||||||
|
select {
|
||||||
|
case <-iceComplete:
|
||||||
|
default:
|
||||||
|
close(iceComplete)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
<-iceComplete
|
||||||
|
if err = offerPC.Close(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if err = answerPC.Close(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -30,6 +30,7 @@ type SettingEngine struct {
|
|||||||
ICERelayAcceptanceMinWait *time.Duration
|
ICERelayAcceptanceMinWait *time.Duration
|
||||||
}
|
}
|
||||||
candidates struct {
|
candidates struct {
|
||||||
|
ICELite bool
|
||||||
ICETrickle bool
|
ICETrickle bool
|
||||||
ICENetworkTypes []NetworkType
|
ICENetworkTypes []NetworkType
|
||||||
}
|
}
|
||||||
@@ -88,6 +89,11 @@ func (e *SettingEngine) SetEphemeralUDPPortRange(portMin, portMax uint16) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLite configures whether or not the ice agent should be a lite agent
|
||||||
|
func (e *SettingEngine) SetLite(lite bool) {
|
||||||
|
e.candidates.ICELite = lite
|
||||||
|
}
|
||||||
|
|
||||||
// SetTrickle configures whether or not the ice agent should gather candidates
|
// SetTrickle configures whether or not the ice agent should gather candidates
|
||||||
// via the trickle method or synchronously.
|
// via the trickle method or synchronously.
|
||||||
func (e *SettingEngine) SetTrickle(trickle bool) {
|
func (e *SettingEngine) SetTrickle(trickle bool) {
|
||||||
|
Reference in New Issue
Block a user