tor.go raw
1 // Package tor provides a Tor hidden service transport for the relay.
2 // It wraps the existing pkg/tor service as a pluggable transport.
3 package tor
4
5 import (
6 "context"
7 "net/http"
8
9 "next.orly.dev/pkg/lol/log"
10
11 torservice "next.orly.dev/pkg/tor"
12 )
13
14 // Config holds Tor transport configuration.
15 type Config struct {
16 // Port is the internal port for the hidden service.
17 Port int
18 // DataDir is the directory for Tor data (torrc, keys, hostname, etc.).
19 DataDir string
20 // Binary is the path to the tor executable.
21 Binary string
22 // SOCKSPort is the port for outbound SOCKS connections (0 = disabled).
23 SOCKSPort int
24 // Handler is the HTTP handler to serve.
25 Handler http.Handler
26 }
27
28 // Transport serves the relay as a Tor hidden service.
29 type Transport struct {
30 cfg *Config
31 service *torservice.Service
32 }
33
34 // New creates a new Tor transport.
35 func New(cfg *Config) *Transport {
36 return &Transport{cfg: cfg}
37 }
38
39 func (t *Transport) Name() string { return "tor" }
40
41 func (t *Transport) Start(ctx context.Context) error {
42 svcCfg := &torservice.Config{
43 Port: t.cfg.Port,
44 DataDir: t.cfg.DataDir,
45 Binary: t.cfg.Binary,
46 SOCKSPort: t.cfg.SOCKSPort,
47 Handler: t.cfg.Handler,
48 }
49
50 var err error
51 t.service, err = torservice.New(svcCfg)
52 if err != nil {
53 return err
54 }
55
56 if err = t.service.Start(); err != nil {
57 t.service = nil
58 return err
59 }
60
61 if addr := t.service.OnionWSAddress(); addr != "" {
62 log.I.F("Tor hidden service listening on port %d, address: %s", t.cfg.Port, addr)
63 } else {
64 log.I.F("Tor hidden service listening on port %d (waiting for .onion address)", t.cfg.Port)
65 }
66
67 return nil
68 }
69
70 func (t *Transport) Stop(ctx context.Context) error {
71 if t.service == nil {
72 return nil
73 }
74 return t.service.Stop()
75 }
76
77 func (t *Transport) Addresses() []string {
78 if t.service == nil {
79 return nil
80 }
81 if addr := t.service.OnionWSAddress(); addr != "" {
82 return []string{addr}
83 }
84 return nil
85 }
86
87 // Service returns the underlying Tor service for access to Tor-specific
88 // functionality (e.g., OnionAddress, DataDir).
89 func (t *Transport) Service() *torservice.Service {
90 return t.service
91 }
92