forked from ipsn/go-libtor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlibtor_internal.go.in
126 lines (111 loc) · 3.34 KB
/
libtor_internal.go.in
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// go-libtor - Self-contained Tor from Go
// Copyright (c) 2018 Péter Szilágyi. All rights reserved.
// Package libtor is a self-contained static tor library.
package libtor
// This file is a simplified clone from github.com/cretz/bine/process/embedded.
/*
#include <stdlib.h>
#include <tor_api.h>
static char** makeCharArray(int size) {
return calloc(sizeof(char*), size);
}
static void setArrayString(char **a, char *s, int n) {
a[n] = s;
}
static void freeCharArray(char **a, int size) {
int i;
for (i = 0; i < size; i++)
free(a[i]);
free(a);
}
*/
import "C"
import (
"context"
"errors"
"fmt"
"net"
"os"
"github.com/cretz/bine/process"
)
// ProviderVersion returns the Tor provider name and version exposed from the
// Tor embedded API.
func ProviderVersion() string {
return C.GoString(C.tor_api_get_provider_version())
}
// Creator implements the bine.process.Creator, permitting libtor to act as an API
// backend for the bine/tor Go interface.
var Creator process.Creator = new(embeddedCreator)
// embeddedCreator implements process.Creator, permitting libtor to act as an API
// backend for the bine/tor Go interface.
type embeddedCreator struct{}
// New implements process.Creator, creating a new embedded tor process.
func (embeddedCreator) New(ctx context.Context, args ...string) (process.Process, error) {
if ctx == nil {
ctx = context.Background()
}
return &embeddedProcess{
ctx: ctx,
conf: C.tor_main_configuration_new(),
args: args,
}, nil
}
// embeddedProcess implements process.Process, permitting libtor to act as an API
// backend for the bine/tor Go interface.
type embeddedProcess struct {
ctx context.Context
conf *C.struct_tor_main_configuration_t
args []string
done chan int
}
// Start implements process.Process, starting up the libtor embedded process.
func (e *embeddedProcess) Start() error {
if e.done != nil {
return errors.New("already started")
}
// Create the char array for the args
args := append([]string{"tor"}, e.args...)
charArray := C.makeCharArray(C.int(len(args)))
for i, a := range args {
C.setArrayString(charArray, C.CString(a), C.int(i))
}
// Build the tor configuration
if code := C.tor_main_configuration_set_command_line(e.conf, C.int(len(args)), charArray); code != 0 {
C.tor_main_configuration_free(e.conf)
C.freeCharArray(charArray, C.int(len(args)))
return fmt.Errorf("failed to set arguments: %v", int(code))
}
// Start tor and return
e.done = make(chan int, 1)
go func() {
defer C.freeCharArray(charArray, C.int(len(args)))
defer C.tor_main_configuration_free(e.conf)
e.done <- int(C.tor_run_main(e.conf))
}()
return nil
}
// Wait implements process.Process, blocking until the embedded process terminates.
func (e *embeddedProcess) Wait() error {
if e.done == nil {
return errors.New("not started")
}
select {
case <-e.ctx.Done():
return e.ctx.Err()
case code := <-e.done:
if code == 0 {
return nil
}
return fmt.Errorf("embedded tor failed: %v", code)
}
}
// EmbeddedControlConn implements process.Process, connecting to the control port
// of the embedded Tor isntance.
func (e *embeddedProcess) EmbeddedControlConn() (net.Conn, error) {
file := os.NewFile(uintptr(C.tor_main_configuration_setup_control_socket(e.conf)), "")
conn, err := net.FileConn(file)
if err != nil {
return nil, fmt.Errorf("unable to create control socket: %v", err)
}
return conn, nil
}