mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-06-22 02:33:49 +03:00
Add http/block outbound & Improve route
This commit is contained in:
@@ -1,31 +0,0 @@
|
||||
package option
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
)
|
||||
|
||||
type ListenAddress netip.Addr
|
||||
|
||||
func (a ListenAddress) MarshalJSON() ([]byte, error) {
|
||||
addr := netip.Addr(a)
|
||||
if !addr.IsValid() {
|
||||
return json.Marshal("")
|
||||
}
|
||||
return json.Marshal(addr.String())
|
||||
}
|
||||
|
||||
func (a *ListenAddress) UnmarshalJSON(bytes []byte) error {
|
||||
var value string
|
||||
err := json.Unmarshal(bytes, &value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
addr, err := netip.ParseAddr(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*a = ListenAddress(addr)
|
||||
return nil
|
||||
}
|
||||
@@ -2,14 +2,15 @@ package option
|
||||
|
||||
import (
|
||||
"github.com/goccy/go-json"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/auth"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
type _Inbound struct {
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Type string `json:"type"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
DirectOptions DirectInboundOptions `json:"-"`
|
||||
SocksOptions SimpleInboundOptions `json:"-"`
|
||||
HTTPOptions SimpleInboundOptions `json:"-"`
|
||||
@@ -22,25 +23,25 @@ type Inbound _Inbound
|
||||
func (h Inbound) Equals(other Inbound) bool {
|
||||
return h.Type == other.Type &&
|
||||
h.Tag == other.Tag &&
|
||||
common.Equals(h.DirectOptions, other.DirectOptions) &&
|
||||
common.Equals(h.SocksOptions, other.SocksOptions) &&
|
||||
common.Equals(h.HTTPOptions, other.HTTPOptions) &&
|
||||
common.Equals(h.MixedOptions, other.MixedOptions) &&
|
||||
common.Equals(h.ShadowsocksOptions, other.ShadowsocksOptions)
|
||||
h.DirectOptions == other.DirectOptions &&
|
||||
h.SocksOptions.Equals(other.SocksOptions) &&
|
||||
h.HTTPOptions.Equals(other.HTTPOptions) &&
|
||||
h.MixedOptions.Equals(other.MixedOptions) &&
|
||||
h.ShadowsocksOptions == other.ShadowsocksOptions
|
||||
}
|
||||
|
||||
func (h Inbound) MarshalJSON() ([]byte, error) {
|
||||
var v any
|
||||
switch h.Type {
|
||||
case "direct":
|
||||
case C.TypeDirect:
|
||||
v = h.DirectOptions
|
||||
case "socks":
|
||||
case C.TypeSocks:
|
||||
v = h.SocksOptions
|
||||
case "http":
|
||||
case C.TypeHTTP:
|
||||
v = h.HTTPOptions
|
||||
case "mixed":
|
||||
case C.TypeMixed:
|
||||
v = h.MixedOptions
|
||||
case "shadowsocks":
|
||||
case C.TypeShadowsocks:
|
||||
v = h.ShadowsocksOptions
|
||||
default:
|
||||
return nil, E.New("unknown inbound type: ", h.Type)
|
||||
@@ -55,15 +56,15 @@ func (h *Inbound) UnmarshalJSON(bytes []byte) error {
|
||||
}
|
||||
var v any
|
||||
switch h.Type {
|
||||
case "direct":
|
||||
case C.TypeDirect:
|
||||
v = &h.DirectOptions
|
||||
case "socks":
|
||||
case C.TypeSocks:
|
||||
v = &h.SocksOptions
|
||||
case "http":
|
||||
case C.TypeHTTP:
|
||||
v = &h.HTTPOptions
|
||||
case "mixed":
|
||||
case C.TypeMixed:
|
||||
v = &h.MixedOptions
|
||||
case "shadowsocks":
|
||||
case C.TypeShadowsocks:
|
||||
v = &h.ShadowsocksOptions
|
||||
default:
|
||||
return nil
|
||||
@@ -99,23 +100,9 @@ type DirectInboundOptions struct {
|
||||
OverridePort uint16 `json:"override_port,omitempty"`
|
||||
}
|
||||
|
||||
func (o DirectInboundOptions) Equals(other DirectInboundOptions) bool {
|
||||
return o.ListenOptions == other.ListenOptions &&
|
||||
common.ComparableSliceEquals(o.Network, other.Network) &&
|
||||
o.OverrideAddress == other.OverrideAddress &&
|
||||
o.OverridePort == other.OverridePort
|
||||
}
|
||||
|
||||
type ShadowsocksInboundOptions struct {
|
||||
ListenOptions
|
||||
Network NetworkList `json:"network,omitempty"`
|
||||
Method string `json:"method"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
func (o ShadowsocksInboundOptions) Equals(other ShadowsocksInboundOptions) bool {
|
||||
return o.ListenOptions == other.ListenOptions &&
|
||||
common.ComparableSliceEquals(o.Network, other.Network) &&
|
||||
o.Method == other.Method &&
|
||||
o.Password == other.Password
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/sagernet/sing-box/common/badjson"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
func ToMap(v any) (*badjson.JSONObject, error) {
|
||||
@@ -33,6 +35,12 @@ func MergeObjects(objects ...any) (*badjson.JSONObject, error) {
|
||||
}
|
||||
|
||||
func MarshallObjects(objects ...any) ([]byte, error) {
|
||||
objects = common.Filter(objects, func(v any) bool {
|
||||
return v != nil
|
||||
})
|
||||
if len(objects) == 1 {
|
||||
return json.Marshal(objects[0])
|
||||
}
|
||||
content, err := MergeObjects(objects...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -53,6 +61,12 @@ func UnmarshallExcluded(inputContent []byte, parentObject any, object any) error
|
||||
for _, key := range parentContent.Keys() {
|
||||
content.Remove(key)
|
||||
}
|
||||
if object == nil {
|
||||
if content.IsEmpty() {
|
||||
return nil
|
||||
}
|
||||
return E.New("unexpected key: ", content.Keys()[0])
|
||||
}
|
||||
inputContent, err = content.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package option
|
||||
|
||||
import "github.com/goccy/go-json"
|
||||
|
||||
type Listable[T comparable] []T
|
||||
|
||||
func (l Listable[T]) MarshalJSON() ([]byte, error) {
|
||||
arrayList := []T(l)
|
||||
if len(arrayList) == 1 {
|
||||
return json.Marshal(arrayList[0])
|
||||
}
|
||||
return json.Marshal(arrayList)
|
||||
}
|
||||
|
||||
func (l *Listable[T]) UnmarshalJSON(bytes []byte) error {
|
||||
err := json.Unmarshal(bytes, (*[]T)(l))
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
var singleItem T
|
||||
err = json.Unmarshal(bytes, &singleItem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*l = []T{singleItem}
|
||||
return nil
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package option
|
||||
|
||||
import (
|
||||
"github.com/goccy/go-json"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
type NetworkList []string
|
||||
|
||||
func (v *NetworkList) UnmarshalJSON(data []byte) error {
|
||||
var networkList []string
|
||||
err := json.Unmarshal(data, &networkList)
|
||||
if err != nil {
|
||||
var networkItem string
|
||||
err = json.Unmarshal(data, &networkItem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
networkList = []string{networkItem}
|
||||
}
|
||||
for _, networkName := range networkList {
|
||||
switch networkName {
|
||||
case C.NetworkTCP, C.NetworkUDP:
|
||||
break
|
||||
default:
|
||||
return E.New("unknown network: " + networkName)
|
||||
}
|
||||
}
|
||||
*v = networkList
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *NetworkList) Build() []string {
|
||||
if len(*v) == 0 {
|
||||
return []string{C.NetworkTCP, C.NetworkUDP}
|
||||
}
|
||||
return *v
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package option
|
||||
|
||||
import (
|
||||
"github.com/goccy/go-json"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
)
|
||||
@@ -11,6 +12,7 @@ type _Outbound struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
DirectOptions DirectOutboundOptions `json:"-"`
|
||||
SocksOptions SocksOutboundOptions `json:"-"`
|
||||
HTTPOptions HTTPOutboundOptions `json:"-"`
|
||||
ShadowsocksOptions ShadowsocksOutboundOptions `json:"-"`
|
||||
}
|
||||
|
||||
@@ -19,12 +21,16 @@ type Outbound _Outbound
|
||||
func (h Outbound) MarshalJSON() ([]byte, error) {
|
||||
var v any
|
||||
switch h.Type {
|
||||
case "direct":
|
||||
case C.TypeDirect:
|
||||
v = h.DirectOptions
|
||||
case "socks":
|
||||
case C.TypeSocks:
|
||||
v = h.SocksOptions
|
||||
case "shadowsocks":
|
||||
case C.TypeHTTP:
|
||||
v = h.HTTPOptions
|
||||
case C.TypeShadowsocks:
|
||||
v = h.ShadowsocksOptions
|
||||
case C.TypeBlock:
|
||||
v = nil
|
||||
default:
|
||||
return nil, E.New("unknown outbound type: ", h.Type)
|
||||
}
|
||||
@@ -38,12 +44,16 @@ func (h *Outbound) UnmarshalJSON(bytes []byte) error {
|
||||
}
|
||||
var v any
|
||||
switch h.Type {
|
||||
case "direct":
|
||||
case C.TypeDirect:
|
||||
v = &h.DirectOptions
|
||||
case "socks":
|
||||
case C.TypeSocks:
|
||||
v = &h.SocksOptions
|
||||
case "shadowsocks":
|
||||
case C.TypeHTTP:
|
||||
v = &h.HTTPOptions
|
||||
case C.TypeShadowsocks:
|
||||
v = &h.ShadowsocksOptions
|
||||
case C.TypeBlock:
|
||||
v = nil
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@@ -71,10 +81,8 @@ type OverrideStreamOptions struct {
|
||||
UDPOverTCP bool `json:"udp_over_tcp,omitempty"`
|
||||
}
|
||||
|
||||
type DirectOutboundOptions struct {
|
||||
DialerOptions
|
||||
OverrideAddress string `json:"override_address,omitempty"`
|
||||
OverridePort uint16 `json:"override_port,omitempty"`
|
||||
func (o *OverrideStreamOptions) IsValid() bool {
|
||||
return o != nil && (o.TLS || o.UDPOverTCP)
|
||||
}
|
||||
|
||||
type ServerOptions struct {
|
||||
@@ -86,10 +94,24 @@ func (o ServerOptions) Build() M.Socksaddr {
|
||||
return M.ParseSocksaddrHostPort(o.Server, o.ServerPort)
|
||||
}
|
||||
|
||||
type DirectOutboundOptions struct {
|
||||
DialerOptions
|
||||
OverrideAddress string `json:"override_address,omitempty"`
|
||||
OverridePort uint16 `json:"override_port,omitempty"`
|
||||
}
|
||||
|
||||
type SocksOutboundOptions struct {
|
||||
DialerOptions
|
||||
ServerOptions
|
||||
Version string `json:"version,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Network NetworkList `json:"network,omitempty"`
|
||||
}
|
||||
|
||||
type HTTPOutboundOptions struct {
|
||||
DialerOptions
|
||||
ServerOptions
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
}
|
||||
@@ -97,6 +119,7 @@ type SocksOutboundOptions struct {
|
||||
type ShadowsocksOutboundOptions struct {
|
||||
DialerOptions
|
||||
ServerOptions
|
||||
Method string `json:"method"`
|
||||
Password string `json:"password"`
|
||||
Method string `json:"method"`
|
||||
Password string `json:"password"`
|
||||
Network NetworkList `json:"network,omitempty"`
|
||||
}
|
||||
|
||||
@@ -8,8 +8,9 @@ import (
|
||||
)
|
||||
|
||||
type RouteOptions struct {
|
||||
GeoIP *GeoIPOptions `json:"geoip,omitempty"`
|
||||
Rules []Rule `json:"rules,omitempty"`
|
||||
GeoIP *GeoIPOptions `json:"geoip,omitempty"`
|
||||
Rules []Rule `json:"rules,omitempty"`
|
||||
DefaultDetour string `json:"default_detour,omitempty"`
|
||||
}
|
||||
|
||||
func (o RouteOptions) Equals(other RouteOptions) bool {
|
||||
@@ -24,17 +25,17 @@ type GeoIPOptions struct {
|
||||
}
|
||||
|
||||
type _Rule struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
DefaultOptions *DefaultRule `json:"-"`
|
||||
LogicalOptions *LogicalRule `json:"-"`
|
||||
Type string `json:"type,omitempty"`
|
||||
DefaultOptions DefaultRule `json:"-"`
|
||||
LogicalOptions LogicalRule `json:"-"`
|
||||
}
|
||||
|
||||
type Rule _Rule
|
||||
|
||||
func (r Rule) Equals(other Rule) bool {
|
||||
return r.Type == other.Type &&
|
||||
common.PtrEquals(r.DefaultOptions, other.DefaultOptions) &&
|
||||
common.PtrEquals(r.LogicalOptions, other.LogicalOptions)
|
||||
r.DefaultOptions.Equals(other.DefaultOptions) &&
|
||||
r.LogicalOptions.Equals(other.LogicalOptions)
|
||||
}
|
||||
|
||||
func (r Rule) MarshalJSON() ([]byte, error) {
|
||||
|
||||
90
option/types.go
Normal file
90
option/types.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package option
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"strings"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
type ListenAddress netip.Addr
|
||||
|
||||
func (a ListenAddress) MarshalJSON() ([]byte, error) {
|
||||
addr := netip.Addr(a)
|
||||
if !addr.IsValid() {
|
||||
return json.Marshal("")
|
||||
}
|
||||
return json.Marshal(addr.String())
|
||||
}
|
||||
|
||||
func (a *ListenAddress) UnmarshalJSON(content []byte) error {
|
||||
var value string
|
||||
err := json.Unmarshal(content, &value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
addr, err := netip.ParseAddr(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*a = ListenAddress(addr)
|
||||
return nil
|
||||
}
|
||||
|
||||
type NetworkList string
|
||||
|
||||
func (v *NetworkList) UnmarshalJSON(content []byte) error {
|
||||
var networkList []string
|
||||
err := json.Unmarshal(content, &networkList)
|
||||
if err != nil {
|
||||
var networkItem string
|
||||
err = json.Unmarshal(content, &networkItem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
networkList = []string{networkItem}
|
||||
}
|
||||
for _, networkName := range networkList {
|
||||
switch networkName {
|
||||
case C.NetworkTCP, C.NetworkUDP:
|
||||
break
|
||||
default:
|
||||
return E.New("unknown network: " + networkName)
|
||||
}
|
||||
}
|
||||
*v = NetworkList(strings.Join(networkList, "\n"))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v NetworkList) Build() []string {
|
||||
if v == "" {
|
||||
return []string{C.NetworkTCP, C.NetworkUDP}
|
||||
}
|
||||
return strings.Split(string(v), "\n")
|
||||
}
|
||||
|
||||
type Listable[T comparable] []T
|
||||
|
||||
func (l Listable[T]) MarshalJSON() ([]byte, error) {
|
||||
arrayList := []T(l)
|
||||
if len(arrayList) == 1 {
|
||||
return json.Marshal(arrayList[0])
|
||||
}
|
||||
return json.Marshal(arrayList)
|
||||
}
|
||||
|
||||
func (l *Listable[T]) UnmarshalJSON(content []byte) error {
|
||||
err := json.Unmarshal(content, (*[]T)(l))
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
var singleItem T
|
||||
err = json.Unmarshal(content, &singleItem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*l = []T{singleItem}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user