use std::io::prelude::*;
use std::fmt;
use std::io;
use std::net::{Shutdown, SocketAddr, ToSocketAddrs};
use rand;
use rand::Rng;
use net::{I2pAddr, I2pSocketAddr, ToI2pSocketAddrs};
use sam::{DEFAULT_API, StreamConnect};
pub struct I2pStream {
inner: StreamConnect,
}
pub struct I2pListener {}
#[derive(Debug)]
pub struct Incoming<'a> { listener: &'a I2pListener }
impl I2pStream {
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)
}
fn connect_addr(sam_addr: &SocketAddr, addr: &I2pSocketAddr) -> io::Result<I2pStream> {
let suffix: String = rand::thread_rng().gen_ascii_chars().take(8).collect();
let nickname = format!("i2prs-{}", suffix);
let stream = StreamConnect::new(sam_addr, &addr.dest().string(), addr.port(), &nickname)?;
Ok(I2pStream { inner: stream })
}
pub fn peer_addr(&self) -> io::Result<I2pSocketAddr> {
self.inner.peer_addr().map(|(d, p)| I2pSocketAddr::new(I2pAddr::new(&d), p))
}
pub fn local_addr(&self) -> io::Result<I2pSocketAddr> {
self.inner.local_addr().map(|(d, p)| I2pSocketAddr::new(I2pAddr::new(&d), p))
}
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
self.inner.shutdown(how)
}
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)
}
}
impl Write for I2pStream {
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");
if let Ok(addr) = self.local_addr() {
res.field("addr", &addr);
}
if let Ok(peer) = self.peer_addr() {
res.field("peer", &peer);
}
res.finish()
}
}
impl I2pListener {
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)
}
fn bind_addr(sam_addr: &SocketAddr, addr: &I2pSocketAddr) -> io::Result<I2pListener> {
unimplemented!();
}
pub fn local_addr(&self) -> io::Result<I2pSocketAddr> {
unimplemented!()
}
pub fn try_clone(&self) -> io::Result<I2pListener> {
unimplemented!()
}
pub fn accept(&self) -> io::Result<(I2pStream, I2pSocketAddr)> {
unimplemented!()
}
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))
}
}
impl fmt::Debug for I2pListener {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
unimplemented!()
}
}