vapored functions should be library
This commit is contained in:
parent
b714115f5f
commit
1b50452647
36
Cargo.lock
generated
36
Cargo.lock
generated
|
@ -1854,24 +1854,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "vapore-client"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ctor",
|
||||
"env_logger",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vapore-proto"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"protobuf",
|
||||
"protobuf-codegen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vapored"
|
||||
name = "vapore"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-tungstenite",
|
||||
|
@ -1894,6 +1877,23 @@ dependencies = [
|
|||
"vapore-proto",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vapore-client"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ctor",
|
||||
"env_logger",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vapore-proto"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"protobuf",
|
||||
"protobuf-codegen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
resolver = "2"
|
||||
members = [
|
||||
"client",
|
||||
"daemon",
|
||||
"lib",
|
||||
"proto",
|
||||
]
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
protobuf
|
||||
];
|
||||
RUST_SRC_PATH = "${rustPackages.rustPlatform.rustLibSrc}";
|
||||
RUST_LOG = "debug,vapored=trace,vapore-client=trace";
|
||||
RUST_LOG = "debug,vapore=trace,vapore-client=trace";
|
||||
RUST_BACKTRACE = "1";
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "vapored"
|
||||
name = "vapore"
|
||||
edition = "2021"
|
||||
version.workspace = true
|
||||
|
||||
|
@ -8,7 +8,6 @@ async-tungstenite = { version = "0.27.0", features = ["tokio-rustls-native-certs
|
|||
base64 = "0.22.1"
|
||||
color-eyre.workspace = true
|
||||
dialoguer = "0.11.0"
|
||||
env_logger.workspace = true
|
||||
flate2 = "1.0.33"
|
||||
futures = "0.3.30"
|
||||
hex = "0.4.3"
|
||||
|
@ -22,3 +21,6 @@ rsa = "0.9.6"
|
|||
serde = { version = "1.0.209", features = ["derive"] }
|
||||
tokio = { version = "1.39", features = ["rt", "rt-multi-thread", "macros", "time"]}
|
||||
vapore-proto.path = "../proto"
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger.workspace = true
|
191
lib/examples/login_qr.rs
Normal file
191
lib/examples/login_qr.rs
Normal file
|
@ -0,0 +1,191 @@
|
|||
use color_eyre::eyre;
|
||||
use rand::RngCore;
|
||||
use vapore::message::CMProtoBufMessage;
|
||||
use vapore_proto::{
|
||||
enums_clientserver::EMsg,
|
||||
steammessages_auth_steamclient::{
|
||||
CAuthentication_BeginAuthSessionViaQR_Request,
|
||||
CAuthentication_BeginAuthSessionViaQR_Response, CAuthentication_DeviceDetails,
|
||||
CAuthentication_PollAuthSessionStatus_Request,
|
||||
CAuthentication_PollAuthSessionStatus_Response, EAuthTokenPlatformType,
|
||||
},
|
||||
steammessages_base::{cmsg_ipaddress, CMsgIPAddress},
|
||||
steammessages_clientserver::CMsgClientLicenseList,
|
||||
steammessages_clientserver_login::{CMsgClientHello, CMsgClientLogon, CMsgClientLogonResponse},
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() -> eyre::Result<()> {
|
||||
env_logger::init();
|
||||
color_eyre::install()?;
|
||||
|
||||
log::info!("Starting vapored");
|
||||
|
||||
let servers = vapore::connection::bootstrap_find_servers().await?;
|
||||
log::debug!("Found servers: {:?}", servers);
|
||||
|
||||
let session = vapore::connection::CMSession::connect(&servers[0]).await?;
|
||||
|
||||
session.send_notification(
|
||||
EMsg::k_EMsgClientHello,
|
||||
CMsgClientHello {
|
||||
protocol_version: Some(0x1002c),
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
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(155);
|
||||
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 11
|
||||
os_type: Some(20),
|
||||
machine_id: Some(machine_id.clone()),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
log::debug!("Got response {:#x?}", response);
|
||||
|
||||
let code = qrcode::QrCode::new(response.body.challenge_url()).unwrap();
|
||||
log::info!(
|
||||
"Got new QR code:\n{}",
|
||||
code.render::<qrcode::render::unicode::Dense1x2>().build()
|
||||
);
|
||||
|
||||
let mut interval = tokio::time::interval(tokio::time::Duration::from_secs_f32(
|
||||
response.body.interval(),
|
||||
));
|
||||
|
||||
let (refresh_token, account_name) = loop {
|
||||
interval.tick().await;
|
||||
let request = CAuthentication_PollAuthSessionStatus_Request {
|
||||
client_id: response.body.client_id,
|
||||
request_id: response.body.request_id.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let response: CMProtoBufMessage<CAuthentication_PollAuthSessionStatus_Response> = session
|
||||
.call_service_method(
|
||||
"Authentication.PollAuthSessionStatus#1".to_string(),
|
||||
request,
|
||||
)
|
||||
.await?;
|
||||
|
||||
log::debug!("Got auth poll status {:#?}", response.body);
|
||||
|
||||
if let Some(access_token) = response.body.refresh_token {
|
||||
let account_name = response.body.account_name.unwrap_or_default();
|
||||
break (access_token, account_name);
|
||||
}
|
||||
|
||||
if let Some(new_url) = response.body.new_challenge_url {
|
||||
let code = qrcode::QrCode::new(new_url)?;
|
||||
log::info!(
|
||||
"Got new QR code:\n{}",
|
||||
code.render::<qrcode::render::unicode::Dense1x2>().build()
|
||||
)
|
||||
};
|
||||
};
|
||||
|
||||
log::debug!(
|
||||
"Got account name {}, access token {}",
|
||||
account_name,
|
||||
refresh_token
|
||||
);
|
||||
|
||||
// normal user, desktop instance, public universe
|
||||
session.set_steam_id(0x0110_0001_0000_0000);
|
||||
|
||||
session.send_notification(
|
||||
EMsg::k_EMsgClientLogon,
|
||||
CMsgClientLogon {
|
||||
account_name: Some(account_name),
|
||||
access_token: Some(refresh_token),
|
||||
machine_name: Some("vapore".to_string()),
|
||||
machine_id: Some(machine_id),
|
||||
client_language: Some("english".to_string()),
|
||||
protocol_version: Some(0x1002c),
|
||||
client_os_type: Some(20),
|
||||
client_package_version: Some(1771),
|
||||
supports_rate_limit_response: Some(true),
|
||||
should_remember_password: Some(true),
|
||||
obfuscated_private_ip: protobuf::MessageField::some(CMsgIPAddress {
|
||||
ip: Some(cmsg_ipaddress::Ip::V4(0xc0a8_0102 ^ 0xbaad_f00d)),
|
||||
..Default::default()
|
||||
}),
|
||||
deprecated_obfustucated_private_ip: Some(0xc0a8_0102 ^ 0xbaad_f00d),
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
let session_cloned = session.clone();
|
||||
tokio::spawn(async move {
|
||||
let license_list_raw = session_cloned
|
||||
.subscribe_message_type(EMsg::k_EMsgClientLicenseList)
|
||||
.recv()
|
||||
.await
|
||||
.unwrap();
|
||||
let license_list: CMProtoBufMessage<CMsgClientLicenseList> =
|
||||
CMProtoBufMessage::deserialize(license_list_raw).unwrap();
|
||||
for license in &license_list.body.licenses {
|
||||
log::info!("Own package ID: {}", license.package_id());
|
||||
}
|
||||
});
|
||||
|
||||
let mut finish_receiver = session.subscribe_message_type(EMsg::k_EMsgClientLogOnResponse);
|
||||
|
||||
let raw_response = finish_receiver.recv().await?;
|
||||
let response: CMProtoBufMessage<CMsgClientLogonResponse> =
|
||||
CMProtoBufMessage::deserialize(raw_response)?;
|
||||
|
||||
log::debug!("Got logon response: {:#x?}", response);
|
||||
|
||||
if response.body.eresult != Some(0x01) {
|
||||
eyre::bail!("Login failed");
|
||||
};
|
||||
|
||||
session.set_steam_id(response.header.steamid());
|
||||
session.set_client_session_id(response.header.client_sessionid());
|
||||
|
||||
if let Some(heartbeat_seconds) = response.body.heartbeat_seconds {
|
||||
if heartbeat_seconds >= 5 {
|
||||
session.begin_heartbeat(heartbeat_seconds as u32);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
use base64::Engine;
|
||||
use color_eyre::eyre::{self, Context, OptionExt};
|
||||
use connection::CMSession;
|
||||
use message::CMProtoBufMessage;
|
||||
use rand::RngCore;
|
||||
use vapore::connection::CMSession;
|
||||
use vapore::message::CMProtoBufMessage;
|
||||
use vapore_proto::{
|
||||
enums::ESessionPersistence,
|
||||
enums_clientserver::EMsg,
|
||||
|
@ -22,9 +22,6 @@ use vapore_proto::{
|
|||
steammessages_clientserver_login::{CMsgClientHello, CMsgClientLogon, CMsgClientLogonResponse},
|
||||
};
|
||||
|
||||
mod connection;
|
||||
mod message;
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() -> eyre::Result<()> {
|
||||
env_logger::init();
|
||||
|
@ -32,10 +29,10 @@ pub async fn main() -> eyre::Result<()> {
|
|||
|
||||
log::info!("Starting vapored");
|
||||
|
||||
let servers = connection::bootstrap_find_servers().await?;
|
||||
let servers = vapore::connection::bootstrap_find_servers().await?;
|
||||
log::debug!("Found servers: {:?}", servers);
|
||||
|
||||
let session = connection::CMSession::connect(&servers[0]).await?;
|
||||
let session = CMSession::connect(&servers[0]).await?;
|
||||
|
||||
session.send_notification(
|
||||
EMsg::k_EMsgClientHello,
|
2
lib/src/lib.rs
Normal file
2
lib/src/lib.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod connection;
|
||||
pub mod message;
|
Loading…
Reference in a new issue