瀏覽代碼

rand: use simple PRNG owned by Interface, sockets access it through Context.

Dario Nieuwenhuis 3 年之前
父節點
當前提交
3644b94b82
共有 10 個文件被更改,包括 114 次插入103 次删除
  1. 3 3
      .github/workflows/test.yml
  2. 0 1
      Cargo.toml
  3. 2 2
      examples/client.rs
  4. 2 2
      examples/httpclient.rs
  5. 2 9
      examples/loopback.rs
  6. 36 0
      src/iface/interface.rs
  7. 0 3
      src/lib.rs
  8. 16 57
      src/rand.rs
  9. 4 4
      src/socket/dhcpv4.rs
  10. 49 22
      src/socket/tcp.rs

+ 3 - 3
.github/workflows/test.yml

@@ -48,7 +48,7 @@ jobs:
         include:
         include:
           # Test alloc feature which requires nightly.
           # Test alloc feature which requires nightly.
           - rust: nightly
           - rust: nightly
-            features: alloc rand-custom-impl medium-ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp
+            features: alloc medium-ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp
     steps:
     steps:
       - uses: actions/checkout@v2
       - uses: actions/checkout@v2
       - uses: actions-rs/toolchain@v1
       - uses: actions-rs/toolchain@v1
@@ -73,8 +73,8 @@ jobs:
 
 
         features:
         features:
           # These feature sets cannot run tests, so we only check they build.
           # These feature sets cannot run tests, so we only check they build.
-          - rand-custom-impl medium-ip medium-ethernet medium-ieee802154 proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async
-          - rand-custom-impl defmt medium-ip medium-ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async
+          - medium-ip medium-ethernet medium-ieee802154 proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async
+          - defmt medium-ip medium-ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async
 
 
     steps:
     steps:
       - uses: actions/checkout@v2
       - uses: actions/checkout@v2

+ 0 - 1
Cargo.toml

@@ -34,7 +34,6 @@ url = "1.0"
 std = ["managed/std", "rand_core/std"]
 std = ["managed/std", "rand_core/std"]
 alloc = ["managed/alloc"]
 alloc = ["managed/alloc"]
 verbose = []
 verbose = []
-rand-custom-impl = []
 "medium-ethernet" = ["socket"]
 "medium-ethernet" = ["socket"]
 "medium-ip" = ["socket"]
 "medium-ip" = ["socket"]
 "medium-ieee802154" = ["socket", "proto-sixlowpan"]
 "medium-ieee802154" = ["socket", "proto-sixlowpan"]

+ 2 - 2
examples/client.rs

@@ -54,8 +54,8 @@ fn main() {
 
 
     let tcp_handle = iface.add_socket(tcp_socket);
     let tcp_handle = iface.add_socket(tcp_socket);
 
 
-    let socket = iface.get_socket::<TcpSocket>(tcp_handle);
-    socket.connect((address, port), 49500).unwrap();
+    let (socket, cx) = iface.get_socket_and_context::<TcpSocket>(tcp_handle);
+    socket.connect(cx, (address, port), 49500).unwrap();
 
 
     let mut tcp_active = false;
     let mut tcp_active = false;
     loop {
     loop {

+ 2 - 2
examples/httpclient.rs

@@ -76,14 +76,14 @@ fn main() {
             }
             }
         }
         }
 
 
-        let socket = iface.get_socket::<TcpSocket>(tcp_handle);
+        let (socket, cx) = iface.get_socket_and_context::<TcpSocket>(tcp_handle);
 
 
         state = match state {
         state = match state {
             State::Connect if !socket.is_active() => {
             State::Connect if !socket.is_active() => {
                 debug!("connecting");
                 debug!("connecting");
                 let local_port = 49152 + rand::random::<u16>() % 16384;
                 let local_port = 49152 + rand::random::<u16>() % 16384;
                 socket
                 socket
-                    .connect((address, url.port().unwrap_or(80)), local_port)
+                    .connect(cx, (address, url.port().unwrap_or(80)), local_port)
                     .unwrap();
                     .unwrap();
                 State::Request
                 State::Request
             }
             }

+ 2 - 9
examples/loopback.rs

@@ -37,14 +37,6 @@ mod mock {
             self.0.get()
             self.0.get()
         }
         }
     }
     }
-
-    struct Rand;
-    smoltcp::rand_custom_impl!(Rand);
-    impl smoltcp::Rand for Rand {
-        fn rand_bytes(buf: &mut [u8]) {
-            buf.fill(0x42);
-        }
-    }
 }
 }
 
 
 #[cfg(feature = "std")]
 #[cfg(feature = "std")]
@@ -153,12 +145,13 @@ fn main() {
             done = true;
             done = true;
         }
         }
 
 
-        let mut socket = iface.get_socket::<TcpSocket>(client_handle);
+        let (mut socket, cx) = iface.get_socket_and_context::<TcpSocket>(client_handle);
         if !socket.is_open() {
         if !socket.is_open() {
             if !did_connect {
             if !did_connect {
                 debug!("connecting");
                 debug!("connecting");
                 socket
                 socket
                     .connect(
                     .connect(
+                        cx,
                         (IpAddress::v4(127, 0, 0, 1), 1234),
                         (IpAddress::v4(127, 0, 0, 1), 1234),
                         (IpAddress::Unspecified, 65000),
                         (IpAddress::Unspecified, 65000),
                     )
                     )

+ 36 - 0
src/iface/interface.rs

@@ -11,6 +11,7 @@ use crate::iface::Routes;
 #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
 #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
 use crate::iface::{NeighborAnswer, NeighborCache};
 use crate::iface::{NeighborAnswer, NeighborCache};
 use crate::phy::{ChecksumCapabilities, Device, DeviceCapabilities, Medium, RxToken, TxToken};
 use crate::phy::{ChecksumCapabilities, Device, DeviceCapabilities, Medium, RxToken, TxToken};
+use crate::rand::Rand;
 use crate::socket::*;
 use crate::socket::*;
 use crate::time::{Duration, Instant};
 use crate::time::{Duration, Instant};
 use crate::wire::*;
 use crate::wire::*;
@@ -54,6 +55,7 @@ pub struct InterfaceInner<'a> {
     /// When to report for (all or) the next multicast group membership via IGMP
     /// When to report for (all or) the next multicast group membership via IGMP
     #[cfg(feature = "proto-igmp")]
     #[cfg(feature = "proto-igmp")]
     igmp_report_state: IgmpReportState,
     igmp_report_state: IgmpReportState,
+    rand: Rand,
 }
 }
 
 
 /// A builder structure used for creating a network interface.
 /// A builder structure used for creating a network interface.
@@ -75,6 +77,7 @@ pub struct InterfaceBuilder<'a, DeviceT: for<'d> Device<'d>> {
     /// Does not share storage with `ipv6_multicast_groups` to avoid IPv6 size overhead.
     /// Does not share storage with `ipv6_multicast_groups` to avoid IPv6 size overhead.
     #[cfg(feature = "proto-igmp")]
     #[cfg(feature = "proto-igmp")]
     ipv4_multicast_groups: ManagedMap<'a, Ipv4Address, ()>,
     ipv4_multicast_groups: ManagedMap<'a, Ipv4Address, ()>,
+    random_seed: u64,
 }
 }
 
 
 impl<'a, DeviceT> InterfaceBuilder<'a, DeviceT>
 impl<'a, DeviceT> InterfaceBuilder<'a, DeviceT>
@@ -134,9 +137,21 @@ let iface = InterfaceBuilder::new(device, vec![])
             routes: Routes::new(ManagedMap::Borrowed(&mut [])),
             routes: Routes::new(ManagedMap::Borrowed(&mut [])),
             #[cfg(feature = "proto-igmp")]
             #[cfg(feature = "proto-igmp")]
             ipv4_multicast_groups: ManagedMap::Borrowed(&mut []),
             ipv4_multicast_groups: ManagedMap::Borrowed(&mut []),
+            random_seed: 0,
         }
         }
     }
     }
 
 
+    /// Set the random seed for this interface.
+    ///
+    /// It is strongly recommended that the random seed is different on each boot,
+    /// to avoid problems with TCP port/sequence collisions.
+    ///
+    /// The seed doesn't have to be cryptographically secure.
+    pub fn random_seed(mut self, random_seed: u64) -> Self {
+        self.random_seed = random_seed;
+        self
+    }
+
     /// Set the Hardware address the interface will use. See also
     /// Set the Hardware address the interface will use. See also
     /// [hardware_addr].
     /// [hardware_addr].
     ///
     ///
@@ -319,6 +334,7 @@ let iface = InterfaceBuilder::new(device, vec![])
                 sequence_no: self.sequence_no,
                 sequence_no: self.sequence_no,
                 #[cfg(feature = "medium-ieee802154")]
                 #[cfg(feature = "medium-ieee802154")]
                 pan_id: self.pan_id,
                 pan_id: self.pan_id,
+                rand: Rand::new(self.random_seed),
             },
             },
         }
         }
     }
     }
@@ -495,6 +511,20 @@ where
         self.sockets.get(handle)
         self.sockets.get(handle)
     }
     }
 
 
+    /// Get a socket by handle, and the socket context.
+    ///
+    /// The context is needed for some socket methods.
+    ///
+    /// # Panics
+    /// This function may panic if the handle does not belong to this socket set
+    /// or the socket has the wrong type.
+    pub fn get_socket_and_context<T: AnySocket<'a>>(
+        &mut self,
+        handle: SocketHandle,
+    ) -> (&mut T, &mut InterfaceInner<'a>) {
+        (self.sockets.get(handle), &mut self.inner)
+    }
+
     /// Remove a socket from the set, without changing its state.
     /// Remove a socket from the set, without changing its state.
     ///
     ///
     /// # Panics
     /// # Panics
@@ -1018,6 +1048,11 @@ impl<'a> InterfaceInner<'a> {
         self.caps.ip_mtu()
         self.caps.ip_mtu()
     }
     }
 
 
+    #[allow(unused)] // unused depending on which sockets are enabled, and in tests
+    pub(crate) fn rand(&mut self) -> &mut Rand {
+        &mut self.rand
+    }
+
     #[cfg(test)]
     #[cfg(test)]
     pub(crate) fn mock() -> Self {
     pub(crate) fn mock() -> Self {
         Self {
         Self {
@@ -1044,6 +1079,7 @@ impl<'a> InterfaceInner<'a> {
             now: Instant::from_millis_const(0),
             now: Instant::from_millis_const(0),
 
 
             ip_addrs: ManagedSlice::Owned(vec![]),
             ip_addrs: ManagedSlice::Owned(vec![]),
+            rand: Rand::new(1234),
             routes: Routes::new(&mut [][..]),
             routes: Routes::new(&mut [][..]),
 
 
             #[cfg(feature = "proto-ipv4")]
             #[cfg(feature = "proto-ipv4")]

+ 0 - 3
src/lib.rs

@@ -134,10 +134,7 @@ use core::fmt;
 #[macro_use]
 #[macro_use]
 mod macros;
 mod macros;
 mod parsers;
 mod parsers;
-
 mod rand;
 mod rand;
-#[cfg(feature = "rand-custom-impl")]
-pub use crate::rand::Rand;
 
 
 #[cfg(any(
 #[cfg(any(
     feature = "medium-ethernet",
     feature = "medium-ethernet",

+ 16 - 57
src/rand.rs

@@ -1,67 +1,26 @@
 #![allow(unsafe_code)]
 #![allow(unsafe_code)]
 #![allow(unused)]
 #![allow(unused)]
 
 
-#[cfg(not(any(test, feature = "std", feature = "rand-custom-impl")))]
-compile_error!("None of the Cargo features `std` or `rand-custom-impl` is enabled. smoltcp needs a `rand` implementation to work. If your target supports `std`, enable the `std` feature to use the OS's RNG. Otherwise, you must enable the `rand-custom-impl` Cargo feature, and supply your own custom implementation using the `smoltcp::rand_custom_impl!()` macro");
-
-pub fn rand_u32() -> u32 {
-    let mut val = [0; 4];
-    rand_bytes(&mut val);
-    u32::from_ne_bytes(val)
+#[derive(Debug)]
+pub(crate) struct Rand {
+    state: u64,
 }
 }
 
 
-/// Fill `buf` with random bytes.
-pub fn rand_bytes(buf: &mut [u8]) {
-    extern "Rust" {
-        fn _smoltcp_rand(buf: &mut [u8]);
+impl Rand {
+    pub(crate) const fn new(seed: u64) -> Self {
+        Self { state: seed }
     }
     }
 
 
-    unsafe { _smoltcp_rand(buf) }
-}
+    pub(crate) fn rand_u32(&mut self) -> u32 {
+        // sPCG32 from https://www.pcg-random.org/paper.html
+        // see also https://nullprogram.com/blog/2017/09/21/
+        const M: u64 = 0xbb2efcec3c39611d;
+        const A: u64 = 0x7590ef39;
 
 
-/// Methods required for a custom rand implementation.
-///
-/// This trait is not intended to be used directly, just to supply a custom rand implementation to smoltcp.
-#[cfg(feature = "rand-custom-impl")]
-pub trait Rand {
-    /// Fill `buf` with random bytes.
-    fn rand_bytes(buf: &mut [u8]);
-}
-
-/// Set the custom rand implementation.
-///
-/// # Example
-///
-/// ```
-/// struct Rand;
-/// smoltcp::rand_custom_impl!(Rand);
-/// impl smoltcp::Rand for Rand {
-///     fn rand_bytes(buf: &mut [u8]) {
-///         // TODO
-///     }
-/// }
-///
-#[macro_export]
-#[cfg(feature = "rand-custom-impl")]
-macro_rules! rand_custom_impl {
-    ($t: ty) => {
-        #[no_mangle]
-        fn _smoltcp_rand(buf: &mut [u8]) {
-            <$t as $crate::Rand>::rand_bytes(buf)
-        }
-    };
-}
+        let s = self.state * M + A;
+        self.state = s;
 
 
-#[cfg(all(feature = "std", not(feature = "rand-custom-impl"), not(test)))]
-#[no_mangle]
-fn _smoltcp_rand(buf: &mut [u8]) {
-    use rand_core::RngCore;
-
-    rand_core::OsRng.fill_bytes(buf)
-}
-
-#[cfg(test)]
-#[no_mangle]
-fn _smoltcp_rand(buf: &mut [u8]) {
-    panic!("Rand should not be used when testing");
+        let shift = 29 - (s >> 61);
+        (s >> shift) as u32
+    }
 }
 }

+ 4 - 4
src/socket/dhcpv4.rs

@@ -370,12 +370,12 @@ impl Dhcpv4Socket {
     }
     }
 
 
     #[cfg(not(test))]
     #[cfg(not(test))]
-    fn random_transaction_id() -> u32 {
-        crate::rand::rand_u32()
+    fn random_transaction_id(cx: &mut Context) -> u32 {
+        cx.rand().rand_u32()
     }
     }
 
 
     #[cfg(test)]
     #[cfg(test)]
-    fn random_transaction_id() -> u32 {
+    fn random_transaction_id(_cx: &mut Context) -> u32 {
         0x12345678
         0x12345678
     }
     }
 
 
@@ -397,7 +397,7 @@ impl Dhcpv4Socket {
 
 
         // We don't directly modify self.transaction_id because sending the packet
         // We don't directly modify self.transaction_id because sending the packet
         // may fail. We only want to update state after succesfully sending.
         // may fail. We only want to update state after succesfully sending.
-        let next_transaction_id = Self::random_transaction_id();
+        let next_transaction_id = Self::random_transaction_id(cx);
 
 
         let mut dhcp_repr = DhcpRepr {
         let mut dhcp_repr = DhcpRepr {
             message_type: DhcpMessageType::Discover,
             message_type: DhcpMessageType::Discover,

+ 49 - 22
src/socket/tcp.rs

@@ -708,7 +708,12 @@ impl<'a> TcpSocket<'a> {
     /// This function returns an error if the socket was open; see [is_open](#method.is_open).
     /// This function returns an error if the socket was open; see [is_open](#method.is_open).
     /// It also returns an error if the local or remote port is zero, or if the remote address
     /// It also returns an error if the local or remote port is zero, or if the remote address
     /// is unspecified.
     /// is unspecified.
-    pub fn connect<T, U>(&mut self, remote_endpoint: T, local_endpoint: U) -> Result<()>
+    pub fn connect<T, U>(
+        &mut self,
+        cx: &mut Context,
+        remote_endpoint: T,
+        local_endpoint: U,
+    ) -> Result<()>
     where
     where
         T: Into<IpEndpoint>,
         T: Into<IpEndpoint>,
         U: Into<IpEndpoint>,
         U: Into<IpEndpoint>,
@@ -743,17 +748,20 @@ impl<'a> TcpSocket<'a> {
         self.remote_endpoint = remote_endpoint;
         self.remote_endpoint = remote_endpoint;
         self.set_state(State::SynSent);
         self.set_state(State::SynSent);
 
 
-        let seq = Self::random_seq_no();
+        let seq = Self::random_seq_no(cx);
         self.local_seq_no = seq;
         self.local_seq_no = seq;
         self.remote_last_seq = seq;
         self.remote_last_seq = seq;
         Ok(())
         Ok(())
     }
     }
 
 
-    fn random_seq_no() -> TcpSeqNumber {
-        #[cfg(test)]
-        return TcpSeqNumber(10000);
-        #[cfg(not(test))]
-        return TcpSeqNumber(crate::rand::rand_u32() as i32);
+    #[cfg(test)]
+    fn random_seq_no(_cx: &mut Context) -> TcpSeqNumber {
+        TcpSeqNumber(10000)
+    }
+
+    #[cfg(not(test))]
+    fn random_seq_no(cx: &mut Context) -> TcpSeqNumber {
+        TcpSeqNumber(cx.rand().rand_u32() as i32)
     }
     }
 
 
     /// Close the transmit half of the full-duplex connection.
     /// Close the transmit half of the full-duplex connection.
@@ -1570,7 +1578,7 @@ impl<'a> TcpSocket<'a> {
 
 
                 self.local_endpoint = IpEndpoint::new(ip_repr.dst_addr(), repr.dst_port);
                 self.local_endpoint = IpEndpoint::new(ip_repr.dst_addr(), repr.dst_port);
                 self.remote_endpoint = IpEndpoint::new(ip_repr.src_addr(), repr.src_port);
                 self.remote_endpoint = IpEndpoint::new(ip_repr.src_addr(), repr.src_port);
-                self.local_seq_no = Self::random_seq_no();
+                self.local_seq_no = Self::random_seq_no(cx);
                 self.remote_seq_no = repr.seq_number + 1;
                 self.remote_seq_no = repr.seq_number + 1;
                 self.remote_last_seq = self.local_seq_no;
                 self.remote_last_seq = self.local_seq_no;
                 self.remote_has_sack = repr.sack_permitted;
                 self.remote_has_sack = repr.sack_permitted;
@@ -3215,23 +3223,27 @@ mod test {
     fn test_connect_validation() {
     fn test_connect_validation() {
         let mut s = socket();
         let mut s = socket();
         assert_eq!(
         assert_eq!(
-            s.socket.connect((IpAddress::Unspecified, 80), LOCAL_END),
+            s.socket
+                .connect(&mut s.cx, (IpAddress::Unspecified, 80), LOCAL_END),
             Err(Error::Unaddressable)
             Err(Error::Unaddressable)
         );
         );
         assert_eq!(
         assert_eq!(
-            s.socket.connect(REMOTE_END, (MOCK_UNSPECIFIED, 0)),
+            s.socket
+                .connect(&mut s.cx, REMOTE_END, (MOCK_UNSPECIFIED, 0)),
             Err(Error::Unaddressable)
             Err(Error::Unaddressable)
         );
         );
         assert_eq!(
         assert_eq!(
-            s.socket.connect((MOCK_UNSPECIFIED, 0), LOCAL_END),
+            s.socket
+                .connect(&mut s.cx, (MOCK_UNSPECIFIED, 0), LOCAL_END),
             Err(Error::Unaddressable)
             Err(Error::Unaddressable)
         );
         );
         assert_eq!(
         assert_eq!(
-            s.socket.connect((IpAddress::Unspecified, 80), LOCAL_END),
+            s.socket
+                .connect(&mut s.cx, (IpAddress::Unspecified, 80), LOCAL_END),
             Err(Error::Unaddressable)
             Err(Error::Unaddressable)
         );
         );
         s.socket
         s.socket
-            .connect(REMOTE_END, LOCAL_END)
+            .connect(&mut s.cx, REMOTE_END, LOCAL_END)
             .expect("Connect failed with valid parameters");
             .expect("Connect failed with valid parameters");
         assert_eq!(s.local_endpoint(), LOCAL_END);
         assert_eq!(s.local_endpoint(), LOCAL_END);
         assert_eq!(s.remote_endpoint(), REMOTE_END);
         assert_eq!(s.remote_endpoint(), REMOTE_END);
@@ -3241,7 +3253,9 @@ mod test {
     fn test_connect() {
     fn test_connect() {
         let mut s = socket();
         let mut s = socket();
         s.local_seq_no = LOCAL_SEQ;
         s.local_seq_no = LOCAL_SEQ;
-        s.socket.connect(REMOTE_END, LOCAL_END.port).unwrap();
+        s.socket
+            .connect(&mut s.cx, REMOTE_END, LOCAL_END.port)
+            .unwrap();
         assert_eq!(
         assert_eq!(
             s.local_endpoint,
             s.local_endpoint,
             IpEndpoint::new(MOCK_UNSPECIFIED, LOCAL_END.port)
             IpEndpoint::new(MOCK_UNSPECIFIED, LOCAL_END.port)
@@ -3275,10 +3289,15 @@ mod test {
     #[test]
     #[test]
     fn test_connect_unspecified_local() {
     fn test_connect_unspecified_local() {
         let mut s = socket();
         let mut s = socket();
-        assert_eq!(s.socket.connect(REMOTE_END, (MOCK_UNSPECIFIED, 80)), Ok(()));
+        assert_eq!(
+            s.socket
+                .connect(&mut s.cx, REMOTE_END, (MOCK_UNSPECIFIED, 80)),
+            Ok(())
+        );
         s.abort();
         s.abort();
         assert_eq!(
         assert_eq!(
-            s.socket.connect(REMOTE_END, (IpAddress::Unspecified, 80)),
+            s.socket
+                .connect(&mut s.cx, REMOTE_END, (IpAddress::Unspecified, 80)),
             Ok(())
             Ok(())
         );
         );
         s.abort();
         s.abort();
@@ -3287,18 +3306,24 @@ mod test {
     #[test]
     #[test]
     fn test_connect_specified_local() {
     fn test_connect_specified_local() {
         let mut s = socket();
         let mut s = socket();
-        assert_eq!(s.socket.connect(REMOTE_END, (MOCK_IP_ADDR_2, 80)), Ok(()));
+        assert_eq!(
+            s.socket
+                .connect(&mut s.cx, REMOTE_END, (MOCK_IP_ADDR_2, 80)),
+            Ok(())
+        );
     }
     }
 
 
     #[test]
     #[test]
     fn test_connect_twice() {
     fn test_connect_twice() {
         let mut s = socket();
         let mut s = socket();
         assert_eq!(
         assert_eq!(
-            s.socket.connect(REMOTE_END, (IpAddress::Unspecified, 80)),
+            s.socket
+                .connect(&mut s.cx, REMOTE_END, (IpAddress::Unspecified, 80)),
             Ok(())
             Ok(())
         );
         );
         assert_eq!(
         assert_eq!(
-            s.socket.connect(REMOTE_END, (IpAddress::Unspecified, 80)),
+            s.socket
+                .connect(&mut s.cx, REMOTE_END, (IpAddress::Unspecified, 80)),
             Err(Error::Illegal)
             Err(Error::Illegal)
         );
         );
     }
     }
@@ -3307,7 +3332,7 @@ mod test {
     fn test_syn_sent_sanity() {
     fn test_syn_sent_sanity() {
         let mut s = socket();
         let mut s = socket();
         s.local_seq_no = LOCAL_SEQ;
         s.local_seq_no = LOCAL_SEQ;
-        s.socket.connect(REMOTE_END, LOCAL_END).unwrap();
+        s.socket.connect(&mut s.cx, REMOTE_END, LOCAL_END).unwrap();
         sanity!(s, socket_syn_sent_with_local_ipendpoint(LOCAL_END));
         sanity!(s, socket_syn_sent_with_local_ipendpoint(LOCAL_END));
     }
     }
 
 
@@ -3562,7 +3587,7 @@ mod test {
             let mut s = socket_with_buffer_sizes(64, *buffer_size);
             let mut s = socket_with_buffer_sizes(64, *buffer_size);
             s.local_seq_no = LOCAL_SEQ;
             s.local_seq_no = LOCAL_SEQ;
             assert_eq!(s.remote_win_shift, *shift_amt);
             assert_eq!(s.remote_win_shift, *shift_amt);
-            s.socket.connect(REMOTE_END, LOCAL_END).unwrap();
+            s.socket.connect(&mut s.cx, REMOTE_END, LOCAL_END).unwrap();
             recv!(
             recv!(
                 s,
                 s,
                 [TcpRepr {
                 [TcpRepr {
@@ -6061,7 +6086,9 @@ mod test {
     fn test_connect_timeout() {
     fn test_connect_timeout() {
         let mut s = socket();
         let mut s = socket();
         s.local_seq_no = LOCAL_SEQ;
         s.local_seq_no = LOCAL_SEQ;
-        s.socket.connect(REMOTE_END, LOCAL_END.port).unwrap();
+        s.socket
+            .connect(&mut s.cx, REMOTE_END, LOCAL_END.port)
+            .unwrap();
         s.set_timeout(Some(Duration::from_millis(100)));
         s.set_timeout(Some(Duration::from_millis(100)));
         recv!(s, time 150, Ok(TcpRepr {
         recv!(s, time 150, Ok(TcpRepr {
             control:    TcpControl::Syn,
             control:    TcpControl::Syn,