Add client/server version checking.
This commit is contained in:
parent
bb1fce886a
commit
64d91c30ff
12
server/build.rs
Normal file
12
server/build.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
fn main()
|
||||||
|
{
|
||||||
|
let output = Command::new("git")
|
||||||
|
.args(&["rev-parse", "HEAD"])
|
||||||
|
.output()
|
||||||
|
.expect("Failed to acquire git HEAD");
|
||||||
|
let git_hash = String::from_utf8(output.stdout).expect("Invalid UTF-8 output from git HEAD");
|
||||||
|
let git_hash = git_hash.trim();
|
||||||
|
println!("cargo:rustc-env=GIT_HASH={}", git_hash);
|
||||||
|
}
|
@ -151,6 +151,12 @@ impl App {
|
|||||||
let mut socket = conn.stream.write().await;
|
let mut socket = conn.stream.write().await;
|
||||||
|
|
||||||
match response.data {
|
match response.data {
|
||||||
|
QRPacketData::RHello(response) => {
|
||||||
|
socket.send(Message::Binary(
|
||||||
|
encode_response(CODE_HELLO, response.encode())
|
||||||
|
)).await.ok();
|
||||||
|
}
|
||||||
|
|
||||||
QRPacketData::RRegister(response) => {
|
QRPacketData::RRegister(response) => {
|
||||||
socket.send(Message::Binary(
|
socket.send(Message::Binary(
|
||||||
encode_response(CODE_REGISTER, response.encode())
|
encode_response(CODE_REGISTER, response.encode())
|
||||||
|
@ -1 +1,2 @@
|
|||||||
|
pub const VERSION :&str = env!("GIT_HASH");
|
||||||
pub const REGISTER_CODE :&str = "mountain";
|
pub const REGISTER_CODE :&str = "mountain";
|
||||||
|
@ -77,6 +77,7 @@ async fn service_http(mut request:hyper::Request<hyper::body::Incoming>, args:Ht
|
|||||||
match request.uri().path() {
|
match request.uri().path() {
|
||||||
"/.js" => {
|
"/.js" => {
|
||||||
output = [
|
output = [
|
||||||
|
format!("let CONFIG_VERSION = \"{}\";", config::VERSION).as_bytes().to_vec(),
|
||||||
format!("let CONFIG_LANGUAGE = {};", language_code).as_bytes().to_vec(),
|
format!("let CONFIG_LANGUAGE = {};", language_code).as_bytes().to_vec(),
|
||||||
output,
|
output,
|
||||||
].concat();
|
].concat();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use bus::Bus;
|
use bus::Bus;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
config,
|
||||||
app::{
|
app::{
|
||||||
authentication::Authentication,
|
authentication::Authentication,
|
||||||
connection::Connection,
|
connection::Connection,
|
||||||
@ -58,10 +59,13 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
|||||||
packet.from,
|
packet.from,
|
||||||
QRPacket::new(id as u32, QRPacketData::RConn)
|
QRPacket::new(id as u32, QRPacketData::RConn)
|
||||||
).ok();
|
).ok();
|
||||||
|
|
||||||
Some(QRPacket::new(0, QRPacketData::None))
|
Some(QRPacket::new(0, QRPacketData::None))
|
||||||
}
|
}
|
||||||
|
|
||||||
QRPacketData::QDisconn => {
|
QRPacketData::QDisconn => {
|
||||||
|
println!("Disconnect: {}", qr.id);
|
||||||
|
|
||||||
// Uninitialize connection
|
// Uninitialize connection
|
||||||
if if let Some(conn) = app.connections.get(qr.id as usize).cloned() {
|
if if let Some(conn) = app.connections.get(qr.id as usize).cloned() {
|
||||||
|
|
||||||
@ -110,12 +114,17 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
|
|||||||
true
|
true
|
||||||
} else { false } {
|
} else { false } {
|
||||||
app.connections.remove(qr.id as usize).ok();
|
app.connections.remove(qr.id as usize).ok();
|
||||||
|
|
||||||
println!("Disconnect: {}", qr.id);
|
|
||||||
}
|
}
|
||||||
Some(QRPacket::new(0, QRPacketData::None))
|
Some(QRPacket::new(0, QRPacketData::None))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRPacketData::QHello => {
|
||||||
|
let response = PacketHelloResponse {
|
||||||
|
version:config::VERSION.to_string(),
|
||||||
|
};
|
||||||
|
Some(QRPacket::new(qr.id, QRPacketData::RHello(response)))
|
||||||
|
}
|
||||||
|
|
||||||
QRPacketData::QRegister(request) => {
|
QRPacketData::QRegister(request) => {
|
||||||
let mut response = PacketRegisterResponse::new();
|
let mut response = PacketRegisterResponse::new();
|
||||||
response.status = STATUS_SERVER_ERROR;
|
response.status = STATUS_SERVER_ERROR;
|
||||||
|
@ -56,6 +56,11 @@ pub async fn handle_ws(ws:WebSocketStream<TokioIo<Upgraded>>, args:HttpServiceAr
|
|||||||
println!("MESSAGE {:x}", code);
|
println!("MESSAGE {:x}", code);
|
||||||
|
|
||||||
match code {
|
match code {
|
||||||
|
CODE_HELLO => {
|
||||||
|
args.bus.send(
|
||||||
|
bus_ds, QRPacket::new(conn_id, QRPacketData::QHello)
|
||||||
|
).ok();
|
||||||
|
}
|
||||||
|
|
||||||
CODE_REGISTER => match PacketRegister::decode(&data, &mut index) {
|
CODE_REGISTER => match PacketRegister::decode(&data, &mut index) {
|
||||||
Ok(packet) => {
|
Ok(packet) => {
|
||||||
@ -207,7 +212,10 @@ pub async fn handle_ws(ws:WebSocketStream<TokioIo<Upgraded>>, args:HttpServiceAr
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => false,
|
Err(e) => {
|
||||||
|
println!("WSS error: {}", e.to_string());
|
||||||
|
false
|
||||||
|
},
|
||||||
}
|
}
|
||||||
None => false,
|
None => false,
|
||||||
} { }
|
} { }
|
||||||
|
@ -22,6 +22,8 @@ pub const STATUS_NOT_IMPL :u16 = 0x00FF;
|
|||||||
** Operation Codes
|
** Operation Codes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
pub const CODE_HELLO :u16 = 0x0001;
|
||||||
|
|
||||||
pub const CODE_REGISTER :u16 = 0x0010;
|
pub const CODE_REGISTER :u16 = 0x0010;
|
||||||
pub const CODE_AUTH :u16 = 0x0011;
|
pub const CODE_AUTH :u16 = 0x0011;
|
||||||
pub const CODE_AUTH_RESUME :u16 = 0x0012;
|
pub const CODE_AUTH_RESUME :u16 = 0x0012;
|
||||||
|
@ -12,6 +12,9 @@ pub enum QRPacketData {
|
|||||||
|
|
||||||
QDisconn,
|
QDisconn,
|
||||||
|
|
||||||
|
QHello,
|
||||||
|
RHello(PacketHelloResponse),
|
||||||
|
|
||||||
QRegister(PacketRegister),
|
QRegister(PacketRegister),
|
||||||
RRegister(PacketRegisterResponse),
|
RRegister(PacketRegisterResponse),
|
||||||
|
|
||||||
|
28
server/src/protocol/packet/hello.rs
Normal file
28
server/src/protocol/packet/hello.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use crate::util::pack::pack_u8;
|
||||||
|
|
||||||
|
use super::Packet;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct PacketHelloResponse {
|
||||||
|
pub version:String,
|
||||||
|
}
|
||||||
|
impl PacketHelloResponse {
|
||||||
|
pub fn new() -> Self
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
version:String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Packet for PacketHelloResponse {
|
||||||
|
type Data = Self;
|
||||||
|
|
||||||
|
fn encode(&self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let version_bytes = self.version.as_bytes().to_vec();
|
||||||
|
[
|
||||||
|
pack_u8(version_bytes.len() as u8),
|
||||||
|
version_bytes,
|
||||||
|
].concat()
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
mod hello; pub use hello::*;
|
||||||
mod connect; pub use connect::*;
|
mod connect; pub use connect::*;
|
||||||
|
|
||||||
mod register; pub use register::*;
|
mod register; pub use register::*;
|
||||||
|
@ -30,6 +30,8 @@ const Status = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const OpCode = {
|
const OpCode = {
|
||||||
|
Hello :0x0001,
|
||||||
|
|
||||||
Register :0x0010,
|
Register :0x0010,
|
||||||
Authenticate :0x0011,
|
Authenticate :0x0011,
|
||||||
Resume :0x0012,
|
Resume :0x0012,
|
||||||
|
@ -13,11 +13,23 @@ const SCENES = {
|
|||||||
load() {
|
load() {
|
||||||
UI.nav([
|
UI.nav([
|
||||||
UI.button(LANG("reconnect"), () => { RECONNECT(); }),
|
UI.button(LANG("reconnect"), () => { RECONNECT(); }),
|
||||||
|
UI.button(LANG("practice"), () => { LOAD(SCENES.GamePractice); }),
|
||||||
], []);
|
], []);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
reconnect() {
|
message(code, data) {
|
||||||
LOAD_URL();
|
switch(code) {
|
||||||
|
case OpCode.Hello: {
|
||||||
|
console.log("CLIENT VERSION: '" + CONFIG_VERSION + "'");
|
||||||
|
console.log("SERVER VERSION: '" + data.version + "'");
|
||||||
|
|
||||||
|
if(CONFIG_VERSION == data.version) {
|
||||||
|
RESUME();
|
||||||
|
} else {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -207,6 +219,7 @@ const SCENES = {
|
|||||||
this.pages = 1;
|
this.pages = 1;
|
||||||
}
|
}
|
||||||
load() {
|
load() {
|
||||||
|
if(SOCKET !== null) {
|
||||||
UI.mainmenu("browse");
|
UI.mainmenu("browse");
|
||||||
|
|
||||||
let indicator_page = UI.div([]);
|
let indicator_page = UI.div([]);
|
||||||
@ -237,6 +250,9 @@ const SCENES = {
|
|||||||
SCENE.refresh();
|
SCENE.refresh();
|
||||||
|
|
||||||
history.pushState(null, "Dzura", "/");
|
history.pushState(null, "Dzura", "/");
|
||||||
|
} else {
|
||||||
|
LOAD(SCENES.Offline);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
refresh() {
|
refresh() {
|
||||||
@ -1010,7 +1026,6 @@ function LOAD(scene, data=null) {
|
|||||||
UI.rebuild();
|
UI.rebuild();
|
||||||
SCENE = new scene();
|
SCENE = new scene();
|
||||||
if(!SCENE.load(data)) { LOAD(SCENES.Browse); }
|
if(!SCENE.load(data)) { LOAD(SCENES.Browse); }
|
||||||
|
|
||||||
UI.update_status();
|
UI.update_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1023,13 +1038,13 @@ function LOAD_URL() {
|
|||||||
|
|
||||||
if(parts.length > 1) {
|
if(parts.length > 1) {
|
||||||
switch(parts[1]) {
|
switch(parts[1]) {
|
||||||
case "continue": LOAD(SCENES.Continue); break;
|
case "continue": LOAD(SCENES.Continue); return;
|
||||||
case "live": LOAD(SCENES.Live); break;
|
case "live": LOAD(SCENES.Live); return;
|
||||||
case "history": LOAD(SCENES.History); break;
|
case "history": LOAD(SCENES.History); return;
|
||||||
case "practice": LOAD(SCENES.GamePractice); break;
|
case "practice": LOAD(SCENES.GamePractice); return;
|
||||||
case "guide": LOAD(SCENES.Guide); break;
|
case "guide": LOAD(SCENES.Guide); return;
|
||||||
case "about": LOAD(SCENES.About); break;
|
case "about": LOAD(SCENES.About); return;
|
||||||
case "challenge": LOAD(SCENES.Challenge); break;
|
case "challenge": LOAD(SCENES.Challenge); return;
|
||||||
|
|
||||||
case "game": {
|
case "game": {
|
||||||
if(parts[2]) {
|
if(parts[2]) {
|
||||||
@ -1038,14 +1053,10 @@ function LOAD_URL() {
|
|||||||
token:token,
|
token:token,
|
||||||
mode:INTERFACE.Mode.Review,
|
mode:INTERFACE.Mode.Review,
|
||||||
});
|
});
|
||||||
} else {
|
return;
|
||||||
LOAD(SCENES.Browse);
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: LOAD(SCENES.Browse);
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
LOAD(SCENES.Browse);
|
LOAD(SCENES.Browse);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -4,6 +4,7 @@ function RECONNECT() {
|
|||||||
SOCKET = new WebSocket("wss://" + location.hostname + ":38612");
|
SOCKET = new WebSocket("wss://" + location.hostname + ":38612");
|
||||||
SOCKET.binaryType = "arraybuffer";
|
SOCKET.binaryType = "arraybuffer";
|
||||||
SOCKET.addEventListener("error", () => {
|
SOCKET.addEventListener("error", () => {
|
||||||
|
console.log("Websocket error.");
|
||||||
SOCKET = null;
|
SOCKET = null;
|
||||||
if(SCENE.disconnect !== undefined) { SCENE.disconnect(); }
|
if(SCENE.disconnect !== undefined) { SCENE.disconnect(); }
|
||||||
});
|
});
|
||||||
@ -20,11 +21,11 @@ function RECONNECT() {
|
|||||||
RECONNECT();
|
RECONNECT();
|
||||||
});
|
});
|
||||||
|
|
||||||
RESUME();
|
MESSAGE_COMPOSE([
|
||||||
|
PACK.u16(OpCode.Hello),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
RESUME();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ function RESUME() {
|
|||||||
secret,
|
secret,
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
if(SCENE.reconnect !== undefined) { SCENE.reconnect(); }
|
LOAD_URL();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +57,18 @@ function MESSAGE(event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch(code) {
|
switch(code) {
|
||||||
|
case OpCode.Hello: {
|
||||||
|
console.log("RECV Hello");
|
||||||
|
|
||||||
|
data = {
|
||||||
|
version:"",
|
||||||
|
};
|
||||||
|
|
||||||
|
result = UNPACK.string(bytes, index, UNPACK.u8);
|
||||||
|
index = result.index;
|
||||||
|
data.version = result.data;
|
||||||
|
} break;
|
||||||
|
|
||||||
case OpCode.Register: {
|
case OpCode.Register: {
|
||||||
console.log("RECV Register");
|
console.log("RECV Register");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user