@@ -138,6 +138,67 @@ pub enum AddrV2 {
138138 Unknown ( u8 , Vec < u8 > ) ,
139139}
140140
141+ /// Error types for [`AddrV2`] to [`SocketAddr`] conversion.
142+ #[ derive( Debug , PartialEq , Eq ) ]
143+ pub enum AddrV2ConversionError {
144+ /// A [`AddrV2::TorV3`] address cannot be converted to a [`SocketAddr`].
145+ TorV3NotSupported ,
146+ /// A [`AddrV2::I2p`] address cannot be converted to a [`SocketAddr`].
147+ I2pNotSupported ,
148+ /// A [`AddrV2::Cjdns`] address can be converted to a [`SocketAddr`],
149+ /// but it won't work with a tradicional socket API.
150+ CjdnsNotRecommended ,
151+ /// A [`AddrV2::Unknown`] address cannot be converted to a [`SocketAddr`].
152+ UnknownNotSupported ,
153+ }
154+
155+ impl fmt:: Display for AddrV2ConversionError {
156+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
157+ match self {
158+ Self :: TorV3NotSupported => write ! ( f, "TorV3 addresses cannot be converted to SocketAddr" ) ,
159+ Self :: I2pNotSupported => write ! ( f, "I2P addresses cannot be converted to SocketAddr" ) ,
160+ Self :: CjdnsNotRecommended => write ! ( f, "CJDNS addresses can be converted to SocketAddr, but won't work with a traditional socket API" ) ,
161+ Self :: UnknownNotSupported => write ! ( f, "Unknown address type cannot be converted to SocketAddr" ) ,
162+ }
163+ }
164+ }
165+
166+ impl std:: error:: Error for AddrV2ConversionError { }
167+
168+
169+ impl From < SocketAddr > for AddrV2 {
170+ fn from ( addr : SocketAddr ) -> Self {
171+ match addr {
172+ SocketAddr :: V4 ( sock) => AddrV2 :: Ipv4 ( * sock. ip ( ) ) ,
173+ SocketAddr :: V6 ( sock) => {
174+ // CJDNS uses the IPv6 network `fc00::/8`
175+ // All CJDNS addresses must have `0xfc00` as the first and second octets
176+ let ip = * sock. ip ( ) ;
177+ if ip. octets ( ) [ 0 ] == 0xfc && ip. octets ( ) [ 1 ] == 0x00 {
178+ AddrV2 :: Cjdns ( ip)
179+ } else {
180+ AddrV2 :: Ipv6 ( ip)
181+ }
182+ }
183+ }
184+ }
185+ }
186+
187+ impl TryFrom < AddrV2 > for SocketAddr {
188+ type Error = AddrV2ConversionError ;
189+
190+ fn try_from ( addr : AddrV2 ) -> Result < SocketAddr , Self :: Error > {
191+ match addr {
192+ AddrV2 :: Ipv4 ( ip) => Ok ( SocketAddr :: V4 ( SocketAddrV4 :: new ( ip, 0 ) ) ) ,
193+ AddrV2 :: Ipv6 ( ip) => Ok ( SocketAddr :: V6 ( SocketAddrV6 :: new ( ip, 0 , 0 , 0 ) ) ) ,
194+ AddrV2 :: Cjdns ( _) => Err ( AddrV2ConversionError :: CjdnsNotRecommended ) ,
195+ AddrV2 :: TorV3 ( _) => Err ( AddrV2ConversionError :: TorV3NotSupported ) ,
196+ AddrV2 :: I2p ( _) => Err ( AddrV2ConversionError :: I2pNotSupported ) ,
197+ AddrV2 :: Unknown ( _, _) => Err ( AddrV2ConversionError :: UnknownNotSupported ) ,
198+ }
199+ }
200+ }
201+
141202impl Encodable for AddrV2 {
142203 fn consensus_encode < W : Write + ?Sized > ( & self , w : & mut W ) -> Result < usize , io:: Error > {
143204 fn encode_addr < W : Write + ?Sized > (
@@ -533,4 +594,98 @@ mod test {
533594
534595 assert_eq ! ( serialize( & addresses) , raw) ;
535596 }
597+
598+ #[ test]
599+ fn socketaddr_to_addrv2_ipv4 ( ) {
600+ let socket = SocketAddr :: V4 ( SocketAddrV4 :: new ( Ipv4Addr :: new ( 192 , 168 , 1 , 1 ) , 8333 ) ) ;
601+ let addr = AddrV2 :: from ( socket) ;
602+
603+ assert_eq ! ( addr, AddrV2 :: Ipv4 ( Ipv4Addr :: new( 192 , 168 , 1 , 1 ) ) ) ;
604+ }
605+
606+ #[ test]
607+ fn socketaddr_to_addrv2_ipv6 ( ) {
608+ let socket = SocketAddr :: V6 ( SocketAddrV6 :: new (
609+ Ipv6Addr :: new ( 0x2001 , 0xdb8 , 0 , 0 , 0 , 0 , 0 , 1 ) ,
610+ 8333 ,
611+ 0 ,
612+ 0 ,
613+ ) ) ;
614+ let addr = AddrV2 :: from ( socket) ;
615+
616+ assert_eq ! ( addr, AddrV2 :: Ipv6 ( Ipv6Addr :: new( 0x2001 , 0xdb8 , 0 , 0 , 0 , 0 , 0 , 1 ) ) ) ;
617+ }
618+
619+ #[ test]
620+ fn socketaddr_to_addrv2_cjdns ( ) {
621+ let socket = SocketAddr :: V6 ( SocketAddrV6 :: new (
622+ Ipv6Addr :: new ( 0xfc00 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ) ,
623+ 8333 ,
624+ 0 ,
625+ 0 ,
626+ ) ) ;
627+ let addr = AddrV2 :: from ( socket) ;
628+
629+ assert_eq ! ( addr, AddrV2 :: Cjdns ( Ipv6Addr :: new( 0xfc00 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ) ) ) ;
630+ }
631+
632+ #[ test]
633+ fn addrv2_to_socketaddr_ipv4 ( ) {
634+ let addr = AddrV2 :: Ipv4 ( Ipv4Addr :: new ( 192 , 168 , 1 , 1 ) ) ;
635+ let socket = SocketAddr :: try_from ( addr) . unwrap ( ) ;
636+
637+ assert_eq ! ( socket, SocketAddr :: V4 ( SocketAddrV4 :: new( Ipv4Addr :: new( 192 , 168 , 1 , 1 ) , 0 ) ) ) ;
638+ }
639+
640+ #[ test]
641+ fn addrv2_to_socketaddr_ipv6 ( ) {
642+ let addr = AddrV2 :: Ipv6 ( Ipv6Addr :: new ( 0x2001 , 0xdb8 , 0 , 0 , 0 , 0 , 0 , 1 ) ) ;
643+ let socket = SocketAddr :: try_from ( addr) . unwrap ( ) ;
644+
645+ assert_eq ! (
646+ socket,
647+ SocketAddr :: V6 ( SocketAddrV6 :: new(
648+ Ipv6Addr :: new( 0x2001 , 0xdb8 , 0 , 0 , 0 , 0 , 0 , 1 ) ,
649+ 0 ,
650+ 0 ,
651+ 0
652+ ) )
653+ ) ;
654+ }
655+
656+ #[ test]
657+ fn addrv2_to_socketaddr_cjdns ( ) {
658+ let addr = AddrV2 :: Cjdns ( Ipv6Addr :: new ( 0xfc00 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ) ) ;
659+ let result = SocketAddr :: try_from ( addr) ;
660+
661+ assert ! ( result. is_err( ) ) ;
662+ assert_eq ! ( result. unwrap_err( ) , AddrV2ConversionError :: CjdnsNotRecommended ) ;
663+ }
664+
665+ #[ test]
666+ fn addrv2_to_socketaddr_torv3 ( ) {
667+ let addr = AddrV2 :: TorV3 ( [ 0 ; 32 ] ) ;
668+ let result = SocketAddr :: try_from ( addr) ;
669+
670+ assert ! ( result. is_err( ) ) ;
671+ assert_eq ! ( result. unwrap_err( ) , AddrV2ConversionError :: TorV3NotSupported ) ;
672+ }
673+
674+ #[ test]
675+ fn addrv2_to_socketaddr_i2p ( ) {
676+ let addr = AddrV2 :: I2p ( [ 0 ; 32 ] ) ;
677+ let result = SocketAddr :: try_from ( addr) ;
678+
679+ assert ! ( result. is_err( ) ) ;
680+ assert_eq ! ( result. unwrap_err( ) , AddrV2ConversionError :: I2pNotSupported ) ;
681+ }
682+
683+ #[ test]
684+ fn addrv2_to_socketaddr_unknown ( ) {
685+ let addr = AddrV2 :: Unknown ( 42 , vec ! [ 1 , 2 , 3 , 4 ] ) ;
686+ let result = SocketAddr :: try_from ( addr) ;
687+
688+ assert ! ( result. is_err( ) ) ;
689+ assert_eq ! ( result. unwrap_err( ) , AddrV2ConversionError :: UnknownNotSupported ) ;
690+ }
536691}
0 commit comments