@@ -55,46 +55,42 @@ type NAT interface {
55
55
56
56
// discoverNATs returns all NATs discovered in the network.
57
57
func discoverNATs (ctx context.Context ) ([]NAT , []error ) {
58
- var nats []NAT
59
- var errs []error
60
-
61
58
type natsAndErrs struct {
62
59
nats []NAT
63
60
errs []error
64
61
}
65
- resCh := make (chan natsAndErrs )
62
+ upnpCh := make (chan natsAndErrs )
63
+ pmpCh := make (chan natsAndErrs )
66
64
67
- var pendingJobs int
68
-
69
- pendingJobs ++
70
65
go func () {
66
+ defer close (upnpCh )
67
+
68
+ // We do these UPNP queries sequentially because some routers will fail to handle parallel requests.
71
69
nats , errs := discoverUPNP_IG1 (ctx )
72
- select {
73
- case resCh <- natsAndErrs {nats , errs }:
74
- case <- ctx .Done ():
75
- }
76
- }()
77
70
78
- pendingJobs ++
79
- go func () {
80
- nats , errs := discoverUPNP_IG2 (ctx )
81
- select {
82
- case resCh <- natsAndErrs {nats , errs }:
83
- case <- ctx .Done ():
71
+ // Do IG2 after IG1 so that its NAT devices will appear as "better" when we
72
+ // find the best NAT to return below.
73
+ n , e := discoverUPNP_IG2 (ctx )
74
+ nats = append (nats , n ... )
75
+ errs = append (errs , e ... )
76
+
77
+ if len (nats ) == 0 {
78
+ // We don't have a NAT. We should try querying all devices over
79
+ // SSDP to find a InternetGatewayDevice. This shouldn't be necessary for
80
+ // a well behaved router.
81
+ n , e = discoverUPNP_GenIGDev (ctx )
82
+ nats = append (nats , n ... )
83
+ errs = append (errs , e ... )
84
84
}
85
- }()
86
85
87
- pendingJobs ++
88
- go func () {
89
- nats , errs := discoverUPNP_GenIGDev (ctx )
90
86
select {
91
- case resCh <- natsAndErrs {nats , errs }:
87
+ case upnpCh <- natsAndErrs {nats , errs }:
92
88
case <- ctx .Done ():
93
89
}
94
90
}()
95
91
96
- pendingJobs ++
97
92
go func () {
93
+ defer close (pmpCh )
98
94
nat , err := discoverNATPMP (ctx )
99
95
var nats []NAT
100
96
var errs []error
@@ -104,15 +100,22 @@ func discoverNATs(ctx context.Context) ([]NAT, []error) {
104
100
nats = append (nats , nat )
105
101
}
106
102
select {
107
- case resCh <- natsAndErrs {nats , errs }:
103
+ case pmpCh <- natsAndErrs {nats , errs }:
108
104
case <- ctx .Done ():
109
105
}
110
106
}()
111
107
112
- for pendingJobs > 0 {
113
- pendingJobs --
108
+ var nats []NAT
109
+ var errs []error
110
+
111
+ for upnpCh != nil && pmpCh != nil {
114
112
select {
115
- case res := <- resCh :
113
+ case res := <- pmpCh :
114
+ pmpCh = nil
115
+ nats = append (nats , res .nats ... )
116
+ errs = append (errs , res .errs ... )
117
+ case res := <- upnpCh :
118
+ upnpCh = nil
116
119
nats = append (nats , res .nats ... )
117
120
errs = append (errs , res .errs ... )
118
121
case <- ctx .Done ():
0 commit comments