github.com/sagernet/sing-box@v1.9.0-rc.20/experimental/clashapi/api_meta.go (about)

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