use std::{net::SocketAddr, sync::Arc};
use shadowsocks::{
config::ServerType,
context::{Context, SharedContext},
dns_resolver::DnsResolver,
net::ConnectOpts,
relay::Address,
};
use crate::config::OutboundProxy;
use crate::{
acl::AccessControl,
config::SecurityConfig,
net::{FlowStat, OutboundProxyClient},
};
#[derive(Clone)]
pub struct ServiceContext {
context: SharedContext,
connect_opts: ConnectOpts,
acl: Option<Arc<AccessControl>>,
flow_stat: Arc<FlowStat>,
outbound_client: Option<Arc<OutboundProxyClient>>,
}
impl Default for ServiceContext {
fn default() -> Self {
Self {
context: Context::new_shared(ServerType::Server),
connect_opts: ConnectOpts::default(),
acl: None,
flow_stat: Arc::new(FlowStat::new()),
outbound_client: None,
}
}
}
impl ServiceContext {
pub fn new() -> Self {
Self::default()
}
pub fn context(&self) -> SharedContext {
self.context.clone()
}
pub fn context_ref(&self) -> &Context {
self.context.as_ref()
}
pub fn set_connect_opts(&mut self, connect_opts: ConnectOpts) {
self.connect_opts = connect_opts;
}
pub fn connect_opts_ref(&self) -> &ConnectOpts {
&self.connect_opts
}
pub fn set_outbound_proxies(&mut self, proxies: Vec<OutboundProxy>) {
self.outbound_client = if proxies.is_empty() {
None
} else {
Some(Arc::new(OutboundProxyClient::from_config(&proxies)))
};
}
pub fn outbound_client(&self) -> Option<&Arc<OutboundProxyClient>> {
self.outbound_client.as_ref()
}
pub fn set_acl(&mut self, acl: Arc<AccessControl>) {
self.acl = Some(acl);
}
pub fn acl(&self) -> Option<&AccessControl> {
self.acl.as_deref()
}
pub fn flow_stat(&self) -> Arc<FlowStat> {
self.flow_stat.clone()
}
pub fn flow_stat_ref(&self) -> &FlowStat {
self.flow_stat.as_ref()
}
pub fn set_dns_resolver(&mut self, resolver: Arc<DnsResolver>) {
let context = Arc::get_mut(&mut self.context).expect("cannot set DNS resolver on a shared context");
context.set_dns_resolver(resolver)
}
pub fn dns_resolver(&self) -> &DnsResolver {
self.context.dns_resolver()
}
pub async fn check_outbound_blocked(&self, addr: &Address) -> bool {
match self.acl {
None => false,
Some(ref acl) => acl.check_outbound_blocked(&self.context, addr).await,
}
}
pub fn check_client_blocked(&self, addr: &SocketAddr) -> bool {
match self.acl {
None => false,
Some(ref acl) => acl.check_client_blocked(addr),
}
}
pub fn set_ipv6_first(&mut self, ipv6_first: bool) {
let context = Arc::get_mut(&mut self.context).expect("cannot set ipv6_first on a shared context");
context.set_ipv6_first(ipv6_first);
}
pub fn set_security_config(&mut self, security: &SecurityConfig) {
let context = Arc::get_mut(&mut self.context).expect("cannot set security on a shared context");
context.set_replay_attack_policy(security.replay_attack.policy);
}
}