p2p 0.6.0

NAT Traversal for P2P communication
use mio::{Poll, PollOpt, Ready, Token};
use socket_collection::{self, TcpSock};
use sodium::crypto::sealedbox;
use std::any::Any;
use std::cell::RefCell;
use std::net::SocketAddr;
use std::rc::Rc;
use std::str::{self, FromStr};
use tcp::{TcpEchoReq, TcpEchoResp};
use {Interface, NatError, NatState};

pub type Finish = Box<FnMut(&mut Interface, &Poll, Token, ::Res<SocketAddr>)>;

pub struct TcpRendezvousClient {
    token: Token,
    sock: TcpSock,
    req: Option<TcpEchoReq>,
    f: Finish,
}

impl TcpRendezvousClient {
    pub fn start(ifc: &mut Interface, poll: &Poll, sock: TcpSock, f: Finish) -> ::Res<Token> {
        let token = ifc.new_token();

        poll.register(
            &sock,
            token,
            Ready::readable() | Ready::writable(),
            PollOpt::edge(),
        )?;

        let client = Rc::new(RefCell::new(TcpRendezvousClient {
            token,
            sock,
            req: Some(TcpEchoReq(ifc.enc_pk().0)),
            f,
        }));

        if ifc.insert_state(token, client.clone()).is_err() {
            debug!("Unable to insert TcpRendezvousClient State!");
            client.borrow_mut().terminate(ifc, poll);
            Err(NatError::TcpRendezvousFailed)
        } else {
            Ok(token)
        }
    }

    fn read(&mut self, ifc: &mut Interface, poll: &Poll) {
        let mut utf8 = Vec::new();
        loop {
            match self.sock.read() {
                Ok(Some(TcpEchoResp(cipher_text))) => {
                    match sealedbox::open(&cipher_text, ifc.enc_pk(), ifc.enc_sk()) {
                        Ok(plain_text) => utf8 = plain_text,
                        Err(()) => {
                            debug!("Error: Failed to decrypt TcpIpEchoResp");
                            return self.handle_err(ifc, poll);
                        }
                    };
                }
                Ok(None) => if utf8.is_empty() {
                    return;
                } else {
                    break;
                },
                Err(socket_collection::SocketError::ZeroByteRead) => {
                    if utf8.is_empty() {
                        debug!("Error: Connection shutdown without getting TcpIpEchoResp");
                        return self.handle_err(ifc, poll);
                    } else {
                        break;
                    }
                }
                Err(e) => {
                    debug!("Tcp Rendezvous client errored out in read: {:?}", e);
                    return self.handle_err(ifc, poll);
                }
            }
        }

        match str::from_utf8(&utf8) {
            Ok(our_ext_addr_str) => match SocketAddr::from_str(our_ext_addr_str) {
                Ok(addr) => self.done(ifc, poll, addr),
                Err(e) => {
                    debug!(
                        "Error: TcpIpEchoResp which contained non-parsable address: {:?}",
                        e
                    );
                    self.handle_err(ifc, poll)
                }
            },
            Err(e) => {
                debug!(
                    "Error: TcpIpEchoResp which contained non-utf8 address: {:?}",
                    e
                );
                self.handle_err(ifc, poll)
            }
        }
    }

    fn write(&mut self, ifc: &mut Interface, poll: &Poll, m: Option<TcpEchoReq>) {
        if let Err(e) = self.sock.write(m.map(|m| (m, 0))) {
            debug!("Tcp Rendezvous client errored out in write: {:?}", e);
            self.handle_err(ifc, poll);
        }
    }

    fn done(&mut self, ifc: &mut Interface, poll: &Poll, ext_addr: SocketAddr) {
        self.terminate(ifc, poll);
        (*self.f)(ifc, poll, self.token, Ok(ext_addr));
    }

    fn handle_err(&mut self, ifc: &mut Interface, poll: &Poll) {
        self.terminate(ifc, poll);
        (*self.f)(ifc, poll, self.token, Err(NatError::TcpRendezvousFailed));
    }
}

impl NatState for TcpRendezvousClient {
    fn ready(&mut self, ifc: &mut Interface, poll: &Poll, event: Ready) {
        if event.is_readable() {
            self.read(ifc, poll)
        } else if event.is_writable() {
            let m = self.req.take();
            self.write(ifc, poll, m)
        } else {
            warn!("Investigate: Ignoring unknown event kind: {:?}", event);
        }
    }

    fn terminate(&mut self, ifc: &mut Interface, poll: &Poll) {
        let _ = ifc.remove_state(self.token);
        let _ = poll.deregister(&self.sock);
    }

    fn as_any(&mut self) -> &mut Any {
        self
    }
}