2024-03-10 15:13:42 -04:00
|
|
|
package parser
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/url"
|
2024-07-20 11:45:04 -04:00
|
|
|
"strconv"
|
2024-03-10 15:13:42 -04:00
|
|
|
"strings"
|
2024-03-22 04:10:15 -04:00
|
|
|
"sub2sing-box/constant"
|
2024-03-20 12:02:38 -04:00
|
|
|
"sub2sing-box/model"
|
2024-03-20 08:54:23 -04:00
|
|
|
"sub2sing-box/util"
|
2024-03-10 15:13:42 -04:00
|
|
|
)
|
|
|
|
|
2024-03-20 12:02:38 -04:00
|
|
|
func ParseShadowsocks(proxy string) (model.Outbound, error) {
|
2024-07-20 11:45:04 -04:00
|
|
|
link, err := url.Parse(proxy)
|
|
|
|
if err != nil {
|
|
|
|
return model.Outbound{}, &ParseError{
|
|
|
|
Type: ErrInvalidStruct,
|
|
|
|
Message: "url parse error",
|
|
|
|
Raw: proxy,
|
|
|
|
}
|
2024-03-10 15:13:42 -04:00
|
|
|
}
|
2024-03-22 04:10:15 -04:00
|
|
|
|
2024-07-20 11:45:04 -04:00
|
|
|
server := link.Hostname()
|
|
|
|
if server == "" {
|
2024-03-22 04:10:15 -04:00
|
|
|
return model.Outbound{}, &ParseError{
|
|
|
|
Type: ErrInvalidStruct,
|
2024-07-20 11:45:04 -04:00
|
|
|
Message: "missing server host",
|
2024-03-22 04:10:15 -04:00
|
|
|
Raw: proxy,
|
|
|
|
}
|
2024-03-10 15:13:42 -04:00
|
|
|
}
|
2024-03-22 04:10:15 -04:00
|
|
|
|
2024-07-20 11:45:04 -04:00
|
|
|
if link.Scheme+"://" != constant.ShadowsocksPrefix {
|
|
|
|
return model.Outbound{}, &ParseError{Type: ErrInvalidPrefix, Raw: proxy}
|
2024-03-10 15:13:42 -04:00
|
|
|
}
|
2024-07-20 11:45:04 -04:00
|
|
|
|
|
|
|
port, err := strconv.Atoi(link.Port())
|
|
|
|
if err != nil {
|
2024-03-22 04:10:15 -04:00
|
|
|
return model.Outbound{}, &ParseError{
|
|
|
|
Type: ErrInvalidStruct,
|
2024-07-20 11:45:04 -04:00
|
|
|
Message: "missing server port",
|
2024-03-22 04:10:15 -04:00
|
|
|
Raw: proxy,
|
|
|
|
}
|
2024-03-10 15:13:42 -04:00
|
|
|
}
|
2024-03-22 04:10:15 -04:00
|
|
|
|
2024-07-20 11:45:04 -04:00
|
|
|
user, err := util.DecodeBase64(link.User.Username())
|
|
|
|
if user == "" {
|
2024-03-22 04:10:15 -04:00
|
|
|
return model.Outbound{}, &ParseError{
|
|
|
|
Type: ErrInvalidStruct,
|
2024-07-20 11:45:04 -04:00
|
|
|
Message: "missing method and password",
|
2024-03-22 04:10:15 -04:00
|
|
|
Raw: proxy,
|
|
|
|
}
|
2024-03-10 15:13:42 -04:00
|
|
|
}
|
2024-07-20 11:45:04 -04:00
|
|
|
methodAndPass := strings.SplitN(user, ":", 2)
|
|
|
|
if len(methodAndPass) != 2 {
|
2024-04-23 02:41:14 -04:00
|
|
|
return model.Outbound{}, &ParseError{
|
2024-07-20 11:45:04 -04:00
|
|
|
Type: ErrInvalidStruct,
|
|
|
|
Message: "missing method and password",
|
2024-04-23 02:41:14 -04:00
|
|
|
Raw: proxy,
|
|
|
|
}
|
2024-03-10 15:13:42 -04:00
|
|
|
}
|
2024-03-22 04:10:15 -04:00
|
|
|
|
2024-07-20 11:45:04 -04:00
|
|
|
query := link.Query()
|
|
|
|
pluginStr := query.Get("plugin")
|
|
|
|
plugin := ""
|
|
|
|
options := ""
|
|
|
|
if pluginStr != "" {
|
|
|
|
arr := strings.SplitN(pluginStr, ";", 2)
|
|
|
|
if len(arr) == 2 {
|
|
|
|
plugin = arr[0]
|
|
|
|
options = arr[1]
|
2024-03-10 15:13:42 -04:00
|
|
|
}
|
|
|
|
}
|
2024-03-22 04:10:15 -04:00
|
|
|
|
2024-03-20 12:02:38 -04:00
|
|
|
result := model.Outbound{
|
2024-03-10 15:13:42 -04:00
|
|
|
Type: "shadowsocks",
|
2024-07-20 11:45:04 -04:00
|
|
|
Tag: link.Fragment,
|
2024-03-20 12:02:38 -04:00
|
|
|
ShadowsocksOptions: model.ShadowsocksOutboundOptions{
|
|
|
|
ServerOptions: model.ServerOptions{
|
|
|
|
Server: server,
|
2024-07-20 11:45:04 -04:00
|
|
|
ServerPort: uint16(port),
|
2024-03-20 12:02:38 -04:00
|
|
|
},
|
2024-07-20 11:45:04 -04:00
|
|
|
Method: methodAndPass[0],
|
|
|
|
Password: methodAndPass[1],
|
|
|
|
Plugin: plugin,
|
|
|
|
PluginOptions: options,
|
2024-03-10 15:13:42 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
return result, nil
|
|
|
|
}
|