p2p/nat: make nat mappings closable by client
After this commit, client can close individual mappings (without closing the whole NAT)
Juan Batiz-Benet committed
Jan 30, 2015 at 20:22 UTC
d7c9ae12ac4282099b27294be15201eda5077a5a
1 file changed
+25
-9
p2p/nat/nat.go
+25
-9
@@ -55,15 +55,16 @@ type NAT struct {
55
proc goprocess.Process // manages nat mappings lifecycle
56
57
mappingmu sync.RWMutex // guards mappings
58
- mappings []*mapping
58
+ mappings map[*mapping]struct{}
59
60
Notifier
61
}
62
63
func newNAT(realNAT nat.NAT) *NAT {
64
return &NAT{
65
- nat: realNAT,
66
- proc: goprocess.WithParent(goprocess.Background()),
65
+ nat: realNAT,
66
+ proc: goprocess.WithParent(goprocess.Background()),
67
+ mappings: make(map[*mapping]struct{}),
68
}
69
}
70
@@ -143,6 +144,9 @@ type Mapping interface {
144
// ExternalAddr returns the external facing address. If the mapping is not
145
// established, addr will be nil, and and ErrNoMapping will be returned.
146
ExternalAddr() (addr ma.Multiaddr, err error)
147
+
148
+ // Close closes the port mapping
149
+ Close() error
150
}
151
152
// keeps republishing
@@ -230,9 +234,9 @@ func (m *mapping) Close() error {
234
// Mappings returns a slice of all NAT mappings
235
func (nat *NAT) Mappings() []Mapping {
236
nat.mappingmu.Lock()
233
- maps2 := make([]Mapping, len(nat.mappings))
234
- for i, m := range nat.mappings {
235
- maps2[i] = m
237
+ maps2 := make([]Mapping, 0, len(nat.mappings))
238
+ for m := range nat.mappings {
239
+ maps2 = append(maps2, m)
240
}
241
nat.mappingmu.Unlock()
242
return maps2
@@ -243,7 +247,13 @@ func (nat *NAT) addMapping(m *mapping) {
247
nat.proc.AddChild(m.proc)
248
249
nat.mappingmu.Lock()
246
- nat.mappings = append(nat.mappings, m)
250
+ nat.mappings[m] = struct{}{}
251
+ nat.mappingmu.Unlock()
252
+}
253
+
254
+func (nat *NAT) rmMapping(m *mapping) {
255
+ nat.mappingmu.Lock()
256
+ delete(nat.mappings, m)
257
nat.mappingmu.Unlock()
258
}
259
@@ -286,10 +296,16 @@ func (nat *NAT) NewMapping(maddr ma.Multiaddr) (Mapping, error) {
296
intport: intport,
297
intaddr: maddr,
298
}
289
- m.proc = periodic.Every(MappingDuration/3, func(worker goprocess.Process) {
290
- nat.establishMapping(m)
299
+ m.proc = goprocess.WithTeardown(func() error {
300
+ nat.rmMapping(m)
301
+ return nil
302
})
303
nat.addMapping(m)
304
+
305
+ m.proc.AddChild(periodic.Every(MappingDuration/3, func(worker goprocess.Process) {
306
+ nat.establishMapping(m)
307
+ }))
308
+
309
// do it once synchronously, so first mapping is done right away, and before exiting,
310
// allowing users -- in the optimistic case -- to use results right after.
311
nat.establishMapping(m)