Fixed to use correct netcomm protobuf

master
noah metz 2024-01-20 21:26:16 -07:00
parent 8efdc7b5ab
commit b25fa4e36d
3 changed files with 79 additions and 13 deletions

@ -1,5 +1,5 @@
extern crate prost_build; extern crate prost_build;
fn main() { fn main() {
prost_build::compile_protos(&["proto/notice.proto"], &["proto/"]).unwrap(); prost_build::compile_protos(&["proto/netcomm.proto"], &["proto/"]).unwrap();
} }

@ -5,7 +5,7 @@ package tm;
import "division.proto"; import "division.proto";
message Announcement { message Announcement {
optional string msg = 1; optional string msg = 1;
optional .Division.DivisionId divId = 2 [default = ALL]; optional tm.Division.DivisionId divId = 2 [default = ALL];
optional uint32 endTime = 3 [default = 0]; optional uint32 endTime = 3 [default = 0];
optional uint32 group = 4 [default = 0]; optional uint32 group = 4 [default = 0];
} }

@ -30,10 +30,6 @@ pub mod tm {
include!(concat!(env!("OUT_DIR"), "/tm.rs")); include!(concat!(env!("OUT_DIR"), "/tm.rs"));
} }
pub fn deserialize_notice(buf: &[u8]) -> Result<tm::Notice, prost::DecodeError> {
tm::Notice::decode(&mut Cursor::new(buf))
}
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
struct DivisionInfo { struct DivisionInfo {
arena: String, arena: String,
@ -261,7 +257,7 @@ struct ConnectMsg {
} }
impl ConnectMsg { impl ConnectMsg {
fn from_welcome(welcome: ConnectMsg, password: &str, uuid: [u8; 16], client_name: [u8; 32]) -> ConnectMsg { fn from_welcome(welcome: ConnectMsg, password: &str, uuid: [u8; 16], client_name: [u8; 32], username: [u8; 16]) -> ConnectMsg {
let mut hasher = Sha256::new(); let mut hasher = Sha256::new();
hasher.update(welcome.pass_hash); hasher.update(welcome.pass_hash);
hasher.update(password); hasher.update(password);
@ -270,8 +266,15 @@ impl ConnectMsg {
return ConnectMsg{ return ConnectMsg{
version: welcome.version, version: welcome.version,
uuid, uuid,
last_notice_id: welcome.last_notice_id, // The TM returns state_valid=0 if last_notice_id < pendingNotices[0].id
username: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // It looks like this check is basically to say "you can't connect if I sent you
// notices you weren't aware of" since in effect it prevents a client from connecting
// if it sends a last_notice_id less than what the TM expects
// To get around it you can just send the (max_u64 - 1) so that the check of
// (last_notice_id + 1) < pendingNotices[0].id always fails.
// The downside is that the TM will not send you any queued notices.
last_notice_id: 0xFFFFFFFFFFFFFFFF - 1,
username,
pass_hash: result.try_into().unwrap(), pass_hash: result.try_into().unwrap(),
pw_valid: welcome.pw_valid, pw_valid: welcome.pw_valid,
state_valid: welcome.state_valid, state_valid: welcome.state_valid,
@ -315,6 +318,33 @@ impl ConnectMsg {
} }
} }
const NOTICE_MSG_LEN: usize = 8;
#[derive(Debug)]
struct NoticeMsg {
notice_id: u64,
notice: tm::Notice,
}
impl NoticeMsg {
fn from_bytes(bytes: Vec<u8>) -> Option<NoticeMsg> {
if bytes.len() < NOTICE_MSG_LEN {
return None;
}
// TODO: figure out what protobuf is containing the notice so that I don't add a static
// offset
let mut pb_data = Cursor::new(bytes[8..].to_vec());
match tm::Notice::decode(&mut pb_data) {
Ok(notice) => Some(NoticeMsg{
notice_id: u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
notice,
}
),
Err(_) => None,
}
}
}
struct TMClient { struct TMClient {
stream: Arc<Mutex<openssl::ssl::SslStream<TcpStream>>>, stream: Arc<Mutex<openssl::ssl::SslStream<TcpStream>>>,
notices: mpsc::Sender<tm::Notice>, notices: mpsc::Sender<tm::Notice>,
@ -323,6 +353,7 @@ struct TMClient {
client_name: [u8; 32], client_name: [u8; 32],
password: String, password: String,
last_seq_num: u64, last_seq_num: u64,
username: [u8; 16],
} }
struct TMConnection { struct TMConnection {
@ -332,7 +363,7 @@ struct TMConnection {
} }
impl TMClient { impl TMClient {
fn new(uuid: [u8; 16], client_name: [u8; 32], password: String) -> (TMClient, TMConnection) { fn new(uuid: [u8; 16], client_name: [u8; 32], password: String, username: [u8; 16]) -> (TMClient, TMConnection) {
let (notice_tx, notice_rx) = mpsc::channel(); let (notice_tx, notice_rx) = mpsc::channel();
let (response_tx, response_rx) = mpsc::channel(); let (response_tx, response_rx) = mpsc::channel();
@ -361,6 +392,7 @@ impl TMClient {
client_name, client_name,
password, password,
last_seq_num: 0xFFFFFFFFFFFFFFFF, last_seq_num: 0xFFFFFFFFFFFFFFFF,
username,
}, },
TMConnection{ TMConnection{
stream: stream_arc, stream: stream_arc,
@ -380,13 +412,34 @@ impl TMClient {
Some(packet) => { Some(packet) => {
self.last_seq_num = packet.seq_num; self.last_seq_num = packet.seq_num;
match packet.msg_type { match packet.msg_type {
// Notice Message
4 => {
match NoticeMsg::from_bytes(packet.data.clone()) {
Some(notice) => {
println!("Received notice: {:?}", notice);
let ack = BackendPacket::new(packet.header, packet.timestamp, 5, self.last_seq_num+1, notice.notice_id.to_le_bytes().to_vec());
self.last_seq_num += 1;
match stream.write(&ack.as_bytes()) {
Ok(_) => println!("Sent ACK for notice {}", notice.notice_id),
Err(error) => println!("ACK error: {:?}", error),
}
},
None => println!("Notice error: {:?}", packet),
}
},
// Response message
3 => {
println!("Received response. TODO: handle these");
},
// Server Message
2 => { 2 => {
match ConnectMsg::from_bytes(packet.data) { match ConnectMsg::from_bytes(packet.data) {
Some(welcome_msg) => { Some(welcome_msg) => {
println!("Welcome msg: {:?}", welcome_msg); println!("Welcome msg: {:?}", welcome_msg);
if welcome_msg.pw_valid == 0 { if welcome_msg.pw_valid == 0 {
let connect_response = ConnectMsg::from_welcome(welcome_msg, &self.password, self.uuid, self.client_name); let connect_response = ConnectMsg::from_welcome(welcome_msg, &self.password, self.uuid, self.client_name, self.username);
let response = BackendPacket::new(packet.header, packet.timestamp, packet.msg_type, self.last_seq_num+1, connect_response.as_bytes()); let response = BackendPacket::new(packet.header, packet.timestamp, packet.msg_type, self.last_seq_num+1, connect_response.as_bytes());
println!("Sending {:X?}", connect_response);
match stream.write(&response.as_bytes()) { match stream.write(&response.as_bytes()) {
Err(error) => println!("Send error: {:?}", error), Err(error) => println!("Send error: {:?}", error),
Ok(sent) => { Ok(sent) => {
@ -394,6 +447,8 @@ impl TMClient {
self.last_seq_num += 1; self.last_seq_num += 1;
}, },
} }
} else if welcome_msg.state_valid == 0 {
println!("pw_valid but not state_valid");
} else { } else {
println!("Connected to TM backend!"); println!("Connected to TM backend!");
} }
@ -405,7 +460,8 @@ impl TMClient {
} }
}, },
None => { None => {
panic!("Failed to parse BackendPacket({}): {}", read, String::from_utf8_lossy(&incoming)); println!("Failed to parse BackendPacket({}): {}", read, String::from_utf8_lossy(&incoming));
thread::sleep(Duration::from_millis(100));
} }
} }
}, },
@ -530,6 +586,15 @@ fn on_match_list_update(notice: tm::Notice, event: Event) -> (Vec<MQTTMessage>,
fn main() { fn main() {
env_logger::init(); env_logger::init();
let mut test = tm::Notice::default();
test.set_id(tm::NoticeId::NoticeRankingsUpdated);
test.set_affected_round(tm::MatchRound::Qual);
let mut div = tm::Division::default();
div.id = Some(1);
test.division = Some(div);
println!("ENCODED_PROTOBUF: {:X?}", test.encode_to_vec());
let mut event = Event{ let mut event = Event{
name: String::from(""), name: String::from(""),
divisions: Vec::new(), divisions: Vec::new(),
@ -569,7 +634,8 @@ fn main() {
let running = true; let running = true;
let uuid = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let uuid = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
let client_name: [u8;32] = [b'r', b'u', b's', b't', b'-', b'b', b'r', b'i', b'd', b'g', b'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let client_name: [u8;32] = [b'r', b'u', b's', b't', b'-', b'b', b'r', b'i', b'd', b'g', b'e', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let (mut tm_client, tm_connection) = TMClient::new(uuid, client_name, String::from("")); let username: [u8;16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let (mut tm_client, tm_connection) = TMClient::new(uuid, client_name, String::from(""), username);
let tm_thread = thread::spawn(move || let tm_thread = thread::spawn(move ||
while running { while running {
tm_client.process(); tm_client.process();