Commits:
-
6407d484
by Elena at 2026-08-19T19:37:53+02:00
fixup! TB 44806: Implement the tor integration in Rust.
TB 44930: Implement the commands on the Rust control port
Add a way to add a handler for when connections are closed.
6 changed files:
Changes:
toolkit/components/tor-integration/test/xpcshell/head.js
| ... |
... |
@@ -190,10 +190,7 @@ class ControlPortClient { |
|
190
|
190
|
} else {
|
|
191
|
191
|
throw new Error("Unknown server protocol");
|
|
192
|
192
|
}
|
|
193
|
|
- const receiver = {
|
|
194
|
|
- onAsyncMessage: message => this.onAsyncMessage(message),
|
|
195
|
|
- };
|
|
196
|
|
- this.#controlPort.start(receiver);
|
|
|
193
|
+ this.#controlPort.start(this);
|
|
197
|
194
|
}
|
|
198
|
195
|
|
|
199
|
196
|
sendCommand(command) {
|
| ... |
... |
@@ -216,4 +213,6 @@ class ControlPortClient { |
|
216
|
213
|
onAsyncMessage(_message) {
|
|
217
|
214
|
Assert.ok(false, "This test does not use async notifications.");
|
|
218
|
215
|
}
|
|
|
216
|
+
|
|
|
217
|
+ onClosed() {}
|
|
219
|
218
|
} |
toolkit/components/tor-integration/test/xpcshell/test_control_port.js
| ... |
... |
@@ -67,18 +67,27 @@ add_task(async function test_invalidSyntax() { |
|
67
|
67
|
class ControlPortClientAsyncNotification extends ControlPortClient {
|
|
68
|
68
|
notificationPromise;
|
|
69
|
69
|
#resolve;
|
|
|
70
|
+ closedPromise;
|
|
|
71
|
+ #closedResolve;
|
|
70
|
72
|
|
|
71
|
73
|
constructor(server) {
|
|
72
|
74
|
super(server);
|
|
73
|
|
- const { promise, resolve } = Promise.withResolvers();
|
|
74
|
|
- this.notificationPromise = promise;
|
|
75
|
|
- this.#resolve = resolve;
|
|
|
75
|
+ this.notificationPromise = new Promise(
|
|
|
76
|
+ resolve => (this.#resolve = resolve)
|
|
|
77
|
+ );
|
|
|
78
|
+ this.closedPromise = new Promise(
|
|
|
79
|
+ resolve => (this.#closedResolve = resolve)
|
|
|
80
|
+ );
|
|
76
|
81
|
}
|
|
77
|
82
|
|
|
78
|
83
|
onAsyncMessage(message) {
|
|
79
|
84
|
Assert.equal(message, "650-Test\r\n650 notification");
|
|
80
|
85
|
this.#resolve();
|
|
81
|
86
|
}
|
|
|
87
|
+
|
|
|
88
|
+ onClosed() {
|
|
|
89
|
+ this.#closedResolve();
|
|
|
90
|
+ }
|
|
82
|
91
|
}
|
|
83
|
92
|
|
|
84
|
93
|
add_task(async function test_asyncNotification() {
|
| ... |
... |
@@ -91,6 +100,7 @@ add_task(async function test_asyncNotification() { |
|
91
|
100
|
await cp.notificationPromise;
|
|
92
|
101
|
cp.close();
|
|
93
|
102
|
server.close();
|
|
|
103
|
+ await cp.closedPromise;
|
|
94
|
104
|
});
|
|
95
|
105
|
});
|
|
96
|
106
|
|
toolkit/components/tor-integration/torITorService.idl
| ... |
... |
@@ -8,6 +8,7 @@ |
|
8
|
8
|
[scriptable, uuid(4b250614-968a-412f-9191-9ffd9d4bd001)]
|
|
9
|
9
|
interface torITorControlPortReceiver : nsISupports {
|
|
10
|
10
|
void onAsyncMessage(in ACString message);
|
|
|
11
|
+ void onClosed();
|
|
11
|
12
|
};
|
|
12
|
13
|
|
|
13
|
14
|
[scriptable, uuid(1389d157-4695-43a2-a7d8-538aaa350766)]
|
toolkit/components/tor-integration/tor_provider/src/ctor/control_port/control_port.rs
| ... |
... |
@@ -5,7 +5,7 @@ |
|
5
|
5
|
|
|
6
|
6
|
use bytes::Bytes;
|
|
7
|
7
|
use std::{
|
|
8
|
|
- cell::Cell,
|
|
|
8
|
+ cell::{Cell, RefCell},
|
|
9
|
9
|
rc::{Rc, Weak},
|
|
10
|
10
|
};
|
|
11
|
11
|
|
| ... |
... |
@@ -25,6 +25,7 @@ struct ControlPortInner { |
|
25
|
25
|
socket: Rc<dyn ControlSocket>,
|
|
26
|
26
|
writer: Rc<CommandWriter>,
|
|
27
|
27
|
message_pump: Rc<MessagePump>,
|
|
|
28
|
+ close_handler: RefCell<Option<Box<dyn FnOnce()>>>,
|
|
28
|
29
|
closed: Cell<bool>,
|
|
29
|
30
|
}
|
|
30
|
31
|
|
| ... |
... |
@@ -41,6 +42,7 @@ impl ControlPortInner { |
|
41
|
42
|
Self::make_data_cb(weak_self.clone()),
|
|
42
|
43
|
Self::make_async_failure_cb(weak_self.clone()),
|
|
43
|
44
|
),
|
|
|
45
|
+ close_handler: RefCell::new(None),
|
|
44
|
46
|
closed: Cell::new(false),
|
|
45
|
47
|
});
|
|
46
|
48
|
cp.message_pump.start().inspect_err(|_| {
|
| ... |
... |
@@ -140,7 +142,22 @@ impl ControlPortInner { |
|
140
|
142
|
}
|
|
141
|
143
|
self.reply_dispatcher.fail_all(ReplyError::ConnectionClosed);
|
|
142
|
144
|
self.reply_dispatcher.set_async_handler(None);
|
|
143
|
|
- self.socket.close()
|
|
|
145
|
+ let res = self.socket.close();
|
|
|
146
|
+ let handler = self.close_handler.borrow_mut().take();
|
|
|
147
|
+ if let Some(h) = handler {
|
|
|
148
|
+ h();
|
|
|
149
|
+ }
|
|
|
150
|
+ res
|
|
|
151
|
+ }
|
|
|
152
|
+
|
|
|
153
|
+ fn set_close_handler(&self, cb: Box<dyn FnOnce()>) {
|
|
|
154
|
+ if self.closed.get() {
|
|
|
155
|
+ // This should never happen in reality, but let's just call the
|
|
|
156
|
+ // callback if it does to make sure the callback is always called.
|
|
|
157
|
+ cb();
|
|
|
158
|
+ return;
|
|
|
159
|
+ }
|
|
|
160
|
+ *self.close_handler.borrow_mut() = Some(cb);
|
|
144
|
161
|
}
|
|
145
|
162
|
}
|
|
146
|
163
|
|
| ... |
... |
@@ -183,4 +200,9 @@ impl ControlPort { |
|
183
|
200
|
pub fn close(&self) -> Result<(), ControlSocketError> {
|
|
184
|
201
|
self.0.close()
|
|
185
|
202
|
}
|
|
|
203
|
+
|
|
|
204
|
+ #[inline]
|
|
|
205
|
+ pub fn set_close_handler(&self, cb: Box<dyn FnOnce()>) {
|
|
|
206
|
+ self.0.set_close_handler(cb);
|
|
|
207
|
+ }
|
|
186
|
208
|
} |
toolkit/components/tor-integration/tor_service/src/control_port.rs
| ... |
... |
@@ -37,6 +37,7 @@ impl ControlPortXpcom { |
|
37
|
37
|
xpcom_method!(start => Start(receiver: *const torITorControlPortReceiver));
|
|
38
|
38
|
pub fn start(&self, receiver: &torITorControlPortReceiver) -> Result<(), nsresult> {
|
|
39
|
39
|
let receiver = RefPtr::new(receiver);
|
|
|
40
|
+ let receiver2 = receiver.clone();
|
|
40
|
41
|
self.control_port
|
|
41
|
42
|
.set_async_handler(Some(Box::new(move |reply| {
|
|
42
|
43
|
let mut buf = Vec::new();
|
| ... |
... |
@@ -58,6 +59,11 @@ impl ControlPortXpcom { |
|
58
|
59
|
// pass nsCStrings created in Rust to C++.
|
|
59
|
60
|
unsafe { receiver.OnAsyncMessage(&*as_str) };
|
|
60
|
61
|
})));
|
|
|
62
|
+ self.control_port.set_close_handler(Box::new(move || {
|
|
|
63
|
+ // Safety: call to an XPCOM method of our interface that we crafted
|
|
|
64
|
+ // to make sure it was exposed on Rust bindings.
|
|
|
65
|
+ unsafe { receiver2.OnClosed() };
|
|
|
66
|
+ }));
|
|
61
|
67
|
Ok(())
|
|
62
|
68
|
}
|
|
63
|
69
|
|
toolkit/components/tor-launcher/TorControlPort.sys.mjs
| ... |
... |
@@ -565,6 +565,9 @@ export class TorController { |
|
565
|
565
|
onAsyncMessage(message) {
|
|
566
|
566
|
self.#handleNotification(message);
|
|
567
|
567
|
},
|
|
|
568
|
+ onClosed() {
|
|
|
569
|
+ self.onClosed();
|
|
|
570
|
+ },
|
|
568
|
571
|
};
|
|
569
|
572
|
this.#socket.start(receiver);
|
|
570
|
573
|
return;
|
|