[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [Git][tpo/applications/tor-browser][tor-browser-153.1.0esr-16.0-1] 6 commits: fixup! TB 44806: Implement the tor integration in Rust.



Title: GitLab

Pier Angelo Vendrame pushed to branch tor-browser-153.1.0esr-16.0-1 at The Tor Project / Applications / Tor Browser

Commits:

  • 3fcf8e84
    by Elena at 2026-08-19T10:58:03+02:00
    fixup! TB 44806: Implement the tor integration in Rust.
    
    TB 44930: Implement the commands on the Rust control port
    
    Rename ITor... interfaces to torITor...
    
    The prefix is basically a namespace, and really few interfaces do not
    have one, so add that prefix also to our interfaces.
    
  • 15498d90
    by Elena at 2026-08-19T11:09:16+02:00
    fixup! TB 44806: Implement the tor integration in Rust.
    
    TB 44930: Implement the commands on the Rust control port
    
    Make it possible to remove the async event handler.
    
    That will help when cleaning stuff up, to make sure not to keep any
    circular reference around.
    
  • 0e880d8f
    by Elena at 2026-08-19T11:09:19+02:00
    fixup! TB 44806: Implement the tor integration in Rust.
    
    TB 44930: Implement the commands on the Rust control port
    
    Stop exposing ReplyFactory to the crate.
    
    That should remain an internal type.
    Instead, we can expose a "make_reply" test utility, to create one reply
    at once. That will be enough.
    
  • 491ab443
    by Elena at 2026-08-19T11:09:19+02:00
    fixup! TB 44806: Implement the tor integration in Rust.
    
    TB 44930: Implement the commands on the Rust control port
    
    Do not add missing CRLF at the control port.
    
    We will be building commands, no need to really include the logic to
    add missing CRLF. Instead, catch malformed commands during development.
    
  • 8a46afe3
    by Elena at 2026-08-19T11:11:03+02:00
    fixup! TB 44806: Implement the tor integration in Rust.
    
    TB 44930: Implement the commands on the Rust control port
    
    Reorder some methods.
    
  • 81b76447
    by Elena at 2026-08-19T11:11:05+02:00
    fixup! TB 44806: Implement the tor integration in Rust.
    
    TB 44930: Implement the commands on the Rust control port
    
    Remove ambiguity on the connection closed error.
    

12 changed files:

Changes:

  • toolkit/components/tor-integration/TorService.h
    ... ... @@ -7,17 +7,17 @@
    7 7
     
    
    8 8
     #include "nsCOMPtr.h"
    
    9 9
     
    
    10
    -#include "ITorService.h"
    
    10
    +#include "torITorService.h"
    
    11 11
     
    
    12 12
     // Inspired by
    
    13 13
     // toolkit/components/extensions/storage/ExtensionStorageComponents.h.
    
    14 14
     
    
    15 15
     // Implemented in Rust
    
    16
    -extern "C" nsresult NewTorServiceImpl(ITorService** aResult);
    
    16
    +extern "C" nsresult NewTorServiceImpl(torITorService** aResult);
    
    17 17
     
    
    18 18
     namespace torproject {
    
    19
    -already_AddRefed<ITorService> NewTorService() {
    
    20
    -  nsCOMPtr<ITorService> service;
    
    19
    +already_AddRefed<torITorService> NewTorService() {
    
    20
    +  nsCOMPtr<torITorService> service;
    
    21 21
       nsresult rv = NewTorServiceImpl(getter_AddRefs(service));
    
    22 22
       if (NS_WARN_IF(NS_FAILED(rv))) {
    
    23 23
         return nullptr;
    

  • toolkit/components/tor-integration/components.conf
    ... ... @@ -6,7 +6,7 @@ Classes = [
    6 6
         {
    
    7 7
             'cid': '{2537313c-e120-408c-a2f6-86e6e1bdf899}',
    
    8 8
             'contract_ids': ['@torproject.org/tor-service;1'],
    
    9
    -        'interfaces': ['ITorService'],
    
    9
    +        'interfaces': ['torITorService'],
    
    10 10
             'constructor': 'torproject::NewTorService',
    
    11 11
             'headers': ['torproject/TorService.h'],
    
    12 12
             'js_name': 'tor',
    

  • toolkit/components/tor-integration/moz.build
    ... ... @@ -3,7 +3,7 @@
    3 3
     # file, You can obtain one at http://mozilla.org/MPL/2.0/.
    
    4 4
     
    
    5 5
     XPIDL_MODULE = "tor"
    
    6
    -XPIDL_SOURCES += ["ITorService.idl"]
    
    6
    +XPIDL_SOURCES += ["torITorService.idl"]
    
    7 7
     XPCOM_MANIFESTS += [
    
    8 8
         "components.conf",
    
    9 9
     ]
    

  • toolkit/components/tor-integration/ITorService.idltoolkit/components/tor-integration/torITorService.idl
    ... ... @@ -6,27 +6,27 @@
    6 6
     #include "nsIFile.idl"
    
    7 7
     
    
    8 8
     [scriptable, uuid(4b250614-968a-412f-9191-9ffd9d4bd001)]
    
    9
    -interface ITorControlPortReceiver : nsISupports {
    
    9
    +interface torITorControlPortReceiver : nsISupports {
    
    10 10
       void onAsyncMessage(in ACString message);
    
    11 11
     };
    
    12 12
     
    
    13 13
     [scriptable, uuid(1389d157-4695-43a2-a7d8-538aaa350766)]
    
    14
    -interface ITorMessageHandler : nsISupports {
    
    14
    +interface torITorMessageHandler : nsISupports {
    
    15 15
       void onMessage(in ACString message);
    
    16 16
       void onError(in ACString error);
    
    17 17
     };
    
    18 18
     
    
    19 19
     // TODO: Remove once we have a provider.
    
    20 20
     [scriptable, uuid(f56d710e-5650-4b8c-8d31-279f360003ee)]
    
    21
    -interface ITorControlPort : nsISupports {
    
    22
    -  void start(in ITorControlPortReceiver receiver);
    
    23
    -  void sendCommand(in ACString command, in ITorMessageHandler handler);
    
    21
    +interface torITorControlPort : nsISupports {
    
    22
    +  void start(in torITorControlPortReceiver receiver);
    
    23
    +  void sendCommand(in ACString command, in torITorMessageHandler handler);
    
    24 24
       void close();
    
    25 25
     };
    
    26 26
     
    
    27 27
     [scriptable, uuid(2537313c-e120-408c-a2f6-86e6e1bdf899)]
    
    28
    -interface ITorService : nsISupports {
    
    28
    +interface torITorService : nsISupports {
    
    29 29
       // For development purposes...
    
    30
    -  ITorControlPort createControlPort(in ACString host, in long port);
    
    31
    -  ITorControlPort createControlPortIPC(in nsIFile socket);
    
    30
    +  torITorControlPort createControlPort(in ACString host, in long port);
    
    31
    +  torITorControlPort createControlPortIPC(in nsIFile socket);
    
    32 32
     };

  • toolkit/components/tor-integration/tor_provider/src/ctor/control_port/control_port.rs
    ... ... @@ -3,7 +3,7 @@
    3 3
     // <http://opensource.org/licenses/MIT>, at your option. This file may not be
    
    4 4
     // copied, modified, or distributed except according to those terms.
    
    5 5
     
    
    6
    -use bytes::{BufMut, Bytes, BytesMut};
    
    6
    +use bytes::Bytes;
    
    7 7
     use std::{
    
    8 8
         cell::Cell,
    
    9 9
         rc::{Rc, Weak},
    
    ... ... @@ -79,35 +79,22 @@ impl ControlPortInner {
    79 79
             }
    
    80 80
         }
    
    81 81
     
    
    82
    -    fn close(&self) -> Result<(), ControlSocketError> {
    
    83
    -        if self.closed.replace(true) {
    
    84
    -            return Ok(());
    
    85
    -        }
    
    86
    -        self.reply_dispatcher.fail_all(ReplyError::ConnectionClosed);
    
    87
    -        self.socket.close()
    
    88
    -    }
    
    89
    -
    
    90
    -    fn set_async_handler(&self, cb: Box<dyn Fn(Reply)>) {
    
    91
    -        self.reply_dispatcher.set_async_handler(cb);
    
    92
    -    }
    
    93
    -
    
    94 82
         fn send_command(
    
    95 83
             self: &Rc<Self>,
    
    96
    -        mut command: Bytes,
    
    84
    +        command: Bytes,
    
    97 85
             handler: Box<dyn FnOnce(Result<Reply, ControlPortError>)>,
    
    98 86
         ) {
    
    99 87
             if self.closed.get() {
    
    100
    -            handler(Err(ControlPortError::ConnectionError(
    
    101
    -                ControlSocketError::ConnectionClosed,
    
    88
    +            handler(Err(ControlPortError::ProtocolError(
    
    89
    +                ReplyError::ConnectionClosed,
    
    102 90
                 )));
    
    103 91
                 return;
    
    104 92
             }
    
    105 93
     
    
    106
    -        if !command.ends_with(b"\r\n") {
    
    107
    -            let mut buf = BytesMut::from(command);
    
    108
    -            buf.put(&b"\r\n"[..]);
    
    109
    -            command = buf.freeze();
    
    110
    -        }
    
    94
    +        debug_assert!(
    
    95
    +            command.ends_with(b"\r\n"),
    
    96
    +            "Commands are expected to end with CRLF."
    
    97
    +        );
    
    111 98
     
    
    112 99
             // The callback is going to be called before other commands are sent,
    
    113 100
             // therefore it is safe to queue the callback at this point, as next
    
    ... ... @@ -128,14 +115,33 @@ impl ControlPortInner {
    128 115
                                 handler(r.map_err(|e| ControlPortError::ProtocolError(e)));
    
    129 116
                             }));
    
    130 117
                         }
    
    131
    -                    Err(e) => {
    
    132
    -                        handler(Err(ControlPortError::from(e)));
    
    118
    +                    Err(ControlSocketError::ConnectionClosed) => {
    
    119
    +                        handler(Err(ControlPortError::ProtocolError(
    
    120
    +                            ReplyError::ConnectionClosed,
    
    121
    +                        )));
    
    122
    +                        this.async_failure();
    
    123
    +                    }
    
    124
    +                    Err(ControlSocketError::ImplementationError(rv)) => {
    
    125
    +                        handler(Err(ControlPortError::ConnectionError(rv)));
    
    133 126
                             this.async_failure();
    
    134 127
                         }
    
    135 128
                     }
    
    136 129
                 }),
    
    137 130
             );
    
    138 131
         }
    
    132
    +
    
    133
    +    fn set_async_handler(&self, cb: Option<Box<dyn Fn(Reply)>>) {
    
    134
    +        self.reply_dispatcher.set_async_handler(cb);
    
    135
    +    }
    
    136
    +
    
    137
    +    fn close(&self) -> Result<(), ControlSocketError> {
    
    138
    +        if self.closed.replace(true) {
    
    139
    +            return Ok(());
    
    140
    +        }
    
    141
    +        self.reply_dispatcher.fail_all(ReplyError::ConnectionClosed);
    
    142
    +        self.reply_dispatcher.set_async_handler(None);
    
    143
    +        self.socket.close()
    
    144
    +    }
    
    139 145
     }
    
    140 146
     
    
    141 147
     impl Drop for ControlPortInner {
    
    ... ... @@ -157,11 +163,6 @@ impl ControlPort {
    157 163
             Ok(Self(ControlPortInner::new(Rc::from(socket))?))
    
    158 164
         }
    
    159 165
     
    
    160
    -    #[inline]
    
    161
    -    pub fn close(&self) -> Result<(), ControlSocketError> {
    
    162
    -        self.0.close()
    
    163
    -    }
    
    164
    -
    
    165 166
         // TODO: Keep only the methods speicifc to commands and remove this one
    
    166 167
         // (tor-browser#44930).
    
    167 168
         #[inline]
    
    ... ... @@ -174,7 +175,12 @@ impl ControlPort {
    174 175
         }
    
    175 176
     
    
    176 177
         #[inline]
    
    177
    -    pub fn set_async_handler(&self, cb: Box<dyn Fn(Reply)>) {
    
    178
    +    pub fn set_async_handler(&self, cb: Option<Box<dyn Fn(Reply)>>) {
    
    178 179
             self.0.set_async_handler(cb);
    
    179 180
         }
    
    181
    +
    
    182
    +    #[inline]
    
    183
    +    pub fn close(&self) -> Result<(), ControlSocketError> {
    
    184
    +        self.0.close()
    
    185
    +    }
    
    180 186
     }

  • toolkit/components/tor-integration/tor_provider/src/ctor/control_port/error.rs
    ... ... @@ -5,14 +5,12 @@
    5 5
     
    
    6 6
     use thiserror::Error;
    
    7 7
     
    
    8
    -use super::super::{ControlSocketError, ReplyError};
    
    8
    +use crate::ctor::ReplyError;
    
    9 9
     
    
    10 10
     #[derive(Error, Debug, Clone, PartialEq, Eq)]
    
    11 11
     pub enum ControlPortError {
    
    12
    -    #[error("connection error")]
    
    13
    -    ConnectionError(#[from] ControlSocketError),
    
    14
    -    #[error("protocol violation")]
    
    12
    +    #[error("connection error: {0:#x}")]
    
    13
    +    ConnectionError(u32),
    
    14
    +    #[error("protocol violation: {0}")]
    
    15 15
         ProtocolError(#[from] ReplyError),
    
    16
    -    #[error("unsuccessful command ({code}): {message}")]
    
    17
    -    TorError { code: u16, message: String },
    
    18 16
     }

  • toolkit/components/tor-integration/tor_provider/src/ctor/reply_parser/dispatcher.rs
    ... ... @@ -56,9 +56,9 @@ impl ReplyDispatcher {
    56 56
         }
    
    57 57
     
    
    58 58
         /// Register the handler for async notifications.
    
    59
    -    pub fn set_async_handler(&self, cb: Box<dyn Fn(Reply)>) {
    
    59
    +    pub fn set_async_handler(&self, cb: Option<Box<dyn Fn(Reply)>>) {
    
    60 60
             // Reentrancy safety: we do not use the handler yet.
    
    61
    -        *self.async_handler.borrow_mut() = Some(Rc::from(cb))
    
    61
    +        *self.async_handler.borrow_mut() = cb.map(|cb| Rc::from(cb));
    
    62 62
         }
    
    63 63
     
    
    64 64
         /// Feed data to parse.
    
    ... ... @@ -290,7 +290,7 @@ mod tests {
    290 290
             let dispatcher = ReplyDispatcher::new();
    
    291 291
             let notification_called = Rc::new(Cell::new(false));
    
    292 292
             let notification_called2 = notification_called.clone();
    
    293
    -        dispatcher.set_async_handler(Box::new(move |r| {
    
    293
    +        dispatcher.set_async_handler(Some(Box::new(move |r| {
    
    294 294
                 assert_eq!(
    
    295 295
                     *r.end_line(),
    
    296 296
                     EndReplyLine {
    
    ... ... @@ -299,7 +299,7 @@ mod tests {
    299 299
                     }
    
    300 300
                 );
    
    301 301
                 notification_called2.set(true);
    
    302
    -        }));
    
    302
    +        })));
    
    303 303
             let reply_called = Rc::new(Cell::new(false));
    
    304 304
             let reply_called2 = reply_called.clone();
    
    305 305
             dispatcher.push_callback(Box::new(move |_| {
    
    ... ... @@ -323,12 +323,12 @@ mod tests {
    323 323
         #[test]
    
    324 324
         fn async_replace_handler() {
    
    325 325
             let dispatcher = ReplyDispatcher::new();
    
    326
    -        dispatcher.set_async_handler(Box::new(move |_| {
    
    326
    +        dispatcher.set_async_handler(Some(Box::new(move |_| {
    
    327 327
                 unreachable!("This handler should never be called, as it has been replaced.");
    
    328
    -        }));
    
    328
    +        })));
    
    329 329
             let called = Rc::new(Cell::new(false));
    
    330 330
             let c = called.clone();
    
    331
    -        dispatcher.set_async_handler(Box::new(move |r| {
    
    331
    +        dispatcher.set_async_handler(Some(Box::new(move |r| {
    
    332 332
                 assert_eq!(
    
    333 333
                     *r.end_line(),
    
    334 334
                     EndReplyLine {
    
    ... ... @@ -337,7 +337,7 @@ mod tests {
    337 337
                     }
    
    338 338
                 );
    
    339 339
                 c.set(true);
    
    340
    -        }));
    
    340
    +        })));
    
    341 341
             assert!(!called.get());
    
    342 342
             dispatcher
    
    343 343
                 .feed(&Bytes::from_static(b"650 Notification\r\n"))
    
    ... ... @@ -345,6 +345,18 @@ mod tests {
    345 345
             assert!(called.get());
    
    346 346
         }
    
    347 347
     
    
    348
    +    #[test]
    
    349
    +    fn async_remove_handler() {
    
    350
    +        let dispatcher = ReplyDispatcher::new();
    
    351
    +        dispatcher.set_async_handler(Some(Box::new(move |_| {
    
    352
    +            unreachable!("This handler should never be called, as it has been replaced.");
    
    353
    +        })));
    
    354
    +        dispatcher.set_async_handler(None);
    
    355
    +        dispatcher
    
    356
    +            .feed(&Bytes::from_static(b"650 Notification\r\n"))
    
    357
    +            .unwrap();
    
    358
    +    }
    
    359
    +
    
    348 360
         #[test]
    
    349 361
         fn sync_async_single_feed() {
    
    350 362
             let dispatcher = ReplyDispatcher::new();
    
    ... ... @@ -356,7 +368,7 @@ mod tests {
    356 368
             }));
    
    357 369
             let async_called = Rc::new(Cell::new(false));
    
    358 370
             let ac = async_called.clone();
    
    359
    -        dispatcher.set_async_handler(Box::new(move |r| {
    
    371
    +        dispatcher.set_async_handler(Some(Box::new(move |r| {
    
    360 372
                 assert_eq!(
    
    361 373
                     *r.end_line(),
    
    362 374
                     EndReplyLine {
    
    ... ... @@ -365,7 +377,7 @@ mod tests {
    365 377
                     }
    
    366 378
                 );
    
    367 379
                 ac.set(true);
    
    368
    -        }));
    
    380
    +        })));
    
    369 381
             dispatcher
    
    370 382
                 .feed(&Bytes::from_static(b"250 OK\r\n650 Notification\r\n"))
    
    371 383
                 .unwrap();
    
    ... ... @@ -450,13 +462,13 @@ mod tests {
    450 462
             let notifications = Rc::new(Cell::new(0));
    
    451 463
             let n = notifications.clone();
    
    452 464
             let d = dispatcher.clone();
    
    453
    -        dispatcher.set_async_handler(Box::new(move |_| {
    
    465
    +        dispatcher.set_async_handler(Some(Box::new(move |_| {
    
    454 466
                 n.set(n.get() + 1);
    
    455 467
                 if n.get() < 2 {
    
    456 468
                     d.feed(&Bytes::from_static(b"650 Notification 2\r\n"))
    
    457 469
                         .unwrap();
    
    458 470
                 }
    
    459
    -        }));
    
    471
    +        })));
    
    460 472
             dispatcher
    
    461 473
                 .feed(&Bytes::from_static(b"650 Notification 1\r\n"))
    
    462 474
                 .unwrap();
    
    ... ... @@ -514,9 +526,9 @@ mod tests {
    514 526
         #[test]
    
    515 527
         fn error_propagation() {
    
    516 528
             let dispatcher = ReplyDispatcher::new();
    
    517
    -        dispatcher.set_async_handler(Box::new(|_| {
    
    529
    +        dispatcher.set_async_handler(Some(Box::new(|_| {
    
    518 530
                 unreachable!("Errors should not be propagated to the async handler.");
    
    519
    -        }));
    
    531
    +        })));
    
    520 532
             let first = Rc::new(Cell::new(false));
    
    521 533
             let f = first.clone();
    
    522 534
             let second = Rc::new(Cell::new(false));
    

  • toolkit/components/tor-integration/tor_provider/src/ctor/reply_parser/mod.rs
    ... ... @@ -15,6 +15,8 @@ mod test_utils;
    15 15
     
    
    16 16
     pub use dispatcher::ReplyDispatcher;
    
    17 17
     pub use error::ReplyError;
    
    18
    -pub(crate) use factory::ReplyFactory;
    
    19 18
     pub use line::{DetailReplyLine, EndReplyLine};
    
    20 19
     pub use reply::Reply;
    
    20
    +
    
    21
    +#[cfg(test)]
    
    22
    +pub(crate) use test_utils::make_reply;

  • toolkit/components/tor-integration/tor_provider/src/ctor/reply_parser/test_utils.rs
    ... ... @@ -6,10 +6,19 @@
    6 6
     use bytes::Bytes;
    
    7 7
     
    
    8 8
     use super::{
    
    9
    +    factory::ReplyFactory,
    
    9 10
         line::{DetailReplyLine, EndReplyLine},
    
    10 11
         reply::Reply,
    
    11 12
     };
    
    12 13
     
    
    14
    +pub(crate) fn make_reply(data: &'static [u8]) -> Reply {
    
    15
    +    let mut factory = ReplyFactory::default();
    
    16
    +    let mut replies = factory.build(&Bytes::from_static(data)).unwrap();
    
    17
    +    assert_eq!(replies.len(), 1);
    
    18
    +    assert!(!factory.has_pending_data());
    
    19
    +    replies.pop_front().unwrap()
    
    20
    +}
    
    21
    +
    
    13 22
     pub(super) fn check_250_ok(reply: &Reply, has_details: bool) {
    
    14 23
         assert_eq!(reply.has_details(), has_details);
    
    15 24
         assert_eq!(
    

  • toolkit/components/tor-integration/tor_service/src/control_port.rs
    ... ... @@ -2,18 +2,20 @@
    2 2
      * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3 3
      * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    
    4 4
     
    
    5
    -use bytes::Bytes;
    
    6 5
     use nserror::nsresult;
    
    7 6
     use nserror::{NS_ERROR_NOT_CONNECTED, NS_OK};
    
    8 7
     use nsstring::{nsACString, nsCString};
    
    9
    -use tor_provider::ctor::ControlPort;
    
    10
    -use tor_provider::ctor::ControlSocketError;
    
    11
    -use xpcom::interfaces::{nsIFile, ITorControlPort, ITorControlPortReceiver, ITorMessageHandler};
    
    8
    +use tor_provider::ctor::{ControlPort, ControlSocketError};
    
    9
    +use xpcom::interfaces::{nsIFile, torITorControlPortReceiver, torITorMessageHandler};
    
    12 10
     use xpcom::RefPtr;
    
    13 11
     
    
    12
    +// Actually used, but the compiler does not detect it.
    
    13
    +#[allow(unused)]
    
    14
    +use xpcom::interfaces::torITorControlPort;
    
    15
    +
    
    14 16
     use super::control_socket::ControlSocketXpcom;
    
    15 17
     
    
    16
    -#[xpcom(implement(ITorControlPort), atomic)]
    
    18
    +#[xpcom(implement(torITorControlPort), atomic)]
    
    17 19
     pub struct ControlPortXpcom {
    
    18 20
         control_port: ControlPort,
    
    19 21
     }
    
    ... ... @@ -32,42 +34,46 @@ impl ControlPortXpcom {
    32 34
             Ok(Self::allocate(InitControlPortXpcom { control_port }))
    
    33 35
         }
    
    34 36
     
    
    35
    -    xpcom_method!(start => Start(receiver: *const ITorControlPortReceiver));
    
    36
    -    pub fn start(&self, receiver: &ITorControlPortReceiver) -> Result<(), nsresult> {
    
    37
    +    xpcom_method!(start => Start(receiver: *const torITorControlPortReceiver));
    
    38
    +    pub fn start(&self, receiver: &torITorControlPortReceiver) -> Result<(), nsresult> {
    
    37 39
             let receiver = RefPtr::new(receiver);
    
    38
    -        self.control_port.set_async_handler(Box::new(move |reply| {
    
    39
    -            let mut buf = Vec::new();
    
    40
    -            if let Err(e) = reply.write_to(&mut buf) {
    
    41
    -                log::error!(
    
    42
    -                    "Cannot convert the reply to the raw message: {}.",
    
    43
    -                    e.to_string()
    
    44
    -                );
    
    45
    -                return;
    
    46
    -            }
    
    47
    -            if buf.ends_with(b"\r\n") {
    
    48
    -                buf.truncate(buf.len() - 2);
    
    49
    -            }
    
    50
    -            // These conversions re-use the buffer, Gecko uses the same
    
    51
    -            // allocator for Rust and C++ (see the nsstring crate).
    
    52
    -            let as_str = nsCString::from(buf);
    
    53
    -            // Safety: call to an XPCOM method that we expect to be exposed on
    
    54
    -            // Rust. As per the documentation in nsstring, it is safe to pass
    
    55
    -            // nsCStrings created in Rust to C++.
    
    56
    -            unsafe { receiver.OnAsyncMessage(&*as_str) };
    
    57
    -        }));
    
    40
    +        self.control_port
    
    41
    +            .set_async_handler(Some(Box::new(move |reply| {
    
    42
    +                let mut buf = Vec::new();
    
    43
    +                if let Err(e) = reply.write_to(&mut buf) {
    
    44
    +                    log::error!(
    
    45
    +                        "Cannot convert the reply to the raw message: {}.",
    
    46
    +                        e.to_string()
    
    47
    +                    );
    
    48
    +                    return;
    
    49
    +                }
    
    50
    +                if buf.ends_with(b"\r\n") {
    
    51
    +                    buf.truncate(buf.len() - 2);
    
    52
    +                }
    
    53
    +                // These conversions re-use the buffer, Gecko uses the same
    
    54
    +                // allocator for Rust and C++ (see the nsstring crate).
    
    55
    +                let as_str = nsCString::from(buf);
    
    56
    +                // Safety: call to an XPCOM method that we expect to be exposed
    
    57
    +                // on Rust. As per the documentation in nsstring, it is safe to
    
    58
    +                // pass nsCStrings created in Rust to C++.
    
    59
    +                unsafe { receiver.OnAsyncMessage(&*as_str) };
    
    60
    +            })));
    
    58 61
             Ok(())
    
    59 62
         }
    
    60 63
     
    
    61
    -    xpcom_method!(send_command => SendCommand(command: *const nsACString, handler: *const ITorMessageHandler));
    
    64
    +    xpcom_method!(send_command => SendCommand(command: *const nsACString, handler: *const torITorMessageHandler));
    
    62 65
         pub fn send_command(
    
    63 66
             &self,
    
    64 67
             command: &nsACString,
    
    65
    -        handler: &ITorMessageHandler,
    
    68
    +        handler: &torITorMessageHandler,
    
    66 69
         ) -> Result<(), nsresult> {
    
    67
    -        let command = Bytes::copy_from_slice(&command[..]);
    
    70
    +        let mut command = command.to_vec();
    
    71
    +        if !command.ends_with(b"\r\n") {
    
    72
    +            command.extend_from_slice(b"\r\n");
    
    73
    +        }
    
    68 74
             let handler = RefPtr::new(handler);
    
    69 75
             self.control_port.send_command(
    
    70
    -            command,
    
    76
    +            command.into(),
    
    71 77
                 Box::new(move |reply| {
    
    72 78
                     let mut buf = Vec::new();
    
    73 79
                     let reply = match reply {
    

  • toolkit/components/tor-integration/tor_service/src/service.rs
    ... ... @@ -4,12 +4,16 @@
    4 4
     
    
    5 5
     use nserror::{nsresult, NS_ERROR_NULL_POINTER, NS_OK};
    
    6 6
     use nsstring::nsACString;
    
    7
    -use xpcom::interfaces::{nsIFile, ITorControlPort, ITorService};
    
    7
    +use xpcom::interfaces::{nsIFile, torITorControlPort};
    
    8 8
     use xpcom::RefPtr;
    
    9 9
     
    
    10 10
     use super::control_port::ControlPortXpcom;
    
    11 11
     
    
    12
    -#[xpcom(implement(ITorService), atomic)]
    
    12
    +// Actually used, but the compiler does not detect it.
    
    13
    +#[allow(unused)]
    
    14
    +use xpcom::interfaces::torITorService;
    
    15
    +
    
    16
    +#[xpcom(implement(torITorService), atomic)]
    
    13 17
     struct TorService {}
    
    14 18
     
    
    15 19
     impl TorService {
    
    ... ... @@ -17,31 +21,31 @@ impl TorService {
    17 21
             TorService::allocate(InitTorService {})
    
    18 22
         }
    
    19 23
     
    
    20
    -    xpcom_method!(create_control_port => CreateControlPort(host: *const nsACString, port: i32, out: *mut *const ITorControlPort));
    
    24
    +    xpcom_method!(create_control_port => CreateControlPort(host: *const nsACString, port: i32, out: *mut *const torITorControlPort));
    
    21 25
         fn create_control_port(
    
    22 26
             &self,
    
    23 27
             host: &nsACString,
    
    24 28
             port: i32,
    
    25
    -        out: *mut *const ITorControlPort,
    
    29
    +        out: *mut *const torITorControlPort,
    
    26 30
         ) -> Result<(), nsresult> {
    
    27 31
             if out.is_null() {
    
    28 32
                 return Err(NS_ERROR_NULL_POINTER);
    
    29 33
             }
    
    30
    -        let cp = RefPtr::new(ControlPortXpcom::new_tcp(host, port)?.coerce::<ITorControlPort>());
    
    34
    +        let cp = RefPtr::new(ControlPortXpcom::new_tcp(host, port)?.coerce::<torITorControlPort>());
    
    31 35
             cp.forget(unsafe { &mut *out });
    
    32 36
             Ok(())
    
    33 37
         }
    
    34 38
     
    
    35
    -    xpcom_method!(create_control_port_ipc => CreateControlPortIPC(socket: *const nsIFile, out: *mut *const ITorControlPort));
    
    39
    +    xpcom_method!(create_control_port_ipc => CreateControlPortIPC(socket: *const nsIFile, out: *mut *const torITorControlPort));
    
    36 40
         fn create_control_port_ipc(
    
    37 41
             &self,
    
    38 42
             socket: &nsIFile,
    
    39
    -        out: *mut *const ITorControlPort,
    
    43
    +        out: *mut *const torITorControlPort,
    
    40 44
         ) -> Result<(), nsresult> {
    
    41 45
             if out.is_null() {
    
    42 46
                 return Err(NS_ERROR_NULL_POINTER);
    
    43 47
             }
    
    44
    -        let cp = RefPtr::new(ControlPortXpcom::new_ipc(socket)?.coerce::<ITorControlPort>());
    
    48
    +        let cp = RefPtr::new(ControlPortXpcom::new_ipc(socket)?.coerce::<torITorControlPort>());
    
    45 49
             cp.forget(unsafe { &mut *out });
    
    46 50
             Ok(())
    
    47 51
         }
    
    ... ... @@ -49,11 +53,11 @@ impl TorService {
    49 53
     
    
    50 54
     // See toolkit/components/extensions/storage/webext_storage_bridge/src/lib.rs.
    
    51 55
     #[no_mangle]
    
    52
    -pub unsafe extern "C" fn NewTorServiceImpl(result: *mut *const ITorService) -> nsresult {
    
    56
    +pub unsafe extern "C" fn NewTorServiceImpl(result: *mut *const torITorService) -> nsresult {
    
    53 57
         if result.is_null() {
    
    54 58
             return NS_ERROR_NULL_POINTER;
    
    55 59
         }
    
    56 60
         let service = TorService::new();
    
    57
    -    RefPtr::new(service.coerce::<ITorService>()).forget(&mut *result);
    
    61
    +    RefPtr::new(service.coerce::<torITorService>()).forget(&mut *result);
    
    58 62
         NS_OK
    
    59 63
     }

  • tools/lint/eslint/eslint-plugin-mozilla/lib/services.json
    ... ... @@ -59,5 +59,5 @@
    59 59
       "nsIXULAppInfo": "appinfo",
    
    60 60
       "nsIXULRuntime": "appinfo",
    
    61 61
       "nsIXULStore": "xulStore",
    
    62
    -  "ITorService": "tor"
    
    62
    +  "torITorService": "tor"
    
    63 63
     }

  • _______________________________________________
    tor-commits mailing list -- tor-commits@xxxxxxxxxxxxxxxxxxxx
    To unsubscribe send an email to tor-commits-leave@xxxxxxxxxxxxxxxxxxxx