Support 1:1 NAT option

Resolves #835
This commit is contained in:
Yutaka Takeda
2019-09-25 02:04:58 -07:00
parent d7ae1a87ba
commit 918412679f
4 changed files with 51 additions and 6 deletions

View File

@@ -23,6 +23,8 @@ func (api *API) NewICEGatherer(opts ICEGatherOptions) (*ICEGatherer, error) {
api.settingEngine.candidates.ICELite, api.settingEngine.candidates.ICELite,
api.settingEngine.candidates.ICENetworkTypes, api.settingEngine.candidates.ICENetworkTypes,
api.settingEngine.candidates.InterfaceFilter, api.settingEngine.candidates.InterfaceFilter,
api.settingEngine.candidates.NAT1To1IPs,
api.settingEngine.candidates.NAT1To1IPCandidate,
opts, opts,
) )
} }

View File

@@ -38,6 +38,8 @@ type ICEGatherer struct {
log logging.LeveledLogger log logging.LeveledLogger
networkTypes []NetworkType networkTypes []NetworkType
interfaceFilter func(string) bool interfaceFilter func(string) bool
nat1To1IPs []string
nat1To1IPCandidateType ice.CandidateType
onLocalCandidateHdlr func(candidate *ICECandidate) onLocalCandidateHdlr func(candidate *ICECandidate)
onStateChangeHdlr func(state ICEGathererState) onStateChangeHdlr func(state ICEGathererState)
@@ -59,6 +61,8 @@ func NewICEGatherer(
lite bool, lite bool,
networkTypes []NetworkType, networkTypes []NetworkType,
interfaceFilter func(string) bool, interfaceFilter func(string) bool,
nat1To1IPs []string,
nat1To1IPCandidate string,
opts ICEGatherOptions, opts ICEGatherOptions,
) (*ICEGatherer, error) { ) (*ICEGatherer, error) {
var validatedServers []*ice.URL var validatedServers []*ice.URL
@@ -79,6 +83,16 @@ func NewICEGatherer(
candidateTypes = append(candidateTypes, ice.CandidateTypeRelay) candidateTypes = append(candidateTypes, ice.CandidateTypeRelay)
} }
var nat1To1IPCandidateType ice.CandidateType
switch nat1To1IPCandidate {
case "host":
nat1To1IPCandidateType = ice.CandidateTypeHost
case "srflx":
nat1To1IPCandidateType = ice.CandidateTypeServerReflexive
default:
nat1To1IPCandidateType = ice.CandidateTypeUnspecified
}
return &ICEGatherer{ return &ICEGatherer{
state: ICEGathererStateNew, state: ICEGathererStateNew,
validatedServers: validatedServers, validatedServers: validatedServers,
@@ -98,6 +112,8 @@ func NewICEGatherer(
prflxAcceptanceMinWait: prflxAcceptanceMinWait, prflxAcceptanceMinWait: prflxAcceptanceMinWait,
relayAcceptanceMinWait: relayAcceptanceMinWait, relayAcceptanceMinWait: relayAcceptanceMinWait,
interfaceFilter: interfaceFilter, interfaceFilter: interfaceFilter,
nat1To1IPs: nat1To1IPs,
nat1To1IPCandidateType: nat1To1IPCandidateType,
}, nil }, nil
} }

View File

@@ -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, false, nil, func(string) bool { return true }, opts) gatherer, err := NewICEGatherer(0, 0, nil, nil, nil, nil, nil, nil, nil, logging.NewDefaultLoggerFactory(), false, false, nil, func(string) bool { return true }, 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, false, []NetworkType{NetworkTypeUDP4}, func(string) bool { return true }, opts) gatherer, err := NewICEGatherer(10000, 10010, &to, &to, &to, &to, &to, &to, &to, logging.NewDefaultLoggerFactory(), false, false, []NetworkType{NetworkTypeUDP4}, func(string) bool { return true }, nil, "", opts)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -34,6 +34,8 @@ type SettingEngine struct {
ICETrickle bool ICETrickle bool
ICENetworkTypes []NetworkType ICENetworkTypes []NetworkType
InterfaceFilter func(string) bool InterfaceFilter func(string) bool
NAT1To1IPs []string
NAT1To1IPCandidate string
} }
LoggerFactory logging.LoggerFactory LoggerFactory logging.LoggerFactory
} }
@@ -114,3 +116,28 @@ func (e *SettingEngine) SetNetworkTypes(candidateTypes []NetworkType) {
func (e *SettingEngine) SetInterfaceFilter(filter func(string) bool) { func (e *SettingEngine) SetInterfaceFilter(filter func(string) bool) {
e.candidates.InterfaceFilter = filter e.candidates.InterfaceFilter = filter
} }
// SetNAT1To1IPs has a list of external IP addresses of 1:1 (D)NAT.
// This is useful when you are host a server using Pion on an AWS EC2 instance
// which has a private address, behind a 1:1 DNAT with a public IP (e.g.
// Elastic IP). In this case, you can give the public IP address so that
// Pion will use the public IP address in its candidate instead of the private IP
// address.
func (e *SettingEngine) SetNAT1To1IPs(ips []string) {
e.candidates.NAT1To1IPs = ips
}
// SetNAT1To1IPCandidate is used along with SetNAT1To1IPs, to tell Pion which
// type of candidate should use the given public IP address.
// Two types of candidates are supported:
// - "host": The public IP address will be used for the host candidate in the SDP.
// - "srflx": A server reflexive candidate with the given public IP address will be added
// to the SDP. If you choose "host", then the private IP address won't be advertised with
// the peer. Also, this option cannot be used along with mDNS.
// If you choose "srflx", it simply adds a server reflexive candidate with the public IP.
// The host candidate is still available along with mDNS capabilities unaffected.
// Please note that you cannot give STUN server URL at the same time. It will result in
// an error otherwise.
func (e *SettingEngine) SetNAT1To1IPCandidate(candidate string) {
e.candidates.NAT1To1IPCandidate = candidate
}