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)
|
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"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"net/textproto"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/cretz/bine/control"
|
||||||
tor035 "github.com/cretz/bine/process/embedded/tor-0.3.5"
|
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() {
|
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)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runTor(args ...string) error {
|
func runTor(args ...string) error {
|
||||||
creator := tor035.NewProcessCreator()
|
process, err := tor035.NewCreator().New(context.Background(), args...)
|
||||||
creator.SetupControlSocket = true
|
|
||||||
process, err := creator.New(context.Background(), args...)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fmt.Printf("Socket pointer: %v\n", tor035.ProcessControlSocket(process))
|
|
||||||
process.Start()
|
process.Start()
|
||||||
err = process.Wait()
|
err = process.Wait()
|
||||||
}
|
}
|
||||||
return err
|
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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/cretz/bine/process"
|
"github.com/cretz/bine/process"
|
||||||
)
|
)
|
||||||
|
@ -50,12 +52,7 @@ static void freeCharArray(char **a, int size) {
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
// ProcessCreator implements process.Creator
|
type embeddedCreator struct{}
|
||||||
type ProcessCreator struct {
|
|
||||||
// If set to true, ProcessControlSocket will have a raw socket to
|
|
||||||
// communicate with Tor on.
|
|
||||||
SetupControlSocket bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProviderVersion returns the Tor provider name and version exposed from the
|
// ProviderVersion returns the Tor provider name and version exposed from the
|
||||||
// Tor embedded API.
|
// Tor embedded API.
|
||||||
|
@ -63,32 +60,27 @@ func ProviderVersion() string {
|
||||||
return C.GoString(C.tor_api_get_provider_version())
|
return C.GoString(C.tor_api_get_provider_version())
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProcessCreator creates a process.Creator for statically-linked Tor
|
// NewCreator creates a process.Creator for statically-linked Tor embedded in
|
||||||
// embedded in the binary.
|
// the binary.
|
||||||
func NewProcessCreator() *ProcessCreator {
|
func NewCreator() process.Creator {
|
||||||
return &ProcessCreator{}
|
return embeddedCreator{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type embeddedProcess struct {
|
type embeddedProcess struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
mainConf *C.struct_tor_main_configuration_t
|
mainConf *C.struct_tor_main_configuration_t
|
||||||
controlSocket uintptr
|
args []string
|
||||||
args []string
|
doneCh chan int
|
||||||
doneCh chan int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New implements process.Creator.New
|
// New implements process.Creator.New
|
||||||
func (p *ProcessCreator) New(ctx context.Context, args ...string) (process.Process, error) {
|
func (embeddedCreator) New(ctx context.Context, args ...string) (process.Process, error) {
|
||||||
ret := &embeddedProcess{
|
return &embeddedProcess{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
|
// TODO: mem leak if they never call Start; consider adding a Close()
|
||||||
mainConf: C.tor_main_configuration_new(),
|
mainConf: C.tor_main_configuration_new(),
|
||||||
args: args,
|
args: args,
|
||||||
}
|
}, nil
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *embeddedProcess) Start() error {
|
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
|
func (e *embeddedProcess) EmbeddedControlConn() (net.Conn, error) {
|
||||||
// ProcessCreator with SetupControlSocket as true. Note, the value of this is
|
file := os.NewFile(uintptr(C.tor_main_configuration_setup_control_socket(e.mainConf)), "")
|
||||||
// invalid when Start returns.
|
conn, err := net.FileConn(file)
|
||||||
func ProcessControlSocket(p process.Process) uintptr {
|
if err != nil {
|
||||||
return p.(*embeddedProcess).controlSocket
|
err = fmt.Errorf("Unable to create conn from control socket: %v", err)
|
||||||
|
}
|
||||||
|
return conn, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ package process
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -26,6 +27,12 @@ type Process interface {
|
||||||
// Wait waits for the Tor process to exit and returns error if it was not a
|
// 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.
|
// successful exit. It is analagous to os/exec.Cmd.Wait.
|
||||||
Wait() error
|
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.
|
// Creator is the interface for process creation.
|
||||||
|
@ -43,11 +50,23 @@ func NewCreator(exePath string) Creator {
|
||||||
return &exeProcessCreator{exePath}
|
return &exeProcessCreator{exePath}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type exeProcess struct {
|
||||||
|
*exec.Cmd
|
||||||
|
}
|
||||||
|
|
||||||
func (e *exeProcessCreator) New(ctx context.Context, args ...string) (Process, error) {
|
func (e *exeProcessCreator) New(ctx context.Context, args ...string) (Process, error) {
|
||||||
cmd := exec.CommandContext(ctx, e.exePath, args...)
|
cmd := exec.CommandContext(ctx, e.exePath, args...)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
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
|
// ControlPortFromFileContents reads a control port file that is written by Tor
|
||||||
|
|
Loading…
Reference in New Issue