* tcp proxy

* fix per review

* fix per review

* Suppress secure_tcp info logs for TCP proxy requests

Signed-off-by: 21pages <sunboeasy@gmail.com>

* copilot review: redact tcp proxy logs, dedupe headers, and avoid body clone

Signed-off-by: 21pages <sunboeasy@gmail.com>

* format common.rs

Signed-off-by: 21pages <sunboeasy@gmail.com>

* copilot review: test function name

Signed-off-by: 21pages <sunboeasy@gmail.com>

* copilot review: format IPv6 tcp proxy log targets correctly

Signed-off-by: 21pages <sunboeasy@gmail.com>

* copilot review: normalize HTTP method before direct request dispatch

Signed-off-by: 21pages <sunboeasy@gmail.com>

* review: extract fallback helper, fix Content-Type override, add overall timeout

- Extract duplicated TCP proxy fallback logic into generic
  `with_tcp_proxy_fallback` helper used by both `post_request` and
  `http_request_sync`, eliminating code drift risk
- Allow caller-supplied Content-Type to override the default in
  `parse_simple_header` instead of silently dropping it
- Take body by reference in `post_request_http` to avoid eager clone
  when no fallback is needed
- Wrap entire `tcp_proxy_request` flow (connect + handshake + send +
  receive) in an overall timeout to prevent indefinite stalls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* review: make is_public case-insensitive and cover mixed-case rustdesk URLs

Signed-off-by: 21pages <sunboeasy@gmail.com>

* oidc: route auth requests through shared HTTP/tcp-proxy path while keeping TLS warmup

Signed-off-by: 21pages <sunboeasy@gmail.com>

* refactor: replace unused TryFrom<Response> with HbbHttpResponse::parse method

  Remove TryFrom<Response> impl that was never called and replace the
  private parse_hbb_http_response helper in account.rs with a public
  parse() method on HbbHttpResponse, eliminating code duplication.

Signed-off-by: 21pages <sunboeasy@gmail.com>

---------

Signed-off-by: 21pages <sunboeasy@gmail.com>
Co-authored-by: 21pages <sunboeasy@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
RustDesk
2026-04-03 23:13:05 +08:00
committed by GitHub
parent cca6a5fe12
commit 4e30ee8d1c
3 changed files with 571 additions and 88 deletions

View File

@@ -1,7 +1,6 @@
use super::HbbHttpResponse;
use crate::hbbs_http::create_http_client_with_url;
use hbb_common::{config::LocalConfig, log, ResultType};
use reqwest::blocking::Client;
use serde_derive::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use std::{
@@ -109,7 +108,7 @@ pub struct AuthBody {
}
pub struct OidcSession {
client: Option<Client>,
warmed_api_server: Option<String>,
state_msg: &'static str,
failed_msg: String,
code_url: Option<OidcAuthUrl>,
@@ -136,7 +135,7 @@ impl Default for UserStatus {
impl OidcSession {
fn new() -> Self {
Self {
client: None,
warmed_api_server: None,
state_msg: REQUESTING_ACCOUNT_AUTH,
failed_msg: "".to_owned(),
code_url: None,
@@ -149,12 +148,13 @@ impl OidcSession {
fn ensure_client(api_server: &str) {
let mut write_guard = OIDC_SESSION.write().unwrap();
if write_guard.client.is_none() {
// This URL is used to detect the appropriate TLS implementation for the server.
let login_option_url = format!("{}/api/login-options", &api_server);
let client = create_http_client_with_url(&login_option_url);
write_guard.client = Some(client);
if write_guard.warmed_api_server.as_deref() == Some(api_server) {
return;
}
// This URL is used to detect the appropriate TLS implementation for the server.
let login_option_url = format!("{}/api/login-options", api_server);
let _ = create_http_client_with_url(&login_option_url);
write_guard.warmed_api_server = Some(api_server.to_owned());
}
fn auth(
@@ -164,26 +164,15 @@ impl OidcSession {
uuid: &str,
) -> ResultType<HbbHttpResponse<OidcAuthUrl>> {
Self::ensure_client(api_server);
let resp = if let Some(client) = &OIDC_SESSION.read().unwrap().client {
client
.post(format!("{}/api/oidc/auth", api_server))
.json(&serde_json::json!({
"op": op,
"id": id,
"uuid": uuid,
"deviceInfo": crate::ui_interface::get_login_device_info(),
}))
.send()?
} else {
hbb_common::bail!("http client not initialized");
};
let status = resp.status();
match resp.try_into() {
Ok(v) => Ok(v),
Err(err) => {
hbb_common::bail!("Http status: {}, err: {}", status, err);
}
}
let body = serde_json::json!({
"op": op,
"id": id,
"uuid": uuid,
"deviceInfo": crate::ui_interface::get_login_device_info(),
})
.to_string();
let resp = crate::post_request_sync(format!("{}/api/oidc/auth", api_server), body, "")?;
HbbHttpResponse::parse(&resp)
}
fn query(
@@ -197,11 +186,19 @@ impl OidcSession {
&[("code", code), ("id", id), ("uuid", uuid)],
)?;
Self::ensure_client(api_server);
if let Some(client) = &OIDC_SESSION.read().unwrap().client {
Ok(client.get(url).send()?.try_into()?)
} else {
hbb_common::bail!("http client not initialized")
#[derive(Deserialize)]
struct HttpResponseBody {
body: String,
}
let resp = crate::http_request_sync(
url.to_string(),
"GET".to_owned(),
None,
"{}".to_owned(),
)?;
let resp = serde_json::from_str::<HttpResponseBody>(&resp)?;
HbbHttpResponse::parse(&resp.body)
}
fn reset(&mut self) {