1
//! Implement a concrete type to build channels over a transport.
2

            
3
use async_trait::async_trait;
4
use futures::{AsyncRead, AsyncWrite};
5
use std::io;
6
use std::sync::{Arc, Mutex};
7
use std::time::Duration;
8
use tracing::instrument;
9

            
10
use crate::factory::{BootstrapReporter, ChannelFactory, IncomingChannelFactory};
11
use crate::transport::TransportImplHelper;
12
use crate::{Error, event::ChanMgrEventSender};
13

            
14
use safelog::MaybeSensitive;
15
use tor_basic_utils::rand_hostname;
16
use tor_error::internal;
17
use tor_linkspec::{ChanTarget, HasChanMethod, IntoOwnedChanTarget, OwnedChanTarget};
18
use tor_proto::channel::ChannelType;
19
use tor_proto::channel::kist::KistParams;
20
use tor_proto::channel::params::ChannelPaddingInstructionsUpdates;
21
use tor_proto::memquota::ChannelAccount;
22
use tor_proto::peer::PeerAddr;
23
use tor_rtcompat::SpawnExt;
24
use tor_rtcompat::{CertifiedConn, Runtime, StreamOps, TlsProvider, tls::TlsConnector};
25

            
26
#[cfg(feature = "relay")]
27
use {safelog::Sensitive, std::net::IpAddr, tor_proto::RelayChannelAuthMaterial};
28

            
29
/// TLS-based channel builder.
30
///
31
/// This is a separate type so that we can keep our channel management code
32
/// network-agnostic.
33
///
34
/// It uses a provided `TransportHelper` type to make a connection (possibly
35
/// directly over TCP, and possibly over some other protocol).  It then
36
/// negotiates TLS over that connection, and negotiates a Tor channel over that
37
/// TLS session.
38
///
39
/// This channel builder does not retry on failure, but it _does_ implement a
40
/// time-out.
41
pub struct ChanBuilder<R: Runtime, H: TransportImplHelper>
42
where
43
    R: tor_rtcompat::TlsProvider<H::Stream>,
44
{
45
    /// Asynchronous runtime for TLS, TCP, spawning, and timeouts.
46
    runtime: R,
47
    /// The transport object that we use to construct streams.
48
    transport: H,
49
    /// Object to build TLS connections.
50
    tls_connector: <R as TlsProvider<H::Stream>>::Connector,
51
    /// Object to accept TLS connections.
52
    #[cfg(feature = "relay")]
53
    tls_acceptor: Option<<R as TlsProvider<H::Stream>>::Acceptor>,
54
    /// Relay authentication key material needed for relay channels.
55
    #[cfg(feature = "relay")]
56
    auth_material: Option<Arc<RelayChannelAuthMaterial>>,
57
    /// Our address(es) to use in the NETINFO cell.
58
    // TODO: We might want one day to support updating the addresses here in the same way we
59
    // support updating the auth_material. One use case for this is the relay config reload.
60
    #[cfg(feature = "relay")]
61
    my_addrs: Vec<IpAddr>,
62
}
63

            
64
impl<R: Runtime, H: TransportImplHelper> ChanBuilder<R, H>
65
where
66
    R: TlsProvider<H::Stream>,
67
{
68
    /// Construct a new client specific ChanBuilder.
69
60
    pub fn new_client(runtime: R, transport: H) -> Self {
70
60
        let tls_connector = <R as TlsProvider<H::Stream>>::tls_connector(&runtime);
71
60
        ChanBuilder {
72
60
            runtime,
73
60
            transport,
74
60
            tls_connector,
75
60
            #[cfg(feature = "relay")]
76
60
            tls_acceptor: None,
77
60
            #[cfg(feature = "relay")]
78
60
            auth_material: None,
79
60
            #[cfg(feature = "relay")]
80
60
            my_addrs: Vec::new(),
81
60
        }
82
60
    }
83

            
84
    /// Construct a new relay specific ChanBuilder.
85
    #[cfg(feature = "relay")]
86
    pub fn new_relay(
87
        runtime: R,
88
        transport: H,
89
        auth_material: Arc<RelayChannelAuthMaterial>,
90
        my_addrs: Vec<IpAddr>,
91
    ) -> crate::Result<Self> {
92
        use tor_error::into_internal;
93
        use tor_rtcompat::tls::TlsAcceptorSettings;
94

            
95
        // Build the TLS acceptor.
96
        let tls_settings = TlsAcceptorSettings::new(auth_material.tls_key_and_cert().clone())
97
            .map_err(into_internal!("Unable to build TLS acceptor setting"))?;
98
        let tls_acceptor = <R as TlsProvider<H::Stream>>::tls_acceptor(&runtime, tls_settings)
99
            .map_err(into_internal!("Unable to build TLS acceptor"))?;
100

            
101
        // Same builder as a client but with auth material and acceptor.
102
        let mut builder = Self::new_client(runtime, transport);
103
        builder.auth_material = Some(auth_material);
104
        builder.tls_acceptor = Some(tls_acceptor);
105
        builder.my_addrs = my_addrs;
106

            
107
        Ok(builder)
108
    }
109

            
110
    /// Build a new `ChanBuilder` with the given `auth_material`, cloning our runtime and transport.
111
    ///
112
    /// This is needed because some relay keys rotate over time.
113
    #[cfg(feature = "relay")]
114
    pub fn rebuild_with_auth_material(
115
        &self,
116
        auth_material: Arc<RelayChannelAuthMaterial>,
117
    ) -> crate::Result<Self>
118
    where
119
        H: Clone,
120
    {
121
        Self::new_relay(
122
            self.runtime.clone(),
123
            self.transport.clone(),
124
            auth_material,
125
            self.my_addrs.clone(),
126
        )
127
    }
128

            
129
    /// Return the outbound channel type of this config.
130
    ///
131
    /// The channel type is used when creating outbound channels. Relays always initiate channels
132
    /// as "relay initiator" while client and bridges behave like a "client initiator".
133
    ///
134
    /// Important: The wrong channel type is returned if this is called before `with_identities()`
135
    /// is called.
136
4
    fn outbound_chan_type(&self) -> ChannelType {
137
        #[cfg(feature = "relay")]
138
4
        if self.auth_material.is_some() {
139
            return ChannelType::RelayInitiator;
140
4
        }
141
4
        ChannelType::ClientInitiator
142
4
    }
143
}
144

            
145
#[async_trait]
146
impl<R: Runtime, H: TransportImplHelper> ChannelFactory for ChanBuilder<R, H>
147
where
148
    R: tor_rtcompat::TlsProvider<H::Stream> + Send + Sync,
149
    H: Send + Sync,
150
{
151
    #[instrument(skip_all, level = "trace")]
152
    async fn connect_via_transport(
153
        &self,
154
        target: &OwnedChanTarget,
155
        reporter: BootstrapReporter,
156
        memquota: ChannelAccount,
157
    ) -> crate::Result<Arc<tor_proto::channel::Channel>> {
158
        use tor_rtcompat::SleepProviderExt;
159

            
160
        // TODO: make this an option.  And make a better value.
161
        let delay = if target.chan_method().is_direct() {
162
            std::time::Duration::new(5, 0)
163
        } else {
164
            std::time::Duration::new(10, 0)
165
        };
166

            
167
        self.runtime
168
            .timeout(delay, self.connect_no_timeout(target, reporter.0, memquota))
169
            .await
170
            .map_err(|_| Error::ChanTimeout {
171
                peer: target.to_logged(),
172
            })?
173
    }
174
}
175

            
176
#[async_trait]
177
impl<R: Runtime, H: TransportImplHelper> IncomingChannelFactory for ChanBuilder<R, H>
178
where
179
    R: tor_rtcompat::TlsProvider<H::Stream> + Send + Sync,
180
    H: Send + Sync,
181
{
182
    type Stream = H::Stream;
183

            
184
    #[cfg(feature = "relay")]
185
    async fn accept_from_transport(
186
        &self,
187
        peer: Sensitive<std::net::SocketAddr>,
188
        stream: Self::Stream,
189
        memquota: ChannelAccount,
190
    ) -> crate::Result<Arc<tor_proto::channel::Channel>> {
191
        use tor_linkspec::OwnedChanTargetBuilder;
192
        use tor_proto::relay::MaybeVerifiableRelayResponderChannel;
193

            
194
        // Note that as we accept a connection, we don't expect any specific identities and so we
195
        // can only build a target from the peer address. This means that the verification process
196
        // will not match the identities seen (if a relay <-> relay channel) to this target which
197
        // is fine as we are a responder.
198
        let target_no_ids = OwnedChanTargetBuilder::default()
199
            .addrs(vec![peer.into_inner()])
200
            .build()
201
            .map_err(|e| internal!("Unable to build chan target from peer sockaddr: {e}"))?;
202
        // Convert into a PeerAddr but keep it sensitive, this can be a client/bridge.
203
        let peer_addr: MaybeSensitive<PeerAddr> =
204
            MaybeSensitive::sensitive(peer.into_inner().into());
205

            
206
        // Helpers: For error mapping.
207
        let map_ioe = |ioe, action| Error::Io {
208
            action,
209
            peer: peer_addr.clone(),
210
            source: ioe,
211
        };
212
        let map_proto = |source, target: &OwnedChanTarget, clock_skew| Error::Proto {
213
            source,
214
            peer: target.to_logged(),
215
            clock_skew,
216
        };
217

            
218
        let tls = self
219
            .tls_acceptor
220
            .as_ref()
221
            .ok_or(internal!("Accepting connection without TLS acceptor"))?
222
            .negotiate_unvalidated(stream, "ignored")
223
            .await
224
            .map_err(|e| map_ioe(e.into(), "TLS negotiation"))?;
225
        let auth_material = self
226
            .auth_material
227
            .as_ref()
228
            .ok_or(internal!(
229
                "Unable to build relay channel without auth material"
230
            ))?
231
            .clone();
232

            
233
        let our_cert = tls
234
            .own_certificate()
235
            .map_err(|e| map_ioe(e.into(), "TLS Certs"))?
236
            .ok_or_else(|| Error::Internal(internal!("TLS connection without our certificate")))?
237
            .into_owned();
238
        let builder = tor_proto::RelayChannelBuilder::new();
239

            
240
        let unverified = builder
241
            .accept(
242
                Sensitive::new(peer_addr.inner()),
243
                self.my_addrs.clone(),
244
                tls,
245
                self.runtime.clone(),
246
                auth_material,
247
                memquota,
248
            )
249
            .handshake(|| self.runtime.wallclock())
250
            .await
251
            .map_err(|e| map_proto(e, &target_no_ids, None))?;
252

            
253
        let (chan, reactor) = match unverified {
254
            MaybeVerifiableRelayResponderChannel::Verifiable(c) => {
255
                let clock_skew = c.clock_skew();
256
                let now = self.runtime.wallclock();
257
                c.verify(&target_no_ids, &our_cert, Some(now))
258
                    .map_err(|e| map_proto(e, &target_no_ids, Some(clock_skew)))?
259
                    .finish()
260
                    .await
261
                    .map_err(|e| map_proto(e, &target_no_ids, Some(clock_skew)))?
262
            }
263
            MaybeVerifiableRelayResponderChannel::NonVerifiable(c) => {
264
                c.finish().map_err(|e| map_proto(e, &target_no_ids, None))?
265
            }
266
        };
267

            
268
        // Launch a task to run the channel reactor.
269
        self.runtime
270
            .spawn(async {
271
                let _ = reactor.run().await;
272
            })
273
            .map_err(|e| Error::from_spawn("responder channel reactor", e))?;
274

            
275
        Ok(chan)
276
    }
277
}
278

            
279
impl<R: Runtime, H: TransportImplHelper> ChanBuilder<R, H>
280
where
281
    R: tor_rtcompat::TlsProvider<H::Stream> + Send + Sync,
282
    H: Send + Sync,
283
{
284
    /// Perform the work of `connect_via_transport`, but without enforcing a timeout.
285
    ///
286
    /// Return a [`Channel`](tor_proto::channel::Channel) on success.
287
    #[instrument(skip_all, level = "trace")]
288
2
    async fn connect_no_timeout(
289
2
        &self,
290
2
        target: &OwnedChanTarget,
291
2
        event_sender: Arc<Mutex<ChanMgrEventSender>>,
292
2
        memquota: ChannelAccount,
293
2
    ) -> crate::Result<Arc<tor_proto::channel::Channel>> {
294
        use tor_rtcompat::tls::CertifiedConn;
295

            
296
        {
297
            event_sender.lock().expect("Lock poisoned").record_attempt();
298
        }
299

            
300
        // Before actually doing the connect, we need to validate the channel target for the relay
301
        // case. There are restrictions we need to apply.
302
        #[cfg(feature = "relay")]
303
        self.validate_relay_target(target)?;
304

            
305
        // 1a. Negotiate the TCP connection or other stream.
306

            
307
        // The returned PeerAddr is the actual address we are connected to.
308
        let (peer_addr, stream) = self.transport.connect(target).await?;
309
        // The peer could be a bridge/guard or a relay. We have to shield it right away to avoid
310
        // leaking the info in the logs but we also want the info for a relay<-> relay.
311
        let peer_addr = match self.outbound_chan_type() {
312
            ChannelType::ClientInitiator => MaybeSensitive::sensitive(peer_addr),
313
            ChannelType::RelayInitiator => MaybeSensitive::not_sensitive(peer_addr),
314
            _ => return Err(Error::Internal(internal!("Unknown outbound channel type"))),
315
        };
316

            
317
4
        let map_ioe = |action: &'static str| {
318
4
            let peer = peer_addr.clone();
319
            move |ioe: io::Error| Error::Io {
320
                action,
321
                peer,
322
                source: ioe.into(),
323
            }
324
4
        };
325

            
326
        {
327
            // TODO(nickm): At some point, it would be helpful to the
328
            // bootstrapping logic if we could distinguish which
329
            // transport just succeeded.
330
            event_sender
331
                .lock()
332
                .expect("Lock poisoned")
333
                .record_tcp_success();
334
        }
335

            
336
        // 1b. Negotiate TLS.
337

            
338
        let hostname = rand_hostname::random_hostname(&mut rand::rng());
339

            
340
        let tls = self
341
            .tls_connector
342
            .negotiate_unvalidated(stream, hostname.as_str())
343
            .await
344
            .map_err(map_ioe("TLS negotiation"))?;
345

            
346
        let peer_tls_cert = tls
347
            .peer_certificate()
348
            .map_err(map_ioe("TLS certs"))?
349
            .ok_or_else(|| Error::Internal(internal!("TLS connection with no peer certificate")))?
350
            // Note: we could skip this "into_owned" if we computed any necessary digest on the
351
            // certificate earlier.  That would require changing out channel negotiation APIs,
352
            // though, and might not be worth it.
353
            .into_owned();
354

            
355
        {
356
            event_sender
357
                .lock()
358
                .expect("Lock poisoned")
359
                .record_tls_finished();
360
        }
361

            
362
        // Store this so we can log it in case we don't recognize it.
363
        let outbound_chan_type = self.outbound_chan_type();
364
        let chan = match outbound_chan_type {
365
            ChannelType::ClientInitiator => {
366
                self.build_client_channel(
367
                    tls,
368
                    peer_addr,
369
                    target,
370
                    &peer_tls_cert,
371
                    memquota,
372
                    event_sender.clone(),
373
                )
374
                .await?
375
            }
376
            #[cfg(feature = "relay")]
377
            ChannelType::RelayInitiator => {
378
                self.build_relay_channel(
379
                    tls,
380
                    peer_addr,
381
                    target,
382
                    &peer_tls_cert,
383
                    memquota,
384
                    event_sender.clone(),
385
                )
386
                .await?
387
            }
388
            _ => {
389
                return Err(Error::Internal(internal!(
390
                    "Unusable channel type for outbound: {outbound_chan_type}",
391
                )));
392
            }
393
        };
394

            
395
        event_sender
396
            .lock()
397
            .expect("Lock poisoned")
398
            .record_handshake_done();
399

            
400
        Ok(chan)
401
2
    }
402

            
403
    /// Validate the given target as in if it is fine to connect to it.
404
    ///
405
    /// We avoid building channels to ourselves as a relay.
406
    #[cfg(feature = "relay")]
407
2
    fn validate_relay_target(&self, target: &OwnedChanTarget) -> crate::Result<()> {
408
        use tor_linkspec::{HasAddrs, HasRelayIds};
409

            
410
        // Make sure we don't attempt to use a PT method for this relay channel.
411
2
        if !target.chan_method().is_direct() {
412
            // Return an internal error because the circuit reactor asking us to use a PT is a code
413
            // flow issue, not a protocol violation.
414
            return Err(Error::UnusableTarget(tor_error::bad_api_usage!(
415
                "Relays don't support outbound PT channels"
416
            )));
417
2
        }
418

            
419
        // Make sure no target address is ourself.
420
2
        for addr in target.addrs() {
421
2
            if self.my_addrs.contains(&addr.ip()) {
422
                return Err(Error::Proto {
423
                    source: tor_proto::Error::ChanProto("Target address is ours".into()),
424
                    peer: target.clone().into(),
425
                    clock_skew: None,
426
                });
427
2
            }
428
        }
429

            
430
        // Make sure that each address has a valid port.
431
2
        if !target.has_all_nonzero_port() {
432
            return Err(Error::Proto {
433
                source: tor_proto::Error::ChanProto("Target address port is invalid".into()),
434
                peer: target.clone().into(),
435
                clock_skew: None,
436
            });
437
2
        }
438

            
439
        // Make sure that all addresses are globally reachable. We need to avoid a relay attempting
440
        // to connect to a local/private network for security reasons as a it could lead to network
441
        // scanning by measuring latency between successful connect() and failures.
442
        //
443
        // If no addresses, it returns true and thus no error.
444
2
        if !target.all_addrs_allowed_for_extend() {
445
            return Err(Error::Proto {
446
                source: tor_proto::Error::ChanProto("Target address is invalid".into()),
447
                peer: target.clone().into(),
448
                clock_skew: None,
449
            });
450
2
        }
451

            
452
        // Client with the relay feature won't have auth material. A relay without it is not
453
        // possible but even if it was, it won't be able to build a channel to itself as a relay
454
        // channel. Hence, returning Ok(()) here is fine as without auth material ourself, we can
455
        // connect wherever.
456
2
        let Some(auth_material) = &self.auth_material else {
457
2
            return Ok(());
458
        };
459
        // Any of our identities match the given target, we are connecting to ourselves, refuse.
460
        if auth_material.has_any_relay_id_from(target) {
461
            Err(Error::Proto {
462
                source: tor_proto::Error::ChanProto(
463
                    "Refusing to build channel to ourselves".into(),
464
                ),
465
                peer: target.clone().into(),
466
                clock_skew: None,
467
            })
468
        } else {
469
            Ok(())
470
        }
471
2
    }
472

            
473
    /// Build a client channel (always initiator).
474
    ///
475
    /// This spawns the Reactor and return the [`tor_proto::channel::Channel`].
476
2
    async fn build_client_channel<T>(
477
2
        &self,
478
2
        tls: T,
479
2
        peer_addr: MaybeSensitive<PeerAddr>,
480
2
        target: &OwnedChanTarget,
481
2
        peer_tls_cert: &[u8],
482
2
        memquota: ChannelAccount,
483
2
        event_sender: Arc<Mutex<ChanMgrEventSender>>,
484
2
    ) -> crate::Result<Arc<tor_proto::channel::Channel>>
485
2
    where
486
2
        T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
487
2
    {
488
        // Helper to map protocol level error.
489
        //
490
        // We are logging the `target` here as these protocol error happens during the handshake
491
        // and we need to log the identities that are being tried but it will honor safe logging
492
        // for the relay <-> relay case which is not ideal but a tradeoff in complexity.
493
2
        let map_proto = |source, target: &OwnedChanTarget, clock_skew| Error::Proto {
494
            source,
495
            peer: target.to_logged(),
496
            clock_skew,
497
        };
498

            
499
2
        let now = self.runtime.wallclock();
500

            
501
        // Get the client specific channel builder.
502
2
        let mut builder = tor_proto::ClientChannelBuilder::new();
503
2
        builder.set_declared_method(target.chan_method());
504

            
505
2
        let unverified = builder
506
2
            .launch(
507
2
                tls,
508
2
                self.runtime.clone(), /* TODO provide ZST SleepProvider instead */
509
2
                memquota,
510
            )
511
2
            .connect(|| self.runtime.wallclock())
512
2
            .await
513
2
            .map_err(|e| Error::from_proto_no_skew(e, target))?;
514

            
515
2
        let clock_skew = unverified.clock_skew();
516
2
        let (chan, reactor) = unverified
517
2
            .verify(target, peer_tls_cert, Some(now))
518
2
            .map_err(|source| match &source {
519
                tor_proto::Error::HandshakeCertsExpired { .. } => {
520
                    event_sender
521
                        .lock()
522
                        .expect("Lock poisoned")
523
                        .record_handshake_done_with_skewed_clock();
524
                    map_proto(source, target, Some(clock_skew))
525
                }
526
                _ => Error::from_proto_no_skew(source, target),
527
            })?
528
2
            .finish(peer_addr)
529
2
            .await
530
2
            .map_err(|e| map_proto(e, target, Some(clock_skew)))?;
531

            
532
        // Launch a task to run the channel reactor.
533
2
        self.runtime
534
2
            .spawn(async {
535
2
                let _ = reactor.run().await;
536
2
            })
537
2
            .map_err(|e| Error::from_spawn("client channel reactor", e))?;
538
2
        Ok(chan)
539
2
    }
540

            
541
    /// Build a relay initiator channel.
542
    ///
543
    /// This spawns the Reactor and return the [`tor_proto::channel::Channel`].
544
    #[cfg(feature = "relay")]
545
    async fn build_relay_channel<T>(
546
        &self,
547
        tls: T,
548
        peer_addr: MaybeSensitive<PeerAddr>,
549
        target: &OwnedChanTarget,
550
        peer_tls_cert: &[u8],
551
        memquota: ChannelAccount,
552
        event_sender: Arc<Mutex<ChanMgrEventSender>>,
553
    ) -> crate::Result<Arc<tor_proto::channel::Channel>>
554
    where
555
        T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
556
    {
557
        let builder = tor_proto::RelayChannelBuilder::new();
558
        let auth_material = self
559
            .auth_material
560
            .as_ref()
561
            .ok_or(internal!(
562
                "Unable to build relay channel without auth material"
563
            ))?
564
            .clone();
565

            
566
        let unverified = builder
567
            .launch(
568
                tls,
569
                self.runtime.clone(), /* TODO provide ZST SleepProvider instead */
570
                auth_material,
571
                self.my_addrs.clone(),
572
                target,
573
                memquota,
574
            )
575
            .connect(|| self.runtime.wallclock())
576
            .await
577
            .map_err(|e| Error::from_proto_no_skew(e, target))?;
578

            
579
        let now = self.runtime.wallclock();
580
        let clock_skew = unverified.clock_skew();
581
        let (chan, reactor) = unverified
582
            .verify(target, peer_tls_cert, Some(now))
583
            .map_err(|source| match &source {
584
                tor_proto::Error::HandshakeCertsExpired { .. } => {
585
                    event_sender
586
                        .lock()
587
                        .expect("Lock poisoned")
588
                        .record_handshake_done_with_skewed_clock();
589
                    Error::Proto {
590
                        source,
591
                        peer: target.to_logged(),
592
                        clock_skew: Some(clock_skew),
593
                    }
594
                }
595
                _ => Error::from_proto_no_skew(source, target),
596
            })?
597
            // Peer address is not sensitive as this is a relay<->relay connection.
598
            .finish(peer_addr.inner())
599
            .await
600
            .map_err(|source| Error::Proto {
601
                source,
602
                peer: target.to_logged(),
603
                clock_skew: Some(clock_skew),
604
            })?;
605

            
606
        // Launch a task to run the channel reactor.
607
        self.runtime
608
            .spawn(async {
609
                let _ = reactor.run().await;
610
            })
611
            .map_err(|e| Error::from_spawn("relay channel reactor", e))?;
612

            
613
        Ok(chan)
614
    }
615
}
616

            
617
impl crate::mgr::AbstractChannel for tor_proto::channel::Channel {
618
    fn is_canonical(&self) -> bool {
619
        self.is_canonical()
620
    }
621
    fn is_canonical_to_peer(&self) -> bool {
622
        self.is_canonical_to_peer()
623
    }
624
2
    fn is_usable(&self) -> bool {
625
2
        !self.is_closing()
626
2
    }
627
2
    fn duration_unused(&self) -> Option<Duration> {
628
2
        self.duration_unused()
629
2
    }
630
108
    fn reparameterize(
631
108
        &self,
632
108
        updates: Arc<ChannelPaddingInstructionsUpdates>,
633
108
    ) -> tor_proto::Result<()> {
634
108
        tor_proto::channel::Channel::reparameterize(self, updates)
635
108
    }
636
    fn reparameterize_kist(&self, kist_params: KistParams) -> tor_proto::Result<()> {
637
        tor_proto::channel::Channel::reparameterize_kist(self, kist_params)
638
    }
639
36
    fn engage_padding_activities(&self) {
640
36
        tor_proto::channel::Channel::engage_padding_activities(self);
641
36
    }
642
}
643

            
644
#[cfg(test)]
645
mod test {
646
    // @@ begin test lint list maintained by maint/add_warning @@
647
    #![allow(clippy::bool_assert_comparison)]
648
    #![allow(clippy::clone_on_copy)]
649
    #![allow(clippy::dbg_macro)]
650
    #![allow(clippy::mixed_attributes_style)]
651
    #![allow(clippy::print_stderr)]
652
    #![allow(clippy::print_stdout)]
653
    #![allow(clippy::single_char_pattern)]
654
    #![allow(clippy::unwrap_used)]
655
    #![allow(clippy::unchecked_time_subtraction)]
656
    #![allow(clippy::useless_vec)]
657
    #![allow(clippy::needless_pass_by_value)]
658
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
659
    use super::*;
660
    use crate::{
661
        Result,
662
        mgr::{AbstractChannel, AbstractChannelFactory},
663
    };
664
    use futures::StreamExt as _;
665
    use std::net::SocketAddr;
666
    use std::time::{Duration, SystemTime};
667
    use tor_linkspec::{ChannelMethod, HasRelayIds, RelayIdType};
668
    use tor_llcrypto::pk::ed25519::Ed25519Identity;
669
    use tor_llcrypto::pk::rsa::RsaIdentity;
670
    use tor_proto::channel::Channel;
671
    use tor_proto::memquota::{ChannelAccount, SpecificAccount as _};
672
    use tor_rtcompat::{NetStreamListener, test_with_one_runtime};
673
    use tor_rtmock::{io::LocalStream, net::MockNetwork};
674

            
675
    #[allow(deprecated)] // TODO #1885
676
    use tor_rtmock::MockSleepRuntime;
677

            
678
    // Make sure that the builder can build a real channel.  To test
679
    // this out, we set up a listener that pretends to have the right
680
    // IP, fake the current time, and use a canned response from
681
    // [`testing::msgs`] crate.
682
    #[test]
683
    fn build_ok() -> Result<()> {
684
        use crate::testing::msgs;
685
        let orport: SocketAddr = msgs::ADDR.parse().unwrap();
686
        let ed: Ed25519Identity = msgs::ED_ID.into();
687
        let rsa: RsaIdentity = msgs::RSA_ID.into();
688
        let client_addr = "192.0.2.17".parse().unwrap();
689
        let tls_cert = msgs::X509_CERT.into();
690
        let target = OwnedChanTarget::builder()
691
            .addrs(vec![orport])
692
            .method(ChannelMethod::Direct(vec![orport]))
693
            .ed_identity(ed)
694
            .rsa_identity(rsa)
695
            .build()
696
            .unwrap();
697
        let now = SystemTime::UNIX_EPOCH + Duration::new(msgs::NOW, 0);
698

            
699
        test_with_one_runtime!(|rt| async move {
700
            // Stub out the internet so that this connection can work.
701
            let network = MockNetwork::new();
702

            
703
            // Set up a client runtime with a given IP
704
            let client_rt = network
705
                .builder()
706
                .add_address(client_addr)
707
                .runtime(rt.clone());
708
            // Mock the current time too
709
            #[allow(deprecated)] // TODO #1885
710
            let client_rt = MockSleepRuntime::new(client_rt);
711

            
712
            // Set up a relay runtime with a different IP
713
            let relay_rt = network
714
                .builder()
715
                .add_address(orport.ip())
716
                .runtime(rt.clone());
717

            
718
            // open a fake TLS listener and be ready to handle a request.
719
            let lis = relay_rt.mock_net().listen_tls(&orport, tls_cert).unwrap();
720

            
721
            // Tell the client to believe in a different timestamp.
722
            client_rt.jump_to(now);
723

            
724
            // Create the channel builder that we want to test.
725
            let transport = crate::transport::DefaultTransport::new(client_rt.clone(), None);
726
            let builder = ChanBuilder::new_client(client_rt, transport);
727

            
728
            let (r1, r2): (Result<Arc<Channel>>, Result<LocalStream>) = futures::join!(
729
                async {
730
                    // client-side: build a channel!
731
                    builder
732
                        .build_channel(
733
                            &target,
734
                            BootstrapReporter::fake(),
735
                            ChannelAccount::new_noop(),
736
                        )
737
                        .await
738
                },
739
                async {
740
                    // relay-side: accept the channel
741
                    // (and pretend to know what we're doing).
742
                    let (mut con, addr) = lis
743
                        .incoming()
744
                        .next()
745
                        .await
746
                        .expect("Closed?")
747
                        .expect("accept failed");
748
                    assert_eq!(client_addr, addr.ip());
749
                    crate::testing::answer_channel_req(&mut con)
750
                        .await
751
                        .expect("answer failed");
752
                    Ok(con)
753
                }
754
            );
755

            
756
            let chan = r1.unwrap();
757
            assert_eq!(chan.identity(RelayIdType::Ed25519), Some((&ed).into()));
758
            assert!(chan.is_usable());
759
            // In theory, time could pass here, so we can't just use
760
            // "assert_eq!(dur_unused, dur_unused2)".
761
            let dur_unused = Channel::duration_unused(&chan);
762
            let dur_unused_2 = AbstractChannel::duration_unused(chan.as_ref());
763
            let dur_unused_3 = Channel::duration_unused(&chan);
764
            assert!(dur_unused.unwrap() <= dur_unused_2.unwrap());
765
            assert!(dur_unused_2.unwrap() <= dur_unused_3.unwrap());
766

            
767
            r2.unwrap();
768
            Ok(())
769
        })
770
    }
771

            
772
    // TODO: Write tests for timeout logic, once there is smarter logic.
773
}