1use std::net;
17
18use crate::{
19 conn_expr::{Addr, ConnectionExpr, Port, PortSet, RouteExpr},
20 error::Error,
21 host_options::HostOptionsTable,
22};
23
24pub fn resolve_routes(
25 conn_expr: &ConnectionExpr,
26 host_opts_table: &HostOptionsTable,
27) -> Result<Routes, Error> {
28 use ConnectionExpr::*;
29 let route_expr = match conn_expr {
30 RouteExpr(ref e) => e,
31 HostKey(ref k) => host_opts_table
32 .get(k)
33 .ok_or_else(|| Error::HostKeyNotFound(k.to_string()))?
34 .conn_expr
35 .try_as_route_expr()
36 .ok_or_else(|| Error::RecursiveHostKeysNotSupported(k.to_string()))?,
37 };
38 Ok(Routes {
39 inner: RoutesInner::try_from_route_expr(route_expr)?,
40 pos: 0,
41 })
42}
43
44#[derive(Clone, Debug)]
45pub enum Route {
46 Direct(net::SocketAddr),
47 Tunneled(TunnelOptions),
52}
53
54#[derive(Clone, Debug)]
55pub struct TunnelOptions {
56 pub ssh_user: Option<String>,
57 pub ssh_addr: Addr,
58 pub ssh_port: Option<Port>,
59 pub host_addr: Addr,
60 pub host_port: Port,
61}
62
63#[derive(Clone, Debug)]
64pub struct Routes {
65 inner: RoutesInner,
66 pos: usize,
67}
68
69impl Iterator for Routes {
70 type Item = Route;
71
72 fn next(&mut self) -> Option<Self::Item> {
73 if self.pos < self.inner.len() {
74 let item = self.inner.produce(self.pos);
75 self.pos += 1;
76 Some(item)
77 } else {
78 None
79 }
80 }
81}
82
83#[derive(Clone, Debug)]
84enum RoutesInner {
85 Direct {
86 ips: Vec<net::IpAddr>,
87 ports: PortSet,
88 },
89 Tunneled {
90 ssh_user: Option<String>,
91 ssh_addr: Addr,
92 ssh_ports: Option<PortSet>,
93 host_addr: Addr,
94 host_ports: PortSet,
95 },
96}
97
98impl RoutesInner {
99 fn try_from_route_expr(route_expr: &RouteExpr) -> Result<Self, Error> {
100 if let Some(ref tunnel) = route_expr.tunnel {
101 let host_addr = route_expr
102 .addr
103 .as_ref()
104 .expect("tunneling should guarantee final host address")
105 .clone();
106 Ok(RoutesInner::Tunneled {
107 ssh_user: tunnel.user.clone(),
108 ssh_addr: tunnel.addr.clone(),
109 ssh_ports: tunnel.ports.clone(),
110 host_addr,
111 host_ports: route_expr.ports.clone(),
112 })
113 } else {
114 let mut ips = match route_expr.addr {
115 None => dns_lookup::lookup_host("localhost")
116 .map_err(|_| Error::DomainNotFound("localhost".to_owned()))?,
117 Some(Addr::Domain(ref domain)) => dns_lookup::lookup_host(domain)
118 .map_err(|_| Error::DomainNotFound(domain.clone()))?,
119 Some(Addr::IP(ip)) => vec![ip],
120 };
121 ips.sort();
122 Ok(RoutesInner::Direct {
123 ips,
124 ports: route_expr.ports.clone(),
125 })
126 }
127 }
128
129 fn len(&self) -> usize {
130 match self {
131 RoutesInner::Direct { ips: addrs, ports } => {
132 addrs.len() * ports.as_slice().len()
133 }
134 RoutesInner::Tunneled {
135 ssh_ports: None,
136 host_ports,
137 ..
138 } => host_ports.as_slice().len(),
139 RoutesInner::Tunneled {
140 ssh_ports: Some(ssh_ports),
141 host_ports,
142 ..
143 } => ssh_ports.as_slice().len() * host_ports.as_slice().len(),
144 }
145 }
146
147 fn produce(&self, ix: usize) -> Route {
148 assert!(ix < self.len());
149 match self {
150 RoutesInner::Direct { ips: addrs, ports } => {
151 let ix_addr = ix % addrs.len();
153 let ix_port = ix / addrs.len();
154 Route::Direct(net::SocketAddr::new(
155 addrs[ix_addr],
156 ports.as_slice()[ix_port],
157 ))
158 }
159 RoutesInner::Tunneled {
160 ssh_user,
161 ssh_addr,
162 ssh_ports: None,
163 host_addr,
164 host_ports,
165 } => Route::Tunneled(TunnelOptions {
166 ssh_user: ssh_user.clone(),
167 ssh_addr: ssh_addr.clone(),
168 ssh_port: None,
169 host_addr: host_addr.clone(),
170 host_port: host_ports.as_slice()[ix],
171 }),
172 RoutesInner::Tunneled {
173 ssh_user,
174 ssh_addr,
175
176 ssh_ports: Some(ssh_ports),
177 host_addr,
178 host_ports,
179 } => {
180 let ssh_ports = ssh_ports.as_slice();
182 let ix_ssh_port = ix % ssh_ports.len();
183 let ix_host_port = ix / ssh_ports.len();
184 Route::Tunneled(TunnelOptions {
185 ssh_user: ssh_user.clone(),
186 ssh_addr: ssh_addr.clone(),
187 ssh_port: Some(ssh_ports[ix_ssh_port]),
188 host_addr: host_addr.clone(),
189 host_port: host_ports.as_slice()[ix_host_port],
190 })
191 }
192 }
193 }
194}
195
196