mirror of
https://github.com/shadowsocks/shadowsocks-rust.git
synced 2026-02-09 01:59:16 +08:00
* Refactored and separate library into crates
- shadowsocks: the core feature of shadowsocks
- shadowsocks-service: library for building shadowsocks services
- dns, http, redir, socks, tunnel
- load balancer
- shadowsocks-rust: release binaries
fix #347
* unified DnsResolver implementation
* unified local service common parameters into ServiceContext
- ServiceContext is common parameters shared between all local
implementations
- Completely removed https local support
* add #292 reply attack protection
* migrated redir local server
* support customizing outbound socket bind address
* manager outbound socket should accepts connect_opts
* republic local implementations
* socks5 udp server should always listen to client address
* socks4 controlled by local-socks4 feature
* socks4 also obey mode configuration
* socks server tcp cannot be disable. add support of udp-bind-addr parameter
* add udp-bind-addr for customizing udp-relay bind-addr
* local-dns infra, support customizing resolver
* fully implements DNS relay server
* support binding to specific interface on Linux-like platform
* tcp cannot be disabled in socks
* enable local-flow-stat
* fixed windows build
* fixed android specific warnings and compile errors
* allow udp_only mode in socks5
* dns relay listens to both TCP and UDP, mode controls outbound upstreams
* dns relay retries twice if request failed
* doc
* fix DnsClient typo
* fix stream EncryptWriter bug
* allow disable logging output
updated dependencies
* add readme
* refine doc
* remove depending on trust-dns-client
* socks4/4a client
* allow socks5 udp_only mode, fixes compile warning
* create standalone socks5 UDP relay server
- socks5 UDP association full cone (NAT2)
* server udp relay supports full cone (NAT2)
* acl moved to crate root
* redir udp relay support full cone (NAT2)
* standard socks5 udp test must use tcp_and_udp mode
* set server context fields with pub APIs
* udp_max_associations and udp_timeout default value set in Config
* local dns resolver retry with fixed attempts
* max_udp_association keeps unlimited by default
* fixed logging binary name
* pops first exited future result for local and server
* update reverse target index cache
* fix ProxyClientStreamWriteHalf that allows sending empty buffers
ref #232
* remove unused import when socks4 is disabled
* make balancer become a globally shared object
* print plugin exit status
* control local, server, manager services in features
96 lines
2.6 KiB
Rust
96 lines
2.6 KiB
Rust
//! SIP002 URL Scheme
|
|
//!
|
|
//! SS-URI = "ss://" userinfo "@" hostname ":" port [ "/" ] [ "?" plugin ] [ "#" tag ]
|
|
//! userinfo = websafe-base64-encode-utf8(method ":" password)
|
|
|
|
use clap::clap_app;
|
|
use qrcode::{types::Color, QrCode};
|
|
|
|
use shadowsocks_service::{
|
|
config::{Config, ConfigType},
|
|
shadowsocks::config::ServerConfig,
|
|
};
|
|
|
|
/// shadowsocks version
|
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
|
|
const BLACK: &str = "\x1b[40m \x1b[0m";
|
|
const WHITE: &str = "\x1b[47m \x1b[0m";
|
|
|
|
fn print_qrcode(encoded: &str) {
|
|
let qrcode = QrCode::new(encoded.as_bytes()).unwrap();
|
|
|
|
for _ in 0..qrcode.width() + 2 {
|
|
print!("{}", WHITE);
|
|
}
|
|
println!();
|
|
|
|
for y in 0..qrcode.width() {
|
|
print!("{}", WHITE);
|
|
for x in 0..qrcode.width() {
|
|
let color = match qrcode[(x, y)] {
|
|
Color::Light => WHITE,
|
|
Color::Dark => BLACK,
|
|
};
|
|
|
|
print!("{}", color);
|
|
}
|
|
println!("{}", WHITE);
|
|
}
|
|
|
|
for _ in 0..qrcode.width() + 2 {
|
|
print!("{}", WHITE);
|
|
}
|
|
println!();
|
|
}
|
|
|
|
fn encode(filename: &str, need_qrcode: bool) {
|
|
let config = Config::load_from_file(filename, ConfigType::Server).unwrap();
|
|
|
|
for svr in config.server {
|
|
let encoded = svr.to_url();
|
|
|
|
println!("{}", encoded);
|
|
|
|
if need_qrcode {
|
|
let encoded = svr.to_qrcode_url();
|
|
print_qrcode(&encoded);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn decode(encoded: &str, need_qrcode: bool) {
|
|
let svrconfig = ServerConfig::from_url(encoded).unwrap();
|
|
|
|
let mut config = Config::new(ConfigType::Server);
|
|
config.server.push(svrconfig);
|
|
|
|
println!("{}", config);
|
|
|
|
if need_qrcode {
|
|
print_qrcode(encoded);
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let app = clap_app!(ssurl =>
|
|
(version: VERSION)
|
|
(about: "Encode and decode ShadowSocks URL")
|
|
(@arg ENCODE_CONFIG_PATH: -e --encode +takes_value conflicts_with[DECODE_CONFIG_PATH] required_unless[DECODE_CONFIG_PATH] "Encode the server configuration in the provided JSON file")
|
|
(@arg DECODE_CONFIG_PATH: -d --decode +takes_value required_unless[ENCODE_CONFIG_PATH] "Decode the server configuration from the provide ShadowSocks URL")
|
|
(@arg QRCODE: -c --qrcode !takes_value "Generate the QRCode with the provided configuration")
|
|
);
|
|
|
|
let matches = app.get_matches();
|
|
|
|
let need_qrcode = matches.is_present("QRCODE");
|
|
|
|
if let Some(file) = matches.value_of("ENCODE_CONFIG_PATH") {
|
|
encode(file, need_qrcode);
|
|
} else if let Some(encoded) = matches.value_of("DECODE_CONFIG_PATH") {
|
|
decode(encoded, need_qrcode);
|
|
} else {
|
|
println!("Use -h for more detail");
|
|
}
|
|
}
|