summaryrefslogtreecommitdiff
path: root/vndbapi/src/io.rs
blob: f4acc9b9898818dfbe056da065c85b2796b8c3c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use std::io;
use std::io::Write;
use std::str;
use tokio_core::io::{Codec, EasyBuf, Io, Framed};
use tokio_proto::pipeline::ClientProto;
use tokio_service::Service;
use futures::{future, Future, BoxFuture};
use rustls::ClientConfig;
use tokio_rustls::{ClientConfigExt,ConnectAsync};
use std::sync::Arc;

use msg::Message;

pub struct MsgCodec;

impl Codec for MsgCodec {
    type In = Message;
    type Out = Message;

    fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<Self::In>> {
        if let Some(i) = buf.as_slice().iter().position(|&b| b == 4) {
            let msg = buf.drain_to(i);
            buf.drain_to(1);
            let msg = match str::from_utf8(msg.as_slice()) {
                Ok(s) => s,
                Err(_) => return Err(io::Error::new(io::ErrorKind::Other, "Invalid UTF-8"))
            };
            match Message::parse(msg) {
                Ok(m) => Ok(Some(m)),
                Err(e) => Err(io::Error::new(io::ErrorKind::Other, e))
            }
        } else {
            Ok(None)
        }
    }

    fn encode(&mut self, msg: Message, buf: &mut Vec<u8>) -> io::Result<()> {
        write!(buf, "{}\x04", msg)
    }
}



pub struct MsgProto;

impl<T: Io + 'static> ClientProto<T> for MsgProto {
    type Request = Message;
    type Response = Message;
    type Transport = Framed<T, MsgCodec>;
    type BindTransport = Result<Self::Transport, io::Error>;
    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(io.framed(MsgCodec))
    }
}



const VNDB_HOST: &'static str = "api.vndb.org";
const VNDB_PORT_RAW: u16 = 19534;
const VNDB_PORT_TLS: u16 = 19535;

use tokio_core::reactor::Core;
use tokio_proto::BindClient;
use tokio_dns::tcp_connect;


pub fn connect(hostname: Option<&str>, port: Option<u16>, tls: Option<&Arc<ClientConfig>>) {
    let hostname = hostname.unwrap_or(VNDB_HOST);
    let port = port.unwrap_or(if tls.is_some() { VNDB_PORT_TLS } else { VNDB_PORT_RAW });

    let mut core = Core::new().unwrap();
    let handle = core.handle();

    println!("Connecting");

    let conn = tcp_connect((hostname, port), core.remote());

    //let c = if let Some(conf) = tls {
    let c = conn.and_then(|c| tls.unwrap().connect_async("api.vndb.org", c));
    //} else {
    //    conn.boxed()
    //};

    let serv = c.map(|c| { MsgProto.bind_client(&handle, c) });
    let serv = core.run(serv).unwrap();
    let ok = core.run(serv.call(Message::parse("login {\"protocol\":1,\"client\":\"vndb-rust\",\"clientver\":\"0.1\"}").unwrap())).unwrap();
    println!("{}", ok);
}