Latest formatting from cargo fmt
This commit is contained in:

committed by
bonedaddy

parent
c23a90ca1c
commit
9f95a08e5f
@ -1,43 +1,44 @@
|
||||
extern crate i2p;
|
||||
extern crate env_logger;
|
||||
extern crate i2p;
|
||||
|
||||
use i2p::net::I2pStream;
|
||||
use std::env;
|
||||
use std::io::{BufReader, Read, Write};
|
||||
|
||||
fn help() {
|
||||
println!("Usage: eepget <host.i2p> [port]")
|
||||
println!("Usage: eepget <host.i2p> [port]")
|
||||
}
|
||||
|
||||
fn print_homepage(host: &str, port: u16) {
|
||||
let mut stream = I2pStream::connect(format!("{}:{}", host, port)).unwrap();
|
||||
let mut stream = I2pStream::connect(format!("{}:{}", host, port)).unwrap();
|
||||
|
||||
let msg = "GET / HTTP/1.1\r\n\r\n";
|
||||
let _ = stream.write(msg.as_bytes());
|
||||
let mut reader = BufReader::new(stream);
|
||||
let mut buffer = String::new();
|
||||
let _ = reader.read_to_string(&mut buffer);
|
||||
let msg = "GET / HTTP/1.1\r\n\r\n";
|
||||
let _ = stream.write(msg.as_bytes());
|
||||
let mut reader = BufReader::new(stream);
|
||||
let mut buffer = String::new();
|
||||
let _ = reader.read_to_string(&mut buffer);
|
||||
|
||||
println!("{}", buffer);
|
||||
println!("{}", buffer);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
let args: Vec<String> = env::args().collect();
|
||||
match args.len() {
|
||||
2 => print_homepage(&args[1], 80),
|
||||
3 => {
|
||||
let host = &args[1];
|
||||
let port = &args[2];
|
||||
let port_num: u16 = match port.parse() {
|
||||
Ok(n) => n,
|
||||
Err(_) => {
|
||||
println!("Port must be an integer");
|
||||
help();
|
||||
return;
|
||||
}
|
||||
};
|
||||
print_homepage(host, port_num)
|
||||
}
|
||||
_ => help(),
|
||||
}
|
||||
env_logger::init();
|
||||
let args: Vec<String> = env::args().collect();
|
||||
match args.len() {
|
||||
2 => print_homepage(&args[1], 80),
|
||||
3 => {
|
||||
let host = &args[1];
|
||||
let port = &args[2];
|
||||
let port_num: u16 = match port.parse() {
|
||||
Ok(n) => n,
|
||||
Err(_) => {
|
||||
println!("Port must be an integer");
|
||||
help();
|
||||
return;
|
||||
}
|
||||
};
|
||||
print_homepage(host, port_num)
|
||||
}
|
||||
_ => help(),
|
||||
}
|
||||
}
|
||||
|
1
rustfmt.toml
Normal file
1
rustfmt.toml
Normal file
@ -0,0 +1 @@
|
||||
hard_tabs = true
|
412
src/net/addr.rs
412
src/net/addr.rs
@ -9,117 +9,117 @@ use std::vec;
|
||||
use crate::net::i2p::I2pAddr;
|
||||
|
||||
pub struct I2pSocketAddr {
|
||||
port: u16,
|
||||
dest: I2pAddr,
|
||||
port: u16,
|
||||
dest: I2pAddr,
|
||||
}
|
||||
|
||||
impl I2pSocketAddr {
|
||||
/// Creates a new socket address from the (dest, port) pair.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr};
|
||||
///
|
||||
/// let socket = I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080);
|
||||
/// assert_eq!(socket.dest(), I2pAddr::new("example.i2p"));
|
||||
/// assert_eq!(socket.port(), 8080);
|
||||
/// ```
|
||||
pub fn new(dest: I2pAddr, port: u16) -> I2pSocketAddr {
|
||||
I2pSocketAddr {
|
||||
port: port,
|
||||
dest: dest,
|
||||
}
|
||||
}
|
||||
/// Creates a new socket address from the (dest, port) pair.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr};
|
||||
///
|
||||
/// let socket = I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080);
|
||||
/// assert_eq!(socket.dest(), I2pAddr::new("example.i2p"));
|
||||
/// assert_eq!(socket.port(), 8080);
|
||||
/// ```
|
||||
pub fn new(dest: I2pAddr, port: u16) -> I2pSocketAddr {
|
||||
I2pSocketAddr {
|
||||
port: port,
|
||||
dest: dest,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the I2P address associated with this socket address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr};
|
||||
///
|
||||
/// let socket = I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080);
|
||||
/// assert_eq!(socket.dest(), I2pAddr::new("example.i2p"));
|
||||
/// ```
|
||||
pub fn dest(&self) -> I2pAddr {
|
||||
self.dest.clone()
|
||||
}
|
||||
/// Returns the I2P address associated with this socket address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr};
|
||||
///
|
||||
/// let socket = I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080);
|
||||
/// assert_eq!(socket.dest(), I2pAddr::new("example.i2p"));
|
||||
/// ```
|
||||
pub fn dest(&self) -> I2pAddr {
|
||||
self.dest.clone()
|
||||
}
|
||||
|
||||
/// Change the I2P address associated with this socket address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr};
|
||||
///
|
||||
/// let mut socket = I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080);
|
||||
/// socket.set_dest(I2pAddr::new("foobar.i2p"));
|
||||
/// assert_eq!(socket.dest(), I2pAddr::new("foobar.i2p"));
|
||||
/// ```
|
||||
pub fn set_dest(&mut self, new_dest: I2pAddr) {
|
||||
self.dest = new_dest;
|
||||
}
|
||||
/// Change the I2P address associated with this socket address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr};
|
||||
///
|
||||
/// let mut socket = I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080);
|
||||
/// socket.set_dest(I2pAddr::new("foobar.i2p"));
|
||||
/// assert_eq!(socket.dest(), I2pAddr::new("foobar.i2p"));
|
||||
/// ```
|
||||
pub fn set_dest(&mut self, new_dest: I2pAddr) {
|
||||
self.dest = new_dest;
|
||||
}
|
||||
|
||||
/// Returns the port number associated with this socket address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr};
|
||||
///
|
||||
/// let socket = I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080);
|
||||
/// assert_eq!(socket.port(), 8080);
|
||||
/// ```
|
||||
pub fn port(&self) -> u16 {
|
||||
self.port
|
||||
}
|
||||
/// Returns the port number associated with this socket address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr};
|
||||
///
|
||||
/// let socket = I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080);
|
||||
/// assert_eq!(socket.port(), 8080);
|
||||
/// ```
|
||||
pub fn port(&self) -> u16 {
|
||||
self.port
|
||||
}
|
||||
|
||||
/// Change the port number associated with this socket address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr};
|
||||
///
|
||||
/// let mut socket = I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080);
|
||||
/// socket.set_port(1025);
|
||||
/// assert_eq!(socket.port(), 1025);
|
||||
/// ```
|
||||
pub fn set_port(&mut self, new_port: u16) {
|
||||
self.port = new_port;
|
||||
}
|
||||
/// Change the port number associated with this socket address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr};
|
||||
///
|
||||
/// let mut socket = I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080);
|
||||
/// socket.set_port(1025);
|
||||
/// assert_eq!(socket.port(), 1025);
|
||||
/// ```
|
||||
pub fn set_port(&mut self, new_port: u16) {
|
||||
self.port = new_port;
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for I2pSocketAddr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}:{}", self.dest(), self.port())
|
||||
}
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}:{}", self.dest(), self.port())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for I2pSocketAddr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for I2pSocketAddr {
|
||||
fn clone(&self) -> I2pSocketAddr {
|
||||
I2pSocketAddr::new(self.dest.clone(), self.port)
|
||||
}
|
||||
fn clone(&self) -> I2pSocketAddr {
|
||||
I2pSocketAddr::new(self.dest.clone(), self.port)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for I2pSocketAddr {
|
||||
fn eq(&self, other: &I2pSocketAddr) -> bool {
|
||||
self.port == other.port && self.dest == other.dest
|
||||
}
|
||||
fn eq(&self, other: &I2pSocketAddr) -> bool {
|
||||
self.port == other.port && self.dest == other.dest
|
||||
}
|
||||
}
|
||||
impl Eq for I2pSocketAddr {}
|
||||
|
||||
impl hash::Hash for I2pSocketAddr {
|
||||
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
||||
(self.port, &self.dest).hash(s)
|
||||
}
|
||||
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
||||
(self.port, &self.dest).hash(s)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for objects which can be converted or resolved to one or more
|
||||
@ -176,161 +176,161 @@ impl hash::Hash for I2pSocketAddr {
|
||||
/// }
|
||||
/// ```
|
||||
pub trait ToI2pSocketAddrs {
|
||||
/// Returned iterator over socket addresses which this type may correspond
|
||||
/// to.
|
||||
type Iter: Iterator<Item = I2pSocketAddr>;
|
||||
/// Returned iterator over socket addresses which this type may correspond
|
||||
/// to.
|
||||
type Iter: Iterator<Item = I2pSocketAddr>;
|
||||
|
||||
/// Converts this object to an iterator of resolved `I2pSocketAddr`s.
|
||||
///
|
||||
/// The returned iterator may not actually yield any values depending on the
|
||||
/// outcome of any resolution performed.
|
||||
///
|
||||
/// Note that this function may block the current thread while resolution is
|
||||
/// performed.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Any errors encountered during resolution will be returned as an `Err`.
|
||||
fn to_socket_addrs(&self) -> io::Result<Self::Iter>;
|
||||
/// Converts this object to an iterator of resolved `I2pSocketAddr`s.
|
||||
///
|
||||
/// The returned iterator may not actually yield any values depending on the
|
||||
/// outcome of any resolution performed.
|
||||
///
|
||||
/// Note that this function may block the current thread while resolution is
|
||||
/// performed.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Any errors encountered during resolution will be returned as an `Err`.
|
||||
fn to_socket_addrs(&self) -> io::Result<Self::Iter>;
|
||||
}
|
||||
|
||||
impl ToI2pSocketAddrs for I2pSocketAddr {
|
||||
type Iter = option::IntoIter<I2pSocketAddr>;
|
||||
fn to_socket_addrs(&self) -> io::Result<option::IntoIter<I2pSocketAddr>> {
|
||||
Ok(Some(self.clone()).into_iter())
|
||||
}
|
||||
type Iter = option::IntoIter<I2pSocketAddr>;
|
||||
fn to_socket_addrs(&self) -> io::Result<option::IntoIter<I2pSocketAddr>> {
|
||||
Ok(Some(self.clone()).into_iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToI2pSocketAddrs for (I2pAddr, u16) {
|
||||
type Iter = option::IntoIter<I2pSocketAddr>;
|
||||
fn to_socket_addrs(&self) -> io::Result<option::IntoIter<I2pSocketAddr>> {
|
||||
let (dest, port) = self.clone();
|
||||
I2pSocketAddr::new(dest, port).to_socket_addrs()
|
||||
}
|
||||
type Iter = option::IntoIter<I2pSocketAddr>;
|
||||
fn to_socket_addrs(&self) -> io::Result<option::IntoIter<I2pSocketAddr>> {
|
||||
let (dest, port) = self.clone();
|
||||
I2pSocketAddr::new(dest, port).to_socket_addrs()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToI2pSocketAddrs for (&'a str, u16) {
|
||||
type Iter = vec::IntoIter<I2pSocketAddr>;
|
||||
fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<I2pSocketAddr>> {
|
||||
let (host, port) = *self;
|
||||
let addr = I2pSocketAddr::new(I2pAddr::new(host), port);
|
||||
Ok(vec![addr].into_iter())
|
||||
}
|
||||
type Iter = vec::IntoIter<I2pSocketAddr>;
|
||||
fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<I2pSocketAddr>> {
|
||||
let (host, port) = *self;
|
||||
let addr = I2pSocketAddr::new(I2pAddr::new(host), port);
|
||||
Ok(vec![addr].into_iter())
|
||||
}
|
||||
}
|
||||
|
||||
// accepts strings like 'example.i2p:12345'
|
||||
impl ToI2pSocketAddrs for str {
|
||||
type Iter = vec::IntoIter<I2pSocketAddr>;
|
||||
fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<I2pSocketAddr>> {
|
||||
macro_rules! try_opt {
|
||||
($e:expr, $msg:expr) => {
|
||||
match $e {
|
||||
Some(r) => r,
|
||||
None => return Err(io::Error::new(io::ErrorKind::InvalidInput, $msg)),
|
||||
}
|
||||
};
|
||||
}
|
||||
type Iter = vec::IntoIter<I2pSocketAddr>;
|
||||
fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<I2pSocketAddr>> {
|
||||
macro_rules! try_opt {
|
||||
($e:expr, $msg:expr) => {
|
||||
match $e {
|
||||
Some(r) => r,
|
||||
None => return Err(io::Error::new(io::ErrorKind::InvalidInput, $msg)),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// split the string by ':' and convert the second part to u16
|
||||
let mut parts_iter = self.rsplitn(2, ':');
|
||||
let port_str = try_opt!(parts_iter.next(), "invalid I2P socket address");
|
||||
let host = try_opt!(parts_iter.next(), "invalid I2P socket address");
|
||||
let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
|
||||
(host, port).to_socket_addrs()
|
||||
}
|
||||
// split the string by ':' and convert the second part to u16
|
||||
let mut parts_iter = self.rsplitn(2, ':');
|
||||
let port_str = try_opt!(parts_iter.next(), "invalid I2P socket address");
|
||||
let host = try_opt!(parts_iter.next(), "invalid I2P socket address");
|
||||
let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
|
||||
(host, port).to_socket_addrs()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToI2pSocketAddrs for &'a [I2pSocketAddr] {
|
||||
type Iter = iter::Cloned<slice::Iter<'a, I2pSocketAddr>>;
|
||||
type Iter = iter::Cloned<slice::Iter<'a, I2pSocketAddr>>;
|
||||
|
||||
fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
|
||||
Ok(self.iter().cloned())
|
||||
}
|
||||
fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
|
||||
Ok(self.iter().cloned())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ToI2pSocketAddrs + ?Sized> ToI2pSocketAddrs for &'a T {
|
||||
type Iter = T::Iter;
|
||||
fn to_socket_addrs(&self) -> io::Result<T::Iter> {
|
||||
(**self).to_socket_addrs()
|
||||
}
|
||||
type Iter = T::Iter;
|
||||
fn to_socket_addrs(&self) -> io::Result<T::Iter> {
|
||||
(**self).to_socket_addrs()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToI2pSocketAddrs for String {
|
||||
type Iter = vec::IntoIter<I2pSocketAddr>;
|
||||
fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<I2pSocketAddr>> {
|
||||
(&**self).to_socket_addrs()
|
||||
}
|
||||
type Iter = vec::IntoIter<I2pSocketAddr>;
|
||||
fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<I2pSocketAddr>> {
|
||||
(&**self).to_socket_addrs()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::net::test::{isa, tsa};
|
||||
use crate::net::*;
|
||||
use net::test::{isa, tsa};
|
||||
use net::*;
|
||||
|
||||
#[test]
|
||||
fn to_socket_addr_i2paddr_u16() {
|
||||
let a = I2pAddr::new("example.i2p");
|
||||
let p = 12345;
|
||||
let e = I2pSocketAddr::new(a.clone(), p);
|
||||
assert_eq!(Ok(vec![e]), tsa((a, p)));
|
||||
}
|
||||
#[test]
|
||||
fn to_socket_addr_i2paddr_u16() {
|
||||
let a = I2pAddr::new("example.i2p");
|
||||
let p = 12345;
|
||||
let e = I2pSocketAddr::new(a.clone(), p);
|
||||
assert_eq!(Ok(vec![e]), tsa((a, p)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_socket_addr_str_u16() {
|
||||
let a = isa(I2pAddr::new("example.i2p"), 24352);
|
||||
assert_eq!(Ok(vec![a]), tsa(("example.i2p", 24352)));
|
||||
#[test]
|
||||
fn to_socket_addr_str_u16() {
|
||||
let a = isa(I2pAddr::new("example.i2p"), 24352);
|
||||
assert_eq!(Ok(vec![a]), tsa(("example.i2p", 24352)));
|
||||
|
||||
let a = isa(I2pAddr::new("example.i2p"), 23924);
|
||||
assert!(tsa(("example.i2p", 23924)).unwrap().contains(&a));
|
||||
}
|
||||
let a = isa(I2pAddr::new("example.i2p"), 23924);
|
||||
assert!(tsa(("example.i2p", 23924)).unwrap().contains(&a));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_socket_addr_str() {
|
||||
let a = isa(I2pAddr::new("example.i2p"), 24352);
|
||||
assert_eq!(Ok(vec![a]), tsa("example.i2p:24352"));
|
||||
#[test]
|
||||
fn to_socket_addr_str() {
|
||||
let a = isa(I2pAddr::new("example.i2p"), 24352);
|
||||
assert_eq!(Ok(vec![a]), tsa("example.i2p:24352"));
|
||||
|
||||
let a = isa(I2pAddr::new("example.i2p"), 23924);
|
||||
assert!(tsa("example.i2p:23924").unwrap().contains(&a));
|
||||
}
|
||||
let a = isa(I2pAddr::new("example.i2p"), 23924);
|
||||
assert!(tsa("example.i2p:23924").unwrap().contains(&a));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_socket_addr_string() {
|
||||
let a = isa(I2pAddr::new("example.i2p"), 24352);
|
||||
assert_eq!(
|
||||
Ok(vec![a.clone()]),
|
||||
tsa(&*format!("{}:{}", "example.i2p", "24352"))
|
||||
);
|
||||
assert_eq!(
|
||||
Ok(vec![a.clone()]),
|
||||
tsa(&format!("{}:{}", "example.i2p", "24352"))
|
||||
);
|
||||
assert_eq!(
|
||||
Ok(vec![a.clone()]),
|
||||
tsa(format!("{}:{}", "example.i2p", "24352"))
|
||||
);
|
||||
#[test]
|
||||
fn to_socket_addr_string() {
|
||||
let a = isa(I2pAddr::new("example.i2p"), 24352);
|
||||
assert_eq!(
|
||||
Ok(vec![a.clone()]),
|
||||
tsa(&*format!("{}:{}", "example.i2p", "24352"))
|
||||
);
|
||||
assert_eq!(
|
||||
Ok(vec![a.clone()]),
|
||||
tsa(&format!("{}:{}", "example.i2p", "24352"))
|
||||
);
|
||||
assert_eq!(
|
||||
Ok(vec![a.clone()]),
|
||||
tsa(format!("{}:{}", "example.i2p", "24352"))
|
||||
);
|
||||
|
||||
let s = format!("{}:{}", "example.i2p", "24352");
|
||||
assert_eq!(Ok(vec![a]), tsa(s));
|
||||
// s has been moved into the tsa call
|
||||
}
|
||||
let s = format!("{}:{}", "example.i2p", "24352");
|
||||
assert_eq!(Ok(vec![a]), tsa(s));
|
||||
// s has been moved into the tsa call
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_dest() {
|
||||
fn i2p(low: u8) -> I2pAddr {
|
||||
I2pAddr::new(&format!("example{}.i2p", low))
|
||||
}
|
||||
#[test]
|
||||
fn set_dest() {
|
||||
fn i2p(low: u8) -> I2pAddr {
|
||||
I2pAddr::new(&format!("example{}.i2p", low))
|
||||
}
|
||||
|
||||
let mut addr = I2pSocketAddr::new(i2p(12), 80);
|
||||
assert_eq!(addr.dest(), i2p(12));
|
||||
addr.set_dest(i2p(13));
|
||||
assert_eq!(addr.dest(), i2p(13));
|
||||
}
|
||||
let mut addr = I2pSocketAddr::new(i2p(12), 80);
|
||||
assert_eq!(addr.dest(), i2p(12));
|
||||
addr.set_dest(i2p(13));
|
||||
assert_eq!(addr.dest(), i2p(13));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_port() {
|
||||
let mut addr = I2pSocketAddr::new(I2pAddr::new("example.i2p"), 80);
|
||||
assert_eq!(addr.port(), 80);
|
||||
addr.set_port(8080);
|
||||
assert_eq!(addr.port(), 8080);
|
||||
}
|
||||
#[test]
|
||||
fn set_port() {
|
||||
let mut addr = I2pSocketAddr::new(I2pAddr::new("example.i2p"), 80);
|
||||
assert_eq!(addr.port(), 80);
|
||||
addr.set_port(8080);
|
||||
assert_eq!(addr.port(), 8080);
|
||||
}
|
||||
}
|
||||
|
@ -37,219 +37,224 @@ use crate::sam::DEFAULT_API;
|
||||
pub struct I2pDatagramSocket {}
|
||||
|
||||
impl I2pDatagramSocket {
|
||||
/// Creates an I2P datagram socket from the given address.
|
||||
///
|
||||
/// The address type can be any implementor of [`ToI2pSocketAddrs`] trait. See
|
||||
/// its documentation for concrete examples.
|
||||
///
|
||||
/// [`ToI2pSocketAddrs`]: ../../i2p/net/trait.ToI2pSocketAddrs.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// ```
|
||||
pub fn bind<A: ToI2pSocketAddrs>(addr: A) -> io::Result<I2pDatagramSocket> {
|
||||
I2pDatagramSocket::bind_via(DEFAULT_API, addr)
|
||||
}
|
||||
/// Creates an I2P datagram socket from the given address.
|
||||
///
|
||||
/// The address type can be any implementor of [`ToI2pSocketAddrs`] trait. See
|
||||
/// its documentation for concrete examples.
|
||||
///
|
||||
/// [`ToI2pSocketAddrs`]: ../../i2p/net/trait.ToI2pSocketAddrs.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// ```
|
||||
pub fn bind<A: ToI2pSocketAddrs>(addr: A) -> io::Result<I2pDatagramSocket> {
|
||||
I2pDatagramSocket::bind_via(DEFAULT_API, addr)
|
||||
}
|
||||
|
||||
pub fn bind_via<A: ToSocketAddrs, B: ToI2pSocketAddrs>(
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
) -> io::Result<I2pDatagramSocket> {
|
||||
super::each_addr(sam_addr, addr, I2pDatagramSocket::bind_addr)
|
||||
}
|
||||
pub fn bind_via<A: ToSocketAddrs, B: ToI2pSocketAddrs>(
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
) -> io::Result<I2pDatagramSocket> {
|
||||
super::each_addr(sam_addr, addr, I2pDatagramSocket::bind_addr)
|
||||
}
|
||||
|
||||
fn bind_addr(_sam_addr: &SocketAddr, _addr: &I2pSocketAddr) -> io::Result<I2pDatagramSocket> {
|
||||
unimplemented!();
|
||||
}
|
||||
fn bind_addr(_sam_addr: &SocketAddr, _addr: &I2pSocketAddr) -> io::Result<I2pDatagramSocket> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/// Receives data from the socket. On success, returns the number of bytes
|
||||
/// read and the address from whence the data came.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// let mut buf = [0; 10];
|
||||
/// let (number_of_bytes, src_addr) = socket.recv_from(&mut buf)
|
||||
/// .expect("Didn't receive data");
|
||||
/// ```
|
||||
pub fn recv_from(&self, _buf: &mut [u8]) -> io::Result<(usize, I2pSocketAddr)> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Receives data from the socket. On success, returns the number of bytes
|
||||
/// read and the address from whence the data came.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// let mut buf = [0; 10];
|
||||
/// let (number_of_bytes, src_addr) = socket.recv_from(&mut buf)
|
||||
/// .expect("Didn't receive data");
|
||||
/// ```
|
||||
pub fn recv_from(&self, _buf: &mut [u8]) -> io::Result<(usize, I2pSocketAddr)> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Receives data from the socket, without removing it from the queue.
|
||||
///
|
||||
/// Successive calls return the same data.
|
||||
///
|
||||
/// On success, returns the number of bytes peeked and the address from
|
||||
/// whence the data came.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// let mut buf = [0; 10];
|
||||
/// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf)
|
||||
/// .expect("Didn't receive data");
|
||||
/// ```
|
||||
pub fn peek_from(&self, _buf: &mut [u8]) -> io::Result<(usize, I2pSocketAddr)> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Receives data from the socket, without removing it from the queue.
|
||||
///
|
||||
/// Successive calls return the same data.
|
||||
///
|
||||
/// On success, returns the number of bytes peeked and the address from
|
||||
/// whence the data came.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// let mut buf = [0; 10];
|
||||
/// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf)
|
||||
/// .expect("Didn't receive data");
|
||||
/// ```
|
||||
pub fn peek_from(&self, _buf: &mut [u8]) -> io::Result<(usize, I2pSocketAddr)> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Sends data on the socket to the given address. On success, returns the
|
||||
/// number of bytes written.
|
||||
///
|
||||
/// Address type can be any implementor of [`ToI2pSocketAddrs`] trait. See
|
||||
/// its documentation for concrete examples.
|
||||
///
|
||||
/// [`ToI2pSocketAddrs`]: ../../std/net/trait.ToI2pSocketAddrs.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.send_to(&[0; 10], "127.0.0.1:4242").expect("couldn't send data");
|
||||
/// ```
|
||||
pub fn send_to<A: ToI2pSocketAddrs>(&self, _buf: &[u8], addr: A)
|
||||
-> io::Result<usize> {
|
||||
match addr.to_socket_addrs()?.next() {
|
||||
Some(_addr) => unimplemented!(),
|
||||
None => Err(Error::new(ErrorKind::InvalidInput,
|
||||
"no addresses to send data to")),
|
||||
}
|
||||
}
|
||||
/// Sends data on the socket to the given address. On success, returns the
|
||||
/// number of bytes written.
|
||||
///
|
||||
/// Address type can be any implementor of [`ToI2pSocketAddrs`] trait. See
|
||||
/// its documentation for concrete examples.
|
||||
///
|
||||
/// [`ToI2pSocketAddrs`]: ../../std/net/trait.ToI2pSocketAddrs.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.send_to(&[0; 10], "127.0.0.1:4242").expect("couldn't send data");
|
||||
/// ```
|
||||
pub fn send_to<A: ToI2pSocketAddrs>(&self, _buf: &[u8], addr: A) -> io::Result<usize> {
|
||||
match addr.to_socket_addrs()?.next() {
|
||||
Some(_addr) => unimplemented!(),
|
||||
None => Err(Error::new(
|
||||
ErrorKind::InvalidInput,
|
||||
"no addresses to send data to",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the socket address that this socket was created from.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr, I2pDatagramSocket};
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// assert_eq!(socket.local_addr().unwrap(),
|
||||
/// I2pSocketAddr::new(I2pAddr::new("example.i2p"), 34254));
|
||||
/// ```
|
||||
pub fn local_addr(&self) -> io::Result<I2pSocketAddr> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Returns the socket address that this socket was created from.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr, I2pDatagramSocket};
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// assert_eq!(socket.local_addr().unwrap(),
|
||||
/// I2pSocketAddr::new(I2pAddr::new("example.i2p"), 34254));
|
||||
/// ```
|
||||
pub fn local_addr(&self) -> io::Result<I2pSocketAddr> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Creates a new independently owned handle to the underlying socket.
|
||||
///
|
||||
/// The returned `I2pDatagramSocket` is a reference to the same socket that this
|
||||
/// object references. Both handles will read and write the same port, and
|
||||
/// options set on one socket will be propagated to the other.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// let socket_clone = socket.try_clone().expect("couldn't clone the socket");
|
||||
/// ```
|
||||
pub fn try_clone(&self) -> io::Result<I2pDatagramSocket> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Creates a new independently owned handle to the underlying socket.
|
||||
///
|
||||
/// The returned `I2pDatagramSocket` is a reference to the same socket that this
|
||||
/// object references. Both handles will read and write the same port, and
|
||||
/// options set on one socket will be propagated to the other.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// let socket_clone = socket.try_clone().expect("couldn't clone the socket");
|
||||
/// ```
|
||||
pub fn try_clone(&self) -> io::Result<I2pDatagramSocket> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Connects this datagram socket to a remote address, allowing the `send` and
|
||||
/// `recv` calls to be used to send data and also applies filters to only
|
||||
/// receive data from the specified address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.connect("127.0.0.1:8080").expect("connect function failed");
|
||||
/// ```
|
||||
pub fn connect<A: ToI2pSocketAddrs>(&self, addr: A) -> io::Result<()> {
|
||||
self.connect_via(DEFAULT_API, addr)
|
||||
}
|
||||
/// Connects this datagram socket to a remote address, allowing the `send` and
|
||||
/// `recv` calls to be used to send data and also applies filters to only
|
||||
/// receive data from the specified address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.connect("127.0.0.1:8080").expect("connect function failed");
|
||||
/// ```
|
||||
pub fn connect<A: ToI2pSocketAddrs>(&self, addr: A) -> io::Result<()> {
|
||||
self.connect_via(DEFAULT_API, addr)
|
||||
}
|
||||
|
||||
pub fn connect_via<A: ToSocketAddrs, B: ToI2pSocketAddrs>(&self, sam_addr: A, addr: B) -> io::Result<()> {
|
||||
super::each_addr(sam_addr, addr, |_sam_addr, _addr| unimplemented!())
|
||||
}
|
||||
pub fn connect_via<A: ToSocketAddrs, B: ToI2pSocketAddrs>(
|
||||
&self,
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
) -> io::Result<()> {
|
||||
super::each_addr(sam_addr, addr, |_sam_addr, _addr| unimplemented!())
|
||||
}
|
||||
|
||||
/// Sends data on the socket to the remote address to which it is connected.
|
||||
///
|
||||
/// The [`connect()`] method will connect this socket to a remote address. This
|
||||
/// method will fail if the socket is not connected.
|
||||
///
|
||||
/// [`connect()`]: #method.connect
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.connect("127.0.0.1:8080").expect("connect function failed");
|
||||
/// socket.send(&[0, 1, 2]).expect("couldn't send message");
|
||||
/// ```
|
||||
pub fn send(&self, _buf: &[u8]) -> io::Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Sends data on the socket to the remote address to which it is connected.
|
||||
///
|
||||
/// The [`connect()`] method will connect this socket to a remote address. This
|
||||
/// method will fail if the socket is not connected.
|
||||
///
|
||||
/// [`connect()`]: #method.connect
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.connect("127.0.0.1:8080").expect("connect function failed");
|
||||
/// socket.send(&[0, 1, 2]).expect("couldn't send message");
|
||||
/// ```
|
||||
pub fn send(&self, _buf: &[u8]) -> io::Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Receives data on the socket from the remote address to which it is
|
||||
/// connected.
|
||||
///
|
||||
/// The `connect` method will connect this socket to a remote address. This
|
||||
/// method will fail if the socket is not connected.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.connect("127.0.0.1:8080").expect("connect function failed");
|
||||
/// let mut buf = [0; 10];
|
||||
/// match socket.recv(&mut buf) {
|
||||
/// Ok(received) => println!("received {} bytes", received),
|
||||
/// Err(e) => println!("recv function failed: {:?}", e),
|
||||
/// }
|
||||
/// ```
|
||||
pub fn recv(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Receives data on the socket from the remote address to which it is
|
||||
/// connected.
|
||||
///
|
||||
/// The `connect` method will connect this socket to a remote address. This
|
||||
/// method will fail if the socket is not connected.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.connect("127.0.0.1:8080").expect("connect function failed");
|
||||
/// let mut buf = [0; 10];
|
||||
/// match socket.recv(&mut buf) {
|
||||
/// Ok(received) => println!("received {} bytes", received),
|
||||
/// Err(e) => println!("recv function failed: {:?}", e),
|
||||
/// }
|
||||
/// ```
|
||||
pub fn recv(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Receives data on the socket from the remote adress to which it is
|
||||
/// connected, without removing that data from the queue. On success,
|
||||
/// returns the number of bytes peeked.
|
||||
///
|
||||
/// Successive calls return the same data.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method will fail if the socket is not connected. The `connect` method
|
||||
/// will connect this socket to a remote address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.connect("127.0.0.1:8080").expect("connect function failed");
|
||||
/// let mut buf = [0; 10];
|
||||
/// match socket.peek(&mut buf) {
|
||||
/// Ok(received) => println!("received {} bytes", received),
|
||||
/// Err(e) => println!("peek function failed: {:?}", e),
|
||||
/// }
|
||||
/// ```
|
||||
pub fn peek(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Receives data on the socket from the remote adress to which it is
|
||||
/// connected, without removing that data from the queue. On success,
|
||||
/// returns the number of bytes peeked.
|
||||
///
|
||||
/// Successive calls return the same data.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method will fail if the socket is not connected. The `connect` method
|
||||
/// will connect this socket to a remote address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pDatagramSocket;
|
||||
///
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// socket.connect("127.0.0.1:8080").expect("connect function failed");
|
||||
/// let mut buf = [0; 10];
|
||||
/// match socket.peek(&mut buf) {
|
||||
/// Ok(received) => println!("received {} bytes", received),
|
||||
/// Err(e) => println!("peek function failed: {:?}", e),
|
||||
/// }
|
||||
/// ```
|
||||
pub fn peek(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
@ -22,80 +22,80 @@ use std::hash;
|
||||
/// I2pAddr::new("abcdefghijklmnopqrstuvwxyz234567abcdefghijklmnopqrst.b32.i2p");
|
||||
/// ```
|
||||
pub struct I2pAddr {
|
||||
inner: String,
|
||||
inner: String,
|
||||
}
|
||||
|
||||
impl I2pAddr {
|
||||
/// Creates a new I2p address from a given string.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::I2pAddr;
|
||||
///
|
||||
/// let addr = I2pAddr::new("example.i2p");
|
||||
/// ```
|
||||
pub fn new(dest: &str) -> I2pAddr {
|
||||
I2pAddr {
|
||||
inner: dest.to_string(),
|
||||
}
|
||||
}
|
||||
/// Creates a new I2p address from a given string.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::I2pAddr;
|
||||
///
|
||||
/// let addr = I2pAddr::new("example.i2p");
|
||||
/// ```
|
||||
pub fn new(dest: &str) -> I2pAddr {
|
||||
I2pAddr {
|
||||
inner: dest.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the String that makes up this address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::I2pAddr;
|
||||
///
|
||||
/// let addr = I2pAddr::new("example.i2p");
|
||||
/// assert_eq!(addr.string(), "example.i2p");
|
||||
/// ```
|
||||
pub fn string(&self) -> String {
|
||||
self.inner.clone()
|
||||
}
|
||||
/// Returns the String that makes up this address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use i2p::net::I2pAddr;
|
||||
///
|
||||
/// let addr = I2pAddr::new("example.i2p");
|
||||
/// assert_eq!(addr.string(), "example.i2p");
|
||||
/// ```
|
||||
pub fn string(&self) -> String {
|
||||
self.inner.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for I2pAddr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "{}", self.inner)
|
||||
}
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "{}", self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for I2pAddr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for I2pAddr {
|
||||
fn clone(&self) -> I2pAddr {
|
||||
I2pAddr::new(&self.inner)
|
||||
}
|
||||
fn clone(&self) -> I2pAddr {
|
||||
I2pAddr::new(&self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for I2pAddr {
|
||||
fn eq(&self, other: &I2pAddr) -> bool {
|
||||
self.inner == other.inner
|
||||
}
|
||||
fn eq(&self, other: &I2pAddr) -> bool {
|
||||
self.inner == other.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for I2pAddr {}
|
||||
|
||||
impl hash::Hash for I2pAddr {
|
||||
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
||||
self.inner.hash(s)
|
||||
}
|
||||
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
||||
self.inner.hash(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for I2pAddr {
|
||||
fn partial_cmp(&self, other: &I2pAddr) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
fn partial_cmp(&self, other: &I2pAddr) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for I2pAddr {
|
||||
fn cmp(&self, other: &I2pAddr) -> Ordering {
|
||||
self.inner.cmp(&other.inner)
|
||||
}
|
||||
fn cmp(&self, other: &I2pAddr) -> Ordering {
|
||||
self.inner.cmp(&other.inner)
|
||||
}
|
||||
}
|
||||
|
@ -14,26 +14,26 @@ mod streaming;
|
||||
mod test;
|
||||
|
||||
fn each_addr<A: ToSocketAddrs, B: ToI2pSocketAddrs, F, T>(
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
mut f: F,
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
mut f: F,
|
||||
) -> io::Result<T>
|
||||
where
|
||||
F: FnMut(&SocketAddr, &I2pSocketAddr) -> io::Result<T>,
|
||||
F: FnMut(&SocketAddr, &I2pSocketAddr) -> io::Result<T>,
|
||||
{
|
||||
let mut last_err = None;
|
||||
for addr in addr.to_socket_addrs()? {
|
||||
for sam_addr in sam_addr.to_socket_addrs()? {
|
||||
match f(&sam_addr, &addr) {
|
||||
Ok(l) => return Ok(l),
|
||||
Err(e) => last_err = Some(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(last_err.unwrap_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"could not resolve to any addresses",
|
||||
)
|
||||
}))
|
||||
let mut last_err = None;
|
||||
for addr in addr.to_socket_addrs()? {
|
||||
for sam_addr in sam_addr.to_socket_addrs()? {
|
||||
match f(&sam_addr, &addr) {
|
||||
Ok(l) => return Ok(l),
|
||||
Err(e) => last_err = Some(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(last_err.unwrap_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"could not resolve to any addresses",
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
@ -4,11 +4,11 @@ use std::fmt;
|
||||
use std::io;
|
||||
use std::net::{Shutdown, SocketAddr, ToSocketAddrs};
|
||||
|
||||
use rand::{self, Rng};
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::{self, Rng};
|
||||
|
||||
use crate::net::{I2pAddr, I2pSocketAddr, ToI2pSocketAddrs};
|
||||
use crate::sam::{DEFAULT_API, StreamConnect};
|
||||
use crate::sam::{StreamConnect, DEFAULT_API};
|
||||
|
||||
/// A structure which represents an I2P stream between a local socket and a
|
||||
/// remote socket.
|
||||
@ -30,7 +30,7 @@ use crate::sam::{DEFAULT_API, StreamConnect};
|
||||
/// } // the stream is closed here
|
||||
/// ```
|
||||
pub struct I2pStream {
|
||||
inner: StreamConnect,
|
||||
inner: StreamConnect,
|
||||
}
|
||||
|
||||
/// Unimplemented
|
||||
@ -72,286 +72,289 @@ pub struct I2pListener {}
|
||||
/// [`I2pListener`]: struct.I2pListener.html
|
||||
#[derive(Debug)]
|
||||
pub struct Incoming<'a> {
|
||||
listener: &'a I2pListener,
|
||||
listener: &'a I2pListener,
|
||||
}
|
||||
|
||||
impl I2pStream {
|
||||
/// Opens a TCP-like connection to a remote host.
|
||||
///
|
||||
/// `addr` is an address of the remote host. Anything which implements
|
||||
/// `ToI2pSocketAddrs` trait can be supplied for the address; see this trait
|
||||
/// documentation for concrete examples.
|
||||
/// In case `ToI2pSocketAddrs::to_socket_addrs()` returns more than one
|
||||
/// entry (which should never be the case), then the first valid and
|
||||
/// reachable address is used.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pStream;
|
||||
///
|
||||
/// if let Ok(stream) = I2pStream::connect("example.i2p:8080") {
|
||||
/// println!("Connected to the server!");
|
||||
/// } else {
|
||||
/// println!("Couldn't connect to server...");
|
||||
/// }
|
||||
/// ```
|
||||
pub fn connect<A: ToI2pSocketAddrs>(addr: A) -> io::Result<I2pStream> {
|
||||
I2pStream::connect_via(DEFAULT_API, addr)
|
||||
}
|
||||
/// Opens a TCP-like connection to a remote host.
|
||||
///
|
||||
/// `addr` is an address of the remote host. Anything which implements
|
||||
/// `ToI2pSocketAddrs` trait can be supplied for the address; see this trait
|
||||
/// documentation for concrete examples.
|
||||
/// In case `ToI2pSocketAddrs::to_socket_addrs()` returns more than one
|
||||
/// entry (which should never be the case), then the first valid and
|
||||
/// reachable address is used.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pStream;
|
||||
///
|
||||
/// if let Ok(stream) = I2pStream::connect("example.i2p:8080") {
|
||||
/// println!("Connected to the server!");
|
||||
/// } else {
|
||||
/// println!("Couldn't connect to server...");
|
||||
/// }
|
||||
/// ```
|
||||
pub fn connect<A: ToI2pSocketAddrs>(addr: A) -> io::Result<I2pStream> {
|
||||
I2pStream::connect_via(DEFAULT_API, addr)
|
||||
}
|
||||
|
||||
pub fn connect_via<A: ToSocketAddrs, B: ToI2pSocketAddrs>(
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
) -> io::Result<I2pStream> {
|
||||
super::each_addr(sam_addr, addr, I2pStream::connect_addr)
|
||||
}
|
||||
pub fn connect_via<A: ToSocketAddrs, B: ToI2pSocketAddrs>(
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
) -> io::Result<I2pStream> {
|
||||
super::each_addr(sam_addr, addr, I2pStream::connect_addr)
|
||||
}
|
||||
|
||||
fn connect_addr(sam_addr: &SocketAddr, addr: &I2pSocketAddr) -> io::Result<I2pStream> {
|
||||
let suffix: String = rand::thread_rng().sample_iter(&Alphanumeric).take(8).collect();
|
||||
let nickname = format!("i2prs-{}", suffix);
|
||||
fn connect_addr(sam_addr: &SocketAddr, addr: &I2pSocketAddr) -> io::Result<I2pStream> {
|
||||
let suffix: String = rand::thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.take(8)
|
||||
.collect();
|
||||
let nickname = format!("i2prs-{}", suffix);
|
||||
|
||||
let stream = StreamConnect::new(sam_addr, &addr.dest().string(), addr.port(), &nickname)?;
|
||||
let stream = StreamConnect::new(sam_addr, &addr.dest().string(), addr.port(), &nickname)?;
|
||||
|
||||
Ok(I2pStream { inner: stream })
|
||||
}
|
||||
Ok(I2pStream { inner: stream })
|
||||
}
|
||||
|
||||
/// Returns the socket address of the remote peer of this I2P connection.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr, I2pStream};
|
||||
///
|
||||
/// let stream = I2pStream::connect("example.i2p:8080")
|
||||
/// .expect("Couldn't connect to the server...");
|
||||
/// assert_eq!(stream.peer_addr().unwrap(),
|
||||
/// I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080));
|
||||
/// ```
|
||||
pub fn peer_addr(&self) -> io::Result<I2pSocketAddr> {
|
||||
self.inner
|
||||
.peer_addr()
|
||||
.map(|(d, p)| I2pSocketAddr::new(I2pAddr::new(&d), p))
|
||||
}
|
||||
/// Returns the socket address of the remote peer of this I2P connection.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr, I2pStream};
|
||||
///
|
||||
/// let stream = I2pStream::connect("example.i2p:8080")
|
||||
/// .expect("Couldn't connect to the server...");
|
||||
/// assert_eq!(stream.peer_addr().unwrap(),
|
||||
/// I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080));
|
||||
/// ```
|
||||
pub fn peer_addr(&self) -> io::Result<I2pSocketAddr> {
|
||||
self.inner
|
||||
.peer_addr()
|
||||
.map(|(d, p)| I2pSocketAddr::new(I2pAddr::new(&d), p))
|
||||
}
|
||||
|
||||
/// Returns the socket address of the local half of this I2P connection.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr, I2pStream};
|
||||
///
|
||||
/// let stream = I2pStream::connect("example.i2p:8080")
|
||||
/// .expect("Couldn't connect to the server...");
|
||||
/// assert_eq!(stream.local_addr().unwrap(),
|
||||
/// I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080));
|
||||
/// ```
|
||||
pub fn local_addr(&self) -> io::Result<I2pSocketAddr> {
|
||||
self.inner
|
||||
.local_addr()
|
||||
.map(|(d, p)| I2pSocketAddr::new(I2pAddr::new(&d), p))
|
||||
}
|
||||
/// Returns the socket address of the local half of this I2P connection.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr, I2pStream};
|
||||
///
|
||||
/// let stream = I2pStream::connect("example.i2p:8080")
|
||||
/// .expect("Couldn't connect to the server...");
|
||||
/// assert_eq!(stream.local_addr().unwrap(),
|
||||
/// I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080));
|
||||
/// ```
|
||||
pub fn local_addr(&self) -> io::Result<I2pSocketAddr> {
|
||||
self.inner
|
||||
.local_addr()
|
||||
.map(|(d, p)| I2pSocketAddr::new(I2pAddr::new(&d), p))
|
||||
}
|
||||
|
||||
/// Shuts down the read, write, or both halves of this connection.
|
||||
///
|
||||
/// This function will cause all pending and future I/O on the specified
|
||||
/// portions to return immediately with an appropriate value (see the
|
||||
/// documentation of [`Shutdown`]).
|
||||
///
|
||||
/// [`Shutdown`]: ../../std/net/enum.Shutdown.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::net::Shutdown;
|
||||
/// use i2p::net::I2pStream;
|
||||
///
|
||||
/// let stream = I2pStream::connect("127.0.0.1:8080")
|
||||
/// .expect("Couldn't connect to the server...");
|
||||
/// stream.shutdown(Shutdown::Both).expect("shutdown call failed");
|
||||
/// ```
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
self.inner.shutdown(how)
|
||||
}
|
||||
/// Shuts down the read, write, or both halves of this connection.
|
||||
///
|
||||
/// This function will cause all pending and future I/O on the specified
|
||||
/// portions to return immediately with an appropriate value (see the
|
||||
/// documentation of [`Shutdown`]).
|
||||
///
|
||||
/// [`Shutdown`]: ../../std/net/enum.Shutdown.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::net::Shutdown;
|
||||
/// use i2p::net::I2pStream;
|
||||
///
|
||||
/// let stream = I2pStream::connect("127.0.0.1:8080")
|
||||
/// .expect("Couldn't connect to the server...");
|
||||
/// stream.shutdown(Shutdown::Both).expect("shutdown call failed");
|
||||
/// ```
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
self.inner.shutdown(how)
|
||||
}
|
||||
|
||||
/// Creates a new independently owned handle to the underlying socket.
|
||||
///
|
||||
/// The returned `I2pStream` is a reference to the same stream that this
|
||||
/// object references. Both handles will read and write the same stream of
|
||||
/// data, and options set on one stream will be propagated to the other
|
||||
/// stream.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pStream;
|
||||
///
|
||||
/// let stream = I2pStream::connect("example.i2p:8080")
|
||||
/// .expect("Couldn't connect to the server...");
|
||||
/// let stream_clone = stream.try_clone().expect("clone failed...");
|
||||
/// ```
|
||||
pub fn try_clone(&self) -> io::Result<I2pStream> {
|
||||
self.inner.duplicate().map(|s| I2pStream { inner: s })
|
||||
}
|
||||
/// Creates a new independently owned handle to the underlying socket.
|
||||
///
|
||||
/// The returned `I2pStream` is a reference to the same stream that this
|
||||
/// object references. Both handles will read and write the same stream of
|
||||
/// data, and options set on one stream will be propagated to the other
|
||||
/// stream.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pStream;
|
||||
///
|
||||
/// let stream = I2pStream::connect("example.i2p:8080")
|
||||
/// .expect("Couldn't connect to the server...");
|
||||
/// let stream_clone = stream.try_clone().expect("clone failed...");
|
||||
/// ```
|
||||
pub fn try_clone(&self) -> io::Result<I2pStream> {
|
||||
self.inner.duplicate().map(|s| I2pStream { inner: s })
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for I2pStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(buf)
|
||||
}
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for I2pStream {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.write(buf)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.write(buf)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for I2pStream {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut res = f.debug_struct("I2pStream");
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut res = f.debug_struct("I2pStream");
|
||||
|
||||
if let Ok(addr) = self.local_addr() {
|
||||
res.field("addr", &addr);
|
||||
}
|
||||
if let Ok(addr) = self.local_addr() {
|
||||
res.field("addr", &addr);
|
||||
}
|
||||
|
||||
if let Ok(peer) = self.peer_addr() {
|
||||
res.field("peer", &peer);
|
||||
}
|
||||
if let Ok(peer) = self.peer_addr() {
|
||||
res.field("peer", &peer);
|
||||
}
|
||||
|
||||
res.finish()
|
||||
}
|
||||
res.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl I2pListener {
|
||||
/// Creates a new `I2pListener` which will be bound to the specified
|
||||
/// address.
|
||||
///
|
||||
/// The returned listener is ready for accepting connections.
|
||||
///
|
||||
/// Binding with a port number of 0 is equivalent to binding on every port.
|
||||
///
|
||||
/// The address type can be any implementor of `ToI2pSocketAddrs` trait. See
|
||||
/// its documentation for concrete examples.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pListener;
|
||||
///
|
||||
/// let listener = I2pListener::bind("127.0.0.1:80").unwrap();
|
||||
/// ```
|
||||
pub fn bind<A: ToI2pSocketAddrs>(addr: A) -> io::Result<I2pListener> {
|
||||
I2pListener::bind_via(DEFAULT_API, addr)
|
||||
}
|
||||
/// Creates a new `I2pListener` which will be bound to the specified
|
||||
/// address.
|
||||
///
|
||||
/// The returned listener is ready for accepting connections.
|
||||
///
|
||||
/// Binding with a port number of 0 is equivalent to binding on every port.
|
||||
///
|
||||
/// The address type can be any implementor of `ToI2pSocketAddrs` trait. See
|
||||
/// its documentation for concrete examples.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pListener;
|
||||
///
|
||||
/// let listener = I2pListener::bind("127.0.0.1:80").unwrap();
|
||||
/// ```
|
||||
pub fn bind<A: ToI2pSocketAddrs>(addr: A) -> io::Result<I2pListener> {
|
||||
I2pListener::bind_via(DEFAULT_API, addr)
|
||||
}
|
||||
|
||||
pub fn bind_via<A: ToSocketAddrs, B: ToI2pSocketAddrs>(
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
) -> io::Result<I2pListener> {
|
||||
super::each_addr(sam_addr, addr, I2pListener::bind_addr)
|
||||
}
|
||||
pub fn bind_via<A: ToSocketAddrs, B: ToI2pSocketAddrs>(
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
) -> io::Result<I2pListener> {
|
||||
super::each_addr(sam_addr, addr, I2pListener::bind_addr)
|
||||
}
|
||||
|
||||
fn bind_addr(_sam_addr: &SocketAddr, _addr: &I2pSocketAddr) -> io::Result<I2pListener> {
|
||||
unimplemented!();
|
||||
}
|
||||
fn bind_addr(_sam_addr: &SocketAddr, _addr: &I2pSocketAddr) -> io::Result<I2pListener> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/// Returns the local socket address of this listener.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr, I2pListener};
|
||||
///
|
||||
/// let listener = I2pListener::bind("127.0.0.1:8080").unwrap();
|
||||
/// assert_eq!(listener.local_addr().unwrap(),
|
||||
/// I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080));
|
||||
/// ```
|
||||
pub fn local_addr(&self) -> io::Result<I2pSocketAddr> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Returns the local socket address of this listener.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::{I2pAddr, I2pSocketAddr, I2pListener};
|
||||
///
|
||||
/// let listener = I2pListener::bind("127.0.0.1:8080").unwrap();
|
||||
/// assert_eq!(listener.local_addr().unwrap(),
|
||||
/// I2pSocketAddr::new(I2pAddr::new("example.i2p"), 8080));
|
||||
/// ```
|
||||
pub fn local_addr(&self) -> io::Result<I2pSocketAddr> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Creates a new independently owned handle to the underlying socket.
|
||||
///
|
||||
/// The returned `TcpListener` is a reference to the same socket that this
|
||||
/// object references. Both handles can be used to accept incoming
|
||||
/// connections and options set on one listener will affect the other.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pListener;
|
||||
///
|
||||
/// let listener = I2pListener::bind("127.0.0.1:8080").unwrap();
|
||||
/// let listener_clone = listener.try_clone().unwrap();
|
||||
/// ```
|
||||
pub fn try_clone(&self) -> io::Result<I2pListener> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Creates a new independently owned handle to the underlying socket.
|
||||
///
|
||||
/// The returned `TcpListener` is a reference to the same socket that this
|
||||
/// object references. Both handles can be used to accept incoming
|
||||
/// connections and options set on one listener will affect the other.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pListener;
|
||||
///
|
||||
/// let listener = I2pListener::bind("127.0.0.1:8080").unwrap();
|
||||
/// let listener_clone = listener.try_clone().unwrap();
|
||||
/// ```
|
||||
pub fn try_clone(&self) -> io::Result<I2pListener> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Accept a new incoming connection from this listener.
|
||||
///
|
||||
/// This function will block the calling thread until a new TCP connection
|
||||
/// is established. When established, the corresponding `TcpStream` and the
|
||||
/// remote peer's address will be returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pListener;
|
||||
///
|
||||
/// let listener = I2pListener::bind("127.0.0.1:8080").unwrap();
|
||||
/// match listener.accept() {
|
||||
/// Ok((_socket, addr)) => println!("new client: {:?}", addr),
|
||||
/// Err(e) => println!("couldn't get client: {:?}", e),
|
||||
/// }
|
||||
/// ```
|
||||
pub fn accept(&self) -> io::Result<(I2pStream, I2pSocketAddr)> {
|
||||
unimplemented!()
|
||||
}
|
||||
/// Accept a new incoming connection from this listener.
|
||||
///
|
||||
/// This function will block the calling thread until a new TCP connection
|
||||
/// is established. When established, the corresponding `TcpStream` and the
|
||||
/// remote peer's address will be returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pListener;
|
||||
///
|
||||
/// let listener = I2pListener::bind("127.0.0.1:8080").unwrap();
|
||||
/// match listener.accept() {
|
||||
/// Ok((_socket, addr)) => println!("new client: {:?}", addr),
|
||||
/// Err(e) => println!("couldn't get client: {:?}", e),
|
||||
/// }
|
||||
/// ```
|
||||
pub fn accept(&self) -> io::Result<(I2pStream, I2pSocketAddr)> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns an iterator over the connections being received on this
|
||||
/// listener.
|
||||
///
|
||||
/// The returned iterator will never return [`None`] and will also not yield
|
||||
/// the peer's [`I2pSocketAddr`] structure.
|
||||
///
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
/// [`I2pSocketAddr`]: ../../std/net/struct.I2pSocketAddr.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pListener;
|
||||
///
|
||||
/// let listener = I2pListener::bind("127.0.0.1:80").unwrap();
|
||||
///
|
||||
/// for stream in listener.incoming() {
|
||||
/// match stream {
|
||||
/// Ok(stream) => {
|
||||
/// println!("new client!");
|
||||
/// }
|
||||
/// Err(e) => { /* connection failed */ }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn incoming(&self) -> Incoming<'_> {
|
||||
Incoming { listener: self }
|
||||
}
|
||||
/// Returns an iterator over the connections being received on this
|
||||
/// listener.
|
||||
///
|
||||
/// The returned iterator will never return [`None`] and will also not yield
|
||||
/// the peer's [`I2pSocketAddr`] structure.
|
||||
///
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
/// [`I2pSocketAddr`]: ../../std/net/struct.I2pSocketAddr.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::I2pListener;
|
||||
///
|
||||
/// let listener = I2pListener::bind("127.0.0.1:80").unwrap();
|
||||
///
|
||||
/// for stream in listener.incoming() {
|
||||
/// match stream {
|
||||
/// Ok(stream) => {
|
||||
/// println!("new client!");
|
||||
/// }
|
||||
/// Err(e) => { /* connection failed */ }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn incoming(&self) -> Incoming {
|
||||
Incoming { listener: self }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Incoming<'a> {
|
||||
type Item = io::Result<I2pStream>;
|
||||
fn next(&mut self) -> Option<io::Result<I2pStream>> {
|
||||
Some(self.listener.accept().map(|p| p.0))
|
||||
}
|
||||
type Item = io::Result<I2pStream>;
|
||||
fn next(&mut self) -> Option<io::Result<I2pStream>> {
|
||||
Some(self.listener.accept().map(|p| p.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for I2pListener {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
|
||||
unimplemented!()
|
||||
}
|
||||
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
use crate::net::{I2pAddr, I2pSocketAddr, ToI2pSocketAddrs};
|
||||
use net::{I2pAddr, I2pSocketAddr, ToI2pSocketAddrs};
|
||||
|
||||
pub fn isa(a: I2pAddr, p: u16) -> I2pSocketAddr {
|
||||
I2pSocketAddr::new(a, p)
|
||||
I2pSocketAddr::new(a, p)
|
||||
}
|
||||
|
||||
pub fn tsa<A: ToI2pSocketAddrs>(a: A) -> Result<Vec<I2pSocketAddr>, String> {
|
||||
match a.to_socket_addrs() {
|
||||
Ok(a) => Ok(a.collect()),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
match a.to_socket_addrs() {
|
||||
Ok(a) => Ok(a.collect()),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
184
src/parsers.rs
184
src/parsers.rs
@ -1,20 +1,22 @@
|
||||
use nom::{space, alphanumeric, named, do_parse, separated_list, take_till_s,
|
||||
tag_s, call, error_position, tag, alt, take_till};
|
||||
use nom::{
|
||||
alphanumeric, alt, call, do_parse, error_position, named, separated_list, space, tag, tag_s,
|
||||
take_till, take_till_s,
|
||||
};
|
||||
|
||||
fn is_space(chr: char) -> bool {
|
||||
chr == ' ' || chr == '\t'
|
||||
chr == ' ' || chr == '\t'
|
||||
}
|
||||
|
||||
fn is_next_line(chr: char) -> bool {
|
||||
chr == '\n'
|
||||
chr == '\n'
|
||||
}
|
||||
|
||||
fn is_space_or_next_line(chr: char) -> bool {
|
||||
is_space(chr) || is_next_line(chr)
|
||||
is_space(chr) || is_next_line(chr)
|
||||
}
|
||||
|
||||
fn is_double_quote(chr: char) -> bool {
|
||||
chr == '\"'
|
||||
chr == '\"'
|
||||
}
|
||||
|
||||
named!(quoted_value <&str, &str>,
|
||||
@ -86,100 +88,100 @@ named!(pub sam_dest_reply <&str, Vec<(&str, &str)> >,
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use nom::ErrorKind;
|
||||
use nom::IResult::Done;
|
||||
use nom::IResult::Error;
|
||||
use nom::ErrorKind;
|
||||
use nom::IResult::Done;
|
||||
use nom::IResult::Error;
|
||||
|
||||
#[test]
|
||||
fn hello() {
|
||||
use crate::parsers::sam_hello;
|
||||
#[test]
|
||||
fn hello() {
|
||||
use parsers::sam_hello;
|
||||
|
||||
assert_eq!(
|
||||
sam_hello("HELLO REPLY RESULT=OK VERSION=3.1\n"),
|
||||
Done("", vec![("RESULT", "OK"), ("VERSION", "3.1")])
|
||||
);
|
||||
assert_eq!(
|
||||
sam_hello("HELLO REPLY RESULT=NOVERSION\n"),
|
||||
Done("", vec![("RESULT", "NOVERSION")])
|
||||
);
|
||||
assert_eq!(
|
||||
sam_hello("HELLO REPLY RESULT=I2P_ERROR MESSAGE=\"Something failed\"\n"),
|
||||
Done(
|
||||
"",
|
||||
vec![("RESULT", "I2P_ERROR"), ("MESSAGE", "Something failed")]
|
||||
)
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
sam_hello("HELLO REPLY RESULT=OK VERSION=3.1\n"),
|
||||
Done("", vec![("RESULT", "OK"), ("VERSION", "3.1")])
|
||||
);
|
||||
assert_eq!(
|
||||
sam_hello("HELLO REPLY RESULT=NOVERSION\n"),
|
||||
Done("", vec![("RESULT", "NOVERSION")])
|
||||
);
|
||||
assert_eq!(
|
||||
sam_hello("HELLO REPLY RESULT=I2P_ERROR MESSAGE=\"Something failed\"\n"),
|
||||
Done(
|
||||
"",
|
||||
vec![("RESULT", "I2P_ERROR"), ("MESSAGE", "Something failed")]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_status() {
|
||||
use crate::parsers::sam_session_status;
|
||||
#[test]
|
||||
fn session_status() {
|
||||
use parsers::sam_session_status;
|
||||
|
||||
assert_eq!(
|
||||
sam_session_status("SESSION STATUS RESULT=OK DESTINATION=privkey\n"),
|
||||
Done("", vec![("RESULT", "OK"), ("DESTINATION", "privkey")])
|
||||
);
|
||||
assert_eq!(
|
||||
sam_session_status("SESSION STATUS RESULT=DUPLICATED_ID\n"),
|
||||
Done("", vec![("RESULT", "DUPLICATED_ID")])
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
sam_session_status("SESSION STATUS RESULT=OK DESTINATION=privkey\n"),
|
||||
Done("", vec![("RESULT", "OK"), ("DESTINATION", "privkey")])
|
||||
);
|
||||
assert_eq!(
|
||||
sam_session_status("SESSION STATUS RESULT=DUPLICATED_ID\n"),
|
||||
Done("", vec![("RESULT", "DUPLICATED_ID")])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stream_status() {
|
||||
use crate::parsers::sam_stream_status;
|
||||
#[test]
|
||||
fn stream_status() {
|
||||
use parsers::sam_stream_status;
|
||||
|
||||
assert_eq!(
|
||||
sam_stream_status("STREAM STATUS RESULT=OK\n"),
|
||||
Done("", vec![("RESULT", "OK")])
|
||||
);
|
||||
assert_eq!(
|
||||
sam_stream_status(
|
||||
"STREAM STATUS RESULT=CANT_REACH_PEER MESSAGE=\"Can't reach peer\"\n"
|
||||
),
|
||||
Done(
|
||||
"",
|
||||
vec![
|
||||
("RESULT", "CANT_REACH_PEER"),
|
||||
("MESSAGE", "Can't reach peer")
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
sam_stream_status("STREAM STATUS RESULT=OK\n"),
|
||||
Done("", vec![("RESULT", "OK")])
|
||||
);
|
||||
assert_eq!(
|
||||
sam_stream_status(
|
||||
"STREAM STATUS RESULT=CANT_REACH_PEER MESSAGE=\"Can't reach peer\"\n"
|
||||
),
|
||||
Done(
|
||||
"",
|
||||
vec![
|
||||
("RESULT", "CANT_REACH_PEER"),
|
||||
("MESSAGE", "Can't reach peer")
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn naming_reply() {
|
||||
use crate::parsers::sam_naming_reply;
|
||||
#[test]
|
||||
fn naming_reply() {
|
||||
use parsers::sam_naming_reply;
|
||||
|
||||
assert_eq!(
|
||||
sam_naming_reply("NAMING REPLY RESULT=OK NAME=name VALUE=dest\n"),
|
||||
Done(
|
||||
"",
|
||||
vec![("RESULT", "OK"), ("NAME", "name"), ("VALUE", "dest")]
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
sam_naming_reply("NAMING REPLY RESULT=KEY_NOT_FOUND\n"),
|
||||
Done("", vec![("RESULT", "KEY_NOT_FOUND")])
|
||||
);
|
||||
assert_eq!(
|
||||
sam_naming_reply("NAMING REPLY RESULT=OK NAME=name VALUE=dest\n"),
|
||||
Done(
|
||||
"",
|
||||
vec![("RESULT", "OK"), ("NAME", "name"), ("VALUE", "dest")]
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
sam_naming_reply("NAMING REPLY RESULT=KEY_NOT_FOUND\n"),
|
||||
Done("", vec![("RESULT", "KEY_NOT_FOUND")])
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
sam_naming_reply("NAMINGREPLY RESULT=KEY_NOT_FOUND\n"),
|
||||
Error(ErrorKind::Tag)
|
||||
);
|
||||
assert_eq!(
|
||||
sam_naming_reply("NAMING REPLY RESULT=KEY_NOT_FOUND\n"),
|
||||
Error(ErrorKind::Tag)
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
sam_naming_reply("NAMINGREPLY RESULT=KEY_NOT_FOUND\n"),
|
||||
Error(ErrorKind::Tag)
|
||||
);
|
||||
assert_eq!(
|
||||
sam_naming_reply("NAMING REPLY RESULT=KEY_NOT_FOUND\n"),
|
||||
Error(ErrorKind::Tag)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dest_reply() {
|
||||
use crate::parsers::sam_dest_reply;
|
||||
#[test]
|
||||
fn dest_reply() {
|
||||
use parsers::sam_dest_reply;
|
||||
|
||||
assert_eq!(
|
||||
sam_dest_reply("DEST REPLY PUB=foo PRIV=foobar\n"),
|
||||
Done("", vec![("PUB", "foo"), ("PRIV", "foobar")])
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
sam_dest_reply("DEST REPLY PUB=foo PRIV=foobar\n"),
|
||||
Done("", vec![("PUB", "foo"), ("PRIV", "foobar")])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
314
src/sam.rs
314
src/sam.rs
@ -17,214 +17,216 @@ static SAM_MIN: &'static str = "3.0";
|
||||
static SAM_MAX: &'static str = "3.1";
|
||||
|
||||
pub enum SessionStyle {
|
||||
Datagram,
|
||||
Raw,
|
||||
Stream,
|
||||
Datagram,
|
||||
Raw,
|
||||
Stream,
|
||||
}
|
||||
|
||||
pub struct SamConnection {
|
||||
conn: TcpStream,
|
||||
conn: TcpStream,
|
||||
}
|
||||
|
||||
pub struct Session {
|
||||
sam: SamConnection,
|
||||
local_dest: String,
|
||||
sam: SamConnection,
|
||||
local_dest: String,
|
||||
}
|
||||
|
||||
pub struct StreamConnect {
|
||||
sam: SamConnection,
|
||||
session: Session,
|
||||
peer_dest: String,
|
||||
peer_port: u16,
|
||||
local_port: u16,
|
||||
sam: SamConnection,
|
||||
session: Session,
|
||||
peer_dest: String,
|
||||
peer_port: u16,
|
||||
local_port: u16,
|
||||
}
|
||||
|
||||
impl SessionStyle {
|
||||
fn string(&self) -> &str {
|
||||
match *self {
|
||||
SessionStyle::Datagram => "DATAGRAM",
|
||||
SessionStyle::Raw => "RAW",
|
||||
SessionStyle::Stream => "STREAM",
|
||||
}
|
||||
}
|
||||
fn string(&self) -> &str {
|
||||
match *self {
|
||||
SessionStyle::Datagram => "DATAGRAM",
|
||||
SessionStyle::Raw => "RAW",
|
||||
SessionStyle::Stream => "STREAM",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_response<'a>(vec: &'a [(&str, &str)]) -> Result<HashMap<&'a str, &'a str>, Error> {
|
||||
let new_vec = vec.clone();
|
||||
let map: HashMap<&str, &str> = new_vec.iter().map(|&(k, v)| (k, v)).collect();
|
||||
let res = map.get("RESULT").unwrap_or(&"OK").clone();
|
||||
let msg = map.get("MESSAGE").unwrap_or(&"").clone();
|
||||
match res {
|
||||
"OK" => Ok(map),
|
||||
"CANT_REACH_PEER" | "KEY_NOT_FOUND" | "PEER_NOT_FOUND" => {
|
||||
Err(Error::new(ErrorKind::NotFound, msg))
|
||||
}
|
||||
"DUPLICATED_DEST" => Err(Error::new(ErrorKind::AddrInUse, msg)),
|
||||
"INVALID_KEY" | "INVALID_ID" => Err(Error::new(ErrorKind::InvalidInput, msg)),
|
||||
"TIMEOUT" => Err(Error::new(ErrorKind::TimedOut, msg)),
|
||||
"I2P_ERROR" => Err(Error::new(ErrorKind::Other, msg)),
|
||||
_ => Err(Error::new(ErrorKind::Other, msg)),
|
||||
}
|
||||
let new_vec = vec.clone();
|
||||
let map: HashMap<&str, &str> = new_vec.iter().map(|&(k, v)| (k, v)).collect();
|
||||
let res = map.get("RESULT").unwrap_or(&"OK").clone();
|
||||
let msg = map.get("MESSAGE").unwrap_or(&"").clone();
|
||||
match res {
|
||||
"OK" => Ok(map),
|
||||
"CANT_REACH_PEER" | "KEY_NOT_FOUND" | "PEER_NOT_FOUND" => {
|
||||
Err(Error::new(ErrorKind::NotFound, msg))
|
||||
}
|
||||
"DUPLICATED_DEST" => Err(Error::new(ErrorKind::AddrInUse, msg)),
|
||||
"INVALID_KEY" | "INVALID_ID" => Err(Error::new(ErrorKind::InvalidInput, msg)),
|
||||
"TIMEOUT" => Err(Error::new(ErrorKind::TimedOut, msg)),
|
||||
"I2P_ERROR" => Err(Error::new(ErrorKind::Other, msg)),
|
||||
_ => Err(Error::new(ErrorKind::Other, msg)),
|
||||
}
|
||||
}
|
||||
|
||||
impl SamConnection {
|
||||
fn send<F>(&mut self, msg: String, reply_parser: F) -> Result<HashMap<String, String>, Error>
|
||||
where
|
||||
F: Fn(&str) -> IResult<&str, Vec<(&str, &str)>>,
|
||||
{
|
||||
debug!("-> {}", &msg);
|
||||
self.conn.write_all(&msg.into_bytes())?;
|
||||
fn send<F>(&mut self, msg: String, reply_parser: F) -> Result<HashMap<String, String>, Error>
|
||||
where
|
||||
F: Fn(&str) -> IResult<&str, Vec<(&str, &str)>>,
|
||||
{
|
||||
debug!("-> {}", &msg);
|
||||
self.conn.write_all(&msg.into_bytes())?;
|
||||
|
||||
let mut reader = BufReader::new(&self.conn);
|
||||
let mut buffer = String::new();
|
||||
reader.read_line(&mut buffer)?;
|
||||
debug!("<- {}", &buffer);
|
||||
let mut reader = BufReader::new(&self.conn);
|
||||
let mut buffer = String::new();
|
||||
reader.read_line(&mut buffer)?;
|
||||
debug!("<- {}", &buffer);
|
||||
|
||||
let response = reply_parser(&buffer);
|
||||
let vec_opts = response.unwrap().1;
|
||||
verify_response(&vec_opts).map(|m| {
|
||||
m.iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
let response = reply_parser(&buffer);
|
||||
let vec_opts = response.unwrap().1;
|
||||
verify_response(&vec_opts).map(|m| {
|
||||
m.iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
fn handshake(&mut self) -> Result<HashMap<String, String>, Error> {
|
||||
let hello_msg = format!(
|
||||
"HELLO VERSION MIN={min} MAX={max} \n",
|
||||
min = SAM_MIN,
|
||||
max = SAM_MAX
|
||||
);
|
||||
self.send(hello_msg, sam_hello)
|
||||
}
|
||||
fn handshake(&mut self) -> Result<HashMap<String, String>, Error> {
|
||||
let hello_msg = format!(
|
||||
"HELLO VERSION MIN={min} MAX={max} \n",
|
||||
min = SAM_MIN,
|
||||
max = SAM_MAX
|
||||
);
|
||||
self.send(hello_msg, sam_hello)
|
||||
}
|
||||
|
||||
pub fn connect<A: ToSocketAddrs>(addr: A) -> Result<SamConnection, Error> {
|
||||
let tcp_stream = TcpStream::connect(addr)?;
|
||||
pub fn connect<A: ToSocketAddrs>(addr: A) -> Result<SamConnection, Error> {
|
||||
let tcp_stream = TcpStream::connect(addr)?;
|
||||
|
||||
let mut socket = SamConnection { conn: tcp_stream };
|
||||
let mut socket = SamConnection { conn: tcp_stream };
|
||||
|
||||
socket.handshake()?;
|
||||
socket.handshake()?;
|
||||
|
||||
Ok(socket)
|
||||
}
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
// TODO: Implement a lookup table
|
||||
pub fn naming_lookup(&mut self, name: &str) -> Result<String, Error> {
|
||||
let create_naming_lookup_msg = format!("NAMING LOOKUP NAME={name} \n", name = name);
|
||||
let ret = self.send(create_naming_lookup_msg, sam_naming_reply)?;
|
||||
Ok(ret["VALUE"].clone())
|
||||
}
|
||||
// TODO: Implement a lookup table
|
||||
pub fn naming_lookup(&mut self, name: &str) -> Result<String, Error> {
|
||||
let create_naming_lookup_msg = format!("NAMING LOOKUP NAME={name} \n", name = name);
|
||||
let ret = self.send(create_naming_lookup_msg, sam_naming_reply)?;
|
||||
Ok(ret["VALUE"].clone())
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<SamConnection> {
|
||||
self.conn.try_clone().map(|s| SamConnection { conn: s })
|
||||
}
|
||||
pub fn duplicate(&self) -> io::Result<SamConnection> {
|
||||
self.conn.try_clone().map(|s| SamConnection { conn: s })
|
||||
}
|
||||
}
|
||||
|
||||
impl Session {
|
||||
pub fn create<A: ToSocketAddrs>(
|
||||
sam_addr: A,
|
||||
destination: &str,
|
||||
nickname: &str,
|
||||
style: SessionStyle,
|
||||
) -> Result<Session, Error> {
|
||||
let mut sam = SamConnection::connect(sam_addr).unwrap();
|
||||
let create_session_msg = format!(
|
||||
"SESSION CREATE STYLE={style} ID={nickname} DESTINATION={destination} \n",
|
||||
style = style.string(),
|
||||
nickname = nickname,
|
||||
destination = destination
|
||||
);
|
||||
pub fn create<A: ToSocketAddrs>(
|
||||
sam_addr: A,
|
||||
destination: &str,
|
||||
nickname: &str,
|
||||
style: SessionStyle,
|
||||
) -> Result<Session, Error> {
|
||||
let mut sam = SamConnection::connect(sam_addr).unwrap();
|
||||
let create_session_msg = format!(
|
||||
"SESSION CREATE STYLE={style} ID={nickname} DESTINATION={destination} \n",
|
||||
style = style.string(),
|
||||
nickname = nickname,
|
||||
destination = destination
|
||||
);
|
||||
|
||||
sam.send(create_session_msg, sam_session_status)?;
|
||||
sam.send(create_session_msg, sam_session_status)?;
|
||||
|
||||
let local_dest = sam.naming_lookup("ME")?;
|
||||
let local_dest = sam.naming_lookup("ME")?;
|
||||
|
||||
Ok(Session {
|
||||
sam: sam,
|
||||
local_dest: local_dest,
|
||||
})
|
||||
}
|
||||
Ok(Session {
|
||||
sam: sam,
|
||||
local_dest: local_dest,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sam_api(&self) -> io::Result<SocketAddr> {
|
||||
self.sam.conn.peer_addr()
|
||||
}
|
||||
pub fn sam_api(&self) -> io::Result<SocketAddr> {
|
||||
self.sam.conn.peer_addr()
|
||||
}
|
||||
|
||||
pub fn naming_lookup(&mut self, name: &str) -> io::Result<String> {
|
||||
self.sam.naming_lookup(name)
|
||||
}
|
||||
pub fn naming_lookup(&mut self, name: &str) -> io::Result<String> {
|
||||
self.sam.naming_lookup(name)
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<Session> {
|
||||
self.sam.duplicate().map(|s| Session {
|
||||
sam: s,
|
||||
local_dest: self.local_dest.clone(),
|
||||
})
|
||||
}
|
||||
pub fn duplicate(&self) -> io::Result<Session> {
|
||||
self.sam.duplicate().map(|s| Session {
|
||||
sam: s,
|
||||
local_dest: self.local_dest.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl StreamConnect {
|
||||
pub fn new<A: ToSocketAddrs>(
|
||||
sam_addr: A,
|
||||
destination: &str,
|
||||
port: u16,
|
||||
nickname: &str,
|
||||
) -> io::Result<StreamConnect> {
|
||||
let mut session = Session::create(sam_addr, "TRANSIENT", nickname, SessionStyle::Stream)?;
|
||||
pub fn new<A: ToSocketAddrs>(
|
||||
sam_addr: A,
|
||||
destination: &str,
|
||||
port: u16,
|
||||
nickname: &str,
|
||||
) -> io::Result<StreamConnect> {
|
||||
let mut session = Session::create(sam_addr, "TRANSIENT", nickname, SessionStyle::Stream)?;
|
||||
|
||||
let mut sam = SamConnection::connect(session.sam_api()?).unwrap();
|
||||
let dest = sam.naming_lookup(destination);
|
||||
let mut sam = SamConnection::connect(session.sam_api()?).unwrap();
|
||||
let dest = sam.naming_lookup(destination);
|
||||
|
||||
let create_stream_msg = format!("STREAM CONNECT ID={nickname} DESTINATION={destination} SILENT=false TO_PORT={port}\n",
|
||||
nickname = nickname,
|
||||
destination = dest.unwrap(),
|
||||
port = port);
|
||||
let create_stream_msg = format!(
|
||||
"STREAM CONNECT ID={nickname} DESTINATION={destination} SILENT=false TO_PORT={port}\n",
|
||||
nickname = nickname,
|
||||
destination = dest.unwrap(),
|
||||
port = port
|
||||
);
|
||||
|
||||
sam.send(create_stream_msg, sam_stream_status)?;
|
||||
sam.send(create_stream_msg, sam_stream_status)?;
|
||||
|
||||
let peer_dest = session.naming_lookup(destination)?;
|
||||
let peer_dest = session.naming_lookup(destination)?;
|
||||
|
||||
Ok(StreamConnect {
|
||||
sam: sam,
|
||||
session: session,
|
||||
peer_dest: peer_dest,
|
||||
peer_port: port,
|
||||
local_port: 0,
|
||||
})
|
||||
}
|
||||
Ok(StreamConnect {
|
||||
sam: sam,
|
||||
session: session,
|
||||
peer_dest: peer_dest,
|
||||
peer_port: port,
|
||||
local_port: 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn peer_addr(&self) -> io::Result<(String, u16)> {
|
||||
Ok((self.peer_dest.clone(), self.peer_port))
|
||||
}
|
||||
pub fn peer_addr(&self) -> io::Result<(String, u16)> {
|
||||
Ok((self.peer_dest.clone(), self.peer_port))
|
||||
}
|
||||
|
||||
pub fn local_addr(&self) -> io::Result<(String, u16)> {
|
||||
Ok((self.session.local_dest.clone(), self.local_port))
|
||||
}
|
||||
pub fn local_addr(&self) -> io::Result<(String, u16)> {
|
||||
Ok((self.session.local_dest.clone(), self.local_port))
|
||||
}
|
||||
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
self.sam.conn.shutdown(how)
|
||||
}
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
self.sam.conn.shutdown(how)
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<StreamConnect> {
|
||||
Ok(StreamConnect {
|
||||
sam: self.sam.duplicate()?,
|
||||
session: self.session.duplicate()?,
|
||||
peer_dest: self.peer_dest.clone(),
|
||||
peer_port: self.peer_port,
|
||||
local_port: self.local_port,
|
||||
})
|
||||
}
|
||||
pub fn duplicate(&self) -> io::Result<StreamConnect> {
|
||||
Ok(StreamConnect {
|
||||
sam: self.sam.duplicate()?,
|
||||
session: self.session.duplicate()?,
|
||||
peer_dest: self.peer_dest.clone(),
|
||||
peer_port: self.peer_port,
|
||||
local_port: self.local_port,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for StreamConnect {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.sam.conn.read(buf)
|
||||
}
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.sam.conn.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for StreamConnect {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.sam.conn.write(buf)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.sam.conn.flush()
|
||||
}
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.sam.conn.write(buf)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.sam.conn.flush()
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn naming_lookup() {
|
||||
use i2p::sam::SamConnection;
|
||||
let mut sam = SamConnection::connect("127.0.0.1:7656").unwrap();
|
||||
{
|
||||
let res = sam.naming_lookup("zzz.i2p");
|
||||
match res {
|
||||
use i2p::sam::SamConnection;
|
||||
let mut sam = SamConnection::connect("127.0.0.1:7656").unwrap();
|
||||
{
|
||||
let res = sam.naming_lookup("zzz.i2p");
|
||||
match res {
|
||||
Ok(d) => {
|
||||
assert_eq!(
|
||||
d,
|
||||
@ -14,5 +14,5 @@ fn naming_lookup() {
|
||||
}
|
||||
Err(ref e) => panic!("An error occurred: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user