@@ -44,7 +44,7 @@ type links struct {
44
44
45
45
type linkProtocol interface {
46
46
dial (ctx context.Context , url * url.URL , info linkInfo , options linkOptions ) (net.Conn , error )
47
- listen (ctx context.Context , url * url.URL , sintf string ) (net.Listener , error )
47
+ listen (ctx context.Context , url * url.URL , sintf string , options linkOptions ) (net.Listener , error )
48
48
}
49
49
50
50
// linkInfo is used as a map key
@@ -72,6 +72,7 @@ type linkOptions struct {
72
72
tlsSNI string
73
73
password []byte
74
74
maxBackoff time.Duration
75
+ multipath bool
75
76
}
76
77
77
78
type Listener struct {
@@ -140,6 +141,7 @@ const ErrLinkPinnedKeyInvalid = linkError("pinned public key is invalid")
140
141
const ErrLinkPasswordInvalid = linkError ("password is invalid" )
141
142
const ErrLinkUnrecognisedSchema = linkError ("link schema unknown" )
142
143
const ErrLinkMaxBackoffInvalid = linkError ("max backoff duration invalid" )
144
+ const ErrLinkMultipathInvalid = linkError ("multipath invalid" )
143
145
144
146
func (l * links ) add (u * url.URL , sintf string , linkType linkType ) error {
145
147
var retErr error
@@ -193,6 +195,17 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
193
195
}
194
196
options .maxBackoff = d
195
197
}
198
+ if p := u .Query ().Get ("multipath" ); p != "" {
199
+ switch p {
200
+ case "true" , "1" :
201
+ options .multipath = true
202
+ case "false" , "0" :
203
+ options .multipath = false
204
+ default :
205
+ retErr = ErrLinkMultipathInvalid
206
+ return
207
+ }
208
+ }
196
209
// SNI headers must contain hostnames and not IP addresses, so we must make sure
197
210
// that we do not populate the SNI with an IP literal. We do this by splitting
198
211
// the host-port combo from the query option and then seeing if it parses to an
@@ -379,7 +392,7 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
379
392
return retErr
380
393
}
381
394
382
- func (l * links ) remove (u * url.URL , sintf string , linkType linkType ) error {
395
+ func (l * links ) remove (u * url.URL , sintf string , _ linkType ) error {
383
396
var retErr error
384
397
phony .Block (l , func () {
385
398
// Generate the link info and see whether we think we already
@@ -422,31 +435,45 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
422
435
cancel ()
423
436
return nil , ErrLinkUnrecognisedSchema
424
437
}
425
- listener , err := protocol .listen (ctx , u , sintf )
426
- if err != nil {
427
- cancel ()
428
- return nil , err
429
- }
430
- li := & Listener {
431
- listener : listener ,
432
- ctx : ctx ,
433
- Cancel : cancel ,
434
- }
435
438
436
439
var options linkOptions
437
440
if p := u .Query ().Get ("priority" ); p != "" {
438
441
pi , err := strconv .ParseUint (p , 10 , 8 )
439
442
if err != nil {
443
+ cancel ()
440
444
return nil , ErrLinkPriorityInvalid
441
445
}
442
446
options .priority = uint8 (pi )
443
447
}
444
448
if p := u .Query ().Get ("password" ); p != "" {
445
449
if len (p ) > blake2b .Size {
450
+ cancel ()
446
451
return nil , ErrLinkPasswordInvalid
447
452
}
448
453
options .password = []byte (p )
449
454
}
455
+ if p := u .Query ().Get ("multipath" ); p != "" {
456
+ switch p {
457
+ case "true" , "1" :
458
+ options .multipath = true
459
+ case "false" , "0" :
460
+ options .multipath = false
461
+ default :
462
+ cancel ()
463
+ return nil , ErrLinkMultipathInvalid
464
+ }
465
+ }
466
+
467
+ listener , err := protocol .listen (ctx , u , sintf , options )
468
+ if err != nil {
469
+ cancel ()
470
+ return nil , err
471
+ }
472
+ li := & Listener {
473
+ listener : listener ,
474
+ ctx : ctx ,
475
+ Cancel : cancel ,
476
+ }
450
477
451
478
go func () {
452
479
l .core .log .Infof ("%s listener started on %s" , strings .ToUpper (u .Scheme ), listener .Addr ())
@@ -567,7 +594,7 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
567
594
switch {
568
595
case err != nil :
569
596
return fmt .Errorf ("write handshake: %w" , err )
570
- case err == nil && n != len (metaBytes ):
597
+ case n != len (metaBytes ):
571
598
return fmt .Errorf ("incomplete handshake send" )
572
599
}
573
600
meta = version_metadata {}
0 commit comments