diff --git a/.gitignore b/.gitignore
index 96ef6c0..026fb6d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/target
Cargo.lock
+.idea/*
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 73f69e0..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
-# Editor-based HTTP Client requests
-/httpRequests/
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 28a804d..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 38ff096..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/tapir-rs.iml b/.idea/tapir-rs.iml
deleted file mode 100644
index 78dfac4..0000000
--- a/.idea/tapir-rs.iml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index ab162ce..6acce43 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,13 +3,11 @@ name = "tapir"
version = "0.1.0"
authors = ["Sarah Jamie Lewis "]
edition = "2018"
+license = "MIT"
+description = "Tapir is a small library for building p2p applications over anonymous communication systems"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-[workspace]
-members = ["deps/rust-socks"]
-
-
[[test]]
name = "simple_setup"
diff --git a/deps/rust-socks/.circleci/config.yml b/deps/rust-socks/.circleci/config.yml
deleted file mode 100644
index 1aa543e..0000000
--- a/deps/rust-socks/.circleci/config.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-restore_registry: &RESTORE_REGISTRY
- restore_cache:
- key: registry
-save_registry: &SAVE_REGISTRY
- save_cache:
- key: registry-{{ .BuildNum }}
- paths:
- - /usr/local/cargo/registry/index
-deps_key: &DEPS_KEY
- key: deps-{{ checksum "~/rust-version" }}-{{ checksum "Cargo.lock" }}
-restore_deps: &RESTORE_DEPS
- restore_cache:
- <<: *DEPS_KEY
-save_deps: &SAVE_DEPS
- save_cache:
- <<: *DEPS_KEY
- paths:
- - target
- - /usr/local/cargo/registry/cache
-
-version: 2
-jobs:
- build:
- docker:
- - image: rust:1.19.0
- working_directory: ~/build
- environment:
- RUSTFLAGS: -D warnings
- steps:
- - checkout
- - run: apt-get update
- - run: apt-get install -y --no-install-recommends dante-server
- - run: danted -D -f .circleci/danted_no_auth.conf
- - run: danted -D -f .circleci/danted_password.conf
- - run: useradd testuser -p '$1$DLEVM6FQ$dNm6etLDprLfwWSLCUtQY/' # password: testpass
- - *RESTORE_REGISTRY
- - run: cargo generate-lockfile
- - *SAVE_REGISTRY
- - run: rustc --version > ~/rust-version
- - *RESTORE_DEPS
- - run: cargo test
- - *SAVE_DEPS
diff --git a/deps/rust-socks/.circleci/danted_no_auth.conf b/deps/rust-socks/.circleci/danted_no_auth.conf
deleted file mode 100644
index 1789ec2..0000000
--- a/deps/rust-socks/.circleci/danted_no_auth.conf
+++ /dev/null
@@ -1,17 +0,0 @@
-logoutput: stdout
-
-internal: lo port = 1080
-external: eth0
-
-socksmethod: none
-clientmethod: none
-
-user.unprivileged: nobody
-
-client pass {
- from: 127.0.0.1/0 port 1-65535 to: 0.0.0.0/0
-}
-
-socks pass {
- from: 127.0.0.1/0 to: 0.0.0.0/0
-}
diff --git a/deps/rust-socks/.circleci/danted_password.conf b/deps/rust-socks/.circleci/danted_password.conf
deleted file mode 100644
index 43ace3c..0000000
--- a/deps/rust-socks/.circleci/danted_password.conf
+++ /dev/null
@@ -1,17 +0,0 @@
-logoutput: stdout
-
-internal: lo port = 1081
-external: eth0
-
-socksmethod: username
-clientmethod: none
-
-user.unprivileged: nobody
-
-client pass {
- from: 127.0.0.1/0 port 1-65535 to: 0.0.0.0/0
-}
-
-socks pass {
- from: 127.0.0.1/0 to: 0.0.0.0/0
-}
diff --git a/deps/rust-socks/.gitignore b/deps/rust-socks/.gitignore
deleted file mode 100644
index 3b874ca..0000000
--- a/deps/rust-socks/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-target
-Cargo.lock
-.idea
-*.iml
diff --git a/deps/rust-socks/Cargo.toml b/deps/rust-socks/Cargo.toml
deleted file mode 100644
index e233fc9..0000000
--- a/deps/rust-socks/Cargo.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-name = "socks"
-version = "0.3.2"
-authors = ["Steven Fackler "]
-license = "MIT/Apache-2.0"
-description = "SOCKS proxy clients"
-repository = "https://github.com/sfackler/rust-socks"
-documentation = "https://docs.rs/socks/0.3.0/socks"
-readme = "README.md"
-
-[dependencies]
-byteorder = "1.0"
-
-[target.'cfg(unix)'.dependencies]
-libc = "0.2"
-
-[target.'cfg(windows)'.dependencies]
-winapi = "0.2.8"
-ws2_32-sys = "0.2.1"
diff --git a/deps/rust-socks/LICENSE-APACHE b/deps/rust-socks/LICENSE-APACHE
deleted file mode 100644
index 8f71f43..0000000
--- a/deps/rust-socks/LICENSE-APACHE
+++ /dev/null
@@ -1,202 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "{}"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright {yyyy} {name of copyright owner}
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
diff --git a/deps/rust-socks/LICENSE-MIT b/deps/rust-socks/LICENSE-MIT
deleted file mode 100644
index e8b0041..0000000
--- a/deps/rust-socks/LICENSE-MIT
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2015 The rust-socks Developers
-
-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.
diff --git a/deps/rust-socks/README.md b/deps/rust-socks/README.md
deleted file mode 100644
index d53cc3b..0000000
--- a/deps/rust-socks/README.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# rust-socks
-[![Build Status](https://travis-ci.org/sfackler/rust-socks.svg?branch=master)](https://travis-ci.org/sfackler/rust-socks)
-
-[Documentation](https://docs.rs/socks/0.2.3/socks)
-
-SOCKS proxy support for Rust.
-
-## License
-
-Licensed under either of
-
- * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
-
-at your option.
-
-### Contribution
-
-Unless you explicitly state otherwise, any contribution intentionally
-submitted for inclusion in the work by you, as defined in the Apache-2.0
-license, shall be dual licensed as above, without any additional terms or
-conditions.
diff --git a/deps/rust-socks/src/lib.rs b/deps/rust-socks/src/lib.rs
deleted file mode 100644
index 6c07649..0000000
--- a/deps/rust-socks/src/lib.rs
+++ /dev/null
@@ -1,158 +0,0 @@
-//! SOCKS proxy clients
-#![doc(html_root_url = "https://docs.rs/socks/0.3.0")]
-#![warn(missing_docs)]
-
-extern crate byteorder;
-
-#[cfg(unix)]
-extern crate libc;
-#[cfg(windows)]
-extern crate winapi;
-#[cfg(windows)]
-extern crate ws2_32;
-
-use std::io;
-use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
-use std::vec;
-
-pub use v4::{Socks4Listener, Socks4Stream};
-pub use v5::{Socks5Datagram, Socks5Listener, Socks5Stream};
-
-mod v4;
-mod v5;
-mod writev;
-
-/// A description of a connection target.
-#[derive(Debug, Clone)]
-pub enum TargetAddr {
- /// Connect to an IP address.
- Ip(SocketAddr),
- /// Connect to a fully qualified domain name.
- ///
- /// The domain name will be passed along to the proxy server and DNS lookup
- /// will happen there.
- Domain(String, u16),
-}
-
-impl ToSocketAddrs for TargetAddr {
- type Iter = Iter;
-
- fn to_socket_addrs(&self) -> io::Result {
- let inner = match *self {
- TargetAddr::Ip(addr) => IterInner::Ip(Some(addr)),
- TargetAddr::Domain(ref domain, port) => {
- let it = (&**domain, port).to_socket_addrs()?;
- IterInner::Domain(it)
- }
- };
- Ok(Iter(inner))
- }
-}
-
-enum IterInner {
- Ip(Option),
- Domain(vec::IntoIter),
-}
-
-/// An iterator over `SocketAddr`s associated with a `TargetAddr`.
-pub struct Iter(IterInner);
-
-impl Iterator for Iter {
- type Item = SocketAddr;
-
- fn next(&mut self) -> Option {
- match self.0 {
- IterInner::Ip(ref mut addr) => addr.take(),
- IterInner::Domain(ref mut it) => it.next(),
- }
- }
-}
-
-/// A trait for objects that can be converted to `TargetAddr`.
-pub trait ToTargetAddr {
- /// Converts the value of `self` to a `TargetAddr`.
- fn to_target_addr(&self) -> io::Result;
-}
-
-impl ToTargetAddr for TargetAddr {
- fn to_target_addr(&self) -> io::Result {
- Ok(self.clone())
- }
-}
-
-impl ToTargetAddr for SocketAddr {
- fn to_target_addr(&self) -> io::Result {
- Ok(TargetAddr::Ip(*self))
- }
-}
-
-impl ToTargetAddr for SocketAddrV4 {
- fn to_target_addr(&self) -> io::Result {
- SocketAddr::V4(*self).to_target_addr()
- }
-}
-
-impl ToTargetAddr for SocketAddrV6 {
- fn to_target_addr(&self) -> io::Result {
- SocketAddr::V6(*self).to_target_addr()
- }
-}
-
-impl ToTargetAddr for (Ipv4Addr, u16) {
- fn to_target_addr(&self) -> io::Result {
- SocketAddrV4::new(self.0, self.1).to_target_addr()
- }
-}
-
-impl ToTargetAddr for (Ipv6Addr, u16) {
- fn to_target_addr(&self) -> io::Result {
- SocketAddrV6::new(self.0, self.1, 0, 0).to_target_addr()
- }
-}
-
-impl<'a> ToTargetAddr for (&'a str, u16) {
- fn to_target_addr(&self) -> io::Result {
- // try to parse as an IP first
- if let Ok(addr) = self.0.parse::() {
- return (addr, self.1).to_target_addr();
- }
-
- if let Ok(addr) = self.0.parse::() {
- return (addr, self.1).to_target_addr();
- }
-
- Ok(TargetAddr::Domain(self.0.to_owned(), self.1))
- }
-}
-
-impl<'a> ToTargetAddr for &'a str {
- fn to_target_addr(&self) -> io::Result {
- // try to parse as an IP first
- if let Ok(addr) = self.parse::() {
- return addr.to_target_addr();
- }
-
- if let Ok(addr) = self.parse::() {
- return addr.to_target_addr();
- }
-
- // split the string by ':' and convert the second part to u16
- let mut parts_iter = self.rsplitn(2, ':');
- let port_str = match parts_iter.next() {
- Some(s) => s,
- None => return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid socket address")),
- };
-
- let host = match parts_iter.next() {
- Some(s) => s,
- None => return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid socket address")),
- };
-
- let port: u16 = match port_str.parse() {
- Ok(p) => p,
- Err(_) => return Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid port value")),
- };
-
- (host, port).to_target_addr()
- }
-}
diff --git a/deps/rust-socks/src/v4.rs b/deps/rust-socks/src/v4.rs
deleted file mode 100644
index 0378367..0000000
--- a/deps/rust-socks/src/v4.rs
+++ /dev/null
@@ -1,270 +0,0 @@
-use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
-use std::io::{self, Read, Write};
-use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, SocketAddrV6, TcpStream, ToSocketAddrs};
-
-use {TargetAddr, ToTargetAddr};
-
-fn read_response(socket: &mut TcpStream) -> io::Result {
- let mut response = [0u8; 8];
- socket.read_exact(&mut response)?;
- let mut response = &response[..];
-
- if response.read_u8()? != 0 {
- return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid response version"));
- }
-
- match response.read_u8()? {
- 90 => {}
- 91 => return Err(io::Error::new(io::ErrorKind::Other, "request rejected or failed")),
- 92 => {
- return Err(io::Error::new(
- io::ErrorKind::PermissionDenied,
- "request rejected because SOCKS server cannot connect to \
- idnetd on the client",
- ))
- }
- 93 => {
- return Err(io::Error::new(
- io::ErrorKind::PermissionDenied,
- "request rejected because the client program and identd \
- report different user-ids",
- ))
- }
- _ => return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid response code")),
- }
-
- let port = response.read_u16::()?;
- let ip = Ipv4Addr::from(response.read_u32::()?);
-
- Ok(SocketAddrV4::new(ip, port))
-}
-
-/// A SOCKS4 client.
-#[derive(Debug)]
-pub struct Socks4Stream {
- socket: TcpStream,
- proxy_addr: SocketAddrV4,
-}
-
-impl Socks4Stream {
- /// Connects to a target server through a SOCKS4 proxy.
- ///
- /// # Note
- ///
- /// If `target` is a `TargetAddr::Domain`, the domain name will be forwarded
- /// to the proxy server using the SOCKS4A protocol extension. If the proxy
- /// server does not support SOCKS4A, consider performing the DNS lookup
- /// locally and passing a `TargetAddr::Ip`.
- pub fn connect(proxy: T, target: U, userid: &str) -> io::Result
- where
- T: ToSocketAddrs,
- U: ToTargetAddr,
- {
- Self::connect_raw(1, proxy, target, userid)
- }
-
- fn connect_raw(command: u8, proxy: T, target: U, userid: &str) -> io::Result
- where
- T: ToSocketAddrs,
- U: ToTargetAddr,
- {
- let mut socket = TcpStream::connect(proxy)?;
-
- let target = target.to_target_addr()?;
-
- let mut packet = vec![];
- let _ = packet.write_u8(4); // version
- let _ = packet.write_u8(command); // command code
- match target.to_target_addr()? {
- TargetAddr::Ip(addr) => {
- let addr = match addr {
- SocketAddr::V4(addr) => addr,
- SocketAddr::V6(_) => {
- return Err(io::Error::new(io::ErrorKind::InvalidInput, "SOCKS4 does not support IPv6"));
- }
- };
- let _ = packet.write_u16::(addr.port());
- let _ = packet.write_u32::((*addr.ip()).into());
- let _ = packet.write_all(userid.as_bytes());
- let _ = packet.write_u8(0);
- }
- TargetAddr::Domain(ref host, port) => {
- let _ = packet.write_u16::(port);
- let _ = packet.write_u32::(Ipv4Addr::new(0, 0, 0, 1).into());
- let _ = packet.write_all(userid.as_bytes());
- let _ = packet.write_u8(0);
- let _ = packet.extend(host.as_bytes());
- let _ = packet.write_u8(0);
- }
- }
-
- socket.write_all(&packet)?;
- let proxy_addr = read_response(&mut socket)?;
-
- Ok(Socks4Stream {
- socket: socket,
- proxy_addr: proxy_addr,
- })
- }
-
- /// Returns the proxy-side address of the connection between the proxy and
- /// target server.
- pub fn proxy_addr(&self) -> SocketAddrV4 {
- self.proxy_addr
- }
-
- /// Returns a shared reference to the inner `TcpStream`.
- pub fn get_ref(&self) -> &TcpStream {
- &self.socket
- }
-
- /// Returns a mutable reference to the inner `TcpStream`.
- pub fn get_mut(&mut self) -> &mut TcpStream {
- &mut self.socket
- }
-
- /// Consumes the `Socks4Stream`, returning the inner `TcpStream`.
- pub fn into_inner(self) -> TcpStream {
- self.socket
- }
-}
-
-impl Read for Socks4Stream {
- fn read(&mut self, buf: &mut [u8]) -> io::Result {
- self.socket.read(buf)
- }
-}
-
-impl<'a> Read for &'a Socks4Stream {
- fn read(&mut self, buf: &mut [u8]) -> io::Result {
- (&self.socket).read(buf)
- }
-}
-
-impl Write for Socks4Stream {
- fn write(&mut self, buf: &[u8]) -> io::Result {
- self.socket.write(buf)
- }
-
- fn flush(&mut self) -> io::Result<()> {
- self.socket.flush()
- }
-}
-
-impl<'a> Write for &'a Socks4Stream {
- fn write(&mut self, buf: &[u8]) -> io::Result {
- (&self.socket).write(buf)
- }
-
- fn flush(&mut self) -> io::Result<()> {
- (&self.socket).flush()
- }
-}
-
-/// A SOCKS4 BIND client.
-#[derive(Debug)]
-pub struct Socks4Listener(Socks4Stream);
-
-impl Socks4Listener {
- /// Initiates a BIND request to the specified proxy.
- ///
- /// The proxy will filter incoming connections based on the value of
- /// `target`.
- pub fn bind(proxy: T, target: U, userid: &str) -> io::Result
- where
- T: ToSocketAddrs,
- U: ToTargetAddr,
- {
- Socks4Stream::connect_raw(2, proxy, target, userid).map(Socks4Listener)
- }
-
- /// The address of the proxy-side TCP listener.
- ///
- /// This should be forwarded to the remote process, which should open a
- /// connection to it.
- pub fn proxy_addr(&self) -> io::Result {
- if self.0.proxy_addr.ip().octets() != [0, 0, 0, 0] {
- Ok(SocketAddr::V4(self.0.proxy_addr()))
- } else {
- let port = self.0.proxy_addr.port();
- let peer = match self.0.socket.peer_addr()? {
- SocketAddr::V4(addr) => SocketAddr::V4(SocketAddrV4::new(*addr.ip(), port)),
- SocketAddr::V6(addr) => SocketAddr::V6(SocketAddrV6::new(*addr.ip(), port, 0, 0)),
- };
- Ok(peer)
- }
- }
-
- /// Waits for the remote process to connect to the proxy server.
- ///
- /// The value of `proxy_addr` should be forwarded to the remote process
- /// before this method is called.
- pub fn accept(mut self) -> io::Result {
- self.0.proxy_addr = read_response(&mut self.0.socket)?;
- Ok(self.0)
- }
-}
-
-#[cfg(test)]
-mod test {
- use std::io::{Read, Write};
- use std::net::{SocketAddr, SocketAddrV4, TcpStream, ToSocketAddrs};
-
- use super::*;
-
- fn google_ip() -> SocketAddrV4 {
- "google.com:80"
- .to_socket_addrs()
- .unwrap()
- .filter_map(|a| match a {
- SocketAddr::V4(a) => Some(a),
- SocketAddr::V6(_) => None,
- })
- .next()
- .unwrap()
- }
-
- #[test]
- fn google() {
- let mut socket = Socks4Stream::connect("127.0.0.1:1080", google_ip(), "").unwrap();
-
- socket.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
- let mut result = vec![];
- socket.read_to_end(&mut result).unwrap();
-
- println!("{}", String::from_utf8_lossy(&result));
- assert!(result.starts_with(b"HTTP/1.0"));
- assert!(result.ends_with(b"