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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
//use std::io::BufWriter;
use std::result::Result;
use std::vec::Vec;
use tokio::net::TcpStream;
use tokio::prelude::*;
use tokio_util::codec::{Framed};
use futures_util::stream::StreamExt;
use futures::SinkExt;
use crate::protocol::frame::QuasselCodec;
use failure::Error;
extern crate log;
// use log::{info, warn, debug};
pub struct Client {
stream: Framed<TcpStream, QuasselCodec>,
pub tls: bool,
pub compression: bool,
}
impl Client {
pub async fn run(&mut self) {
// TODO while endlessly loops over same stream element
while let Some(msg) = self.stream.next().await {
println!("bing");
let msg = msg.unwrap();
handle_login_message(self, &msg).await.unwrap();
};
}
pub async fn connect(address: &'static str, port: u64, tls: bool, compression: bool) -> Result<Client, Error> {
use crate::protocol::primitive::deserialize::Deserialize;
use crate::protocol::message::ConnAck;
use crate::protocol::primitive::{StringList};
use crate::protocol::message::ClientInit;
use crate::protocol::message::handshake::HandshakeSerialize;
let mut s = TcpStream::connect(format!("{}:{}", address, port)).await?;
// Set Features
let mut init: Vec<u8> = vec![];
let mut handshake: u32 = 0x42b33f00;
if tls {
handshake |= 0x01;
}
if compression {
handshake |= 0x02;
}
let mut proto: u32 = 0x00000002;
let fin: u32 = 0x80000000;
proto |= fin;
init.extend(handshake.to_be_bytes().iter());
init.extend(proto.to_be_bytes().iter());
s.write(&init).await?;
let mut buf = [0; 4];
s.read(&mut buf).await?;
let (_, val) = ConnAck::parse(&buf).unwrap();
println!("Received: {:?}", val);
let codec = QuasselCodec::builder()
.compression(compression)
.new_codec();
let stream = Framed::new(s, codec);
let mut client = Client {
stream: stream,
tls: tls,
compression: compression,
};
let mut features = StringList::new();
features.push("SynchronizedMarkerLine".to_string());
features.push("Authenticators".to_string());
features.push("ExtendedFeatures".to_string());
let client_init = ClientInit {
client_version:String::from("Rust 0.0.0"),
client_date: String::from("1579009211"),
feature_list: features,
client_features: 0x00008000,
};
client.stream.send(client_init.serialize()?).await?;
return Ok(client);
}
}
pub async fn handle_login_message(client: &mut Client, buf: &[u8]) -> Result<(), Error> {
use crate::protocol::message::ClientLogin;
use crate::protocol::message::handshake::{HandshakeSerialize, HandshakeDeserialize, VariantMap};
use crate::protocol::error::ProtocolError;
use crate::util::get_msg_type;
let (_, res) = VariantMap::parse(buf)?;
println!("res {:?}", res);
let msgtype = get_msg_type(&res["MsgType"])?;
match msgtype {
"ClientInitAck" => {
let login = ClientLogin {user: "audron".to_string(), password: "audron".to_string()};
client.stream.send(login.serialize()?).await?;
},
"ClientInitReject" => { println!("init failed: {:?}", res) },
"ClientLoginAck" => { println!("login done: {:?}", res) },
"ClientLoginReject" => { println!("login failed: {:?}", res)},
_ => bail!(ProtocolError::WrongMsgType)
}
return Ok(());
}
|