diff --git a/src/sys/windows.rs b/src/sys/windows.rs index 02de234b..b1fa20fc 100644 --- a/src/sys/windows.rs +++ b/src/sys/windows.rs @@ -35,7 +35,7 @@ use windows_sys::Win32::Networking::WinSock::{ #[cfg(feature = "all")] use windows_sys::Win32::Networking::WinSock::{ - IP6T_SO_ORIGINAL_DST, SOL_IP, SO_ORIGINAL_DST, SO_PROTOCOL_INFOW, + IP6T_SO_ORIGINAL_DST, SOL_IP, SO_EXCLUSIVEADDRUSE, SO_ORIGINAL_DST, SO_PROTOCOL_INFOW, }; use windows_sys::Win32::System::Threading::INFINITE; @@ -1089,6 +1089,46 @@ impl crate::Socket { } } + /// Get the value of the `SO_EXCLUSIVEADDRUSE` option on this socket. + /// + /// For more information about this option, see [`set_exclusive_address`]. + /// + /// [`set_exclusive_address`]: crate::Socket::set_exclusive_address + #[cfg(feature = "all")] + pub fn exclusive_address(&self) -> io::Result { + unsafe { + getsockopt::(self.as_raw(), SOL_SOCKET, SO_EXCLUSIVEADDRUSE) + .map(|exclusive| exclusive != 0) + } + } + + /// Set value for the `SO_EXCLUSIVEADDRUSE` option on this socket. + /// + /// This is the opposite of `SO_REUSEADDR` (see [`set_reuse_address`]): it + /// prevents other sockets from binding to the same address and port as + /// this socket, even when they set `SO_REUSEADDR`. On Windows (unlike + /// Unix), without this option another socket that sets `SO_REUSEADDR` can + /// bind to the address and port this socket is bound to and take over its + /// traffic. + /// + /// # Notes + /// + /// This option must be set before calling [`bind`] to have any effect. + /// + /// [`set_reuse_address`]: crate::Socket::set_reuse_address + /// [`bind`]: crate::Socket::bind + #[cfg(feature = "all")] + pub fn set_exclusive_address(&self, exclusive: bool) -> io::Result<()> { + unsafe { + setsockopt( + self.as_raw(), + SOL_SOCKET, + SO_EXCLUSIVEADDRUSE, + exclusive as c_int, + ) + } + } + /// Returns the [`Protocol`] of this socket by checking the `SO_PROTOCOL_INFOW` /// option on this socket. /// diff --git a/tests/socket.rs b/tests/socket.rs index 6fc58549..0f390e3a 100644 --- a/tests/socket.rs +++ b/tests/socket.rs @@ -1453,6 +1453,8 @@ test!( #[cfg(not(any(target_os = "redox", target_os = "wasi")))] test!(out_of_band_inline, set_out_of_band_inline(true)); test!(reuse_address, set_reuse_address(true)); +#[cfg(all(feature = "all", windows))] +test!(exclusive_address, set_exclusive_address(true)); #[cfg(all( feature = "all", not(any(