Can send first message to steam
This commit is contained in:
parent
8b1ad9078a
commit
07c6320c71
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -471,6 +471,12 @@ version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "home"
|
name = "home"
|
||||||
version = "0.5.9"
|
version = "0.5.9"
|
||||||
|
@ -1612,9 +1618,11 @@ dependencies = [
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
|
"hex",
|
||||||
"keyvalues-serde",
|
"keyvalues-serde",
|
||||||
"log",
|
"log",
|
||||||
"protobuf",
|
"protobuf",
|
||||||
|
"rand",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
|
@ -8,9 +8,11 @@ async-tungstenite = { version = "0.27.0", features = ["tokio-rustls-native-certs
|
||||||
color-eyre.workspace = true
|
color-eyre.workspace = true
|
||||||
env_logger.workspace = true
|
env_logger.workspace = true
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
|
hex = "0.4.3"
|
||||||
keyvalues-serde.workspace = true
|
keyvalues-serde.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
protobuf.workspace = true
|
protobuf.workspace = true
|
||||||
|
rand = "0.8.5"
|
||||||
reqwest = { version = "0.12", features = ["rustls-tls-native-roots"], default-features = false}
|
reqwest = { version = "0.12", features = ["rustls-tls-native-roots"], default-features = false}
|
||||||
serde = { version = "1.0.209", features = ["derive"] }
|
serde = { version = "1.0.209", features = ["derive"] }
|
||||||
tokio = { version = "1.39", features = ["rt", "rt-multi-thread", "macros"]}
|
tokio = { version = "1.39", features = ["rt", "rt-multi-thread", "macros"]}
|
||||||
|
|
|
@ -41,6 +41,7 @@ pub async fn bootstrap_find_servers() -> eyre::Result<Vec<String>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A message sent over the socket. Can be either sent or recieved
|
/// A message sent over the socket. Can be either sent or recieved
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct CMProtoBufMessage<T: protobuf::Message> {
|
pub struct CMProtoBufMessage<T: protobuf::Message> {
|
||||||
pub action: enums_clientserver::EMsg,
|
pub action: enums_clientserver::EMsg,
|
||||||
pub header: steammessages_base::CMsgProtoBufHeader,
|
pub header: steammessages_base::CMsgProtoBufHeader,
|
||||||
|
@ -54,7 +55,7 @@ impl<T: protobuf::Message> CMProtoBufMessage<T> {
|
||||||
let length = 4 + 4 + self.header.compute_size() + self.body.compute_size();
|
let length = 4 + 4 + self.header.compute_size() + self.body.compute_size();
|
||||||
let mut out = Vec::with_capacity(length.try_into()?);
|
let mut out = Vec::with_capacity(length.try_into()?);
|
||||||
|
|
||||||
out.extend_from_slice(&self.action.value().to_le_bytes());
|
out.extend_from_slice(&(self.action.value() as u32 | 0x80000000).to_le_bytes());
|
||||||
out.extend_from_slice(&self.header.cached_size().to_le_bytes());
|
out.extend_from_slice(&self.header.cached_size().to_le_bytes());
|
||||||
self.header.write_to_vec(&mut out)?;
|
self.header.write_to_vec(&mut out)?;
|
||||||
self.body.write_to_vec(&mut out)?;
|
self.body.write_to_vec(&mut out)?;
|
||||||
|
@ -74,6 +75,7 @@ impl<T: protobuf::Message> CMProtoBufMessage<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A message sent over the socket, but the body is still serialized
|
/// A message sent over the socket, but the body is still serialized
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct CMRawProtoBufMessage {
|
pub struct CMRawProtoBufMessage {
|
||||||
pub action: enums_clientserver::EMsg,
|
pub action: enums_clientserver::EMsg,
|
||||||
pub header: steammessages_base::CMsgProtoBufHeader,
|
pub header: steammessages_base::CMsgProtoBufHeader,
|
||||||
|
@ -232,6 +234,33 @@ impl CMSession {
|
||||||
CMProtoBufMessage::<Response>::deserialize(response_raw)
|
CMProtoBufMessage::<Response>::deserialize(response_raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send a message without a jobid
|
||||||
|
pub async fn send_notification<T: protobuf::Message>(
|
||||||
|
&mut self,
|
||||||
|
action: enums_clientserver::EMsg,
|
||||||
|
body: T,
|
||||||
|
) -> eyre::Result<()> {
|
||||||
|
let header = steammessages_base::CMsgProtoBufHeader {
|
||||||
|
steamid: self.steam_id,
|
||||||
|
realm: Some(self.realm),
|
||||||
|
client_sessionid: Some(self.client_session_id),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let message = CMProtoBufMessage {
|
||||||
|
action,
|
||||||
|
header,
|
||||||
|
body,
|
||||||
|
};
|
||||||
|
|
||||||
|
let serialized = message.serialize()?;
|
||||||
|
|
||||||
|
self.socket
|
||||||
|
.send(tungstenite::protocol::Message::Binary(serialized))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether the current session is authenticated
|
/// Whether the current session is authenticated
|
||||||
pub fn is_authed(&self) -> bool {
|
pub fn is_authed(&self) -> bool {
|
||||||
self.steam_id.is_some()
|
self.steam_id.is_some()
|
||||||
|
|
|
@ -1,4 +1,14 @@
|
||||||
use color_eyre::eyre;
|
use color_eyre::eyre;
|
||||||
|
use rand::RngCore;
|
||||||
|
use vapore_proto::{
|
||||||
|
enums_clientserver::EMsg,
|
||||||
|
steammessages_auth_steamclient::{
|
||||||
|
CAuthentication_BeginAuthSessionViaQR_Request,
|
||||||
|
CAuthentication_BeginAuthSessionViaQR_Response, CAuthentication_DeviceDetails,
|
||||||
|
EAuthTokenPlatformType,
|
||||||
|
},
|
||||||
|
steammessages_clientserver_login::CMsgClientHello,
|
||||||
|
};
|
||||||
|
|
||||||
mod connection;
|
mod connection;
|
||||||
|
|
||||||
|
@ -12,7 +22,66 @@ pub async fn main() -> eyre::Result<()> {
|
||||||
let servers = connection::bootstrap_find_servers().await?;
|
let servers = connection::bootstrap_find_servers().await?;
|
||||||
log::debug!("Found servers: {:?}", servers);
|
log::debug!("Found servers: {:?}", servers);
|
||||||
|
|
||||||
let session = connection::CMSession::connect(&servers[0]).await?;
|
let mut session = connection::CMSession::connect(&servers[0]).await?;
|
||||||
|
|
||||||
|
session
|
||||||
|
.send_notification(
|
||||||
|
EMsg::k_EMsgClientHello,
|
||||||
|
CMsgClientHello {
|
||||||
|
protocol_version: Some(0x1002c),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
log::debug!("Sent hello");
|
||||||
|
|
||||||
|
// machine_id is supposed to be a binary key/value with the SHA1 of the machine's
|
||||||
|
// BB3: Machine GUID
|
||||||
|
// FF2: MAC address
|
||||||
|
// 3B3: Disk ID
|
||||||
|
// We should probably make these consistent so Valve doesn't get suspicious,
|
||||||
|
// but for now let's make them random
|
||||||
|
// TODO: Find a more generic way to make this
|
||||||
|
let mut machine_id = Vec::with_capacity(161);
|
||||||
|
machine_id.extend_from_slice(b"\x00MessageObject\x00");
|
||||||
|
for key in [b"BB3", b"FF2", b"3B3"] {
|
||||||
|
let mut data = [0u8; 20];
|
||||||
|
rand::thread_rng().fill_bytes(&mut data);
|
||||||
|
let hex_bytes = hex::encode(data).into_bytes();
|
||||||
|
|
||||||
|
// Type is string
|
||||||
|
machine_id.push(b'\x01');
|
||||||
|
machine_id.extend_from_slice(key);
|
||||||
|
machine_id.push(b'\x00');
|
||||||
|
machine_id.extend_from_slice(&hex_bytes);
|
||||||
|
machine_id.push(b'\x00');
|
||||||
|
}
|
||||||
|
// suitable end bytes
|
||||||
|
machine_id.extend_from_slice(b"\x08\x08");
|
||||||
|
|
||||||
|
let response = session
|
||||||
|
.call_service_method::<_, CAuthentication_BeginAuthSessionViaQR_Response>(
|
||||||
|
"Authentication.BeginAuthSessionViaQR#1".to_string(),
|
||||||
|
CAuthentication_BeginAuthSessionViaQR_Request {
|
||||||
|
device_details: protobuf::MessageField::some(CAuthentication_DeviceDetails {
|
||||||
|
device_friendly_name: Some("vapore".to_string()),
|
||||||
|
platform_type: Some(protobuf::EnumOrUnknown::new(
|
||||||
|
EAuthTokenPlatformType::k_EAuthTokenPlatformType_SteamClient,
|
||||||
|
)),
|
||||||
|
// Windows 10
|
||||||
|
os_type: Some(16),
|
||||||
|
// Unknown
|
||||||
|
gaming_device_type: Some(1),
|
||||||
|
machine_id: Some(machine_id),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
log::debug!("Got response {:#x?}", response);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue