113 lines
2.9 KiB
Go
113 lines
2.9 KiB
Go
package web
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"time"
|
|
|
|
"ananta-ps/internal/config"
|
|
"ananta-ps/internal/gameserver"
|
|
)
|
|
|
|
type DebugServer struct {
|
|
cfg *config.Config
|
|
gameServer *gameserver.Server
|
|
httpSrv *http.Server
|
|
cancelFunc context.CancelFunc
|
|
}
|
|
|
|
func NewDebug(cfg *config.Config, gameServer *gameserver.Server) *DebugServer {
|
|
return &DebugServer{
|
|
cfg: cfg,
|
|
gameServer: gameServer,
|
|
}
|
|
}
|
|
|
|
func (d *DebugServer) Start() error {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
d.cancelFunc = cancel
|
|
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/", d.handleIndex)
|
|
mux.HandleFunc("/api/status", d.handleStatus)
|
|
|
|
addr := fmt.Sprintf("%s:%d", d.cfg.Network.BindHost, 5809)
|
|
d.httpSrv = &http.Server{
|
|
Addr: addr,
|
|
Handler: mux,
|
|
}
|
|
|
|
ln, err := net.Listen("tcp", addr)
|
|
if err != nil {
|
|
cancel()
|
|
return err
|
|
}
|
|
go func() {
|
|
log.Printf("[DEBUG-API] Debug WebUI panel at http://%s:5809/", d.cfg.Network.AdvertisedHost)
|
|
if err := d.httpSrv.Serve(ln); err != nil && err != http.ErrServerClosed {
|
|
log.Printf("[DEBUG-API] Debug server error: %v", err)
|
|
}
|
|
}()
|
|
|
|
_ = ctx
|
|
return nil
|
|
}
|
|
|
|
func (d *DebugServer) Stop() error {
|
|
if d.cancelFunc != nil {
|
|
d.cancelFunc()
|
|
}
|
|
if d.httpSrv != nil {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
_ = d.httpSrv.Shutdown(ctx)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *DebugServer) handleIndex(w http.ResponseWriter, r *http.Request) {
|
|
html := `<!doctype html>
|
|
<html>
|
|
<head><meta charset="utf-8"><title>Ananta Debug WebUI</title></head>
|
|
<body style="background:#111; color:#eee; font-family:monospace; padding:20px;">
|
|
<h2>Ananta Private Server Debug Monitor (Port 5809)</h2>
|
|
<div id="status">Connecting to runtime...</div>
|
|
<pre id="info" style="margin-top:20px; background:#222; padding:15px; border-radius:5px;"></pre>
|
|
<script>
|
|
async function refresh() {
|
|
try {
|
|
const res = await fetch("/api/status");
|
|
const data = await res.json();
|
|
document.getElementById("status").innerHTML = "Status: <b>ONLINE</b> | Active Sessions: " + data.activeSessions;
|
|
document.getElementById("info").innerText = JSON.stringify(data, null, 2);
|
|
} catch (e) {
|
|
document.getElementById("status").innerText = "Offline: " + e;
|
|
}
|
|
}
|
|
setInterval(refresh, 2000);
|
|
refresh();
|
|
</script>
|
|
</body>
|
|
</html>`
|
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
w.Write([]byte(html))
|
|
}
|
|
|
|
func (d *DebugServer) handleStatus(w http.ResponseWriter, r *http.Request) {
|
|
sessions := d.gameServer.GetActiveSessions()
|
|
data := map[string]interface{}{
|
|
"online": true,
|
|
"version": d.cfg.Client.Version,
|
|
"activeSessions": len(sessions),
|
|
"advertisedHost": d.cfg.Network.AdvertisedHost,
|
|
"gamePort": d.cfg.Network.GamePort,
|
|
"loginPorts": d.cfg.Network.LoginPorts,
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(data)
|
|
}
|