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

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

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

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

            
24
#[cfg(feature = "relay")]
25
use {
26
    futures::{AsyncRead, AsyncWrite},
27
    std::net::IpAddr,
28
    tor_proto::{RelayIdentities, peer::PeerAddr},
29
    tor_rtcompat::{CertifiedConn, StreamOps},
30
};
31

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

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

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

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

            
104
        // Same builder as a client but with identities and acceptor.
105
        let mut builder = Self::new_client(runtime, transport);
106
        builder.identities = Some(identities);
107
        builder.tls_acceptor = Some(tls_acceptor);
108
        builder.my_addrs = my_addrs;
109

            
110
        Ok(builder)
111
    }
112

            
113
    /// Build a new `ChanBuilder` with the given `identities`, cloning our runtime and transport.
114
    ///
115
    /// This is needed because the relay identities rotate over time.
116
    #[cfg(feature = "relay")]
117
    pub fn rebuild_with_identities(&self, identities: Arc<RelayIdentities>) -> crate::Result<Self>
118
    where
119
        H: Clone,
120
    {
121
        Self::new_relay(
122
            self.runtime.clone(),
123
            self.transport.clone(),
124
            identities,
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.identities.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
        let target = OwnedChanTargetBuilder::default()
195
            .addrs(vec![peer.into_inner()])
196
            .build()
197
            .map_err(|e| internal!("Unable to build chan target from peer sockaddr: {e}"))?;
198
        // Convert into a PeerAddr but keep it sensitive, this can be a client/bridge.
199
        let peer_addr: MaybeSensitive<PeerAddr> =
200
            MaybeSensitive::sensitive(peer.into_inner().into());
201

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

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

            
229
        let peer_cert = tls
230
            .peer_certificate()
231
            .map_err(|e| map_ioe(e.into(), "TLS Certs"))?
232
            .ok_or_else(|| Error::Internal(internal!("TLS connection with no peer certificate")))?
233
            // Note: we could skip this "into_owned" if we computed any necessary digest on the
234
            // certificate earlier.  That would require changing out channel negotiation APIs,
235
            // though, and might not be worth it.
236
            .into_owned();
237
        let our_cert = tls
238
            .own_certificate()
239
            .map_err(|e| map_ioe(e.into(), "TLS Certs"))?
240
            .ok_or_else(|| Error::Internal(internal!("TLS connection without our certificate")))?
241
            .into_owned();
242
        let builder = tor_proto::RelayChannelBuilder::new();
243

            
244
        let unverified = builder
245
            .accept(
246
                Sensitive::new(peer_addr.inner()),
247
                self.my_addrs.clone(),
248
                tls,
249
                self.runtime.clone(),
250
                identities,
251
                memquota,
252
            )
253
            .handshake(|| self.runtime.wallclock())
254
            .await
255
            .map_err(|e| map_proto(e, &target, None))?;
256

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

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

            
279
        Ok(chan)
280
    }
281
}
282

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

            
300
        {
301
            event_sender.lock().expect("Lock poisoned").record_attempt();
302
        }
303

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

            
309
        // 1a. Negotiate the TCP connection or other stream.
310

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

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

            
330
        // Helper to map protocol level error.
331
        //
332
        // We are logging the `target` here as these protocol error happens during the handshake
333
        // and we need to log the identities that are being tried but it will honor safe logging
334
        // for the relay <-> relay case which is not ideal but a tradeoff in complexity.
335
        let map_proto = |source, target: &OwnedChanTarget, clock_skew| Error::Proto {
336
            source,
337
            peer: target.to_logged(),
338
            clock_skew,
339
        };
340

            
341
        {
342
            // TODO(nickm): At some point, it would be helpful to the
343
            // bootstrapping logic if we could distinguish which
344
            // transport just succeeded.
345
            event_sender
346
                .lock()
347
                .expect("Lock poisoned")
348
                .record_tcp_success();
349
        }
350

            
351
        // 1b. Negotiate TLS.
352

            
353
        let hostname = rand_hostname::random_hostname(&mut rand::rng());
354

            
355
        let tls = self
356
            .tls_connector
357
            .negotiate_unvalidated(stream, hostname.as_str())
358
            .await
359
            .map_err(map_ioe("TLS negotiation"))?;
360

            
361
        let peer_cert = tls
362
            .peer_certificate()
363
            .map_err(map_ioe("TLS certs"))?
364
            .ok_or_else(|| Error::Internal(internal!("TLS connection with no peer certificate")))?
365
            // Note: we could skip this "into_owned" if we computed any necessary digest on the
366
            // certificate earlier.  That would require changing out channel negotiation APIs,
367
            // though, and might not be worth it.
368
            .into_owned();
369

            
370
        {
371
            event_sender
372
                .lock()
373
                .expect("Lock poisoned")
374
                .record_tls_finished();
375
        }
376
        let now = self.runtime.wallclock();
377

            
378
        // Store this so we can log it in case we don't recognize it.
379
        let outbound_chan_type = self.outbound_chan_type();
380
        let chan = match outbound_chan_type {
381
            ChannelType::ClientInitiator => {
382
                // Get the client specific channel builder.
383
                let mut builder = tor_proto::ClientChannelBuilder::new();
384
                builder.set_declared_method(target.chan_method());
385
                // Going full sensitive.
386
                let peer_addr = Sensitive::new(peer_addr.inner());
387

            
388
                let unverified = builder
389
                    .launch(
390
                        tls,
391
                        self.runtime.clone(), /* TODO provide ZST SleepProvider instead */
392
                        memquota,
393
                    )
394
2
                    .connect(|| self.runtime.wallclock())
395
                    .await
396
                    .map_err(|e| Error::from_proto_no_skew(e, target))?;
397

            
398
                let clock_skew = unverified.clock_skew();
399
                let (chan, reactor) = unverified
400
                    .verify(target, &peer_cert, Some(now))
401
                    .map_err(|source| match &source {
402
                        tor_proto::Error::HandshakeCertsExpired { .. } => {
403
                            event_sender
404
                                .lock()
405
                                .expect("Lock poisoned")
406
                                .record_handshake_done_with_skewed_clock();
407
                            map_proto(source, target, Some(clock_skew))
408
                        }
409
                        _ => Error::from_proto_no_skew(source, target),
410
                    })?
411
                    .finish(peer_addr)
412
                    .await
413
                    .map_err(|e| map_proto(e, target, Some(clock_skew)))?;
414

            
415
                // Launch a task to run the channel reactor.
416
                self.runtime
417
2
                    .spawn(async {
418
2
                        let _ = reactor.run().await;
419
2
                    })
420
                    .map_err(|e| Error::from_spawn("client channel reactor", e))?;
421
                chan
422
            }
423
            #[cfg(feature = "relay")]
424
            ChannelType::RelayInitiator => {
425
                self.build_relay_channel(
426
                    tls,
427
                    peer_addr.inner(),
428
                    target,
429
                    &peer_cert,
430
                    memquota,
431
                    event_sender.clone(),
432
                )
433
                .await?
434
            }
435
            _ => {
436
                return Err(Error::Internal(internal!(
437
                    "Unusable channel type for outbound: {outbound_chan_type}",
438
                )));
439
            }
440
        };
441

            
442
        event_sender
443
            .lock()
444
            .expect("Lock poisoned")
445
            .record_handshake_done();
446

            
447
        Ok(chan)
448
2
    }
449

            
450
    /// Validate the given target as in if it is fine to connect to it.
451
    ///
452
    /// We avoid building channels to ourselves as a relay.
453
    #[cfg(feature = "relay")]
454
2
    fn validate_relay_target(&self, target: &OwnedChanTarget) -> crate::Result<()> {
455
        use tor_linkspec::HasRelayIds;
456
        // Client with the relay feature won't have identities. A relay without identities is not
457
        // possible but even if it was, it won't be able to build a channel to itself as a relay
458
        // channel. Hence, returning Ok(()) here is fine as without identities ourself, we can
459
        // connect wherever.
460
2
        let Some(identities) = &self.identities else {
461
2
            return Ok(());
462
        };
463
        // Any of our identities match the given target, we are connecting to ourselves, refuse.
464
        if identities.has_any_relay_id_from(target) {
465
            Err(Error::Proto {
466
                source: tor_proto::Error::ChanProto(
467
                    "Refusing to build channel to ourselves".into(),
468
                ),
469
                peer: target.clone().into(),
470
                clock_skew: None,
471
            })
472
        } else {
473
            Ok(())
474
        }
475
2
    }
476

            
477
    /// Build a relay initiator channel.
478
    ///
479
    /// This spawns the Reactor and return the [`tor_proto::channel::Channel`].
480
    #[cfg(feature = "relay")]
481
    async fn build_relay_channel<T>(
482
        &self,
483
        tls: T,
484
        peer_addr: PeerAddr,
485
        target: &OwnedChanTarget,
486
        peer_cert: &[u8],
487
        memquota: ChannelAccount,
488
        event_sender: Arc<Mutex<ChanMgrEventSender>>,
489
    ) -> crate::Result<Arc<tor_proto::channel::Channel>>
490
    where
491
        T: AsyncRead + AsyncWrite + CertifiedConn + StreamOps + Send + Unpin + 'static,
492
    {
493
        let builder = tor_proto::RelayChannelBuilder::new();
494
        let identities = self
495
            .identities
496
            .as_ref()
497
            .ok_or(internal!(
498
                "Unable to build relay channel without identities"
499
            ))?
500
            .clone();
501

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

            
515
        let now = self.runtime.wallclock();
516
        let clock_skew = unverified.clock_skew();
517
        let (chan, reactor) = unverified
518
            .verify(target, peer_cert, Some(now))
519
            .map_err(|source| match &source {
520
                tor_proto::Error::HandshakeCertsExpired { .. } => {
521
                    event_sender
522
                        .lock()
523
                        .expect("Lock poisoned")
524
                        .record_handshake_done_with_skewed_clock();
525
                    Error::Proto {
526
                        source,
527
                        peer: target.to_logged(),
528
                        clock_skew: Some(clock_skew),
529
                    }
530
                }
531
                _ => Error::from_proto_no_skew(source, target),
532
            })?
533
            .finish(peer_addr)
534
            .await
535
            .map_err(|source| Error::Proto {
536
                source,
537
                peer: target.to_logged(),
538
                clock_skew: Some(clock_skew),
539
            })?;
540

            
541
        // Launch a task to run the channel reactor.
542
        self.runtime
543
            .spawn(async {
544
                let _ = reactor.run().await;
545
            })
546
            .map_err(|e| Error::from_spawn("relay channel reactor", e))?;
547

            
548
        Ok(chan)
549
    }
550
}
551

            
552
impl crate::mgr::AbstractChannel for tor_proto::channel::Channel {
553
    fn is_canonical(&self) -> bool {
554
        self.is_canonical()
555
    }
556
    fn is_canonical_to_peer(&self) -> bool {
557
        self.is_canonical_to_peer()
558
    }
559
2
    fn is_usable(&self) -> bool {
560
2
        !self.is_closing()
561
2
    }
562
2
    fn duration_unused(&self) -> Option<Duration> {
563
2
        self.duration_unused()
564
2
    }
565
108
    fn reparameterize(
566
108
        &self,
567
108
        updates: Arc<ChannelPaddingInstructionsUpdates>,
568
108
    ) -> tor_proto::Result<()> {
569
108
        tor_proto::channel::Channel::reparameterize(self, updates)
570
108
    }
571
    fn reparameterize_kist(&self, kist_params: KistParams) -> tor_proto::Result<()> {
572
        tor_proto::channel::Channel::reparameterize_kist(self, kist_params)
573
    }
574
36
    fn engage_padding_activities(&self) {
575
36
        tor_proto::channel::Channel::engage_padding_activities(self);
576
36
    }
577
}
578

            
579
#[cfg(test)]
580
mod test {
581
    // @@ begin test lint list maintained by maint/add_warning @@
582
    #![allow(clippy::bool_assert_comparison)]
583
    #![allow(clippy::clone_on_copy)]
584
    #![allow(clippy::dbg_macro)]
585
    #![allow(clippy::mixed_attributes_style)]
586
    #![allow(clippy::print_stderr)]
587
    #![allow(clippy::print_stdout)]
588
    #![allow(clippy::single_char_pattern)]
589
    #![allow(clippy::unwrap_used)]
590
    #![allow(clippy::unchecked_time_subtraction)]
591
    #![allow(clippy::useless_vec)]
592
    #![allow(clippy::needless_pass_by_value)]
593
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
594
    use super::*;
595
    use crate::{
596
        Result,
597
        mgr::{AbstractChannel, AbstractChannelFactory},
598
    };
599
    use futures::StreamExt as _;
600
    use std::net::SocketAddr;
601
    use std::time::{Duration, SystemTime};
602
    use tor_linkspec::{ChannelMethod, HasRelayIds, RelayIdType};
603
    use tor_llcrypto::pk::ed25519::Ed25519Identity;
604
    use tor_llcrypto::pk::rsa::RsaIdentity;
605
    use tor_proto::channel::Channel;
606
    use tor_proto::memquota::{ChannelAccount, SpecificAccount as _};
607
    use tor_rtcompat::{NetStreamListener, test_with_one_runtime};
608
    use tor_rtmock::{io::LocalStream, net::MockNetwork};
609

            
610
    #[allow(deprecated)] // TODO #1885
611
    use tor_rtmock::MockSleepRuntime;
612

            
613
    // Make sure that the builder can build a real channel.  To test
614
    // this out, we set up a listener that pretends to have the right
615
    // IP, fake the current time, and use a canned response from
616
    // [`testing::msgs`] crate.
617
    #[test]
618
    fn build_ok() -> Result<()> {
619
        use crate::testing::msgs;
620
        let orport: SocketAddr = msgs::ADDR.parse().unwrap();
621
        let ed: Ed25519Identity = msgs::ED_ID.into();
622
        let rsa: RsaIdentity = msgs::RSA_ID.into();
623
        let client_addr = "192.0.2.17".parse().unwrap();
624
        let tls_cert = msgs::X509_CERT.into();
625
        let target = OwnedChanTarget::builder()
626
            .addrs(vec![orport])
627
            .method(ChannelMethod::Direct(vec![orport]))
628
            .ed_identity(ed)
629
            .rsa_identity(rsa)
630
            .build()
631
            .unwrap();
632
        let now = SystemTime::UNIX_EPOCH + Duration::new(msgs::NOW, 0);
633

            
634
        test_with_one_runtime!(|rt| async move {
635
            // Stub out the internet so that this connection can work.
636
            let network = MockNetwork::new();
637

            
638
            // Set up a client runtime with a given IP
639
            let client_rt = network
640
                .builder()
641
                .add_address(client_addr)
642
                .runtime(rt.clone());
643
            // Mock the current time too
644
            #[allow(deprecated)] // TODO #1885
645
            let client_rt = MockSleepRuntime::new(client_rt);
646

            
647
            // Set up a relay runtime with a different IP
648
            let relay_rt = network
649
                .builder()
650
                .add_address(orport.ip())
651
                .runtime(rt.clone());
652

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

            
656
            // Tell the client to believe in a different timestamp.
657
            client_rt.jump_to(now);
658

            
659
            // Create the channel builder that we want to test.
660
            let transport = crate::transport::DefaultTransport::new(client_rt.clone(), None);
661
            let builder = ChanBuilder::new_client(client_rt, transport);
662

            
663
            let (r1, r2): (Result<Arc<Channel>>, Result<LocalStream>) = futures::join!(
664
                async {
665
                    // client-side: build a channel!
666
                    builder
667
                        .build_channel(
668
                            &target,
669
                            BootstrapReporter::fake(),
670
                            ChannelAccount::new_noop(),
671
                        )
672
                        .await
673
                },
674
                async {
675
                    // relay-side: accept the channel
676
                    // (and pretend to know what we're doing).
677
                    let (mut con, addr) = lis
678
                        .incoming()
679
                        .next()
680
                        .await
681
                        .expect("Closed?")
682
                        .expect("accept failed");
683
                    assert_eq!(client_addr, addr.ip());
684
                    crate::testing::answer_channel_req(&mut con)
685
                        .await
686
                        .expect("answer failed");
687
                    Ok(con)
688
                }
689
            );
690

            
691
            let chan = r1.unwrap();
692
            assert_eq!(chan.identity(RelayIdType::Ed25519), Some((&ed).into()));
693
            assert!(chan.is_usable());
694
            // In theory, time could pass here, so we can't just use
695
            // "assert_eq!(dur_unused, dur_unused2)".
696
            let dur_unused = Channel::duration_unused(&chan);
697
            let dur_unused_2 = AbstractChannel::duration_unused(chan.as_ref());
698
            let dur_unused_3 = Channel::duration_unused(&chan);
699
            assert!(dur_unused.unwrap() <= dur_unused_2.unwrap());
700
            assert!(dur_unused_2.unwrap() <= dur_unused_3.unwrap());
701

            
702
            r2.unwrap();
703
            Ok(())
704
        })
705
    }
706

            
707
    // TODO: Write tests for timeout logic, once there is smarter logic.
708
}