frpc_lib/loader/
reflection_checker.rs

1use std::error::Error;
2
3use anyhow::Result;
4
5use super::{reflection_loader_v1, reflection_loader_v1alpha};
6
7#[derive(Debug)]
8pub enum TryGetReflectionVersionResponse {
9    DetectedVersion(ReflectionVersion),
10    VersionUndetectable,
11    ConnectionError { error: Box<dyn Error + Send + Sync> },
12}
13
14#[derive(Debug)]
15pub enum ReflectionVersion {
16    V1,
17    V1Alpha,
18}
19
20pub(crate) async fn try_get_reflection_version(
21    server_url: String,
22) -> Result<TryGetReflectionVersionResponse> {
23    let v1_implemented = reflection_loader_v1::check_implemented(server_url.clone()).await;
24
25    match v1_implemented {
26        Ok(true) => {
27            return Ok(TryGetReflectionVersionResponse::DetectedVersion(
28                ReflectionVersion::V1,
29            ))
30        }
31        Ok(_) => {}
32        Err(e) => {
33            if let Some(transport) = &e.downcast_ref::<tonic::transport::Error>() {
34                let source = transport.source();
35
36                match source {
37                    Some(source) => {
38                        if source.is::<tonic::ConnectError>() {
39                            return Ok(TryGetReflectionVersionResponse::ConnectionError {
40                                error: e.into(),
41                            });
42                        }
43                    }
44                    None => {}
45                };
46            }
47        }
48    };
49
50    let v1alpha_implemented = reflection_loader_v1alpha::check_implemented(server_url).await;
51
52    match v1alpha_implemented {
53        Ok(true) => {
54            return Ok(TryGetReflectionVersionResponse::DetectedVersion(
55                ReflectionVersion::V1Alpha,
56            ))
57        }
58        Ok(_) => {}
59        Err(e) => {
60            if let Some(transport) = &e.downcast_ref::<tonic::transport::Error>() {
61                let source = transport.source();
62
63                match source {
64                    Some(source) => {
65                        if source.is::<tonic::ConnectError>() {
66                            return Ok(TryGetReflectionVersionResponse::ConnectionError {
67                                error: e.into(),
68                            });
69                        }
70                    }
71                    None => {}
72                };
73            }
74        }
75    };
76
77    Ok(TryGetReflectionVersionResponse::VersionUndetectable)
78}