bine/process/process.go

83 lines
2.7 KiB
Go
Raw Normal View History

2018-05-14 20:18:32 +00:00
// Package process is the low-level abstraction for a Tor instance.
//
2018-05-14 20:36:29 +00:00
// The standard use is to create a Creator with NewCreator and the path to the
// Tor executable. The child package 'embedded' can be used if Tor is statically
// linked in the binary. Most developers will prefer the tor package adjacent to
// this one for a higher level abstraction over the process and control port
// connection.
2018-05-10 18:11:18 +00:00
package process
2018-05-14 20:18:32 +00:00
import (
"context"
"fmt"
"net"
2018-05-14 20:18:32 +00:00
"os"
"os/exec"
"strconv"
"strings"
2020-10-15 21:38:02 +00:00
"git.openprivacy.ca/openprivacy/bine/torutil"
2018-05-14 20:18:32 +00:00
)
2018-05-14 19:47:05 +00:00
// Process is the interface implemented by Tor processes.
2018-05-10 21:29:16 +00:00
type Process interface {
2018-05-14 20:36:29 +00:00
// Start starts the Tor process in the background and returns. It is
// analagous to os/exec.Cmd.Start.
2018-05-14 18:11:18 +00:00
Start() error
2018-05-14 20:36:29 +00:00
// Wait waits for the Tor process to exit and returns error if it was not a
2018-05-17 19:37:22 +00:00
// successful exit. It is analagous to os/exec.Cmd.Wait.
2018-05-14 18:11:18 +00:00
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)
2018-05-10 18:11:18 +00:00
}
2018-05-14 20:18:32 +00:00
// Creator is the interface for process creation.
type Creator interface {
New(ctx context.Context, args ...string) (Process, error)
}
type CmdCreatorFunc func(ctx context.Context, args ...string) (*exec.Cmd, error)
2018-05-14 20:18:32 +00:00
2018-05-14 20:36:29 +00:00
// NewCreator creates a Creator for external Tor process execution based on the
// given exe path.
2018-05-14 20:18:32 +00:00
func NewCreator(exePath string) Creator {
return CmdCreatorFunc(func(ctx context.Context, args ...string) (*exec.Cmd, error) {
cmd := exec.CommandContext(ctx, exePath, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd, nil
})
2018-05-14 20:18:32 +00:00
}
type exeProcess struct {
*exec.Cmd
}
func (c CmdCreatorFunc) New(ctx context.Context, args ...string) (Process, error) {
cmd, err := c(ctx, args...)
return &exeProcess{cmd}, err
}
// 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
2018-05-14 20:18:32 +00:00
}
2018-05-14 20:36:29 +00:00
// ControlPortFromFileContents reads a control port file that is written by Tor
// when ControlPortWriteToFile is set.
2018-05-14 20:18:32 +00:00
func ControlPortFromFileContents(contents string) (int, error) {
contents = strings.TrimSpace(contents)
_, port, ok := torutil.PartitionString(contents, ':')
2018-05-14 20:18:32 +00:00
if !ok || !strings.HasPrefix(contents, "PORT=") {
return 0, fmt.Errorf("Invalid port format: %v", contents)
}
return strconv.Atoi(port)
}