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.LoggerFactory,
|
||||
api.settingEngine.candidates.ICETrickle,
|
||||
api.settingEngine.candidates.ICELite,
|
||||
api.settingEngine.candidates.ICENetworkTypes,
|
||||
opts,
|
||||
)
|
||||
|
@@ -21,6 +21,7 @@ type ICEGatherer struct {
|
||||
validatedServers []*ice.URL
|
||||
|
||||
agentIsTrickle bool
|
||||
lite bool
|
||||
agent *ice.Agent
|
||||
|
||||
portMin uint16
|
||||
@@ -54,6 +55,7 @@ func NewICEGatherer(
|
||||
relayAcceptanceMinWait *time.Duration,
|
||||
loggerFactory logging.LoggerFactory,
|
||||
agentIsTrickle bool,
|
||||
lite bool,
|
||||
networkTypes []NetworkType,
|
||||
opts ICEGatherOptions,
|
||||
) (*ICEGatherer, error) {
|
||||
@@ -69,7 +71,9 @@ func NewICEGatherer(
|
||||
}
|
||||
|
||||
candidateTypes := []ice.CandidateType{}
|
||||
if opts.ICEGatherPolicy == ICETransportPolicyRelay {
|
||||
if lite {
|
||||
candidateTypes = append(candidateTypes, ice.CandidateTypeHost)
|
||||
} else if opts.ICEGatherPolicy == ICETransportPolicyRelay {
|
||||
candidateTypes = append(candidateTypes, ice.CandidateTypeRelay)
|
||||
}
|
||||
|
||||
@@ -83,6 +87,7 @@ func NewICEGatherer(
|
||||
loggerFactory: loggerFactory,
|
||||
log: loggerFactory.NewLogger("ice"),
|
||||
agentIsTrickle: agentIsTrickle,
|
||||
lite: lite,
|
||||
networkTypes: networkTypes,
|
||||
candidateTypes: candidateTypes,
|
||||
candidateSelectionTimeout: candidateSelectionTimeout,
|
||||
@@ -103,6 +108,7 @@ func (g *ICEGatherer) createAgent() error {
|
||||
|
||||
config := &ice.AgentConfig{
|
||||
Trickle: g.agentIsTrickle,
|
||||
Lite: g.lite,
|
||||
Urls: g.validatedServers,
|
||||
PortMin: g.portMin,
|
||||
PortMax: g.portMax,
|
||||
|
@@ -22,7 +22,7 @@ func TestNewICEGatherer_Success(t *testing.T) {
|
||||
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 {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -71,7 +71,7 @@ func TestICEGather_LocalCandidateOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
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 {
|
||||
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)
|
||||
if pc.configuration.SDPSemantics == SDPSemanticsPlanB {
|
||||
midValue = "data"
|
||||
@@ -869,6 +874,10 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error {
|
||||
if desc.Type == SDPTypeOffer {
|
||||
weOffer = false
|
||||
}
|
||||
remoteIsLite := false
|
||||
if liteValue, haveRemoteIs := desc.parsed.Attribute(sdp.AttrKeyICELite); haveRemoteIs && liteValue == sdp.AttrKeyICELite {
|
||||
remoteIsLite = true
|
||||
}
|
||||
|
||||
fingerprint, haveFingerprint := desc.parsed.Attribute("fingerprint")
|
||||
for _, m := range pc.RemoteDescription().parsed.MediaDescriptions {
|
||||
@@ -940,7 +949,10 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error {
|
||||
|
||||
// Start the ice transport
|
||||
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
|
||||
}
|
||||
err := pc.iceTransport.Start(
|
||||
|
@@ -556,3 +556,75 @@ func TestGatherOnSetLocalDescription(t *testing.T) {
|
||||
|
||||
<-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
|
||||
}
|
||||
candidates struct {
|
||||
ICELite bool
|
||||
ICETrickle bool
|
||||
ICENetworkTypes []NetworkType
|
||||
}
|
||||
@@ -88,6 +89,11 @@ func (e *SettingEngine) SetEphemeralUDPPortRange(portMin, portMax uint16) error
|
||||
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
|
||||
// via the trickle method or synchronously.
|
||||
func (e *SettingEngine) SetTrickle(trickle bool) {
|
||||
|
Reference in New Issue
Block a user