make local port selection deterministic and detach from the control port to improve performane
This commit is contained in:
parent
85d80d893c
commit
23e043ad93
|
@ -3,3 +3,4 @@
|
|||
examples/basic/basic
|
||||
examples/listener/listener
|
||||
examples/dialer/dialer
|
||||
.idea/*
|
||||
|
|
|
@ -111,7 +111,7 @@ func (c *Conn) NewOnion(config *NewOnionConfig) (*OnionInfo, error) {
|
|||
}
|
||||
request := fmt.Sprintf("ADD_ONION %s:%s%s%s", hsKeyType, hsKeyStr, portStr, flagsStr)
|
||||
resp, err := c.Request(request)
|
||||
if err != nil {
|
||||
if err != nil && fmt.Sprintf("%v", err) != "550 Unspecified Tor error: Onion address collision" {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -153,11 +153,6 @@ func (c *Conn) NewOnion(config *NewOnionConfig) (*OnionInfo, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if serviceID == "" {
|
||||
// This should *NEVER* happen, since the command succeded, and the spec
|
||||
// guarantees that this will always be present.
|
||||
return nil, newProtocolError("failed to determine service ID")
|
||||
}
|
||||
|
||||
oi := new(OnionInfo)
|
||||
oi.RawResponse = resp
|
||||
|
|
33
listener.go
33
listener.go
|
@ -8,11 +8,15 @@
|
|||
package bulb
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
goodrand "crypto/rand"
|
||||
"fmt"
|
||||
"net"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
"golang.org/x/crypto/sha3"
|
||||
badrand "math/rand"
|
||||
"encoding/binary"
|
||||
"crypto"
|
||||
)
|
||||
|
||||
type onionAddr struct {
|
||||
info *OnionInfo
|
||||
|
@ -55,7 +59,13 @@ func (l *onionListener) Addr() net.Addr {
|
|||
// All of virtual ports specified in vports will be mapped to the port to which
|
||||
// the underlying TCP listener binded. PortSpecs in config will be ignored since
|
||||
// there is only one mapping for a vports set is possible.
|
||||
|
||||
// [DEPRECATED] generate a random port to listen on (this is for backwards compatibility)
|
||||
func (c *Conn) NewListener(config *NewOnionConfig, vports ...uint16) (net.Listener, error) {
|
||||
return c.RecoverListener(config, "", vports...)
|
||||
}
|
||||
|
||||
func (c *Conn) RecoverListener(config *NewOnionConfig, onion string, vports ...uint16) (net.Listener, error) {
|
||||
var cfg NewOnionConfig
|
||||
if config == nil {
|
||||
cfg = NewOnionConfig{
|
||||
|
@ -65,7 +75,20 @@ func (c *Conn) NewListener(config *NewOnionConfig, vports ...uint16) (net.Listen
|
|||
cfg = *config
|
||||
}
|
||||
|
||||
const loopbackAddr = "127.0.0.1:0"
|
||||
var port int
|
||||
if onion == "" { // generate a random port for ephemeral programs
|
||||
seedbytes := make([]byte, 2)
|
||||
goodrand.Read(seedbytes)
|
||||
port = int(binary.LittleEndian.Uint16(seedbytes))
|
||||
if port < 1024 { // because why not ^ea
|
||||
port = 1024 + int(seedbytes[0]) + int(seedbytes[1])
|
||||
}
|
||||
} else { // generate a deterministic port for resumptive programs
|
||||
seedbytes := sha3.New224().Sum([]byte(onion))
|
||||
seed := badrand.NewSource(int64(binary.LittleEndian.Uint64(seedbytes[:8])))
|
||||
port = badrand.New(seed).Intn(64511) + 1024
|
||||
}
|
||||
var loopbackAddr = "127.0.0.1:" + strconv.Itoa(port)
|
||||
|
||||
// Listen on the loopback interface.
|
||||
tcpListener, err := net.Listen("tcp4", loopbackAddr)
|
||||
|
@ -79,7 +102,7 @@ func (c *Conn) NewListener(config *NewOnionConfig, vports ...uint16) (net.Listen
|
|||
}
|
||||
|
||||
if len(vports) < 1 {
|
||||
return nil, newProtocolError("no virual ports specified")
|
||||
return nil, newProtocolError("no virtual ports specified")
|
||||
}
|
||||
targetPortStr := strconv.FormatUint((uint64)(tAddr.Port), 10)
|
||||
var portSpecs []OnionPortSpec
|
||||
|
|
Reference in New Issue