mirror of
https://github.com/shadowsocks/shadowsocks-rust.git
synced 2026-02-09 01:59:16 +08:00
updated code structure, added dns cache
This commit is contained in:
@@ -105,6 +105,7 @@ It supports the following features:
|
||||
* `UDP_ASSOCIATION` and `BIND` command
|
||||
* Socks5 authentication
|
||||
* <del>Extend configuration format</del>
|
||||
* <del>DNS cache</del>
|
||||
* Fully testing on servers
|
||||
* Performance testing and improvement
|
||||
* Multiple workers
|
||||
|
||||
112
src/relay/mod.rs
112
src/relay/mod.rs
@@ -24,123 +24,13 @@
|
||||
pub use self::local::RelayLocal;
|
||||
pub use self::server::RelayServer;
|
||||
|
||||
use std::fmt::{Show, Formatter, FormatError};
|
||||
use std::io::net::ip::{SocketAddr, Port};
|
||||
use std::io::net::ip::{Ipv4Addr, Ipv6Addr};
|
||||
|
||||
mod tcprelay;
|
||||
// pub mod udprelay;
|
||||
pub mod local;
|
||||
pub mod server;
|
||||
mod loadbalancing;
|
||||
mod socks5;
|
||||
|
||||
pub trait Relay {
|
||||
fn run(&self);
|
||||
}
|
||||
|
||||
pub const SOCKS5_VERSION : u8 = 0x05;
|
||||
|
||||
pub const SOCKS5_AUTH_METHOD_NONE : u8 = 0x00;
|
||||
pub const SOCKS5_AUTH_METHOD_GSSAPI : u8 = 0x01;
|
||||
pub const SOCKS5_AUTH_METHOD_PASSWORD : u8 = 0x02;
|
||||
pub const SOCKS5_AUTH_METHOD_NOT_ACCEPTABLE : u8 = 0xff;
|
||||
|
||||
pub const SOCKS5_CMD_TCP_CONNECT : u8 = 0x01;
|
||||
pub const SOCKS5_CMD_TCP_BIND : u8 = 0x02;
|
||||
pub const SOCKS5_CMD_UDP_ASSOCIATE : u8 = 0x03;
|
||||
|
||||
pub const SOCKS5_ADDR_TYPE_IPV4 : u8 = 0x01;
|
||||
pub const SOCKS5_ADDR_TYPE_DOMAIN_NAME : u8 = 0x03;
|
||||
pub const SOCKS5_ADDR_TYPE_IPV6 : u8 = 0x04;
|
||||
|
||||
pub const SOCKS5_REPLY_SUCCEEDED : u8 = 0x00;
|
||||
pub const SOCKS5_REPLY_GENERAL_FAILURE : u8 = 0x01;
|
||||
pub const SOCKS5_REPLY_CONNECTION_NOT_ALLOWED : u8 = 0x02;
|
||||
pub const SOCKS5_REPLY_NETWORK_UNREACHABLE : u8 = 0x03;
|
||||
pub const SOCKS5_REPLY_HOST_UNREACHABLE : u8 = 0x04;
|
||||
pub const SOCKS5_REPLY_CONNECTION_REFUSED : u8 = 0x05;
|
||||
pub const SOCKS5_REPLY_TTL_EXPIRED : u8 = 0x06;
|
||||
pub const SOCKS5_REPLY_COMMAND_NOT_SUPPORTED : u8 = 0x07;
|
||||
pub const SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED : u8 = 0x08;
|
||||
|
||||
#[deriving(Show)]
|
||||
pub enum Sock5CmdType {
|
||||
Sock5CmdTcpConnect,
|
||||
Sock5CmdTcpBind,
|
||||
Sock5CmdUdpAssociate,
|
||||
}
|
||||
|
||||
pub struct DomainNameAddr {
|
||||
pub domain_name: String,
|
||||
pub port: Port,
|
||||
}
|
||||
|
||||
impl Show for DomainNameAddr {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
|
||||
f.write(format!("{}:{}", self.domain_name, self.port).as_slice().as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Show)]
|
||||
pub enum Sock5AddrType {
|
||||
Sock5SocketAddr(SocketAddr),
|
||||
Sock5DomainNameAddr(DomainNameAddr),
|
||||
}
|
||||
|
||||
pub fn parse_request_header(buf: &[u8]) -> Result<(uint, Sock5AddrType), u8> {
|
||||
let atyp = buf[0];
|
||||
match atyp {
|
||||
SOCKS5_ADDR_TYPE_IPV4 => {
|
||||
if buf.len() < 7 {
|
||||
fail!("Invalid header");
|
||||
}
|
||||
|
||||
let raw_addr = buf.slice(1, 5);
|
||||
let v4addr = Ipv4Addr(raw_addr[0], raw_addr[1], raw_addr[2], raw_addr[3]);
|
||||
|
||||
let raw_port = buf.slice(5, 7);
|
||||
let port = (raw_port[0] as u16 << 8) | raw_port[1] as u16;
|
||||
|
||||
Ok((7u, Sock5SocketAddr(SocketAddr{ip: v4addr, port: port})))
|
||||
},
|
||||
SOCKS5_ADDR_TYPE_IPV6 => {
|
||||
if buf.len() < 19 {
|
||||
fail!("Invalid header");
|
||||
}
|
||||
|
||||
let raw_addr = buf.slice(1, 17);
|
||||
let v6addr = Ipv6Addr((raw_addr[0] as u16 << 8) | raw_addr[1] as u16,
|
||||
(raw_addr[2] as u16 << 8) | raw_addr[3] as u16,
|
||||
(raw_addr[4] as u16 << 8) | raw_addr[5] as u16,
|
||||
(raw_addr[6] as u16 << 8) | raw_addr[7] as u16,
|
||||
(raw_addr[8] as u16 << 8) | raw_addr[9] as u16,
|
||||
(raw_addr[10] as u16 << 8) | raw_addr[11] as u16,
|
||||
(raw_addr[12] as u16 << 8) | raw_addr[13] as u16,
|
||||
(raw_addr[14] as u16 << 8) | raw_addr[15] as u16);
|
||||
|
||||
let raw_port = buf.slice(17, 19);
|
||||
// Big Endian
|
||||
let port = (raw_port[0] as u16 << 8) | raw_port[1] as u16;
|
||||
|
||||
Ok((19u, Sock5SocketAddr(SocketAddr{ip: v6addr, port: port})))
|
||||
},
|
||||
SOCKS5_ADDR_TYPE_DOMAIN_NAME => {
|
||||
let addr_len = buf[1] as uint;
|
||||
if buf.len() < 4 + addr_len {
|
||||
fail!("Invalid header");
|
||||
}
|
||||
let raw_addr = buf.slice(2, 2 + addr_len);
|
||||
let raw_port = buf.slice(2 + addr_len, 4 + addr_len);
|
||||
let port = (raw_port[0] as u16 << 8) | raw_port[1] as u16;
|
||||
|
||||
Ok((4 + addr_len, Sock5DomainNameAddr(DomainNameAddr{
|
||||
domain_name: String::from_utf8(raw_addr.to_vec()).unwrap(),
|
||||
port: port,
|
||||
})))
|
||||
},
|
||||
_ => {
|
||||
// Address type not supported
|
||||
Err(SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
140
src/relay/socks5.rs
Normal file
140
src/relay/socks5.rs
Normal file
@@ -0,0 +1,140 @@
|
||||
// The MIT License (MIT)
|
||||
|
||||
// Copyright (c) 2014 Y. T. CHUNG
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use std::fmt::{Show, Formatter, FormatError};
|
||||
use std::io::net::ip::{SocketAddr, Port};
|
||||
use std::io::net::ip::{Ipv4Addr, Ipv6Addr};
|
||||
|
||||
pub const SOCKS5_VERSION : u8 = 0x05;
|
||||
|
||||
pub const SOCKS5_AUTH_METHOD_NONE : u8 = 0x00;
|
||||
pub const SOCKS5_AUTH_METHOD_GSSAPI : u8 = 0x01;
|
||||
pub const SOCKS5_AUTH_METHOD_PASSWORD : u8 = 0x02;
|
||||
pub const SOCKS5_AUTH_METHOD_NOT_ACCEPTABLE : u8 = 0xff;
|
||||
|
||||
pub const SOCKS5_CMD_TCP_CONNECT : u8 = 0x01;
|
||||
pub const SOCKS5_CMD_TCP_BIND : u8 = 0x02;
|
||||
pub const SOCKS5_CMD_UDP_ASSOCIATE : u8 = 0x03;
|
||||
|
||||
pub const SOCKS5_ADDR_TYPE_IPV4 : u8 = 0x01;
|
||||
pub const SOCKS5_ADDR_TYPE_DOMAIN_NAME : u8 = 0x03;
|
||||
pub const SOCKS5_ADDR_TYPE_IPV6 : u8 = 0x04;
|
||||
|
||||
pub const SOCKS5_REPLY_SUCCEEDED : u8 = 0x00;
|
||||
pub const SOCKS5_REPLY_GENERAL_FAILURE : u8 = 0x01;
|
||||
pub const SOCKS5_REPLY_CONNECTION_NOT_ALLOWED : u8 = 0x02;
|
||||
pub const SOCKS5_REPLY_NETWORK_UNREACHABLE : u8 = 0x03;
|
||||
pub const SOCKS5_REPLY_HOST_UNREACHABLE : u8 = 0x04;
|
||||
pub const SOCKS5_REPLY_CONNECTION_REFUSED : u8 = 0x05;
|
||||
pub const SOCKS5_REPLY_TTL_EXPIRED : u8 = 0x06;
|
||||
pub const SOCKS5_REPLY_COMMAND_NOT_SUPPORTED : u8 = 0x07;
|
||||
pub const SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED : u8 = 0x08;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[deriving(Show)]
|
||||
pub enum CommandType {
|
||||
TcpConnect,
|
||||
TcpBind,
|
||||
UdpAssociate,
|
||||
}
|
||||
|
||||
pub struct DomainNameAddr {
|
||||
pub domain_name: String,
|
||||
pub port: Port,
|
||||
}
|
||||
|
||||
impl Show for DomainNameAddr {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
|
||||
f.write(format!("{}:{}", self.domain_name, self.port).as_slice().as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
pub enum AddressType {
|
||||
SocketAddress(SocketAddr),
|
||||
DomainNameAddress(DomainNameAddr),
|
||||
}
|
||||
|
||||
impl Show for AddressType {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
|
||||
match *self {
|
||||
SocketAddress(ref addr) => addr.fmt(f),
|
||||
DomainNameAddress(ref addr) => addr.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_request_header(buf: &[u8]) -> Result<(uint, AddressType), u8> {
|
||||
let atyp = buf[0];
|
||||
match atyp {
|
||||
SOCKS5_ADDR_TYPE_IPV4 => {
|
||||
if buf.len() < 7 {
|
||||
fail!("Invalid header");
|
||||
}
|
||||
|
||||
let raw_addr = buf.slice(1, 5);
|
||||
let v4addr = Ipv4Addr(raw_addr[0], raw_addr[1], raw_addr[2], raw_addr[3]);
|
||||
|
||||
let raw_port = buf.slice(5, 7);
|
||||
let port = (raw_port[0] as u16 << 8) | raw_port[1] as u16;
|
||||
|
||||
Ok((7u, SocketAddress(SocketAddr{ip: v4addr, port: port})))
|
||||
},
|
||||
SOCKS5_ADDR_TYPE_IPV6 => {
|
||||
if buf.len() < 19 {
|
||||
fail!("Invalid header");
|
||||
}
|
||||
|
||||
let raw_addr = buf.slice(1, 17);
|
||||
let v6addr = Ipv6Addr((raw_addr[0] as u16 << 8) | raw_addr[1] as u16,
|
||||
(raw_addr[2] as u16 << 8) | raw_addr[3] as u16,
|
||||
(raw_addr[4] as u16 << 8) | raw_addr[5] as u16,
|
||||
(raw_addr[6] as u16 << 8) | raw_addr[7] as u16,
|
||||
(raw_addr[8] as u16 << 8) | raw_addr[9] as u16,
|
||||
(raw_addr[10] as u16 << 8) | raw_addr[11] as u16,
|
||||
(raw_addr[12] as u16 << 8) | raw_addr[13] as u16,
|
||||
(raw_addr[14] as u16 << 8) | raw_addr[15] as u16);
|
||||
|
||||
let raw_port = buf.slice(17, 19);
|
||||
// Big Endian
|
||||
let port = (raw_port[0] as u16 << 8) | raw_port[1] as u16;
|
||||
|
||||
Ok((19u, SocketAddress(SocketAddr{ip: v6addr, port: port})))
|
||||
},
|
||||
SOCKS5_ADDR_TYPE_DOMAIN_NAME => {
|
||||
let addr_len = buf[1] as uint;
|
||||
if buf.len() < 4 + addr_len {
|
||||
fail!("Invalid header");
|
||||
}
|
||||
let raw_addr = buf.slice(2, 2 + addr_len);
|
||||
let raw_port = buf.slice(2 + addr_len, 4 + addr_len);
|
||||
let port = (raw_port[0] as u16 << 8) | raw_port[1] as u16;
|
||||
|
||||
Ok((4 + addr_len, DomainNameAddress(DomainNameAddr{
|
||||
domain_name: String::from_utf8(raw_addr.to_vec()).unwrap(),
|
||||
port: port,
|
||||
})))
|
||||
},
|
||||
_ => {
|
||||
// Address type not supported
|
||||
Err(SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED)
|
||||
}
|
||||
}
|
||||
}
|
||||
62
src/relay/tcprelay/dnscache.rs
Normal file
62
src/relay/tcprelay/dnscache.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
// The MIT License (MIT)
|
||||
|
||||
// Copyright (c) 2014 Y. T. CHUNG
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#[phase(plugin, link)]
|
||||
extern crate log;
|
||||
|
||||
use std::io::net::addrinfo::get_host_addresses;
|
||||
use std::collections::lru_cache::LruCache;
|
||||
use std::io::net::ip::IpAddr;
|
||||
|
||||
const DNS_CACHE_CAPACITY: uint = 200;
|
||||
|
||||
pub struct DnsCache {
|
||||
lru_cache: LruCache<String, IpAddr>,
|
||||
}
|
||||
|
||||
impl DnsCache {
|
||||
pub fn new() -> DnsCache {
|
||||
DnsCache {
|
||||
lru_cache: LruCache::new(DNS_CACHE_CAPACITY),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get<'a>(&mut self, addr: &str) -> Option<IpAddr> {
|
||||
match self.lru_cache.get(&addr.to_string()).map(|x| *x) {
|
||||
Some(a) => {
|
||||
Some(a.clone())
|
||||
},
|
||||
None => {
|
||||
let ipaddr = match get_host_addresses(addr) {
|
||||
Ok(addr_list) => {
|
||||
addr_list[0]
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Error while resolving {}: {}", addr, err);
|
||||
return None
|
||||
}
|
||||
};
|
||||
self.lru_cache.put(addr.to_string(), ipaddr);
|
||||
Some(ipaddr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,13 +35,17 @@ use std::io::net::ip::{Ipv4Addr, Ipv6Addr};
|
||||
use config::Config;
|
||||
|
||||
use relay::Relay;
|
||||
use relay::parse_request_header;
|
||||
use relay::socks5::parse_request_header;
|
||||
use relay::tcprelay::send_error_reply;
|
||||
use relay::{SOCKS5_VERSION, SOCKS5_AUTH_METHOD_NONE};
|
||||
use relay::{SOCKS5_CMD_TCP_CONNECT, SOCKS5_CMD_TCP_BIND, SOCKS5_CMD_UDP_ASSOCIATE};
|
||||
use relay::{SOCKS5_ADDR_TYPE_IPV6, SOCKS5_ADDR_TYPE_IPV4};
|
||||
use relay::{SOCKS5_REPLY_COMMAND_NOT_SUPPORTED, SOCKS5_REPLY_HOST_UNREACHABLE, SOCKS5_REPLY_NETWORK_UNREACHABLE};
|
||||
use relay::SOCKS5_REPLY_SUCCEEDED;
|
||||
use relay::socks5::{SOCKS5_VERSION, SOCKS5_AUTH_METHOD_NONE};
|
||||
use relay::socks5::{SOCKS5_CMD_TCP_CONNECT, SOCKS5_CMD_TCP_BIND, SOCKS5_CMD_UDP_ASSOCIATE};
|
||||
use relay::socks5::{SOCKS5_ADDR_TYPE_IPV6, SOCKS5_ADDR_TYPE_IPV4};
|
||||
use relay::socks5::{
|
||||
SOCKS5_REPLY_COMMAND_NOT_SUPPORTED,
|
||||
SOCKS5_REPLY_HOST_UNREACHABLE,
|
||||
SOCKS5_REPLY_NETWORK_UNREACHABLE
|
||||
};
|
||||
use relay::socks5::SOCKS5_REPLY_SUCCEEDED;
|
||||
use relay::loadbalancing::server::{LoadBalancer, RoundRobin};
|
||||
|
||||
use crypto::cipher;
|
||||
|
||||
@@ -27,8 +27,9 @@ extern crate log;
|
||||
extern crate native;
|
||||
|
||||
use std::io::TcpStream;
|
||||
use relay::SOCKS5_VERSION;
|
||||
use relay::socks5::SOCKS5_VERSION;
|
||||
|
||||
mod dnscache;
|
||||
pub mod local;
|
||||
pub mod server;
|
||||
|
||||
|
||||
@@ -24,21 +24,19 @@
|
||||
#[phase(plugin, link)]
|
||||
extern crate log;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::io::{Listener, TcpListener, Acceptor, TcpStream};
|
||||
use std::io::net::ip::{Port, IpAddr};
|
||||
use std::io::{EndOfFile, TimedOut, BrokenPipe};
|
||||
|
||||
use config::{Config, SingleServer, MultipleServer};
|
||||
use relay::Relay;
|
||||
use relay::{parse_request_header, Sock5SocketAddr, Sock5DomainNameAddr};
|
||||
use relay::socks5::{parse_request_header, SocketAddress, DomainNameAddress};
|
||||
use relay::tcprelay::dnscache::DnsCache;
|
||||
|
||||
use crypto::cipher;
|
||||
use crypto::cipher::Cipher;
|
||||
use crypto::cipher::CipherVariant;
|
||||
|
||||
use std::io::net::addrinfo::get_host_addresses;
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct TcpRelayServer {
|
||||
config: Config,
|
||||
@@ -63,18 +61,6 @@ impl TcpRelayServer {
|
||||
}
|
||||
}
|
||||
|
||||
fn connect_remote(addrs: Vec<IpAddr>, port: Port) -> Option<TcpStream> {
|
||||
for addr in addrs.iter() {
|
||||
match TcpStream::connect(addr.to_string().as_slice(), port) {
|
||||
Ok(s) => {
|
||||
return Some(s)
|
||||
},
|
||||
Err(..) => {}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn handle_connect_remote(local_stream: &mut TcpStream, remote_stream: &mut TcpStream,
|
||||
cipher: &mut CipherVariant) {
|
||||
let mut buf = [0u8, .. 0xffff];
|
||||
@@ -162,6 +148,8 @@ impl Relay for TcpRelayServer {
|
||||
|
||||
info!("Shadowsocks listening on {}:{}", server_addr, server_port);
|
||||
|
||||
let dnscache_arc = Arc::new(Mutex::new(DnsCache::new()));
|
||||
|
||||
loop {
|
||||
match acceptor.accept() {
|
||||
Ok(mut stream) => {
|
||||
@@ -169,6 +157,7 @@ impl Relay for TcpRelayServer {
|
||||
|
||||
let password = password.clone();
|
||||
let encrypt_method = encrypt_method.clone();
|
||||
let dnscache = dnscache_arc.clone();
|
||||
|
||||
spawn(proc() {
|
||||
let mut cipher = cipher::with_name(encrypt_method.as_slice(),
|
||||
@@ -192,7 +181,7 @@ impl Relay for TcpRelayServer {
|
||||
};
|
||||
info!("Connecting to {}", addr);
|
||||
let mut remote_stream = match addr {
|
||||
Sock5SocketAddr(sockaddr) => {
|
||||
SocketAddress(sockaddr) => {
|
||||
match TcpStream::connect(sockaddr.ip.to_string().as_slice(), sockaddr.port) {
|
||||
Ok(s) => s,
|
||||
Err(err) => {
|
||||
@@ -200,24 +189,16 @@ impl Relay for TcpRelayServer {
|
||||
}
|
||||
}
|
||||
},
|
||||
Sock5DomainNameAddr(domainaddr) => {
|
||||
let addrs = match get_host_addresses(domainaddr.domain_name.as_slice()) {
|
||||
Ok(ipaddrs) => ipaddrs,
|
||||
Err(e) => {
|
||||
fail!("Error occurs while get_host_addresses: {}", e);
|
||||
DomainNameAddress(ref domainaddr) => {
|
||||
let ipaddr = match dnscache.lock().get(domainaddr.domain_name.as_slice()) {
|
||||
Some(addr) => addr,
|
||||
None => {
|
||||
fail!("Failed to resolve host {}", domainaddr)
|
||||
}
|
||||
};
|
||||
|
||||
if addrs.len() == 0 {
|
||||
fail!("Cannot resolve host {}, empty host list", domainaddr.domain_name);
|
||||
}
|
||||
|
||||
match TcpRelayServer::connect_remote(addrs, domainaddr.port) {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
fail!("Unable to resolve host {}", domainaddr)
|
||||
}
|
||||
}
|
||||
TcpStream::connect(ipaddr.to_string().as_slice(), domainaddr.port)
|
||||
.ok().expect(format!("Unable to connect host {}", domainaddr).as_slice())
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user