github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/node/parser/shadowsocksr.go (about)

     1  package parser
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/base64"
     6  	"errors"
     7  	"log/slog"
     8  	"net/url"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/Asutorufa/yuhaiin/pkg/log"
    13  	"github.com/Asutorufa/yuhaiin/pkg/protos/node/point"
    14  	"github.com/Asutorufa/yuhaiin/pkg/protos/node/protocol"
    15  	"github.com/Asutorufa/yuhaiin/pkg/protos/node/subscribe"
    16  	"github.com/Asutorufa/yuhaiin/pkg/utils/yerror"
    17  )
    18  
    19  func init() {
    20  	store.Store(subscribe.Type_shadowsocksr, func(data []byte) (*point.Point, error) {
    21  		data = bytes.TrimPrefix(data, []byte("ssr://"))
    22  		dst := make([]byte, base64.RawStdEncoding.DecodedLen(len(data)))
    23  		_, err := base64.RawURLEncoding.Decode(dst, data)
    24  		if err != nil {
    25  			log.Warn("parse shadowsocksr failed", slog.String("data", string(data)), slog.Any("err", err))
    26  		}
    27  		// ParseLink parse a base64 encode ssr link
    28  		decodeStr := bytes.Split(dst, []byte{'/', '?'})
    29  
    30  		x := strings.Split(string(decodeStr[0]), ":")
    31  		if len(x) != 6 {
    32  			return nil, errors.New("link: " + string(decodeStr[0]) + " is not shadowsocksr link")
    33  		}
    34  		if len(decodeStr) <= 1 {
    35  			decodeStr = append(decodeStr, []byte{})
    36  		}
    37  		query, _ := url.ParseQuery(string(decodeStr[1]))
    38  
    39  		port, err := strconv.ParseUint(x[1], 10, 16)
    40  		if err != nil {
    41  			return nil, errors.New("invalid port")
    42  		}
    43  
    44  		password, err := base64.RawURLEncoding.DecodeString(x[5])
    45  		if err != nil {
    46  			log.Warn("parse shadowsocksr password failed", "err", err)
    47  		}
    48  
    49  		return &point.Point{
    50  			Origin: point.Origin_remote,
    51  			Name:   "[ssr]" + string(yerror.Ignore(base64.RawURLEncoding.DecodeString(query.Get("remarks")))),
    52  			Protocols: []*protocol.Protocol{
    53  				{
    54  					Protocol: &protocol.Protocol_Simple{
    55  						Simple: &protocol.Simple{
    56  							Host: x[0],
    57  							Port: int32(port),
    58  						},
    59  					},
    60  				},
    61  				{
    62  					Protocol: &protocol.Protocol_Shadowsocksr{
    63  						Shadowsocksr: &protocol.Shadowsocksr{
    64  							Server:     x[0],
    65  							Port:       x[1],
    66  							Protocol:   x[2],
    67  							Method:     x[3],
    68  							Obfs:       x[4],
    69  							Password:   string(password),
    70  							Obfsparam:  string(yerror.Ignore(base64.RawURLEncoding.DecodeString(query.Get("obfsparam")))),
    71  							Protoparam: string(yerror.Ignore(base64.RawURLEncoding.DecodeString(query.Get("protoparam")))),
    72  						},
    73  					},
    74  				},
    75  			},
    76  		}, nil
    77  	})
    78  }