add /stats endpoint.

This commit is contained in:
m1k1o 2021-03-19 21:33:49 +01:00
parent 9771b551df
commit bbae073104
4 changed files with 55 additions and 10 deletions

View File

@ -33,6 +33,7 @@ For n.eko room management software visit https://github.com/m1k1o/neko-rooms.
- Added `VIDEO_BITRATE` and `AUDIO_BITRATE` in kbit/s to control stream quality (in collaboration with @mbattista).
- Added `MAX_FPS`, where you can specify max WebRTC frame rate. When set to `0`, frame rate won't be capped and you can enjoy your real `60fps` experience. Originally, it was constant at `25fps`.
- Invite links. You can invite people and they don't need to enter passwords by themselves (and get confused about user accounts that do not exits). You can put your password in URL using `?pwd=<your-password>` and it will be automatically used when logging in.
- Added `/stats?pwd=<admin>` endpoint to get total active connections.
### Bugs
- Fixed minor gst pipeline bug.

View File

@ -2,6 +2,7 @@ package http
import (
"context"
"encoding/json"
"fmt"
"net/http"
"os"
@ -23,7 +24,7 @@ type Server struct {
}
func New(conf *config.Server, webSocketHandler types.WebSocketHandler) *Server {
logger := log.With().Str("module", "webrtc").Logger()
logger := log.With().Str("module", "http").Logger()
router := chi.NewRouter()
// router.Use(middleware.Recoverer) // Recover from panics without crashing server
@ -34,6 +35,31 @@ func New(conf *config.Server, webSocketHandler types.WebSocketHandler) *Server {
webSocketHandler.Upgrade(w, r)
})
router.Get("/stats", func(w http.ResponseWriter, r *http.Request) {
password := r.URL.Query().Get("pwd")
isAdmin, err := webSocketHandler.IsAdmin(password)
if err != nil {
w.WriteHeader(http.StatusForbidden)
fmt.Fprint(w, err)
return
}
if !isAdmin {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "bad authorization")
return
}
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(struct{
Connections uint32 `json:"connections"`
}{
Connections: webSocketHandler.TotalConns(),
}); err != nil {
logger.Warn().Err(err).Msg("failed writing json error response")
}
})
router.Get("/health", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("true"))
})

View File

@ -12,4 +12,6 @@ type WebSocketHandler interface {
Start() error
Shutdown() error
Upgrade(w http.ResponseWriter, r *http.Request) error
TotalConns() uint32
IsAdmin(password string) (bool, error)
}

View File

@ -3,6 +3,7 @@ package websocket
import (
"fmt"
"net/http"
"sync/atomic"
"time"
"github.com/gorilla/websocket"
@ -38,6 +39,7 @@ func New(sessions types.SessionManager, remote types.RemoteManager, broadcast ty
banned: make(map[string]bool),
locked: false,
},
conns: 0,
}
}
@ -51,6 +53,7 @@ type WebSocketHandler struct {
remote types.RemoteManager
conf *config.WebSocket
handler *MessageHandler
conns uint32
shutdown chan bool
}
@ -179,18 +182,38 @@ func (ws *WebSocketHandler) Upgrade(w http.ResponseWriter, r *http.Request) erro
Str("address", connection.RemoteAddr().String()).
Msg("new connection created")
atomic.AddUint32(&ws.conns, uint32(1))
defer func() {
ws.logger.
Debug().
Str("session", id).
Str("address", connection.RemoteAddr().String()).
Msg("session ended")
atomic.AddUint32(&ws.conns, ^uint32(0))
}()
ws.handle(connection, id)
return nil
}
func (ws *WebSocketHandler) TotalConns() uint32 {
return atomic.LoadUint32(&ws.conns)
}
func (ws *WebSocketHandler) IsAdmin(password string) (bool, error) {
if password == ws.conf.AdminPassword {
return true, nil
}
if password == ws.conf.Password {
return false, nil
}
return false, fmt.Errorf("invalid password")
}
func (ws *WebSocketHandler) authenticate(r *http.Request) (string, string, bool, error) {
ip := r.RemoteAddr
@ -208,15 +231,8 @@ func (ws *WebSocketHandler) authenticate(r *http.Request) (string, string, bool,
return "", ip, false, fmt.Errorf("no password provided")
}
if passwords[0] == ws.conf.AdminPassword {
return id, ip, true, nil
}
if passwords[0] == ws.conf.Password {
return id, ip, false, nil
}
return "", ip, false, fmt.Errorf("invalid password: %s", passwords[0])
isAdmin, err := ws.IsAdmin(passwords[0])
return id, ip, isAdmin, err
}
func (ws *WebSocketHandler) handle(connection *websocket.Conn, id string) {