Repository: rust
Issue: [libs] Add `TcpStream::keepalive` and `TcpStream::set_keepalive`
Labels: T-libs-api,C-feature-request

Today [an issue was filed](https://github.com/async-rs/async-std/issues/718) in `async-std` asking how to set the `SO_KEEPALIVE` option on our `TcpStream`. Because we've only implemented methods that are available in `std` as well, we never added these methods. But I think there's a strong case to add these methods to `std::net::TcpStream`.

`TcpStream` already supports lots of control methods natively including: `set_read_timeout`, `set_write_timeout`, `set_ttl`, and `set_nodelay`. `set_keepalive` would be a method along the same lines providing a convenient way to set yet another low-level option. And there's a clear need for it: at least 3 other low-level TCP related libraries expose `keepalive` and `set_keepalive` (see the "Prior Art" section for more on this).

## Implementation

The implementation can probably entirely copied from [`net2::TcpStreamExt`](https://docs.rs/net2/0.2.33/net2/trait.TcpStreamExt.html#tymethod.keepalive). Unlike some of the other methods in that genre, these methods can operate entirely on an already instantiated socket.

Also between all existing implementations that I've found, there's consensus that the shape of the methods should be as follows:

```rust
impl TcpStream {
    fn set_keepalive(&self, keepalive: Option<Duration>) -> Result<()>;
    fn keepalive(&self) -> Result<Option<Duration>>;
}
```

## Prior Art
- [`net2::TcpStreamExt`](https://docs.rs/net2/0.2.33/net2/trait.TcpStreamExt.html#tymethod.keepalive) exposes both `keepalive` and `set_keepalive`.
- [`tokio::net::TcpStream`](https://docs.rs/tokio/0.2.13/tokio/net/struct.TcpStream.html#method.keepalive) exposes both `keepalive` and `set_keepalive`.
- [`socket2::Socket`](https://docs.rs/socket2/0.3.11/socket2/struct.Socket.html#method.set_keepalive) exposes both `keepalive` and `set_keepalive`.

## Prior Discussion

I couldn't find any references to `TcpStream::{keepalive,set_keepalive}` directly but https://github.com/rust-lang/rust/issues/27773 seems to touch on the general topic. Also https://github.com/rust-lang/rust/pull/28339 introduced many of the socket controls mentioned earlier, but doesn't seem to mention `keepalive` either.

---

__edit:__ I've since found https://github.com/rust-lang/rust/pull/31945#issuecomment-189784913 and https://github.com/rust-lang/rust/pull/24594 which mention `TcpStream::keepalive`. In particular https://github.com/rust-lang/rust/pull/31945#issuecomment-189784913 mentions:

> We should probably split the keepalive functionality into two methods to mirror how things work, (...) but that should be worked out in the net2 crate.

Discussion seems to have been started in https://github.com/rust-lang-nursery/net2-rs/issues/29, but hasn't progressed since 2016.

## Drawbacks

I don't think there are any. Back in 2015 it seems these methods weren't added as part of Rust 1.0 because the libs team wanted to be cautious of what to include. But I think in the years since it's proven to be a useful addition that's seen a lot of use throughout the ecosystem, and now might be a good time to consider adding these to `std`.