electrum_client/socks/
mod.rs

1//! SOCKS proxy clients
2
3use std::io;
4use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
5use std::vec;
6
7pub use self::v4::{Socks4Listener, Socks4Stream};
8pub use self::v5::{Socks5Datagram, Socks5Listener, Socks5Stream};
9
10mod v4;
11mod v5;
12mod writev;
13
14/// A description of a connection target.
15#[derive(Debug, Clone)]
16pub enum TargetAddr {
17    /// Connect to an IP address.
18    Ip(SocketAddr),
19    /// Connect to a fully qualified domain name.
20    ///
21    /// The domain name will be passed along to the proxy server and DNS lookup
22    /// will happen there.
23    Domain(String, u16),
24}
25
26impl ToSocketAddrs for TargetAddr {
27    type Iter = Iter;
28
29    fn to_socket_addrs(&self) -> io::Result<Iter> {
30        let inner = match *self {
31            TargetAddr::Ip(addr) => IterInner::Ip(Some(addr)),
32            TargetAddr::Domain(ref domain, port) => {
33                let it = (&**domain, port).to_socket_addrs()?;
34                IterInner::Domain(it)
35            }
36        };
37        Ok(Iter(inner))
38    }
39}
40
41enum IterInner {
42    Ip(Option<SocketAddr>),
43    Domain(vec::IntoIter<SocketAddr>),
44}
45
46/// An iterator over `SocketAddr`s associated with a `TargetAddr`.
47pub struct Iter(IterInner);
48
49impl Iterator for Iter {
50    type Item = SocketAddr;
51
52    fn next(&mut self) -> Option<SocketAddr> {
53        match self.0 {
54            IterInner::Ip(ref mut addr) => addr.take(),
55            IterInner::Domain(ref mut it) => it.next(),
56        }
57    }
58}
59
60/// A trait for objects that can be converted to `TargetAddr`.
61pub trait ToTargetAddr {
62    /// Converts the value of `self` to a `TargetAddr`.
63    fn to_target_addr(&self) -> io::Result<TargetAddr>;
64}
65
66impl ToTargetAddr for TargetAddr {
67    fn to_target_addr(&self) -> io::Result<TargetAddr> {
68        Ok(self.clone())
69    }
70}
71
72impl ToTargetAddr for SocketAddr {
73    fn to_target_addr(&self) -> io::Result<TargetAddr> {
74        Ok(TargetAddr::Ip(*self))
75    }
76}
77
78impl ToTargetAddr for SocketAddrV4 {
79    fn to_target_addr(&self) -> io::Result<TargetAddr> {
80        SocketAddr::V4(*self).to_target_addr()
81    }
82}
83
84impl ToTargetAddr for SocketAddrV6 {
85    fn to_target_addr(&self) -> io::Result<TargetAddr> {
86        SocketAddr::V6(*self).to_target_addr()
87    }
88}
89
90impl ToTargetAddr for (Ipv4Addr, u16) {
91    fn to_target_addr(&self) -> io::Result<TargetAddr> {
92        SocketAddrV4::new(self.0, self.1).to_target_addr()
93    }
94}
95
96impl ToTargetAddr for (Ipv6Addr, u16) {
97    fn to_target_addr(&self) -> io::Result<TargetAddr> {
98        SocketAddrV6::new(self.0, self.1, 0, 0).to_target_addr()
99    }
100}
101
102impl ToTargetAddr for (&str, u16) {
103    fn to_target_addr(&self) -> io::Result<TargetAddr> {
104        // try to parse as an IP first
105        if let Ok(addr) = self.0.parse::<Ipv4Addr>() {
106            return (addr, self.1).to_target_addr();
107        }
108
109        if let Ok(addr) = self.0.parse::<Ipv6Addr>() {
110            return (addr, self.1).to_target_addr();
111        }
112
113        Ok(TargetAddr::Domain(self.0.to_owned(), self.1))
114    }
115}
116
117impl ToTargetAddr for &str {
118    fn to_target_addr(&self) -> io::Result<TargetAddr> {
119        // try to parse as an IP first
120        if let Ok(addr) = self.parse::<SocketAddrV4>() {
121            return addr.to_target_addr();
122        }
123
124        if let Ok(addr) = self.parse::<SocketAddrV6>() {
125            return addr.to_target_addr();
126        }
127
128        // split the string by ':' and convert the second part to u16
129        let mut parts_iter = self.rsplitn(2, ':');
130        let port_str = match parts_iter.next() {
131            Some(s) => s,
132            None => {
133                return Err(io::Error::new(
134                    io::ErrorKind::InvalidInput,
135                    "invalid socket address",
136                ))
137            }
138        };
139
140        let host = match parts_iter.next() {
141            Some(s) => s,
142            None => {
143                return Err(io::Error::new(
144                    io::ErrorKind::InvalidInput,
145                    "invalid socket address",
146                ))
147            }
148        };
149
150        let port: u16 = match port_str.parse() {
151            Ok(p) => p,
152            Err(_) => {
153                return Err(io::Error::new(
154                    io::ErrorKind::InvalidInput,
155                    "invalid port value",
156                ))
157            }
158        };
159
160        (host, port).to_target_addr()
161    }
162}