More explicit embedded socket support for issue #13
This commit is contained in:
parent
b4e16a90bf
commit
8ba66edb0c
|
@ -110,3 +110,7 @@ func (e *embeddedProcess) Wait() error {
|
|||
return fmt.Errorf("Command completed with error exit code: %v", code)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *embeddedProcess) EmbeddedControlConn() (net.Conn, error) {
|
||||
return nil, process.ErrControlConnUnsupported
|
||||
}
|
|
@ -4,26 +4,59 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/textproto"
|
||||
"os"
|
||||
|
||||
"github.com/cretz/bine/control"
|
||||
tor035 "github.com/cretz/bine/process/embedded/tor-0.3.5"
|
||||
)
|
||||
|
||||
// Simply calls Tor will the same parameters
|
||||
// Simply calls Tor will the same parameters, unless "embedconn" is the arg
|
||||
func main() {
|
||||
if err := runTor(os.Args[1:]...); err != nil {
|
||||
fmt.Printf("Provider version: %v\n", tor035.ProviderVersion())
|
||||
var err error
|
||||
if len(os.Args) == 2 && os.Args[1] == "embedconn" {
|
||||
fmt.Println("Testing embedded conn")
|
||||
err = testEmbedConn()
|
||||
} else {
|
||||
fmt.Println("Running Tor with given args")
|
||||
err = runTor(os.Args[1:]...)
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func runTor(args ...string) error {
|
||||
creator := tor035.NewProcessCreator()
|
||||
creator.SetupControlSocket = true
|
||||
process, err := creator.New(context.Background(), args...)
|
||||
process, err := tor035.NewCreator().New(context.Background(), args...)
|
||||
if err == nil {
|
||||
fmt.Printf("Socket pointer: %v\n", tor035.ProcessControlSocket(process))
|
||||
process.Start()
|
||||
err = process.Wait()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func testEmbedConn() error {
|
||||
process, err := tor035.NewCreator().New(context.Background())
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed creating process: %v", err)
|
||||
}
|
||||
// Try to create an embedded conn
|
||||
embedConn, err := process.EmbeddedControlConn()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed creating embedded control conn: %v", err)
|
||||
}
|
||||
if err = process.Start(); err != nil {
|
||||
return fmt.Errorf("Failed starting process: %v", err)
|
||||
}
|
||||
controlConn := control.NewConn(textproto.NewConn(embedConn))
|
||||
info, err := controlConn.GetInfo("version")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed getting version: %v", err)
|
||||
}
|
||||
fmt.Printf("Got info, %v: %v\n", info[0].Key, info[0].Val)
|
||||
if err = process.Wait(); err != nil {
|
||||
return fmt.Errorf("Failed waiting for process: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ package tor035
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/cretz/bine/process"
|
||||
)
|
||||
|
@ -50,12 +52,7 @@ static void freeCharArray(char **a, int size) {
|
|||
*/
|
||||
import "C"
|
||||
|
||||
// ProcessCreator implements process.Creator
|
||||
type ProcessCreator struct {
|
||||
// If set to true, ProcessControlSocket will have a raw socket to
|
||||
// communicate with Tor on.
|
||||
SetupControlSocket bool
|
||||
}
|
||||
type embeddedCreator struct{}
|
||||
|
||||
// ProviderVersion returns the Tor provider name and version exposed from the
|
||||
// Tor embedded API.
|
||||
|
@ -63,32 +60,27 @@ func ProviderVersion() string {
|
|||
return C.GoString(C.tor_api_get_provider_version())
|
||||
}
|
||||
|
||||
// NewProcessCreator creates a process.Creator for statically-linked Tor
|
||||
// embedded in the binary.
|
||||
func NewProcessCreator() *ProcessCreator {
|
||||
return &ProcessCreator{}
|
||||
// NewCreator creates a process.Creator for statically-linked Tor embedded in
|
||||
// the binary.
|
||||
func NewCreator() process.Creator {
|
||||
return embeddedCreator{}
|
||||
}
|
||||
|
||||
type embeddedProcess struct {
|
||||
ctx context.Context
|
||||
mainConf *C.struct_tor_main_configuration_t
|
||||
controlSocket uintptr
|
||||
args []string
|
||||
doneCh chan int
|
||||
ctx context.Context
|
||||
mainConf *C.struct_tor_main_configuration_t
|
||||
args []string
|
||||
doneCh chan int
|
||||
}
|
||||
|
||||
// New implements process.Creator.New
|
||||
func (p *ProcessCreator) New(ctx context.Context, args ...string) (process.Process, error) {
|
||||
ret := &embeddedProcess{
|
||||
ctx: ctx,
|
||||
func (embeddedCreator) New(ctx context.Context, args ...string) (process.Process, error) {
|
||||
return &embeddedProcess{
|
||||
ctx: ctx,
|
||||
// TODO: mem leak if they never call Start; consider adding a Close()
|
||||
mainConf: C.tor_main_configuration_new(),
|
||||
args: args,
|
||||
}
|
||||
// If they want a control socket, this is where we add it
|
||||
if p.SetupControlSocket {
|
||||
ret.controlSocket = uintptr(C.tor_main_configuration_setup_control_socket(ret.mainConf))
|
||||
}
|
||||
return ret, nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (e *embeddedProcess) Start() error {
|
||||
|
@ -136,9 +128,11 @@ func (e *embeddedProcess) Wait() error {
|
|||
}
|
||||
}
|
||||
|
||||
// ProcessControlSocket returns a non-zero value for a process created by a
|
||||
// ProcessCreator with SetupControlSocket as true. Note, the value of this is
|
||||
// invalid when Start returns.
|
||||
func ProcessControlSocket(p process.Process) uintptr {
|
||||
return p.(*embeddedProcess).controlSocket
|
||||
func (e *embeddedProcess) EmbeddedControlConn() (net.Conn, error) {
|
||||
file := os.NewFile(uintptr(C.tor_main_configuration_setup_control_socket(e.mainConf)), "")
|
||||
conn, err := net.FileConn(file)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Unable to create conn from control socket: %v", err)
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ package process
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
|
@ -26,6 +27,12 @@ type Process interface {
|
|||
// Wait waits for the Tor process to exit and returns error if it was not a
|
||||
// successful exit. It is analagous to os/exec.Cmd.Wait.
|
||||
Wait() error
|
||||
// ControlConn is used for statically linked, embedded processes to create
|
||||
// a controller connection. For non-embedded processes or Tor versions that
|
||||
// don't support embedded control connections, ErrControlConnUnsupported is
|
||||
// returned. Note, this should only be called once per process before
|
||||
// Start, and the connection does not need to be closed.
|
||||
EmbeddedControlConn() (net.Conn, error)
|
||||
}
|
||||
|
||||
// Creator is the interface for process creation.
|
||||
|
@ -43,11 +50,23 @@ func NewCreator(exePath string) Creator {
|
|||
return &exeProcessCreator{exePath}
|
||||
}
|
||||
|
||||
type exeProcess struct {
|
||||
*exec.Cmd
|
||||
}
|
||||
|
||||
func (e *exeProcessCreator) New(ctx context.Context, args ...string) (Process, error) {
|
||||
cmd := exec.CommandContext(ctx, e.exePath, args...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd, nil
|
||||
return &exeProcess{cmd}, nil
|
||||
}
|
||||
|
||||
// ErrControlConnUnsupported is returned by Process.EmbeddedControlConn when
|
||||
// it is unsupported.
|
||||
var ErrControlConnUnsupported = fmt.Errorf("Control conn not supported")
|
||||
|
||||
func (e *exeProcess) EmbeddedControlConn() (net.Conn, error) {
|
||||
return nil, ErrControlConnUnsupported
|
||||
}
|
||||
|
||||
// ControlPortFromFileContents reads a control port file that is written by Tor
|
||||
|
|
Loading…
Reference in New Issue