feat(protocol): per-platform TS3 client_version selection
ConnectOptions previously took tsclientlib's default Version. Servers that strictly check the announced client signature could refuse or downgrade those sessions. Add pick_client_version() that selects a stable signed descriptor matching the runtime OS: Windows -> Version::Windows_5_0_0_beta51 Linux -> Version::Linux_5_0_0_beta51 macOS -> Version::macOS_5_0_0_beta51 Android -> Version::Android_3_5_0__7 iOS -> Version::iOS_3_5_6 other -> Linux fallback All five variants are guaranteed to exist in the vendored tsproto-types enum at compile time; build fails loudly if upstream removes one. Wired into Connection::build(...).version(pick_client_version()) on every connect. Emits 'selected TS3 client_version' info log line so the choice is visible in chanora.log.
This commit is contained in:
@@ -28,13 +28,68 @@ use tsclientlib::data::{self, Channel, Client};
|
|||||||
use tsclientlib::prelude::*;
|
use tsclientlib::prelude::*;
|
||||||
use tsclientlib::{
|
use tsclientlib::{
|
||||||
ChannelId as TsChannelId, Connection, DisconnectOptions, Identity, MessageHandle,
|
ChannelId as TsChannelId, Connection, DisconnectOptions, Identity, MessageHandle,
|
||||||
OutCommandExt, StreamItem,
|
OutCommandExt, StreamItem, Version,
|
||||||
};
|
};
|
||||||
use tsproto_packets::packets::{InAudioBuf, OutPacket};
|
use tsproto_packets::packets::{InAudioBuf, OutPacket};
|
||||||
|
|
||||||
use crate::dto::{ChannelId, ChannelInfo, ClientId, ClientInfo, ServerSnapshot};
|
use crate::dto::{ChannelId, ChannelInfo, ClientId, ClientInfo, ServerSnapshot};
|
||||||
use crate::ProtocolError;
|
use crate::ProtocolError;
|
||||||
|
|
||||||
|
/// Pick the TeamSpeak `client_version`/platform/signature triple
|
||||||
|
/// (sourced from `ReSpeak/tsdeclarations/Versions.csv`, baked into
|
||||||
|
/// `tsproto-types` at vendor-time) that best matches the *runtime*
|
||||||
|
/// platform Chanora is executing on.
|
||||||
|
///
|
||||||
|
/// Per-platform selection (set by the project owner):
|
||||||
|
///
|
||||||
|
/// * Windows / Linux / macOS desktops announce as TeamSpeak **5
|
||||||
|
/// beta51** — the latest TS5 desktop signature in the vendored
|
||||||
|
/// `tsproto-types` enum. TS5 servers expect this shape; TS3
|
||||||
|
/// servers are happy to accept any well-formed signed client
|
||||||
|
/// descriptor and have no codec-version coupling.
|
||||||
|
/// * Android announces as **3.5.0__7** (the latest Android
|
||||||
|
/// signature in the vendored enum).
|
||||||
|
/// * iOS announces as **3.5.6** (latest iOS signature in the
|
||||||
|
/// vendored enum).
|
||||||
|
///
|
||||||
|
/// All five variants are guaranteed to exist in the generated
|
||||||
|
/// `Version` enum at compile time; if upstream rotates the CSV the
|
||||||
|
/// build will fail loudly here rather than silently fall back.
|
||||||
|
fn pick_client_version() -> Version {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
Version::Windows_5_0_0_beta51
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
{
|
||||||
|
Version::macOS_5_0_0_beta51
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
|
{
|
||||||
|
Version::iOS_3_5_6
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
{
|
||||||
|
Version::Android_3_5_0__7
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
Version::Linux_5_0_0_beta51
|
||||||
|
}
|
||||||
|
#[cfg(not(any(
|
||||||
|
target_os = "windows",
|
||||||
|
target_os = "macos",
|
||||||
|
target_os = "ios",
|
||||||
|
target_os = "android",
|
||||||
|
target_os = "linux"
|
||||||
|
)))]
|
||||||
|
{
|
||||||
|
// Last-ditch fallback for unanticipated targets (BSDs,
|
||||||
|
// Solaris-likes). Linux signature is the closest analogue.
|
||||||
|
Version::Linux_5_0_0_beta51
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Typed configuration for a connection attempt.
|
/// Typed configuration for a connection attempt.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ConnectConfig {
|
pub struct ConnectConfig {
|
||||||
@@ -331,7 +386,15 @@ async fn connection_task(
|
|||||||
// Pass the resolved SocketAddr directly to tsclientlib so it
|
// Pass the resolved SocketAddr directly to tsclientlib so it
|
||||||
// skips its own resolver entirely (tsclientlib accepts
|
// skips its own resolver entirely (tsclientlib accepts
|
||||||
// SocketAddr via the From<SocketAddr> for ServerAddress impl).
|
// SocketAddr via the From<SocketAddr> for ServerAddress impl).
|
||||||
let mut builder = Connection::build(resolved).name(cfg.nickname.clone());
|
let client_version = pick_client_version();
|
||||||
|
info!(
|
||||||
|
target: "chanora_protocol",
|
||||||
|
client_version = %client_version,
|
||||||
|
"selected TS3 client_version for this platform"
|
||||||
|
);
|
||||||
|
let mut builder = Connection::build(resolved)
|
||||||
|
.name(cfg.nickname.clone())
|
||||||
|
.version(client_version);
|
||||||
|
|
||||||
let identity = match cfg.identity.as_deref() {
|
let identity = match cfg.identity.as_deref() {
|
||||||
Some(s) => match Identity::new_from_str(s) {
|
Some(s) => match Identity::new_from_str(s) {
|
||||||
|
|||||||
Reference in New Issue
Block a user