backend: handle app already running logic + refactor response
This commit is contained in:
Generated
+1
@@ -671,6 +671,7 @@ dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"hex",
|
||||
"hmac-sha256",
|
||||
"http",
|
||||
"libc",
|
||||
"moonlight-common-c-sys",
|
||||
"openssl",
|
||||
|
||||
@@ -9,6 +9,7 @@ directories = "6.0.0"
|
||||
getrandom = { version = "0.3.3", features = ["std"] }
|
||||
hex = "0.4.3"
|
||||
hmac-sha256 = "1.1.12"
|
||||
http = "1.3.1"
|
||||
libc = "0.2.174"
|
||||
moonlight-common-c-sys = { path = "../moonlight-common-c-sys" }
|
||||
openssl = "0.10.73"
|
||||
|
||||
@@ -4,7 +4,12 @@ use salvo::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::{debug, error};
|
||||
|
||||
use crate::{common::AppResult, state::StateReader};
|
||||
use crate::{
|
||||
common,
|
||||
common::{AppError, AppResult},
|
||||
responses,
|
||||
state::StateReader,
|
||||
};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct AppListRespApp {
|
||||
@@ -29,6 +34,7 @@ struct App {
|
||||
title: String,
|
||||
id: u64,
|
||||
hdr_supported: bool,
|
||||
active: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
@@ -40,7 +46,7 @@ struct GetAppsResponse {
|
||||
impl crate::backend::Backend {
|
||||
#[craft(endpoint(status_codes(StatusCode::OK, StatusCode::INTERNAL_SERVER_ERROR)))]
|
||||
pub async fn get_apps(self: ::std::sync::Arc<Self>) -> AppResult<Json<GetAppsResponse>> {
|
||||
let standard_error = Err(crate::common::AppError {
|
||||
let standard_error = Err(AppError {
|
||||
status_code: StatusCode::INTERNAL_SERVER_ERROR,
|
||||
description: "failed to get available apps".to_string(),
|
||||
});
|
||||
@@ -67,7 +73,29 @@ impl crate::backend::Backend {
|
||||
};
|
||||
|
||||
for (_, server) in servers.into_iter() {
|
||||
let mut base_url = crate::common::base_url(
|
||||
let mut server_info_base_url = common::base_url(
|
||||
"https",
|
||||
&server.host,
|
||||
server.https_port(),
|
||||
&unique_id,
|
||||
"serverinfo",
|
||||
None,
|
||||
);
|
||||
|
||||
let server_info = common::get_url(&mut server_info_base_url, true)
|
||||
.await
|
||||
.unwrap();
|
||||
debug!("server_info: {server_info}");
|
||||
let server_info: responses::ServerInfoResponse =
|
||||
match serde_xml_rs::from_str(&server_info) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
error!("Could not parse serverinfo response: {e}");
|
||||
return standard_error;
|
||||
}
|
||||
};
|
||||
|
||||
let mut base_url = common::base_url(
|
||||
"https",
|
||||
&server.host,
|
||||
server.https_port(),
|
||||
@@ -76,7 +104,7 @@ impl crate::backend::Backend {
|
||||
None,
|
||||
);
|
||||
|
||||
let resp = match crate::common::get_url(&mut base_url, true).await {
|
||||
let resp = match common::get_url(&mut base_url, true).await {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
error!("could not get applist from server {}: {}", server.name, e);
|
||||
@@ -103,6 +131,7 @@ impl crate::backend::Backend {
|
||||
title: a.app_title,
|
||||
hdr_supported: a.is_hdr_supported,
|
||||
id: a.id,
|
||||
active: a.id == server_info.currentgame,
|
||||
})
|
||||
.rev()
|
||||
.collect();
|
||||
|
||||
@@ -9,6 +9,7 @@ mod common;
|
||||
mod gamestream;
|
||||
mod pair;
|
||||
mod proxy;
|
||||
mod responses;
|
||||
mod state;
|
||||
mod stream;
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct ServerInfoResponse {
|
||||
pub hostname: String,
|
||||
pub appversion: String,
|
||||
pub GfeVersion: String,
|
||||
pub uniqueid: uuid::Uuid,
|
||||
pub HttpsPort: u16,
|
||||
pub ExternalPort: u16,
|
||||
pub MaxLumaPixelsHEVC: u64,
|
||||
pub mac: String,
|
||||
//pub ServerCommand: String,
|
||||
//pub Permission: u64,
|
||||
//pub VirtualDisplayCapable: bool,
|
||||
//pub VirtualDisplayDriverReady: bool,
|
||||
pub LocalIP: String,
|
||||
pub ServerCodecModeSupport: i32,
|
||||
pub PairStatus: u64,
|
||||
pub currentgame: u64,
|
||||
pub state: String,
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use moonlight_common_c_sys::SCM_H264;
|
||||
use salvo::prelude::*;
|
||||
@@ -6,7 +8,7 @@ use tracing::{debug, error, info};
|
||||
|
||||
use crate::{
|
||||
common::{AppError, AppResult, get_url},
|
||||
proxy,
|
||||
proxy, responses,
|
||||
state::{GamestreamServer, StateReadAccess, StateReader},
|
||||
};
|
||||
|
||||
@@ -25,33 +27,16 @@ struct PostStreamStartResponse {
|
||||
//cert_hash: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ServerInfoResponse {
|
||||
hostname: String,
|
||||
appversion: String,
|
||||
GfeVersion: String,
|
||||
uniqueid: uuid::Uuid,
|
||||
HttpsPort: u16,
|
||||
ExternalPort: u16,
|
||||
MaxLumaPixelsHEVC: u64,
|
||||
mac: String,
|
||||
//ServerCommand: String,
|
||||
//Permission: u64,
|
||||
//VirtualDisplayCapable: bool,
|
||||
//VirtualDisplayDriverReady: bool,
|
||||
LocalIP: String,
|
||||
ServerCodecModeSupport: i32,
|
||||
PairStatus: u64,
|
||||
currentgame: u64,
|
||||
state: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct LaunchResponse {
|
||||
#[serde(rename = "@status_code")]
|
||||
status_code: String,
|
||||
#[serde(rename = "@status_message")]
|
||||
status_message: Option<String>,
|
||||
#[serde(rename = "sessionUrl0")]
|
||||
session_url_0: url::Url,
|
||||
session_url_0: Option<url::Url>,
|
||||
#[serde(rename = "gamesession")]
|
||||
game_session: u64,
|
||||
game_session: Option<u64>,
|
||||
}
|
||||
|
||||
fn get_server(reader: &StateReadAccess, server: &String) -> Result<Option<GamestreamServer>> {
|
||||
@@ -108,7 +93,7 @@ impl crate::backend::Backend {
|
||||
Ok(s) => match s {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
info!("No server with name: {}", body.server);
|
||||
error!("No server with name: {}", body.server);
|
||||
return Err(AppError {
|
||||
status_code: StatusCode::BAD_REQUEST,
|
||||
description: "No server configured with that name.".to_string(),
|
||||
@@ -139,8 +124,9 @@ impl crate::backend::Backend {
|
||||
);
|
||||
|
||||
let server_info = crate::common::get_url(&mut base_url, true).await.unwrap();
|
||||
debug!("app_info: {server_info}");
|
||||
let server_info: ServerInfoResponse = match serde_xml_rs::from_str(&server_info) {
|
||||
debug!("server_info: {server_info}");
|
||||
let server_info: responses::ServerInfoResponse = match serde_xml_rs::from_str(&server_info)
|
||||
{
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
error!("Could not parse serverinfo response: {e}");
|
||||
@@ -227,6 +213,36 @@ impl crate::backend::Backend {
|
||||
}
|
||||
};
|
||||
|
||||
let Ok(launch_resp_status) = http::StatusCode::from_str(&launch_response.status_code)
|
||||
else {
|
||||
error!(
|
||||
"Server returned invalid status code: {}",
|
||||
launch_response.status_code
|
||||
);
|
||||
return standard_error;
|
||||
};
|
||||
if !launch_resp_status.is_success() {
|
||||
let status_message = launch_response
|
||||
.status_message
|
||||
.unwrap_or("Server did not provide a status message".to_string());
|
||||
|
||||
info!("Could not launch game: {}", status_message,);
|
||||
return Err(AppError {
|
||||
status_code: StatusCode::INTERNAL_SERVER_ERROR,
|
||||
description: format!("Could not launch game: {}", status_message),
|
||||
});
|
||||
}
|
||||
|
||||
let Some(url) = launch_response.session_url_0 else {
|
||||
error!("Server response was missing session_url_0");
|
||||
return standard_error;
|
||||
};
|
||||
|
||||
let Some(game_session) = launch_response.game_session else {
|
||||
error!("Server response was missing game_session");
|
||||
return standard_error;
|
||||
};
|
||||
|
||||
let stream_id = uuid::Uuid::new_v4();
|
||||
|
||||
let server_codec_mode_support = if server_info.ServerCodecModeSupport == 0 {
|
||||
@@ -237,8 +253,8 @@ impl crate::backend::Backend {
|
||||
|
||||
let stream = crate::backend::Stream {
|
||||
id: stream_id,
|
||||
url: launch_response.session_url_0,
|
||||
game_session: launch_response.game_session,
|
||||
url,
|
||||
game_session,
|
||||
server_address: server.host.clone(),
|
||||
stream_config: body.stream_config.clone(),
|
||||
app_version: server_info.appversion,
|
||||
|
||||
Reference in New Issue
Block a user