Docs and beginning of simple iface and examples
This commit is contained in:
parent
dc2d829ca3
commit
2c4f45c285
|
@ -4,6 +4,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ExtendCircuit invokes EXTENDCIRCUIT and returns the circuit ID on success.
|
||||||
func (c *Conn) ExtendCircuit(circuitID string, path []string, purpose string) (string, error) {
|
func (c *Conn) ExtendCircuit(circuitID string, path []string, purpose string) (string, error) {
|
||||||
if circuitID == "" {
|
if circuitID == "" {
|
||||||
circuitID = "0"
|
circuitID = "0"
|
||||||
|
@ -22,10 +23,12 @@ func (c *Conn) ExtendCircuit(circuitID string, path []string, purpose string) (s
|
||||||
return resp.Reply[strings.LastIndexByte(resp.Reply, ' ')+1:], nil
|
return resp.Reply[strings.LastIndexByte(resp.Reply, ' ')+1:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCircuitPurpose invokes SETCIRCUITPURPOSE.
|
||||||
func (c *Conn) SetCircuitPurpose(circuitID string, purpose string) error {
|
func (c *Conn) SetCircuitPurpose(circuitID string, purpose string) error {
|
||||||
return c.sendRequestIgnoreResponse("SETCIRCUITPURPOSE %v purpose=%v", circuitID, purpose)
|
return c.sendRequestIgnoreResponse("SETCIRCUITPURPOSE %v purpose=%v", circuitID, purpose)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloseCircuit invokes CLOSECIRCUIT.
|
||||||
func (c *Conn) CloseCircuit(circuitID string, flags []string) error {
|
func (c *Conn) CloseCircuit(circuitID string, flags []string) error {
|
||||||
cmd := "CLOSECIRCUIT " + circuitID
|
cmd := "CLOSECIRCUIT " + circuitID
|
||||||
for _, flag := range flags {
|
for _, flag := range flags {
|
||||||
|
|
|
@ -6,10 +6,12 @@ import (
|
||||||
"github.com/cretz/bine/util"
|
"github.com/cretz/bine/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SetConf invokes SETCONF.
|
||||||
func (c *Conn) SetConf(entries ...*KeyVal) error {
|
func (c *Conn) SetConf(entries ...*KeyVal) error {
|
||||||
return c.sendSetConf("SETCONF", entries)
|
return c.sendSetConf("SETCONF", entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResetConf invokes RESETCONF.
|
||||||
func (c *Conn) ResetConf(entries ...*KeyVal) error {
|
func (c *Conn) ResetConf(entries ...*KeyVal) error {
|
||||||
return c.sendSetConf("RESETCONF", entries)
|
return c.sendSetConf("RESETCONF", entries)
|
||||||
}
|
}
|
||||||
|
@ -24,6 +26,7 @@ func (c *Conn) sendSetConf(cmd string, entries []*KeyVal) error {
|
||||||
return c.sendRequestIgnoreResponse(cmd)
|
return c.sendRequestIgnoreResponse(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetConf invokes GETCONF and returns the values for the requested keys.
|
||||||
func (c *Conn) GetConf(keys ...string) ([]*KeyVal, error) {
|
func (c *Conn) GetConf(keys ...string) ([]*KeyVal, error) {
|
||||||
resp, err := c.SendRequest("GETCONF %v", strings.Join(keys, " "))
|
resp, err := c.SendRequest("GETCONF %v", strings.Join(keys, " "))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -47,6 +50,7 @@ func (c *Conn) GetConf(keys ...string) ([]*KeyVal, error) {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SaveConf invokes SAVECONF.
|
||||||
func (c *Conn) SaveConf(force bool) error {
|
func (c *Conn) SaveConf(force bool) error {
|
||||||
cmd := "SAVECONF"
|
cmd := "SAVECONF"
|
||||||
if force {
|
if force {
|
||||||
|
@ -55,6 +59,7 @@ func (c *Conn) SaveConf(force bool) error {
|
||||||
return c.sendRequestIgnoreResponse(cmd)
|
return c.sendRequestIgnoreResponse(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadConf invokes LOADCONF.
|
||||||
func (c *Conn) LoadConf(conf string) error {
|
func (c *Conn) LoadConf(conf string) error {
|
||||||
return c.sendRequestIgnoreResponse("+LOADCONF\r\n%v\r\n.", conf)
|
return c.sendRequestIgnoreResponse("+LOADCONF\r\n%v\r\n.", conf)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,11 @@ import (
|
||||||
"github.com/cretz/bine/util"
|
"github.com/cretz/bine/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// EventCode represents an asynchronous event code (ref control spec 4.1)
|
||||||
type EventCode string
|
type EventCode string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// EventCodeAddrMap is ADDRMAP
|
||||||
EventCodeAddrMap EventCode = "ADDRMAP"
|
EventCodeAddrMap EventCode = "ADDRMAP"
|
||||||
EventCodeBandwidth EventCode = "BW"
|
EventCodeBandwidth EventCode = "BW"
|
||||||
EventCodeBuildTimeoutSet EventCode = "BUILDTIMEOUT_SET"
|
EventCodeBuildTimeoutSet EventCode = "BUILDTIMEOUT_SET"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
|
// GetHiddenServiceDescriptorAsync invokes HSFETCH.
|
||||||
func (c *Conn) GetHiddenServiceDescriptorAsync(address string, server string) error {
|
func (c *Conn) GetHiddenServiceDescriptorAsync(address string, server string) error {
|
||||||
cmd := "HSFETCH " + address
|
cmd := "HSFETCH " + address
|
||||||
if server != "" {
|
if server != "" {
|
||||||
|
@ -8,6 +9,7 @@ func (c *Conn) GetHiddenServiceDescriptorAsync(address string, server string) er
|
||||||
return c.sendRequestIgnoreResponse(cmd)
|
return c.sendRequestIgnoreResponse(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PostHiddenServiceDescriptorAsync invokes HSPOST.
|
||||||
func (c *Conn) PostHiddenServiceDescriptorAsync(desc string, servers []string, address string) error {
|
func (c *Conn) PostHiddenServiceDescriptorAsync(desc string, servers []string, address string) error {
|
||||||
cmd := "+HSPOST"
|
cmd := "+HSPOST"
|
||||||
for _, server := range servers {
|
for _, server := range servers {
|
||||||
|
|
|
@ -6,14 +6,17 @@ import (
|
||||||
"github.com/cretz/bine/util"
|
"github.com/cretz/bine/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Signal invokes SIGNAL.
|
||||||
func (c *Conn) Signal(signal string) error {
|
func (c *Conn) Signal(signal string) error {
|
||||||
return c.sendRequestIgnoreResponse("SIGNAL %v", signal)
|
return c.sendRequestIgnoreResponse("SIGNAL %v", signal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Quit invokes QUIT.
|
||||||
func (c *Conn) Quit() error {
|
func (c *Conn) Quit() error {
|
||||||
return c.sendRequestIgnoreResponse("QUIT")
|
return c.sendRequestIgnoreResponse("QUIT")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MapAddresses invokes MAPADDRESS and returns mapped addresses.
|
||||||
func (c *Conn) MapAddresses(addresses ...*KeyVal) ([]*KeyVal, error) {
|
func (c *Conn) MapAddresses(addresses ...*KeyVal) ([]*KeyVal, error) {
|
||||||
cmd := "MAPADDRESS"
|
cmd := "MAPADDRESS"
|
||||||
for _, address := range addresses {
|
for _, address := range addresses {
|
||||||
|
@ -33,6 +36,7 @@ func (c *Conn) MapAddresses(addresses ...*KeyVal) ([]*KeyVal, error) {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetInfo invokes GETINTO and returns values for requested keys.
|
||||||
func (c *Conn) GetInfo(keys ...string) ([]*KeyVal, error) {
|
func (c *Conn) GetInfo(keys ...string) ([]*KeyVal, error) {
|
||||||
resp, err := c.SendRequest("GETINFO %v", strings.Join(keys, " "))
|
resp, err := c.SendRequest("GETINFO %v", strings.Join(keys, " "))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -47,6 +51,7 @@ func (c *Conn) GetInfo(keys ...string) ([]*KeyVal, error) {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PostDescriptor invokes POSTDESCRIPTOR.
|
||||||
func (c *Conn) PostDescriptor(descriptor string, purpose string, cache string) error {
|
func (c *Conn) PostDescriptor(descriptor string, purpose string, cache string) error {
|
||||||
cmd := "+POSTDESCRIPTOR"
|
cmd := "+POSTDESCRIPTOR"
|
||||||
if purpose != "" {
|
if purpose != "" {
|
||||||
|
@ -59,11 +64,12 @@ func (c *Conn) PostDescriptor(descriptor string, purpose string, cache string) e
|
||||||
return c.sendRequestIgnoreResponse(cmd)
|
return c.sendRequestIgnoreResponse(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UseFeatures invokes USEFEATURE.
|
||||||
func (c *Conn) UseFeatures(features ...string) error {
|
func (c *Conn) UseFeatures(features ...string) error {
|
||||||
return c.sendRequestIgnoreResponse("USEFEATURE " + strings.Join(features, " "))
|
return c.sendRequestIgnoreResponse("USEFEATURE " + strings.Join(features, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: can this take multiple
|
// ResolveAsync invokes RESOLVE.
|
||||||
func (c *Conn) ResolveAsync(address string, reverse bool) error {
|
func (c *Conn) ResolveAsync(address string, reverse bool) error {
|
||||||
cmd := "RESOLVE "
|
cmd := "RESOLVE "
|
||||||
if reverse {
|
if reverse {
|
||||||
|
@ -72,10 +78,12 @@ func (c *Conn) ResolveAsync(address string, reverse bool) error {
|
||||||
return c.sendRequestIgnoreResponse(cmd + address)
|
return c.sendRequestIgnoreResponse(cmd + address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TakeOwnership invokes TAKEOWNERSHIP.
|
||||||
func (c *Conn) TakeOwnership() error {
|
func (c *Conn) TakeOwnership() error {
|
||||||
return c.sendRequestIgnoreResponse("TAKEOWNERSHIP")
|
return c.sendRequestIgnoreResponse("TAKEOWNERSHIP")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DropGuards invokes DROPGUARDS.
|
||||||
func (c *Conn) DropGuards() error {
|
func (c *Conn) DropGuards() error {
|
||||||
return c.sendRequestIgnoreResponse("DROPGUARDS")
|
return c.sendRequestIgnoreResponse("DROPGUARDS")
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,27 +12,39 @@ import (
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// KeyType is a key type for Key in AddOnion.
|
||||||
type KeyType string
|
type KeyType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
KeyTypeNew KeyType = "NEW"
|
// KeyTypeNew is NEW.
|
||||||
KeyTypeRSA1024 KeyType = "RSA1024"
|
KeyTypeNew KeyType = "NEW"
|
||||||
|
// KeyTypeRSA1024 is RSA1024.
|
||||||
|
KeyTypeRSA1024 KeyType = "RSA1024"
|
||||||
|
// KeyTypeED25519V3 is ED25519-V3.
|
||||||
KeyTypeED25519V3 KeyType = "ED25519-V3"
|
KeyTypeED25519V3 KeyType = "ED25519-V3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// KeyAlgo is a key algorithm for GenKey on AddOnion.
|
||||||
type KeyAlgo string
|
type KeyAlgo string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
KeyAlgoBest KeyAlgo = "BEST"
|
// KeyAlgoBest is BEST.
|
||||||
KeyAlgoRSA1024 KeyAlgo = "RSA1024"
|
KeyAlgoBest KeyAlgo = "BEST"
|
||||||
|
// KeyAlgoRSA1024 is RSA1024.
|
||||||
|
KeyAlgoRSA1024 KeyAlgo = "RSA1024"
|
||||||
|
// KeyAlgoED25519V3 is ED25519-V3.
|
||||||
KeyAlgoED25519V3 KeyAlgo = "ED25519-V3"
|
KeyAlgoED25519V3 KeyAlgo = "ED25519-V3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Key is a type of key to use for AddOnion. Implementations include GenKey, RSAKey, and ED25519Key.
|
||||||
type Key interface {
|
type Key interface {
|
||||||
|
// Type is the KeyType for AddOnion.
|
||||||
Type() KeyType
|
Type() KeyType
|
||||||
|
// Blob is the serialized key for AddOnion.
|
||||||
Blob() string
|
Blob() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KeyFromString creates a Key for AddOnion based on a response string.
|
||||||
func KeyFromString(str string) (Key, error) {
|
func KeyFromString(str string) (Key, error) {
|
||||||
typ, blob, _ := util.PartitionString(str, ':')
|
typ, blob, _ := util.PartitionString(str, ':')
|
||||||
switch KeyType(typ) {
|
switch KeyType(typ) {
|
||||||
|
@ -47,14 +59,22 @@ func KeyFromString(str string) (Key, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenKey is a Key for AddOnion that asks Tor to generate a key for the given algorithm.
|
||||||
type GenKey KeyAlgo
|
type GenKey KeyAlgo
|
||||||
|
|
||||||
|
// GenKeyFromBlob creates a GenKey for the given response blob which is a KeyAlgo.
|
||||||
func GenKeyFromBlob(blob string) GenKey { return GenKey(KeyAlgo(blob)) }
|
func GenKeyFromBlob(blob string) GenKey { return GenKey(KeyAlgo(blob)) }
|
||||||
func (GenKey) Type() KeyType { return KeyTypeNew }
|
|
||||||
func (g GenKey) Blob() string { return string(g) }
|
|
||||||
|
|
||||||
|
// Type implements Key.Type.
|
||||||
|
func (GenKey) Type() KeyType { return KeyTypeNew }
|
||||||
|
|
||||||
|
// Blob implements Key.Blob.
|
||||||
|
func (g GenKey) Blob() string { return string(g) }
|
||||||
|
|
||||||
|
// RSAKey is a Key for AddOnion that is a RSA-1024 key (i.e. v2).
|
||||||
type RSAKey struct{ *rsa.PrivateKey }
|
type RSAKey struct{ *rsa.PrivateKey }
|
||||||
|
|
||||||
|
// RSA1024KeyFromBlob creates a RSAKey for the given response blob.
|
||||||
func RSA1024KeyFromBlob(blob string) (*RSAKey, error) {
|
func RSA1024KeyFromBlob(blob string) (*RSAKey, error) {
|
||||||
byts, err := base64.StdEncoding.DecodeString(blob)
|
byts, err := base64.StdEncoding.DecodeString(blob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -66,13 +86,19 @@ func RSA1024KeyFromBlob(blob string) (*RSAKey, error) {
|
||||||
}
|
}
|
||||||
return &RSAKey{rsaKey}, nil
|
return &RSAKey{rsaKey}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Type implements Key.Type.
|
||||||
func (*RSAKey) Type() KeyType { return KeyTypeRSA1024 }
|
func (*RSAKey) Type() KeyType { return KeyTypeRSA1024 }
|
||||||
|
|
||||||
|
// Blob implements Key.Blob.
|
||||||
func (r *RSAKey) Blob() string {
|
func (r *RSAKey) Blob() string {
|
||||||
return base64.StdEncoding.EncodeToString(x509.MarshalPKCS1PrivateKey(r.PrivateKey))
|
return base64.StdEncoding.EncodeToString(x509.MarshalPKCS1PrivateKey(r.PrivateKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ED25519Key is a Key for AddOnion that is a ed25519 key (i.e. v3).
|
||||||
type ED25519Key ed25519.PrivateKey
|
type ED25519Key ed25519.PrivateKey
|
||||||
|
|
||||||
|
// ED25519KeyFromBlob creates a ED25519Key for the given response blob.
|
||||||
func ED25519KeyFromBlob(blob string) (ED25519Key, error) {
|
func ED25519KeyFromBlob(blob string) (ED25519Key, error) {
|
||||||
byts, err := base64.StdEncoding.DecodeString(blob)
|
byts, err := base64.StdEncoding.DecodeString(blob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -80,24 +106,40 @@ func ED25519KeyFromBlob(blob string) (ED25519Key, error) {
|
||||||
}
|
}
|
||||||
return ED25519Key(ed25519.PrivateKey(byts)), nil
|
return ED25519Key(ed25519.PrivateKey(byts)), nil
|
||||||
}
|
}
|
||||||
func (ED25519Key) Type() KeyType { return KeyTypeED25519V3 }
|
|
||||||
|
// Type implements Key.Type.
|
||||||
|
func (ED25519Key) Type() KeyType { return KeyTypeED25519V3 }
|
||||||
|
|
||||||
|
// Blob implements Key.Blob.
|
||||||
func (e ED25519Key) Blob() string { return base64.StdEncoding.EncodeToString(e) }
|
func (e ED25519Key) Blob() string { return base64.StdEncoding.EncodeToString(e) }
|
||||||
|
|
||||||
|
// AddOnionRequest is a set of request params for AddOnion.
|
||||||
type AddOnionRequest struct {
|
type AddOnionRequest struct {
|
||||||
Key Key
|
// Key is the key to use or GenKey if Tor should generate it.
|
||||||
Flags []string
|
Key Key
|
||||||
MaxStreams int
|
// Flags are ADD_ONION flags.
|
||||||
Ports map[string]string
|
Flags []string
|
||||||
|
// MaxStreams is ADD_ONION MaxStreams.
|
||||||
|
MaxStreams int
|
||||||
|
// Ports are ADD_ONION Port values. Key is virtual port, value is target port (or can be empty to use virtual port).
|
||||||
|
Ports map[string]string
|
||||||
|
// ClientAuths are ADD_ONION ClientAuth values. If value is empty string, Tor will generate the password.
|
||||||
ClientAuths map[string]string
|
ClientAuths map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddOnionResponse is the response for AddOnion.
|
||||||
type AddOnionResponse struct {
|
type AddOnionResponse struct {
|
||||||
ServiceID string
|
// ServiceID is the ADD_ONION response ServiceID value.
|
||||||
Key Key
|
ServiceID string
|
||||||
|
// Key is the ADD_ONION response PrivateKey value.
|
||||||
|
Key Key
|
||||||
|
// ClientAuths are the ADD_ONION response ClientAuth values.
|
||||||
ClientAuths map[string]string
|
ClientAuths map[string]string
|
||||||
|
// RawResponse is the raw ADD_ONION response.
|
||||||
RawResponse *Response
|
RawResponse *Response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddOnion invokes ADD_ONION and returns its response.
|
||||||
func (c *Conn) AddOnion(req *AddOnionRequest) (*AddOnionResponse, error) {
|
func (c *Conn) AddOnion(req *AddOnionRequest) (*AddOnionResponse, error) {
|
||||||
// Build command
|
// Build command
|
||||||
if req.Key == nil {
|
if req.Key == nil {
|
||||||
|
@ -148,6 +190,7 @@ func (c *Conn) AddOnion(req *AddOnionRequest) (*AddOnionResponse, error) {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DelOnion invokes DELONION.
|
||||||
func (c *Conn) DelOnion(serviceID string) error {
|
func (c *Conn) DelOnion(serviceID string) error {
|
||||||
return c.sendRequestIgnoreResponse("DELONION %v", serviceID)
|
return c.sendRequestIgnoreResponse("DELONION %v", serviceID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Start tor with default config
|
||||||
|
t, err := tor.Start(nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
// Add a handler
|
||||||
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("Hello, World!"))
|
||||||
|
})
|
||||||
|
// Create an onion service to listen on 8080 but show as 80
|
||||||
|
l, err := t.Listen(&tor.OnionConf{Port: 80, TargetPort: 8080})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
// Serve on HTTP
|
||||||
|
log.Fatal(http.Serve(l, nil))
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package tor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Tor struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type StartConf struct {
|
||||||
|
// TODO: docs...Nil means contet.Background
|
||||||
|
Context context.Context
|
||||||
|
// TODO: docs...Empty string means just "tor" either locally or on PATH
|
||||||
|
ExePath string
|
||||||
|
// TODO: docs...If true, doesn't use exe path, uses statically compiled Tor
|
||||||
|
Embedded bool
|
||||||
|
// TODO: docs...If 0, Tor is asked to store the control port in a temporary file in the data directory that is
|
||||||
|
// deleted after read
|
||||||
|
ControlPort int
|
||||||
|
// TODO: docs...If not empty, this is the data directory used and *TempDataDir* fields are unused
|
||||||
|
DataDir string
|
||||||
|
// TODO: docs...If not empty, this is the parent directory that a child dir is created for data. If empty, the
|
||||||
|
// current dir is assumed. This has no effect if DataDir is set.
|
||||||
|
TempDataDirBase string
|
||||||
|
// TODO: docs...If true the temporary data dir is not deleted on close. This has no effect if DataDir is set.
|
||||||
|
RetainTempDataDir bool
|
||||||
|
// TODO: docs...Any extra CLI arguments to pass to Tor. This are applied after other CLI args.
|
||||||
|
ExtraArgs []string
|
||||||
|
// TODO: docs...
|
||||||
|
DebugWriter io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tor) Start(conf *StartConf) error {
|
||||||
|
// actualConf := *conf
|
||||||
|
panic("TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
type OnionConf struct {
|
||||||
|
Port int
|
||||||
|
TargetPort int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tor) Listen(conf *OnionConf) (net.Listener, error) {
|
||||||
|
panic("TODO")
|
||||||
|
}
|
Loading…
Reference in New Issue