From b25ea51a15d826a1a50f004e09c071c57c9fd9be Mon Sep 17 00:00:00 2001 From: Dominik Nakamura Date: Thu, 11 Mar 2021 20:59:32 +0900 Subject: [PATCH] Check OBS and plugin version after connecting --- src/client/mod.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++-- src/lib.rs | 11 +++++++++- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 3e1e9af..b640cd5 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -18,6 +18,7 @@ use futures_util::{ stream::{SplitSink, StreamExt}, }; use log::{debug, error, trace}; +use semver::VersionReq; use serde::de::DeserializeOwned; #[cfg(feature = "events")] use tokio::sync::broadcast; @@ -118,6 +119,9 @@ where pub broadcast_capacity: Option, } +const OBS_STUDIO_VERSION: &str = "^26.1.2"; +const OBS_WEBSOCKET_VERSION: &str = "~4.9.0"; + impl ConnectConfig where H: AsRef, @@ -227,14 +231,42 @@ impl Client { let write = Mutex::new(write); let id_counter = AtomicU64::new(1); - Ok(Self { + let client = Self { write, id_counter, receivers, #[cfg(feature = "events")] event_sender: Arc::downgrade(&event_sender), handle: Some(handle), - }) + }; + + client.verify_versions().await?; + + Ok(client) + } + + async fn verify_versions(&self) -> Result<()> { + let version = self.general().get_version().await?; + // These are guaranteed to succeed and covered by tests. Therefore, it's safe to unwrap. + // Unfortunately there is (currently) no "safe" way to create version req. + let obs_studio = VersionReq::parse(OBS_STUDIO_VERSION).unwrap(); + let obs_websocket = VersionReq::parse(OBS_WEBSOCKET_VERSION).unwrap(); + + if !obs_studio.matches(&version.obs_studio_version) { + return Err(Error::ObsStudioVersion( + version.obs_studio_version, + obs_studio, + )); + } + + if !obs_websocket.matches(&version.obs_websocket_version) { + return Err(Error::ObsWebsocketVersion( + version.obs_websocket_version, + obs_websocket, + )); + } + + Ok(()) } async fn send_message(&self, req: RequestType<'_>) -> Result @@ -442,3 +474,23 @@ impl Drop for Client { drop(self.disconnect()); } } + +#[cfg(test)] +mod tests { + use semver::Version; + + use super::*; + + #[test] + fn verify_version_req() { + let obs_studio = VersionReq::parse(OBS_STUDIO_VERSION).unwrap(); + assert!(obs_studio.matches(&Version::parse("26.1.100").unwrap())); + assert!(obs_studio.matches(&Version::parse("26.100.100").unwrap())); + assert!(!obs_studio.matches(&Version::parse("27.0.0").unwrap())); + + let obs_websocket = VersionReq::parse(OBS_WEBSOCKET_VERSION).unwrap(); + assert!(obs_websocket.matches(&Version::parse("4.9.100").unwrap())); + assert!(!obs_websocket.matches(&Version::parse("4.100.100").unwrap())); + assert!(!obs_websocket.matches(&Version::parse("5.0.0").unwrap())); + } +} diff --git a/src/lib.rs b/src/lib.rs index 82e53e0..d2b2757 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,9 @@ #![warn(missing_docs, rust_2018_idioms, clippy::all)] -pub use client::Client; +pub use semver::{Version, VersionReq}; + +pub use self::client::Client; pub mod client; pub mod common; @@ -80,4 +82,11 @@ pub enum Error { /// event stream). #[error("currently not connected to obs-websocket")] Disconnected, + /// The OBS studio version of the connected instance doesn't match the required version for this + /// crate. + #[error("obs studio version {0} doesn't match required {1}")] + ObsStudioVersion(Version, VersionReq), + /// The obs-websocket plugin version doesn't match the required version for this crate. + #[error("obs-websocket version {0} doesn't match required {1}")] + ObsWebsocketVersion(Version, VersionReq), }