Fix integration with clash-dashboard

This commit is contained in:
世界 2022-07-22 09:29:13 +08:00
parent 8004ff51f0
commit 3838d3070d
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
6 changed files with 58 additions and 72 deletions

View File

@ -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 {

View File

@ -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,35 +21,10 @@ 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))
}
render.JSON(w, r, render.M{
"providers": render.M{
"default": render.M{
"name": "default",
"type": "Proxy",
"proxies": proxies,
"vehicleType": "Compatible",
},
},
})
}
func getProviders(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, render.M{
"providers": render.M{},
})
}
func getProvider(w http.ResponseWriter, r *http.Request) {

View File

@ -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() == "" {

View File

@ -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) {

View File

@ -1,4 +1,4 @@
package trafficontroll
package trafficontrol
import (
"time"

View File

@ -1,4 +1,4 @@
package trafficontroll
package trafficontrol
import (
"net"