@@ -3,7 +3,7 @@ mod tests;
33
44use crate :: fmt;
55use crate :: io:: { self , ErrorKind } ;
6- use crate :: net:: { Ipv4Addr , Ipv6Addr , SocketAddr , ToSocketAddrs } ;
6+ use crate :: net:: { Ipv4Addr , Ipv6Addr , SocketAddr , SocketAddrFamily , ToSocketAddrs } ;
77use crate :: sys_common:: net as net_imp;
88use crate :: sys_common:: { AsInner , FromInner , IntoInner } ;
99use crate :: time:: Duration ;
@@ -811,3 +811,100 @@ impl fmt::Debug for UdpSocket {
811811 self . 0 . fmt ( f)
812812 }
813813}
814+
815+ /// A UDP Socket that is not bound to a `SocketAddr` yet.
816+ ///
817+ /// This socket is designed to support socket configurations _before_
818+ /// binding to a `SocketAddr`. After configurations, this socket
819+ /// can be bound and translated into a [`UdpSocket`].
820+ ///
821+ /// # Example
822+ ///
823+ /// ```no_run
824+ /// #![feature(unbound_socket)]
825+ /// use std::net::{SocketAddr, SocketAddrFamily, UnboundUdpSocket};
826+ ///
827+ /// fn main() -> std::io::Result<()> {
828+ /// let unbound_socket = UnboundUdpSocket::new(SocketAddrFamily::InetV4)?;
829+ /// unbound_socket.set_reuseaddr(true)?;
830+ /// let addr = SocketAddr::from(([127, 0, 0, 1], 5500));
831+ /// let _udp_socket = unbound_socket.bind(&addr)?;
832+ /// Ok(())
833+ /// }
834+ /// ```
835+ #[ unstable( feature = "unbound_socket" , issue = "none" ) ]
836+ pub struct UnboundUdpSocket {
837+ inner : net_imp:: UnboundUdpSocket ,
838+ }
839+
840+ impl UnboundUdpSocket {
841+ /// Creates a new unbound UDP socket with `addr_family`.
842+ #[ unstable( feature = "unbound_socket" , issue = "none" ) ]
843+ pub fn new ( addr_family : SocketAddrFamily ) -> io:: Result < UnboundUdpSocket > {
844+ let inner = net_imp:: UnboundUdpSocket :: new ( addr_family) ?;
845+ Ok ( Self { inner } )
846+ }
847+
848+ /// Sets `SO_REUSEADDR` option for the socket.
849+ ///
850+ /// In general, this option allows a second caller to bind to a `(addr, port)` again,
851+ /// where the `addr` could be the `unspecified` address. However it behaves with subtle
852+ /// differences on different platforms. Please be sure to check your platform for
853+ /// the exact expected behaviors.
854+ ///
855+ /// This method can only be called before `bind`, otherwise will fail.
856+ #[ unstable( feature = "unbound_socket" , issue = "none" ) ]
857+ pub fn set_reuseaddr ( & self , enable : bool ) -> io:: Result < ( ) > {
858+ self . inner . set_reuseaddr ( enable)
859+ }
860+
861+ /// Sets `SO_REUSEPORT` option for the socket.
862+ ///
863+ /// In general, this option allows a second caller to bind to a same `(addr, port)`
864+ /// pair again, if the first caller has enabled this option too. Please check with
865+ /// your specific platform for the details of the behavior.
866+ ///
867+ /// This option is only available for UNIX-like platforms and not Windows platforms.
868+ #[ unstable( feature = "unbound_socket" , issue = "none" ) ]
869+ pub fn set_reuseport ( & self , enable : bool ) -> io:: Result < ( ) > {
870+ self . inner . set_reuseport ( enable)
871+ }
872+
873+ /// Sets `SO_EXCLUSIVEADDRUSE` option for the socket.
874+ ///
875+ /// This option is only available in Windows. Its purpose is to prevent
876+ /// any other caller to "reuse" the same (addr, port), even if they call
877+ /// `set_reuseaddr(true)`. This method returns an error on non-Windows platforms.
878+ #[ unstable( feature = "unbound_socket" , issue = "none" ) ]
879+ pub fn set_exclusiveaddruse ( & self , enable : bool ) -> io:: Result < ( ) > {
880+ self . inner . set_exclusiveaddruse ( enable)
881+ }
882+
883+ /// Binds to `addr`, consumes this unbound socket and returns a [`UdpSocket`].
884+ #[ unstable( feature = "unbound_socket" , issue = "none" ) ]
885+ pub fn bind ( self , addr : & SocketAddr ) -> io:: Result < UdpSocket > {
886+ let net_imp = self . inner . bind ( addr) ?;
887+ Ok ( UdpSocket ( net_imp) )
888+ }
889+ }
890+
891+ #[ unstable( feature = "unbound_socket" , issue = "none" ) ]
892+ impl fmt:: Debug for UnboundUdpSocket {
893+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
894+ self . inner . fmt ( f)
895+ }
896+ }
897+
898+ #[ unstable( feature = "unbound_socket" , issue = "none" ) ]
899+ impl AsInner < net_imp:: UnboundUdpSocket > for UnboundUdpSocket {
900+ fn as_inner ( & self ) -> & net_imp:: UnboundUdpSocket {
901+ & self . inner
902+ }
903+ }
904+
905+ #[ unstable( feature = "unbound_socket" , issue = "none" ) ]
906+ impl IntoInner < net_imp:: UnboundUdpSocket > for UnboundUdpSocket {
907+ fn into_inner ( self ) -> net_imp:: UnboundUdpSocket {
908+ self . inner
909+ }
910+ }
0 commit comments