summaryrefslogtreecommitdiffhomepage
path: root/mullvad-ios/src/api_client/access_method_resolver.rs
blob: 5c6720c72955cac0fc3d5a530023ece0563bc908 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use mullvad_api::{
    ApiEndpoint,
    access_mode::AccessMethodResolver,
    proxy::{ApiConnectionMode, ProxyConfig},
};
use mullvad_encrypted_dns_proxy::state::EncryptedDnsProxyState;
use mullvad_types::access_method::{AccessMethod, BuiltInAccessMethod};
use talpid_types::net::{
    AllowedClients, AllowedEndpoint, Endpoint, TransportProtocol, proxy::CustomProxy,
};
use tonic::async_trait;

use super::{
    address_cache_provider::SwiftAddressCacheWrapper,
    shadowsocks_loader::SwiftShadowsocksLoaderWrapper,
};

#[derive(Debug)]
pub struct SwiftAccessMethodResolver {
    endpoint: ApiEndpoint,
    domain: String,
    state: EncryptedDnsProxyState,
    bridge_provider: SwiftShadowsocksLoaderWrapper,
    address_cache: SwiftAddressCacheWrapper,
}

impl SwiftAccessMethodResolver {
    pub fn new(
        endpoint: ApiEndpoint,
        domain: String,
        state: EncryptedDnsProxyState,
        bridge_provider: SwiftShadowsocksLoaderWrapper,
        address_cache: SwiftAddressCacheWrapper,
    ) -> Self {
        Self {
            endpoint,
            domain,
            state,
            bridge_provider,
            address_cache,
        }
    }
}

#[async_trait]
impl AccessMethodResolver for SwiftAccessMethodResolver {
    async fn resolve_access_method_setting(
        &mut self,
        access_method: &AccessMethod,
    ) -> Option<(AllowedEndpoint, ApiConnectionMode)> {
        let connection_mode = match access_method {
            AccessMethod::BuiltIn(BuiltInAccessMethod::Direct) => ApiConnectionMode::Direct,
            AccessMethod::BuiltIn(BuiltInAccessMethod::Bridge) => {
                let bridge = self.bridge_provider.get_bridges()?;
                let proxy = CustomProxy::Shadowsocks(bridge);
                ApiConnectionMode::Proxied(ProxyConfig::from(proxy))
            }
            AccessMethod::BuiltIn(BuiltInAccessMethod::EncryptedDnsProxy) => {
                if let Err(error) = self.state.fetch_configs(self.domain.as_str()).await {
                    log::error!("{error:#?}");
                }
                let Some(edp) = self.state.next_configuration() else {
                    log::warn!("Could not select next Encrypted DNS proxy config");
                    return None;
                };
                ApiConnectionMode::Proxied(ProxyConfig::from(edp))
            }
            AccessMethod::Custom(config) => {
                ApiConnectionMode::Proxied(ProxyConfig::from(config.clone()))
            }
        };

        let allowed_endpoint = {
            let endpoint = connection_mode.get_endpoint().unwrap_or_else(|| {
                Endpoint::from_socket_address(
                    self.endpoint.address.unwrap(),
                    TransportProtocol::Tcp,
                )
            });
            let clients = AllowedClients::All;
            AllowedEndpoint { endpoint, clients }
        };

        Some((allowed_endpoint, connection_mode))
    }

    async fn default_connection_mode(&self) -> AllowedEndpoint {
        let endpoint =
            Endpoint::from_socket_address(self.address_cache.get_addrs(), TransportProtocol::Tcp);

        AllowedEndpoint {
            endpoint,
            clients: AllowedClients::All,
        }
    }
}