github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/experimental/clashapi/api_meta.go (about)

     1  package clashapi
     2  
     3  import (
     4  	"bytes"
     5  	"net/http"
     6  	"time"
     7  
     8  	"github.com/inazumav/sing-box/common/json"
     9  	"github.com/inazumav/sing-box/experimental/clashapi/trafficontrol"
    10  	"github.com/sagernet/websocket"
    11  
    12  	"github.com/go-chi/chi/v5"
    13  	"github.com/go-chi/render"
    14  )
    15  
    16  // API created by Clash.Meta
    17  
    18  func (s *Server) setupMetaAPI(r chi.Router) {
    19  	r.Get("/memory", memory(s.trafficManager))
    20  	r.Mount("/group", groupRouter(s))
    21  }
    22  
    23  type Memory struct {
    24  	Inuse   uint64 `json:"inuse"`
    25  	OSLimit uint64 `json:"oslimit"` // maybe we need it in the future
    26  }
    27  
    28  func memory(trafficManager *trafficontrol.Manager) func(w http.ResponseWriter, r *http.Request) {
    29  	return func(w http.ResponseWriter, r *http.Request) {
    30  		var wsConn *websocket.Conn
    31  		if websocket.IsWebSocketUpgrade(r) {
    32  			var err error
    33  			wsConn, err = upgrader.Upgrade(w, r, nil)
    34  			if err != nil {
    35  				return
    36  			}
    37  		}
    38  
    39  		if wsConn == nil {
    40  			w.Header().Set("Content-Type", "application/json")
    41  			render.Status(r, http.StatusOK)
    42  		}
    43  
    44  		tick := time.NewTicker(time.Second)
    45  		defer tick.Stop()
    46  		buf := &bytes.Buffer{}
    47  		var err error
    48  		first := true
    49  		for range tick.C {
    50  			buf.Reset()
    51  
    52  			inuse := trafficManager.Snapshot().Memory
    53  
    54  			// make chat.js begin with zero
    55  			// this is shit var,but we need output 0 for first time
    56  			if first {
    57  				first = false
    58  				inuse = 0
    59  			}
    60  			if err := json.NewEncoder(buf).Encode(Memory{
    61  				Inuse:   inuse,
    62  				OSLimit: 0,
    63  			}); err != nil {
    64  				break
    65  			}
    66  			if wsConn == nil {
    67  				_, err = w.Write(buf.Bytes())
    68  				w.(http.Flusher).Flush()
    69  			} else {
    70  				err = wsConn.WriteMessage(websocket.TextMessage, buf.Bytes())
    71  			}
    72  
    73  			if err != nil {
    74  				break
    75  			}
    76  		}
    77  	}
    78  }