@@ -78,7 +78,8 @@ impl SingboxProcessor {
7878 serde_json:: to_string ( & names) . unwrap_or_else ( |_| "[]" . to_string ( ) )
7979 }
8080
81- /// Convert Clash VMess parameters to Sing-box format
81+ /// Convert VMess parameters to Sing-box format
82+ /// Handles both Clash-style flat params and Sing-box-style nested objects
8283 pub fn convert_vmess_params_to_singbox (
8384 config : & mut serde_json:: Map < String , serde_json:: Value > ,
8485 params : & std:: collections:: HashMap < String , serde_json:: Value > ,
@@ -102,31 +103,44 @@ impl SingboxProcessor {
102103 }
103104 }
104105
106+ // TLS handling — detect sing-box style nested tls object vs Clash-style boolean
107+ if let Some ( tls) = params. get ( "tls" ) {
108+ if let Some ( tls_obj) = tls. as_object ( ) {
109+ // Sing-box style: tls is already a full object, pass through
110+ let mut tls_config = tls_obj. clone ( ) ;
111+ tls_config
112+ . entry ( "enabled" . to_string ( ) )
113+ . or_insert ( serde_json:: Value :: Bool ( true ) ) ;
114+ config. insert ( "tls" . to_string ( ) , serde_json:: Value :: Object ( tls_config) ) ;
115+ } else if tls. as_bool ( ) . unwrap_or ( false ) {
116+ // Clash style: tls is a boolean, build from flat params
117+ let mut tls_config = serde_json:: Map :: new ( ) ;
118+ tls_config. insert ( "enabled" . to_string ( ) , serde_json:: Value :: Bool ( true ) ) ;
119+
120+ if let Some ( servername) = params. get ( "servername" ) . or ( params. get ( "sni" ) ) {
121+ tls_config. insert ( "server_name" . to_string ( ) , servername. clone ( ) ) ;
122+ }
105123
106- // TLS handling
107- let tls_enabled = params
108- . get ( "tls" )
109- . and_then ( |v| v. as_bool ( ) )
110- . unwrap_or ( false ) ;
111-
112- if tls_enabled {
113- let mut tls_config = serde_json:: Map :: new ( ) ;
114- tls_config. insert ( "enabled" . to_string ( ) , serde_json:: Value :: Bool ( true ) ) ;
124+ if let Some ( skip) = params. get ( "skip-cert-verify" ) {
125+ tls_config. insert ( "insecure" . to_string ( ) , skip. clone ( ) ) ;
126+ }
115127
116- // servername → server_name
117- if let Some ( servername) = params. get ( "servername" ) . or ( params. get ( "sni" ) ) {
118- tls_config. insert ( "server_name" . to_string ( ) , servername. clone ( ) ) ;
128+ config. insert ( "tls" . to_string ( ) , serde_json:: Value :: Object ( tls_config) ) ;
119129 }
130+ }
120131
121- // skip-cert-verify → insecure
122- if let Some ( skip) = params. get ( "skip-cert-verify" ) {
123- tls_config. insert ( "insecure" . to_string ( ) , skip. clone ( ) ) ;
132+ // Transport handling — detect sing-box style nested transport object first
133+ if let Some ( transport) = params. get ( "transport" ) {
134+ if let Some ( transport_obj) = transport. as_object ( ) {
135+ config. insert (
136+ "transport" . to_string ( ) ,
137+ serde_json:: Value :: Object ( transport_obj. clone ( ) ) ,
138+ ) ;
139+ return ;
124140 }
125-
126- config. insert ( "tls" . to_string ( ) , serde_json:: Value :: Object ( tls_config) ) ;
127141 }
128142
129- // Transport handling (ws, grpc, h2, http)
143+ // Clash-style transport from "network" + opts
130144 if let Some ( network) = params. get ( "network" ) . and_then ( |v| v. as_str ( ) ) {
131145 let mut transport = serde_json:: Map :: new ( ) ;
132146 transport. insert (
@@ -194,30 +208,42 @@ impl SingboxProcessor {
194208 }
195209 }
196210
197- /// Convert Clash Trojan parameters to Sing-box format
211+ /// Convert Trojan parameters to Sing-box format
212+ /// Handles both Clash-style flat params (sni, skip-cert-verify) and
213+ /// Sing-box-style nested objects (tls: {enabled, server_name, insecure})
198214 pub fn convert_trojan_params_to_singbox (
199215 config : & mut serde_json:: Map < String , serde_json:: Value > ,
200216 params : & std:: collections:: HashMap < String , serde_json:: Value > ,
201217 ) {
202- // TLS is typically enabled by default for Trojan
203- let mut tls_config = serde_json:: Map :: new ( ) ;
204- tls_config. insert ( "enabled" . to_string ( ) , serde_json:: Value :: Bool ( true ) ) ;
205-
206- if let Some ( sni) = params. get ( "sni" ) . or ( params. get ( "servername" ) ) {
207- tls_config. insert ( "server_name" . to_string ( ) , sni. clone ( ) ) ;
208- }
209-
210- if let Some ( skip) = params. get ( "skip-cert-verify" ) {
211- tls_config. insert ( "insecure" . to_string ( ) , skip. clone ( ) ) ;
218+ // Check if params already contain a sing-box style tls object
219+ if let Some ( tls) = params. get ( "tls" ) {
220+ if let Some ( tls_obj) = tls. as_object ( ) {
221+ let mut tls_config = tls_obj. clone ( ) ;
222+ tls_config
223+ . entry ( "enabled" . to_string ( ) )
224+ . or_insert ( serde_json:: Value :: Bool ( true ) ) ;
225+ config. insert ( "tls" . to_string ( ) , serde_json:: Value :: Object ( tls_config) ) ;
226+ } else {
227+ // tls is a boolean or other non-object — build from flat params
228+ Self :: build_trojan_tls_from_flat_params ( config, params) ;
229+ }
230+ } else {
231+ // No tls key — build from Clash-style flat params
232+ Self :: build_trojan_tls_from_flat_params ( config, params) ;
212233 }
213234
214- if let Some ( alpn) = params. get ( "alpn" ) {
215- tls_config. insert ( "alpn" . to_string ( ) , alpn. clone ( ) ) ;
235+ // Check if params already contain a sing-box style transport object
236+ if let Some ( transport) = params. get ( "transport" ) {
237+ if let Some ( transport_obj) = transport. as_object ( ) {
238+ config. insert (
239+ "transport" . to_string ( ) ,
240+ serde_json:: Value :: Object ( transport_obj. clone ( ) ) ,
241+ ) ;
242+ return ;
243+ }
216244 }
217245
218- config. insert ( "tls" . to_string ( ) , serde_json:: Value :: Object ( tls_config) ) ;
219-
220- // Transport handling
246+ // Clash-style transport from "network" + opts
221247 if let Some ( network) = params. get ( "network" ) . and_then ( |v| v. as_str ( ) ) {
222248 let mut transport = serde_json:: Map :: new ( ) ;
223249 transport. insert (
@@ -254,6 +280,28 @@ impl SingboxProcessor {
254280 }
255281 }
256282 }
283+
284+ fn build_trojan_tls_from_flat_params (
285+ config : & mut serde_json:: Map < String , serde_json:: Value > ,
286+ params : & std:: collections:: HashMap < String , serde_json:: Value > ,
287+ ) {
288+ let mut tls_config = serde_json:: Map :: new ( ) ;
289+ tls_config. insert ( "enabled" . to_string ( ) , serde_json:: Value :: Bool ( true ) ) ;
290+
291+ if let Some ( sni) = params. get ( "sni" ) . or ( params. get ( "servername" ) ) {
292+ tls_config. insert ( "server_name" . to_string ( ) , sni. clone ( ) ) ;
293+ }
294+
295+ if let Some ( skip) = params. get ( "skip-cert-verify" ) {
296+ tls_config. insert ( "insecure" . to_string ( ) , skip. clone ( ) ) ;
297+ }
298+
299+ if let Some ( alpn) = params. get ( "alpn" ) {
300+ tls_config. insert ( "alpn" . to_string ( ) , alpn. clone ( ) ) ;
301+ }
302+
303+ config. insert ( "tls" . to_string ( ) , serde_json:: Value :: Object ( tls_config) ) ;
304+ }
257305}
258306
259307impl ProtocolProcessor for SingboxProcessor {
0 commit comments