Initial work on connecting to servers

This commit is contained in:
Thinkofname 2016-03-20 12:04:02 +00:00
parent 189c063f67
commit fd4df88c32
9 changed files with 233 additions and 23 deletions

30
openssl/Cargo.lock generated
View File

@ -2,8 +2,8 @@
name = "steven_openssl"
version = "0.0.1"
dependencies = [
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -16,11 +16,10 @@ dependencies = [
]
[[package]]
name = "gcc"
version = "0.3.13"
name = "gdi32-sys"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -29,6 +28,11 @@ name = "libc"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libressl-pnacl-sys"
version = "2.1.6"
@ -39,13 +43,14 @@ dependencies = [
[[package]]
name = "openssl-sys"
version = "0.6.5"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"user32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -79,6 +84,15 @@ dependencies = [
"rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "user32-sys"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.3"

View File

@ -1,3 +1,4 @@
#![feature(unique)]
#![allow(dead_code)]
extern crate libc;
use std::mem;
@ -54,7 +55,7 @@ extern {
}
pub struct EVPCipher {
internal: *mut EVP_CIPHER_CTX,
internal: ptr::Unique<EVP_CIPHER_CTX>,
block_size: usize,
}
@ -62,17 +63,17 @@ pub struct EVPCipher {
impl EVPCipher {
pub fn new(key: &Vec<u8>, iv: &Vec<u8>, decrypt: bool) -> EVPCipher {
unsafe {
let e = EVPCipher {
internal: EVP_CIPHER_CTX_new(),
let mut e = EVPCipher {
internal: ptr::Unique::new(EVP_CIPHER_CTX_new()),
block_size: EVP_CIPHER_block_size(EVP_aes_128_cfb8()) as usize,
};
EVP_CIPHER_CTX_init(e.internal);
EVP_CIPHER_CTX_init(e.internal.get_mut());
if decrypt {
if EVP_DecryptInit_ex(e.internal, EVP_aes_128_cfb8(), ptr::null_mut(), key.as_ptr(), iv.as_ptr()) == 0 {
if EVP_DecryptInit_ex(e.internal.get_mut(), EVP_aes_128_cfb8(), ptr::null_mut(), key.as_ptr(), iv.as_ptr()) == 0 {
panic!("Init error");
}
} else {
if EVP_EncryptInit_ex(e.internal, EVP_aes_128_cfb8(), ptr::null_mut(), key.as_ptr(), iv.as_ptr()) == 0 {
if EVP_EncryptInit_ex(e.internal.get_mut(), EVP_aes_128_cfb8(), ptr::null_mut(), key.as_ptr(), iv.as_ptr()) == 0 {
panic!("Init error");
}
}
@ -84,7 +85,7 @@ impl EVPCipher {
unsafe {
let mut out = Vec::with_capacity(data.len());
let mut out_len: libc::c_int = 0;
if EVP_DecryptUpdate(self.internal, out.as_mut_ptr(), &mut out_len, data.as_ptr(), data.len() as libc::c_int) == 0 {
if EVP_DecryptUpdate(self.internal.get_mut(), out.as_mut_ptr(), &mut out_len, data.as_ptr(), data.len() as libc::c_int) == 0 {
panic!("Decrypt error")
}
out.set_len(out_len as usize);
@ -96,7 +97,7 @@ impl EVPCipher {
unsafe {
let mut out = Vec::with_capacity(data.len());
let mut out_len: libc::c_int = 0;
if EVP_EncryptUpdate(self.internal, out.as_mut_ptr(), &mut out_len, data.as_ptr(), data.len() as libc::c_int) == 0 {
if EVP_EncryptUpdate(self.internal.get_mut(), out.as_mut_ptr(), &mut out_len, data.as_ptr(), data.len() as libc::c_int) == 0 {
panic!("Encrypt error")
}
out.set_len(out_len as usize);
@ -109,8 +110,8 @@ impl EVPCipher {
impl Drop for EVPCipher {
fn drop(&mut self) {
unsafe {
EVP_CIPHER_CTX_cleanup(self.internal);
EVP_CIPHER_CTX_free(self.internal);
EVP_CIPHER_CTX_cleanup(self.internal.get_mut());
EVP_CIPHER_CTX_free(self.internal.get_mut());
}
}
}

View File

@ -52,6 +52,8 @@ pub mod chunk_builder;
use std::sync::{Arc, RwLock, Mutex};
use std::marker::PhantomData;
use std::thread;
use std::sync::mpsc;
const CL_BRAND: console::CVar<String> = console::CVar {
ty: PhantomData,
@ -73,6 +75,51 @@ pub struct Game {
server: server::Server,
chunk_builder: chunk_builder::ChunkBuilder,
connect_reply: Option<mpsc::Receiver<Result<server::Server, protocol::Error>>>,
}
impl Game {
pub fn connect_to(&mut self, address: &str) {
let (tx, rx) = mpsc::channel();
self.connect_reply = Some(rx);
let address = address.to_owned();
let resources = self.resource_manager.clone();
thread::spawn(move || {
tx.send(server::Server::connect(resources, &address)).unwrap();
});
}
pub fn tick(&mut self) {
let mut clear_reply = false;
if let Some(ref recv) = self.connect_reply {
if let Ok(server) = recv.try_recv() {
clear_reply = true;
match server {
Ok(val) => {
self.screen_sys.pop_screen();
self.server = val;
},
Err(err) => {
let msg = match err {
protocol::Error::Disconnect(val) => val,
err => {
let mut msg = format::TextComponent::new(&format!("{}", err));
msg.modifier.color = Some(format::Color::Red);
format::Component::Text(msg)
},
};
self.screen_sys.replace_screen(Box::new(screen::ServerList::new(
Some(msg)
)));
}
}
}
}
if clear_reply {
self.connect_reply = None;
}
}
}
fn main() {
@ -135,6 +182,7 @@ fn main() {
should_close: false,
mouse_pos: (0, 0),
chunk_builder: chunk_builder::ChunkBuilder::new(textures),
connect_reply: None,
};
while !game.should_close {
@ -157,6 +205,7 @@ fn main() {
game.renderer.camera.yaw = 0.0;
}
game.tick();
game.server.tick();
game.chunk_builder.tick(&mut game.server.world, &mut game.renderer);

View File

@ -631,6 +631,7 @@ pub enum State {
#[derive(Debug)]
pub enum Error {
Err(String),
Disconnect(format::Component),
IOError(io::Error),
}
@ -644,6 +645,7 @@ impl ::std::error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::Err(ref val) => &val[..],
Error::Disconnect(_) => "Disconnect",
Error::IOError(ref e) => e.description(),
}
}
@ -653,6 +655,7 @@ impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
Error::Err(ref val) => write!(f, "protocol error: {}", val),
Error::Disconnect(ref val) => write!(f, "{}", val),
Error::IOError(ref e) => e.fmt(f),
}
}
@ -660,10 +663,10 @@ impl ::std::fmt::Display for Error {
pub struct Conn {
stream: TcpStream,
host: String,
port: u16,
pub host: String,
pub port: u16,
direction: Direction,
state: State,
pub state: State,
cipher: Option<openssl::EVPCipher>,

View File

@ -317,6 +317,10 @@ impl Renderer {
self.ui.tick(width, height);
}
pub fn clear_chunks(&mut self) {
self.chunks.clear();
}
fn ensure_element_buffer(&mut self, size: usize) {
if self.element_buffer_size < size {
let (data, ty) = self::generate_element_buffer(size);

101
src/screen/connecting.rs Normal file
View File

@ -0,0 +1,101 @@
// Copyright 2016 Matthew Collins
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::rc::Rc;
use ui;
use render;
use format::{self, Component, TextComponent};
pub struct Connecting {
elements: Option<UIElements>,
target: String,
}
struct UIElements {
logo: ui::logo::Logo,
elements: ui::Collection,
}
impl Connecting {
pub fn new(target: &str) -> Connecting {
Connecting {
elements: None,
target: target.to_owned(),
}
}
}
impl super::Screen for Connecting {
fn on_active(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
let logo = ui::logo::Logo::new(renderer.resources.clone(), renderer, ui_container);
let mut elements = ui::Collection::new();
let mut connect_msg = ui::Formatted::new(
renderer,
Component::Text(TextComponent::new("Connecting to")),
0.0, -16.0
);
connect_msg.set_v_attach(ui::VAttach::Middle);
connect_msg.set_h_attach(ui::HAttach::Center);
elements.add(ui_container.add(connect_msg));
let mut msg = TextComponent::new(&self.target);
msg.modifier.color = Some(format::Color::Yellow);
let mut server_msg = ui::Formatted::new(
renderer,
Component::Text(msg),
0.0, 16.0
);
server_msg.set_v_attach(ui::VAttach::Middle);
server_msg.set_h_attach(ui::HAttach::Center);
elements.add(ui_container.add(server_msg));
// Disclaimer
let mut warn = ui::Text::new(renderer,
"Not affiliated with Mojang/Minecraft",
5.0,
5.0,
255,
200,
200);
warn.set_v_attach(ui::VAttach::Bottom);
warn.set_h_attach(ui::HAttach::Right);
elements.add(ui_container.add(warn));
self.elements = Some(UIElements {
logo: logo,
elements: elements,
});
}
fn on_deactive(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
// Clean up
{
let elements = self.elements.as_mut().unwrap();
elements.logo.remove(ui_container);
elements.elements.remove_all(ui_container);
}
self.elements = None
}
fn tick(&mut self,
_delta: f64,
renderer: &mut render::Renderer,
ui_container: &mut ui::Container) {
let elements = self.elements.as_mut().unwrap();
elements.logo.tick(renderer, ui_container);
}
}

View File

@ -16,6 +16,7 @@ mod server_list;
pub use self::server_list::*;
mod login;
pub use self::login::*;
pub mod connecting;
use std::rc::Rc;

View File

@ -179,8 +179,9 @@ impl ServerList {
});
}));
back.add_click_func(Rc::new(move |_, _| {
println!("Connecting to {}", address);
back.add_click_func(Rc::new(move |game, _| {
game.screen_sys.replace_screen(Box::new(super::connecting::Connecting::new(&address)));
game.connect_to(&address);
}));
}

View File

@ -28,6 +28,42 @@ pub struct Server {
}
impl Server {
pub fn connect(resources: Arc<RwLock<resources::Manager>>, address: &str) -> Result<Server, protocol::Error> {
let mut conn = try!(protocol::Conn::new(address));
let host = conn.host.clone();
let port = conn.port;
try!(conn.write_packet(protocol::packet::handshake::serverbound::Handshake {
protocol_version: protocol::VarInt(protocol::SUPPORTED_PROTOCOL),
host: host,
port: port,
next: protocol::VarInt(2),
}));
conn.state = protocol::State::Login;
try!(conn.write_packet(protocol::packet::login::serverbound::LoginStart {
username: "Thinkofdeath".to_owned()
}));
let packet = match conn.read_packet().unwrap() {
protocol::packet::Packet::EncryptionRequest(val) => val,
protocol::packet::Packet::LoginDisconnect(val) => {
return Err(protocol::Error::Disconnect(val.reason));
},
val => panic!("Wrong packet: {:?}", val),
};
unimplemented!();
let version = resources.read().unwrap().version();
Ok(Server {
conn: Some(conn),
world: world::World::new(),
resources: resources,
version: version,
})
}
pub fn dummy_server(resources: Arc<RwLock<resources::Manager>>) -> Server {
let mut world = world::World::new();
let mut rng = rand::thread_rng();