|
|
|
@ -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
|
|
|
|
|