mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 08:31:30 +00:00
Fix integration with clash-dashboard
This commit is contained in:
parent
8004ff51f0
commit
3838d3070d
|
@ -7,14 +7,14 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/experimental/clashapi/trafficontroll"
|
||||
"github.com/sagernet/sing-box/experimental/clashapi/trafficontrol"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/render"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
func connectionRouter(trafficManager *trafficontroll.Manager) http.Handler {
|
||||
func connectionRouter(trafficManager *trafficontrol.Manager) http.Handler {
|
||||
r := chi.NewRouter()
|
||||
r.Get("/", getConnections(trafficManager))
|
||||
r.Delete("/", closeAllConnections(trafficManager))
|
||||
|
@ -22,7 +22,7 @@ func connectionRouter(trafficManager *trafficontroll.Manager) http.Handler {
|
|||
return r
|
||||
}
|
||||
|
||||
func getConnections(trafficManager *trafficontroll.Manager) func(w http.ResponseWriter, r *http.Request) {
|
||||
func getConnections(trafficManager *trafficontrol.Manager) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if !websocket.IsWebSocketUpgrade(r) {
|
||||
snapshot := trafficManager.Snapshot()
|
||||
|
@ -72,7 +72,7 @@ func getConnections(trafficManager *trafficontroll.Manager) func(w http.Response
|
|||
}
|
||||
}
|
||||
|
||||
func closeConnection(trafficManager *trafficontroll.Manager) func(w http.ResponseWriter, r *http.Request) {
|
||||
func closeConnection(trafficManager *trafficontrol.Manager) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "id")
|
||||
snapshot := trafficManager.Snapshot()
|
||||
|
@ -86,7 +86,7 @@ func closeConnection(trafficManager *trafficontroll.Manager) func(w http.Respons
|
|||
}
|
||||
}
|
||||
|
||||
func closeAllConnections(trafficManager *trafficontroll.Manager) func(w http.ResponseWriter, r *http.Request) {
|
||||
func closeAllConnections(trafficManager *trafficontrol.Manager) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
snapshot := trafficManager.Snapshot()
|
||||
for _, c := range snapshot.Connections {
|
||||
|
|
|
@ -4,15 +4,13 @@ import (
|
|||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/render"
|
||||
)
|
||||
|
||||
func proxyProviderRouter(server *Server, router adapter.Router) http.Handler {
|
||||
func proxyProviderRouter() http.Handler {
|
||||
r := chi.NewRouter()
|
||||
r.Get("/", getProviders(server, router))
|
||||
r.Get("/", getProviders)
|
||||
|
||||
r.Route("/{name}", func(r chi.Router) {
|
||||
r.Use(parseProviderName, findProviderByName)
|
||||
|
@ -23,36 +21,11 @@ func proxyProviderRouter(server *Server, router adapter.Router) http.Handler {
|
|||
return r
|
||||
}
|
||||
|
||||
func getProviders(server *Server, router adapter.Router) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var proxies []any
|
||||
proxies = append(proxies, render.M{
|
||||
"history": []*DelayHistory{},
|
||||
"name": "DIRECT",
|
||||
"type": "Direct",
|
||||
"udp": true,
|
||||
})
|
||||
proxies = append(proxies, render.M{
|
||||
"history": []*DelayHistory{},
|
||||
"name": "REJECT",
|
||||
"type": "Reject",
|
||||
"udp": true,
|
||||
})
|
||||
for _, detour := range router.Outbounds() {
|
||||
proxies = append(proxies, proxyInfo(server, detour))
|
||||
}
|
||||
func getProviders(w http.ResponseWriter, r *http.Request) {
|
||||
render.JSON(w, r, render.M{
|
||||
"providers": render.M{
|
||||
"default": render.M{
|
||||
"name": "default",
|
||||
"type": "Proxy",
|
||||
"proxies": proxies,
|
||||
"vehicleType": "Compatible",
|
||||
},
|
||||
},
|
||||
"providers": render.M{},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func getProvider(w http.ResponseWriter, r *http.Request) {
|
||||
/*provider := r.Context().Value(CtxKeyProvider).(provider.ProxyProvider)
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/render"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func proxyRouter(server *Server, router adapter.Router) http.Handler {
|
||||
|
@ -85,17 +86,20 @@ func proxyInfo(server *Server, detour adapter.Outbound) *badjson.JSONObject {
|
|||
info.Put("name", detour.Tag())
|
||||
info.Put("udp", common.Contains(detour.Network(), C.NetworkUDP))
|
||||
|
||||
delayHistory, loaded := server.delayHistory[detour.Tag()]
|
||||
if loaded {
|
||||
info.Put("history", []*DelayHistory{delayHistory, delayHistory})
|
||||
} else {
|
||||
info.Put("history", []*DelayHistory{{Time: time.Now()}, {Time: time.Now()}})
|
||||
}
|
||||
|
||||
var delayHistory *DelayHistory
|
||||
var loaded bool
|
||||
if isSelector {
|
||||
selector := detour.(*outbound.Selector)
|
||||
info.Put("now", selector.Now())
|
||||
info.Put("all", selector.All())
|
||||
delayHistory, loaded = server.delayHistory[selector.Now()]
|
||||
} else {
|
||||
delayHistory, loaded = server.delayHistory[detour.Tag()]
|
||||
}
|
||||
if loaded {
|
||||
info.Put("history", []*DelayHistory{delayHistory})
|
||||
} else {
|
||||
info.Put("history", []*DelayHistory{})
|
||||
}
|
||||
return &info
|
||||
}
|
||||
|
@ -103,30 +107,39 @@ func proxyInfo(server *Server, detour adapter.Outbound) *badjson.JSONObject {
|
|||
func getProxies(server *Server, router adapter.Router) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var proxyMap badjson.JSONObject
|
||||
outbounds := common.Filter(router.Outbounds(), func(detour adapter.Outbound) bool {
|
||||
return detour.Tag() != ""
|
||||
})
|
||||
|
||||
allProxies := make([]string, 0, len(outbounds))
|
||||
|
||||
for _, detour := range outbounds {
|
||||
switch detour.Type() {
|
||||
case C.TypeDirect, C.TypeBlock:
|
||||
continue
|
||||
}
|
||||
allProxies = append(allProxies, detour.Tag())
|
||||
}
|
||||
|
||||
defaultTag := router.DefaultOutbound(C.NetworkTCP).Tag()
|
||||
if defaultTag == "" {
|
||||
defaultTag = allProxies[0]
|
||||
}
|
||||
|
||||
sort.Slice(allProxies, func(i, j int) bool {
|
||||
return allProxies[i] == defaultTag
|
||||
})
|
||||
|
||||
// fix clash dashboard
|
||||
proxyMap.Put("DIRECT", map[string]any{
|
||||
"type": "Direct",
|
||||
"name": "DIRECT",
|
||||
"udp": true,
|
||||
"history": []*DelayHistory{},
|
||||
})
|
||||
proxyMap.Put("GLOBAL", map[string]any{
|
||||
"type": "Selector",
|
||||
"type": "Fallback",
|
||||
"name": "GLOBAL",
|
||||
"udp": true,
|
||||
"history": []*DelayHistory{},
|
||||
"all": []string{},
|
||||
"now": "",
|
||||
})
|
||||
proxyMap.Put("REJECT", map[string]any{
|
||||
"type": "Reject",
|
||||
"name": "REJECT",
|
||||
"udp": true,
|
||||
"history": []*DelayHistory{},
|
||||
"all": allProxies,
|
||||
"now": defaultTag,
|
||||
})
|
||||
|
||||
outbounds := router.Outbounds()
|
||||
for i, detour := range outbounds {
|
||||
var tag string
|
||||
if detour.Tag() == "" {
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/experimental/clashapi/trafficontroll"
|
||||
"github.com/sagernet/sing-box/experimental/clashapi/trafficontrol"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
|
@ -30,7 +30,7 @@ var _ adapter.ClashServer = (*Server)(nil)
|
|||
type Server struct {
|
||||
logger log.Logger
|
||||
httpServer *http.Server
|
||||
trafficManager *trafficontroll.Manager
|
||||
trafficManager *trafficontrol.Manager
|
||||
delayHistory map[string]*DelayHistory
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ type DelayHistory struct {
|
|||
}
|
||||
|
||||
func NewServer(router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) *Server {
|
||||
trafficManager := trafficontroll.NewManager()
|
||||
trafficManager := trafficontrol.NewManager()
|
||||
chiRouter := chi.NewRouter()
|
||||
server := &Server{
|
||||
logFactory.NewLogger("clash-api"),
|
||||
|
@ -68,7 +68,7 @@ func NewServer(router adapter.Router, logFactory log.ObservableFactory, options
|
|||
r.Mount("/proxies", proxyRouter(server, router))
|
||||
r.Mount("/rules", ruleRouter(router))
|
||||
r.Mount("/connections", connectionRouter(trafficManager))
|
||||
r.Mount("/providers/proxies", proxyProviderRouter(server, router))
|
||||
r.Mount("/providers/proxies", proxyProviderRouter())
|
||||
r.Mount("/providers/rules", ruleProviderRouter())
|
||||
r.Mount("/script", scriptRouter())
|
||||
r.Mount("/profile", profileRouter())
|
||||
|
@ -106,14 +106,14 @@ func (s *Server) Close() error {
|
|||
}
|
||||
|
||||
func (s *Server) RoutedConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, matchedRule adapter.Rule) net.Conn {
|
||||
return trafficontroll.NewTCPTracker(conn, s.trafficManager, castMetadata(metadata), matchedRule)
|
||||
return trafficontrol.NewTCPTracker(conn, s.trafficManager, castMetadata(metadata), matchedRule)
|
||||
}
|
||||
|
||||
func (s *Server) RoutedPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, matchedRule adapter.Rule) N.PacketConn {
|
||||
return trafficontroll.NewUDPTracker(conn, s.trafficManager, castMetadata(metadata), matchedRule)
|
||||
return trafficontrol.NewUDPTracker(conn, s.trafficManager, castMetadata(metadata), matchedRule)
|
||||
}
|
||||
|
||||
func castMetadata(metadata adapter.InboundContext) trafficontroll.Metadata {
|
||||
func castMetadata(metadata adapter.InboundContext) trafficontrol.Metadata {
|
||||
var inbound string
|
||||
if metadata.Inbound != "" {
|
||||
inbound = metadata.InboundType + "/" + metadata.Inbound
|
||||
|
@ -126,7 +126,7 @@ func castMetadata(metadata adapter.InboundContext) trafficontroll.Metadata {
|
|||
} else {
|
||||
domain = metadata.Destination.Fqdn
|
||||
}
|
||||
return trafficontroll.Metadata{
|
||||
return trafficontrol.Metadata{
|
||||
NetWork: metadata.Network,
|
||||
Type: inbound,
|
||||
SrcIP: metadata.Source.Addr,
|
||||
|
@ -189,7 +189,7 @@ type Traffic struct {
|
|||
Down int64 `json:"down"`
|
||||
}
|
||||
|
||||
func traffic(trafficManager *trafficontroll.Manager) func(w http.ResponseWriter, r *http.Request) {
|
||||
func traffic(trafficManager *trafficontrol.Manager) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var wsConn *websocket.Conn
|
||||
if websocket.IsWebSocketUpgrade(r) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package trafficontroll
|
||||
package trafficontrol
|
||||
|
||||
import (
|
||||
"time"
|
|
@ -1,4 +1,4 @@
|
|||
package trafficontroll
|
||||
package trafficontrol
|
||||
|
||||
import (
|
||||
"net"
|
Loading…
Reference in a new issue