Fully implement the login screen (Closes #6)
This commit is contained in:
parent
3d6f5ba904
commit
0d42d59ed9
|
@ -16,6 +16,7 @@
|
|||
|
||||
use openssl;
|
||||
use serde_json;
|
||||
use hyper;
|
||||
|
||||
pub mod mojang;
|
||||
|
||||
|
@ -633,6 +634,8 @@ pub enum Error {
|
|||
Err(String),
|
||||
Disconnect(format::Component),
|
||||
IOError(io::Error),
|
||||
Json(serde_json::Error),
|
||||
Hyper(hyper::Error),
|
||||
}
|
||||
|
||||
impl convert::From<io::Error> for Error {
|
||||
|
@ -641,12 +644,26 @@ impl convert::From<io::Error> for Error {
|
|||
}
|
||||
}
|
||||
|
||||
impl convert::From<serde_json::Error> for Error {
|
||||
fn from(e: serde_json::Error) -> Error {
|
||||
Error::Json(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl convert::From<hyper::Error> for Error {
|
||||
fn from(e: hyper::Error) -> Error {
|
||||
Error::Hyper(e)
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
Error::Json(ref e) => e.description(),
|
||||
Error::Hyper(ref e) => e.description(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -657,6 +674,8 @@ impl ::std::fmt::Display for Error {
|
|||
Error::Err(ref val) => write!(f, "protocol error: {}", val),
|
||||
Error::Disconnect(ref val) => write!(f, "{}", val),
|
||||
Error::IOError(ref e) => e.fmt(f),
|
||||
Error::Json(ref e) => e.fmt(f),
|
||||
Error::Hyper(ref e) => e.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,10 @@
|
|||
|
||||
use openssl;
|
||||
use serde_json;
|
||||
use serde_json::builder::ObjectBuilder;
|
||||
use hyper;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Profile {
|
||||
pub username: String,
|
||||
pub id: String,
|
||||
|
@ -23,9 +25,85 @@ pub struct Profile {
|
|||
}
|
||||
|
||||
const JOIN_URL: &'static str = "https://sessionserver.mojang.com/session/minecraft/join";
|
||||
const LOGIN_URL: &'static str = "https://authserver.mojang.com/authenticate";
|
||||
const REFRESH_URL: &'static str = "https://authserver.mojang.com/refresh";
|
||||
const VALIDATE_URL: &'static str = "https://authserver.mojang.com/validate";
|
||||
|
||||
impl Profile {
|
||||
pub fn join_server(&self, server_id: &String, shared_key: &Vec<u8>, public_key: &Vec<u8>) {
|
||||
pub fn login(username: &str, password: &str, token: &str) -> Result<Profile, super::Error> {
|
||||
let req_msg = ObjectBuilder::new()
|
||||
.insert("username", username)
|
||||
.insert("password", password)
|
||||
.insert("clientToken", token)
|
||||
.insert_object("agent", |b| b
|
||||
.insert("name", "Minecraft")
|
||||
.insert("version", 1)
|
||||
)
|
||||
.unwrap();
|
||||
let req = try!(serde_json::to_string(&req_msg));
|
||||
|
||||
let client = hyper::Client::new();
|
||||
let res = try!(client.post(LOGIN_URL)
|
||||
.body(&req)
|
||||
.header(hyper::header::ContentType("application/json".parse().unwrap()))
|
||||
.send());
|
||||
|
||||
let ret: serde_json::Value = try!(serde_json::from_reader(res));
|
||||
if let Some(error) = ret.find("error").and_then(|v| v.as_string()) {
|
||||
return Err(super::Error::Err(format!(
|
||||
"{}: {}",
|
||||
error,
|
||||
ret.find("errorMessage").and_then(|v| v.as_string()).unwrap())
|
||||
));
|
||||
}
|
||||
Ok(Profile {
|
||||
username: ret.lookup("selectedProfile.name").and_then(|v| v.as_string()).unwrap().to_owned(),
|
||||
id: ret.lookup("selectedProfile.id").and_then(|v| v.as_string()).unwrap().to_owned(),
|
||||
access_token: ret.find("accessToken").and_then(|v| v.as_string()).unwrap().to_owned(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn refresh(self, token: &str) -> Result<Profile, super::Error> {
|
||||
let req_msg = ObjectBuilder::new()
|
||||
.insert("accessToken", self.access_token.clone())
|
||||
.insert("clientToken", token)
|
||||
.unwrap();
|
||||
let req = try!(serde_json::to_string(&req_msg));
|
||||
|
||||
let client = hyper::Client::new();
|
||||
let res = try!(client.post(VALIDATE_URL)
|
||||
.body(&req)
|
||||
.header(hyper::header::ContentType("application/json".parse().unwrap()))
|
||||
.send());
|
||||
|
||||
if res.status != hyper::status::StatusCode::NoContent {
|
||||
println!("Rerefeshing");
|
||||
// Refresh needed
|
||||
let res = try!(client.post(REFRESH_URL)
|
||||
.body(&req)
|
||||
.header(hyper::header::ContentType("application/json".parse().unwrap()))
|
||||
.send());
|
||||
|
||||
let ret: serde_json::Value = try!(serde_json::from_reader(res));
|
||||
if let Some(error) = ret.find("error").and_then(|v| v.as_string()) {
|
||||
return Err(super::Error::Err(format!(
|
||||
"{}: {}",
|
||||
error,
|
||||
ret.find("errorMessage").and_then(|v| v.as_string()).unwrap())
|
||||
));
|
||||
}
|
||||
return Ok(Profile {
|
||||
username: ret.lookup("selectedProfile.name").and_then(|v| v.as_string()).unwrap().to_owned(),
|
||||
id: ret.lookup("selectedProfile.id").and_then(|v| v.as_string()).unwrap().to_owned(),
|
||||
access_token: ret.find("accessToken").and_then(|v| v.as_string()).unwrap().to_owned(),
|
||||
});
|
||||
}
|
||||
println!("Reuse");
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
// TODO
|
||||
pub fn join_server(&self, server_id: &str, shared_key: &Vec<u8>, public_key: &Vec<u8>) {
|
||||
let mut sha1 = openssl::SHA1::new();
|
||||
sha1.update(server_id.as_bytes());
|
||||
sha1.update(&shared_key[..]);
|
||||
|
@ -46,7 +124,7 @@ impl Profile {
|
|||
hash_val.to_owned()
|
||||
};
|
||||
|
||||
let join_msg = serde_json::builder::ObjectBuilder::new()
|
||||
let join_msg = ObjectBuilder::new()
|
||||
.insert("accessToken", &self.access_token)
|
||||
.insert("selectedProfile", &self.id)
|
||||
.insert("serverId", hash_str)
|
||||
|
@ -66,6 +144,10 @@ impl Profile {
|
|||
};
|
||||
panic!("{:?}", ret);
|
||||
}
|
||||
|
||||
pub fn is_complete(&self) -> bool {
|
||||
!self.username.is_empty() && !self.id.is_empty() && !self.access_token.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
fn twos_compliment(data: &mut Vec<u8>) {
|
||||
|
|
Loading…
Reference in New Issue