carrier 0.12.2

carrier is a generic secure message system for IoT
use mio::*;
use mio::net::{UdpSocket};
use mio::net::{TcpStream};
use std::net::{SocketAddr};
use std::thread;
use std::io::{Read,Write};
use bytes::BytesMut;
use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian};
use mio_extras::channel;

pub struct Handle {
    pub guard:  channel::Sender<()>,
    pub addr:   SocketAddr,
}

pub fn spawn (addr: SocketAddr) -> Handle {
    let (guard, onded) = channel::channel();

    let udp = UdpSocket::bind(&"127.0.0.1:0".parse().unwrap()).unwrap();
    let local_addr = udp.local_addr().unwrap();
    debug!("bridge opened udp {:?} <----> tcp {:?}", 
           local_addr, addr);

    thread::Builder::new().name(format!("tcp").to_string()).spawn(move || {
        let poll = Poll::new().unwrap();


        let mut udpaddr = None;

        let mut tcp = TcpStream::connect(&addr).unwrap();

        poll.register(&tcp,     Token(0), Ready::readable(), PollOpt::level()).unwrap();
        poll.register(&udp,     Token(1), Ready::readable(), PollOpt::level()).unwrap();
        poll.register(&onded,   Token(2), Ready::readable(), PollOpt::level()).unwrap();


        let mut inbuf  = [0;4096];
        let mut tcpbuf = BytesMut::new();
        let mut next   = None;

        let mut events = Events::with_capacity(1024);
        loop {
            poll.poll(&mut events, None).unwrap();
            for event in events.iter() {
                match event.token().0 {
                    0 => {
                        match tcp.read(&mut inbuf) {
                            Err(e) => {
                                warn!("tcp bridge ended: {}", e);
                                return;
                            }
                            Ok(n) if n == 0  => {
                                warn!("tcp bridge ended: CLOSE");
                                return;
                            }
                            Ok(n) => {
                                tcpbuf.extend_from_slice(&inbuf[..n]);
                                if next.is_none() && tcpbuf.len() >= 4 {
                                    let head_bytes = tcpbuf.split_to(2);
                                    let ver = (&head_bytes[..]).read_u16::<LittleEndian>().unwrap();
                                    if ver != 69 {
                                        warn!("tcp bridge ended: corrupt {}", ver);
                                        return;
                                    }

                                    let head_bytes = tcpbuf.split_to(2);
                                    next = Some((&head_bytes[..]).read_u16::<LittleEndian>().unwrap());
                                }
                                if let Some(next_h) = next {
                                    if tcpbuf.len() >= next_h as usize {
                                        trace!("received packet of size {}", next_h);
                                        if let Some(udpaddr) = udpaddr {
                                            udp.send_to(&tcpbuf.split_to(next_h as usize), &udpaddr).ok();
                                        }
                                    }
                                    next = None;
                                }
                            }
                        }
                    },
                    1 => {
                        match udp.recv_from(&mut inbuf) {
                            Err(e) => {
                                warn!("tcp bridge ended: {}", e);
                                return;
                            }
                            Ok((n, addr)) => {
                                udpaddr = Some(addr);
                                trace!("sending packet of size {}", n);
                                let mut b = Vec::new();
                                b.write_u16::<LittleEndian>(69 as u16).ok();
                                b.write_u16::<LittleEndian>(n as u16).ok();
                                b.extend_from_slice(&inbuf[..n]);

                                tcp.write(&b).ok();
                            }
                        }
                    },
                    _ => {
                        debug!("tcp bridge ended: guard dropped");
                        return
                    },
                }
            }
        }
    }).unwrap();

    Handle{
        guard,
        addr: local_addr,
    }
}