From 1fc161c53cb8fc2662b6b37e8f357cfd6eb996d5 Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Mon, 21 Mar 2016 10:55:31 +0000 Subject: [PATCH] Allow connecting to servers --- src/console/mod.rs | 2 ++ src/main.rs | 6 ++-- src/protocol/mod.rs | 4 +-- src/protocol/mojang.rs | 18 ++++++------ src/server.rs | 62 +++++++++++++++++++++++++++++++++++++----- src/ui/mod.rs | 3 ++ 6 files changed, 74 insertions(+), 21 deletions(-) diff --git a/src/console/mod.rs b/src/console/mod.rs index 4944654..3b1e0cf 100644 --- a/src/console/mod.rs +++ b/src/console/mod.rs @@ -74,6 +74,8 @@ pub struct Console { position: f64, } +unsafe impl Send for Console {} + impl Console { pub fn new() -> Console { Console { diff --git a/src/main.rs b/src/main.rs index d4bb213..18b3ea7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -86,8 +86,9 @@ impl Game { self.connect_reply = Some(rx); let address = address.to_owned(); let resources = self.resource_manager.clone(); + let console = self.console.clone(); thread::spawn(move || { - tx.send(server::Server::connect(resources, &address)).unwrap(); + tx.send(server::Server::connect(resources, console, &address)).unwrap(); }); } @@ -99,6 +100,7 @@ impl Game { match server { Ok(val) => { self.screen_sys.pop_screen(); + self.renderer.clear_chunks(); self.server = val; }, Err(err) => { @@ -176,7 +178,7 @@ fn main() { let textures = renderer.get_textures(); let mut game = Game { - server: server::Server::dummy_server(resource_manager.clone()), + server: server::Server::dummy_server(resource_manager.clone(), con.clone()), renderer: renderer, screen_sys: screen_sys, resource_manager: resource_manager, diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 0fcf3a1..918fd03 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -362,7 +362,7 @@ pub struct LenPrefixed { } impl LenPrefixed { - fn new(data: Vec) -> LenPrefixed { + pub fn new(data: Vec) -> LenPrefixed { LenPrefixed { len: Default::default(), data: data, @@ -418,7 +418,7 @@ pub struct LenPrefixedBytes { } impl LenPrefixedBytes { - fn new(data: Vec) -> LenPrefixedBytes { + pub fn new(data: Vec) -> LenPrefixedBytes { LenPrefixedBytes { len: Default::default(), data: data, diff --git a/src/protocol/mojang.rs b/src/protocol/mojang.rs index c416787..83bea16 100644 --- a/src/protocol/mojang.rs +++ b/src/protocol/mojang.rs @@ -100,8 +100,7 @@ impl Profile { Ok(self) } - // TODO - pub fn join_server(&self, server_id: &str, shared_key: &Vec, public_key: &Vec) { + pub fn join_server(&self, server_id: &str, shared_key: &Vec, public_key: &Vec) -> Result<(), super::Error> { let mut sha1 = openssl::SHA1::new(); sha1.update(server_id.as_bytes()); sha1.update(&shared_key[..]); @@ -130,17 +129,16 @@ impl Profile { let join = serde_json::to_string(&join_msg).unwrap(); let client = hyper::Client::new(); - let res = client.post(JOIN_URL) + let res = try!(client.post(JOIN_URL) .body(&join) .header(hyper::header::ContentType("application/json".parse().unwrap())) - .send() - .unwrap(); + .send()); - let ret: serde_json::Value = match serde_json::from_reader(res) { - Result::Ok(val) => val, - Result::Err(_) => return, - }; - panic!("{:?}", ret); + if res.status == hyper::status::StatusCode::NoContent { + Ok(()) + } else { + Err(super::Error::Err("Failed to auth with server".to_owned())) + } } pub fn is_complete(&self) -> bool { diff --git a/src/server.rs b/src/server.rs index c6c93c0..b16a07a 100644 --- a/src/server.rs +++ b/src/server.rs @@ -12,24 +12,28 @@ // See the License for the specific language governing permissions and // limitations under the License. -use protocol; +use protocol::{self, mojang}; use world; use world::block::{self, BlockSet}; use rand::{self, Rng}; -use std::sync::{Arc, RwLock}; +use std::sync::{Arc, RwLock, Mutex}; use resources; +use openssl; +use console; +use auth; pub struct Server { conn: Option, pub world: world::World, resources: Arc>, + console: Arc>, version: usize, } impl Server { - pub fn connect(resources: Arc>, address: &str) -> Result { + pub fn connect(resources: Arc>, console: Arc>, address: &str) -> Result { let mut conn = try!(protocol::Conn::new(address)); let host = conn.host.clone(); @@ -45,24 +49,67 @@ impl Server { username: "Thinkofdeath".to_owned() })); - let packet = match conn.read_packet().unwrap() { + let packet = match try!(conn.read_packet()) { protocol::packet::Packet::EncryptionRequest(val) => val, protocol::packet::Packet::LoginDisconnect(val) => return Err(protocol::Error::Disconnect(val.reason)), val => return Err(protocol::Error::Err(format!("Wrong packet: {:?}", val))), }; - unimplemented!(); + let mut key = openssl::PublicKey::new(&packet.public_key.data); + let shared = openssl::gen_random(16); + + let shared_e = key.encrypt(&shared); + let token_e = key.encrypt(&packet.verify_token.data); + + let profile = { + let console = console.lock().unwrap(); + mojang::Profile { + username: console.get(auth::CL_USERNAME).clone(), + id: console.get(auth::CL_UUID).clone(), + access_token: console.get(auth::AUTH_TOKEN).clone(), + } + }; + try!(profile.join_server(&packet.server_id, &shared, &packet.public_key.data)); + + try!(conn.write_packet(protocol::packet::login::serverbound::EncryptionResponse { + shared_secret: protocol::LenPrefixedBytes::new(shared_e), + verify_token: protocol::LenPrefixedBytes::new(token_e), + })); + + let mut read = conn.clone(); // TODO + let mut write = conn.clone(); + + read.enable_encyption(&shared, true); + write.enable_encyption(&shared, false); + + loop { + match try!(read.read_packet()) { + protocol::packet::Packet::SetInitialCompression(val) => { + read.set_compresssion(val.threshold.0, true); + write.set_compresssion(val.threshold.0, false); + } + protocol::packet::Packet::LoginSuccess(val) => { + debug!("Login: {} {}", val.username, val.uuid); + read.state = protocol::State::Play; + write.state = protocol::State::Play; + break; + } + protocol::packet::Packet::LoginDisconnect(val) => return Err(protocol::Error::Disconnect(val.reason)), + val => return Err(protocol::Error::Err(format!("Wrong packet: {:?}", val))), + } + } let version = resources.read().unwrap().version(); Ok(Server { - conn: Some(conn), + conn: Some(write), world: world::World::new(), resources: resources, + console: console, version: version, }) } - pub fn dummy_server(resources: Arc>) -> Server { + pub fn dummy_server(resources: Arc>, console: Arc>) -> Server { let mut world = world::World::new(); let mut rng = rand::thread_rng(); for x in -7*16 .. 7*16 { @@ -80,6 +127,7 @@ impl Server { version: version, resources: resources, + console: console, } } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index f002f88..e98f960 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -536,6 +536,9 @@ impl Container { } pub fn cycle_focus(&mut self) { + if self.elements_list.is_empty() { + return; + } // Find the last focused element let i = self.elements_list.iter() .map(|v| self.elements.get(v).unwrap())