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
use std::env;
use std::fs::File;
use std::io::{self, Read};
use std::path::Path;

use serde_json;

static LOCAL_ADDR: &str = "0.0.0.0:6009";
static SERVER_ADDR: &str = "0.0.0.0:9006";
static PASSWORD: &str = "password";
static METHOD: &str = "aes-256-cfb";
static TIMEOUT: u64 = 100;
static KEEPALIVE_PEARID: u64 = 600;

#[derive(Serialize, Deserialize, Debug, Default, Clone)]
pub struct Config {
    pub local_addr: String,
    pub server_addr: String,
    pub password: String,
    pub method: String,
    pub timeout: u64,
    pub keepalive_period: u64,
}

impl Config {
    pub fn new<P: AsRef<Path>>(path: P) -> Result<Config, io::Error> {
        let mut config = Config {
            ..Default::default()
        };

        if let Ok(mut file) = File::open(path) {
            let mut contents = String::new();
            file.read_to_string(&mut contents)?;
            config = match serde_json::from_str(&contents) {
                Ok(c) => c,
                Err(e) => {
                    return Err(io::Error::new(io::ErrorKind::Other, e));
                }
            };
        }

        if config.local_addr.is_empty() {
            config.local_addr = if let Ok(addr) = env::var("SHADOWSOCKS_LOCAL_ADDR") {
                addr
            } else {
                LOCAL_ADDR.to_string()
            }
        }

        if config.server_addr.is_empty() {
            config.server_addr = if let Ok(addr) = env::var("SHADOWSOCKS_SERVER_ADDR") {
                addr
            } else {
                SERVER_ADDR.to_string()
            }
        }

        if config.password.is_empty() {
            config.password = if let Ok(addr) = env::var("SHADOWSOCKS_PASSWORD") {
                addr
            } else {
                PASSWORD.to_string()
            }
        }

        if config.method.is_empty() {
            config.method = if let Ok(addr) = env::var("SHADOWSOCKS_METHOD") {
                addr
            } else {
                METHOD.to_string()
            }
        }

        if config.timeout == 0 {
            config.timeout = if let Ok(timeout) = env::var("SHADOWSOCKS_TIMEOUT") {
                timeout.parse().expect("invalid timeout value")
            } else {
                TIMEOUT
            }
        }

        if config.keepalive_period == 0 {
            config.keepalive_period =
                if let Ok(keepalive_period) = env::var("SHADOWSOCKS_KEEPALIVE_PERIOD") {
                    keepalive_period
                        .parse()
                        .expect("invalid keepalive_period value")
                } else {
                    KEEPALIVE_PEARID
                }
        }

        Ok(config)
    }
}