1//
2// TORThread.m
3// Tor
4//
5// Created by Conrad Kramer on 7/19/15.
6//
7
8#import "TORThread.h"
9#import "TORConfiguration.h"
10
11NS_ASSUME_NONNULL_BEGIN
12
13// When the tor.xcframework binary is not present (development builds without the framework
14// binary), this stub compiles successfully. TorManager will time out waiting for the control
15// socket and transition to .failed("Control socket timeout") — acceptable for local dev.
16#if __has_include(<feature/api/tor_api.h>)
17
18#import <feature/api/tor_api.h>
19#import "TORLogging.h"
20
21static __weak TORThread *_thread = nil;
22
23@interface TORThread ()
24@property (nonatomic, readonly, copy, nullable) NSArray<NSString *> *arguments;
25@end
26
27@implementation TORThread
28
29+ (nullable TORThread *)activeThread { return _thread; }
30
31- (instancetype)init { return [self initWithArguments:nil]; }
32
33- (instancetype)initWithConfiguration:(nullable TORConfiguration *)configuration {
34 return [self initWithArguments:[configuration compile]];
35}
36
37- (instancetype)initWithArguments:(nullable NSArray<NSString *> *)arguments {
38 NSAssert(_thread == nil, @"There can only be one TORThread per process");
39 self = [super init];
40 if (!self) return nil;
41 _thread = self;
42 _arguments = [arguments copy];
43 self.name = @"Tor";
44 return self;
45}
46
47- (void)main {
48 NSArray *arguments = self.arguments;
49 int argc = (int)(arguments.count + 1);
50 char *argv[argc];
51 argv[0] = "tor";
52 for (NSUInteger idx = 0; idx < arguments.count; idx++)
53 argv[idx + 1] = (char *)[arguments[idx] UTF8String];
54 argv[argc] = NULL;
55
56 tor_main_configuration_t *cfg = tor_main_configuration_new();
57 tor_main_configuration_set_command_line(cfg, argc, argv);
58 tor_run_main(cfg);
59 tor_main_configuration_free(cfg);
60}
61
62@end
63
64#else // Framework binary not available — provide no-op stub for local development builds
65
66static __weak TORThread *_thread = nil;
67
68@interface TORThread ()
69@property (nonatomic, readonly, copy, nullable) NSArray<NSString *> *arguments;
70@end
71
72@implementation TORThread
73
74+ (nullable TORThread *)activeThread { return _thread; }
75
76- (instancetype)init { return [self initWithArguments:nil]; }
77
78- (instancetype)initWithConfiguration:(nullable TORConfiguration *)configuration {
79 return [self initWithArguments:nil];
80}
81
82- (instancetype)initWithArguments:(nullable NSArray<NSString *> *)arguments {
83 self = [super init];
84 if (!self) return nil;
85 _thread = self;
86 _arguments = [arguments copy];
87 self.name = @"Tor";
88 return self;
89}
90
91- (void)main {
92 // Tor binary not available — no-op stub. TorManager will time out on control socket.
93}
94
95@end
96
97#endif // __has_include(<feature/api/tor_api.h>)
98
99NS_ASSUME_NONNULL_END