@@ -83,6 +83,7 @@ pub struct Proxy {
8383
8484 // vmess
8585 pub username : Option < String > ,
86+ pub uuid : Option < String > ,
8687
8788 pub amux : Option < bool > ,
8889 pub amux_max : Option < i32 > ,
@@ -120,6 +121,7 @@ impl Default for Proxy {
120121 ws_host : None ,
121122 sni : None ,
122123 username : None ,
124+ uuid : None ,
123125 amux : Some ( false ) ,
124126 amux_max : Some ( 8 ) ,
125127 amux_con : Some ( 2 ) ,
@@ -534,6 +536,9 @@ pub fn from_lines(lines: Vec<io::Result<String>>) -> Result<Config> {
534536 "username" => {
535537 proxy. username = Some ( v. to_string ( ) ) ;
536538 }
539+ "uuid" => {
540+ proxy. uuid = Some ( v. to_string ( ) ) ;
541+ }
537542 "amux" => proxy. amux = if v == "true" { Some ( true ) } else { Some ( false ) } ,
538543 "amux-max" => {
539544 let i = v. parse :: < i32 > ( ) . ok ( ) ;
@@ -599,6 +604,22 @@ pub fn from_lines(lines: Vec<io::Result<String>>) -> Result<Config> {
599604 } ;
600605 proxy. port = Some ( port) ;
601606
607+ // parse positional params
608+ let pos_params = & params[ 2 ..] ;
609+ for ( i, param) in pos_params. iter ( ) . enumerate ( ) {
610+ if param. contains ( '=' ) {
611+ continue ;
612+ }
613+ match ( proxy. protocol . as_str ( ) , i) {
614+ ( "ss" | "shadowsocks" , 0 ) => proxy. encrypt_method = Some ( param. clone ( ) ) ,
615+ ( "ss" | "shadowsocks" , 1 ) => proxy. password = Some ( param. clone ( ) ) ,
616+ ( "trojan" , 0 ) => proxy. password = Some ( param. clone ( ) ) ,
617+ ( "vmess" , 0 ) => proxy. username = Some ( param. clone ( ) ) ,
618+ ( "vless" , 0 ) => proxy. password = Some ( param. clone ( ) ) ,
619+ _ => ( ) ,
620+ }
621+ }
622+
602623 // compat
603624 if let "ss" = proxy. protocol . as_str ( ) {
604625 proxy. protocol = "shadowsocks" . to_string ( ) ;
@@ -1065,7 +1086,10 @@ pub fn to_common(conf: &Config) -> Result<common::Config> {
10651086 let settings = common:: VlessOutboundSettings {
10661087 address : ext_proxy. address . clone ( ) ,
10671088 port : ext_proxy. port ,
1068- uuid : ext_proxy. password . clone ( ) , // vless uses uuid from password
1089+ uuid : ext_proxy
1090+ . uuid
1091+ . clone ( )
1092+ . or_else ( || ext_proxy. password . clone ( ) ) , // prioritize uuid, then password
10691093 } ;
10701094
10711095 let mut next_tag = ext_proxy. tag . clone ( ) ;
@@ -1227,7 +1251,10 @@ pub fn to_common(conf: &Config) -> Result<common::Config> {
12271251 } else {
12281252 ext_proxy. port
12291253 } ,
1230- uuid : ext_proxy. username . clone ( ) ,
1254+ uuid : ext_proxy
1255+ . uuid
1256+ . clone ( )
1257+ . or_else ( || ext_proxy. username . clone ( ) ) ,
12311258 security : Some (
12321259 ext_proxy
12331260 . encrypt_method
@@ -1462,6 +1489,16 @@ Vmess = vmess, 1.2.3.4, 443, username, amux=true, sni=www.google.com
14621489 assert ! ( tags. contains( &&"Vmess_tls_xxx" . to_string( ) ) ) ;
14631490 assert ! ( tags. contains( &&"Vmess_amux_xxx" . to_string( ) ) ) ;
14641491 assert ! ( tags. contains( &&"Vmess_vmess_xxx" . to_string( ) ) ) ;
1492+ let vmess = outbounds
1493+ . iter ( )
1494+ . find ( |o| o. tag == Some ( "Vmess_vmess_xxx" . to_string ( ) ) )
1495+ . unwrap ( ) ;
1496+ if let common:: OutboundSettings :: VMess { settings } = & vmess. settings {
1497+ assert_eq ! (
1498+ settings. as_ref( ) . unwrap( ) . uuid,
1499+ Some ( "username" . to_string( ) )
1500+ ) ;
1501+ }
14651502 }
14661503
14671504 #[ test]
@@ -1496,6 +1533,72 @@ tun-dns-server = 8.8.8.8, 8.8.4.4
14961533 }
14971534 }
14981535
1536+ #[ test]
1537+ fn test_vmess_vless_uuid ( ) {
1538+ let conf = r#"
1539+ [Proxy]
1540+ Vmess1 = vmess, 1.2.3.4, 443, username, uuid=uuid1
1541+ Vmess2 = vmess, 1.2.3.4, 443, username
1542+ Vless1 = vless, 1.2.3.4, 443, password, uuid=uuid2
1543+ Vless2 = vless, 1.2.3.4, 443, password
1544+ "# ;
1545+ let lines: Vec < io:: Result < String > > = conf. lines ( ) . map ( |s| Ok ( s. to_string ( ) ) ) . collect ( ) ;
1546+ let config = from_lines ( lines) . unwrap ( ) ;
1547+ let common = to_common ( & config) . unwrap ( ) ;
1548+
1549+ let outbounds = common. outbounds . unwrap ( ) ;
1550+
1551+ // Vmess1: should use uuid1
1552+ let vmess1 = outbounds
1553+ . iter ( )
1554+ . find ( |o| o. tag == Some ( "Vmess1_vmess_xxx" . to_string ( ) ) )
1555+ . unwrap ( ) ;
1556+ if let common:: OutboundSettings :: VMess { settings } = & vmess1. settings {
1557+ assert_eq ! ( settings. as_ref( ) . unwrap( ) . uuid, Some ( "uuid1" . to_string( ) ) ) ;
1558+ } else {
1559+ panic ! ( "Not vmess: {:?}" , vmess1. settings) ;
1560+ }
1561+
1562+ // Vmess2: should use username
1563+ let vmess2 = outbounds
1564+ . iter ( )
1565+ . find ( |o| o. tag == Some ( "Vmess2_vmess_xxx" . to_string ( ) ) )
1566+ . unwrap ( ) ;
1567+ if let common:: OutboundSettings :: VMess { settings } = & vmess2. settings {
1568+ assert_eq ! (
1569+ settings. as_ref( ) . unwrap( ) . uuid,
1570+ Some ( "username" . to_string( ) )
1571+ ) ;
1572+ } else {
1573+ panic ! ( "Not vmess: {:?}" , vmess2. settings) ;
1574+ }
1575+
1576+ // Vless1: should use uuid2
1577+ let vless1 = outbounds
1578+ . iter ( )
1579+ . find ( |o| o. tag == Some ( "Vless1" . to_string ( ) ) )
1580+ . unwrap ( ) ;
1581+ if let common:: OutboundSettings :: Vless { settings } = & vless1. settings {
1582+ assert_eq ! ( settings. as_ref( ) . unwrap( ) . uuid, Some ( "uuid2" . to_string( ) ) ) ;
1583+ } else {
1584+ panic ! ( "Not vless: {:?}" , vless1. settings) ;
1585+ }
1586+
1587+ // Vless2: should use password
1588+ let vless2 = outbounds
1589+ . iter ( )
1590+ . find ( |o| o. tag == Some ( "Vless2" . to_string ( ) ) )
1591+ . unwrap ( ) ;
1592+ if let common:: OutboundSettings :: Vless { settings } = & vless2. settings {
1593+ assert_eq ! (
1594+ settings. as_ref( ) . unwrap( ) . uuid,
1595+ Some ( "password" . to_string( ) )
1596+ ) ;
1597+ } else {
1598+ panic ! ( "Not vless: {:?}" , vless2. settings) ;
1599+ }
1600+ }
1601+
14991602 #[ test]
15001603 fn test_mptp_proxy_group ( ) {
15011604 let conf = r#"
0 commit comments