summaryrefslogtreecommitdiff
path: root/internal/models/client.go
diff options
context:
space:
mode:
authorsergei <sergei@em-sysadmin.xyz>2026-04-14 06:23:55 +0400
committersergei <sergei@em-sysadmin.xyz>2026-04-14 06:23:55 +0400
commit3d51aa455006903345f554a2dd90034993796114 (patch)
tree62a7be2faf047f5eb7886feebc3b815556f03d7f /internal/models/client.go
downloadvpnem-3d51aa455006903345f554a2dd90034993796114.tar.gz
vpnem-3d51aa455006903345f554a2dd90034993796114.tar.bz2
vpnem-3d51aa455006903345f554a2dd90034993796114.zip
vpnem: VPN infrastructure with load-balanced multi-protocol nodesHEADmain
- Multi-protocol VPS nodes (VLESS-REALITY + Hysteria2 + SOCKS5) - Smart load balancing via recommendation API - Windows/Linux client (Go + Wails + sing-box) - Server API with RealIP detection and connection tracking - Auto-deployment via vpnui control plane - Silent Windows installer with UAC elevation - Load-based server recommendation (no sticky sessions) - Best Server one-click connection workflow
Diffstat (limited to 'internal/models/client.go')
-rw-r--r--internal/models/client.go59
1 files changed, 59 insertions, 0 deletions
diff --git a/internal/models/client.go b/internal/models/client.go
new file mode 100644
index 0000000..f086594
--- /dev/null
+++ b/internal/models/client.go
@@ -0,0 +1,59 @@
+package models
+
+import "time"
+
+// ActiveSession tracks a currently active VPN connection.
+type ActiveSession struct {
+ ClientIP string `json:"client_ip"` // real public IP of client (from X-Forwarded-For)
+ ServerIP string `json:"server_ip"` // VPN server IP they connected to
+ NodeID string `json:"node_id"` // catalog node ID
+ OS string `json:"os"`
+ Version string `json:"version"`
+ ConnectedAt time.Time `json:"connected_at"`
+ LastHeartbeat time.Time `json:"last_seen"`
+}
+
+// StudioRecord tracks a studio's home server assignment.
+// A studio = all clients sharing the same public IP.
+type StudioRecord struct {
+ ClientIP string `json:"client_ip"` // public IP = studio identifier
+ HomeServerIP string `json:"home_server_ip"` // assigned "home" server
+ HomeNodeID string `json:"home_node_id"`
+ HomeAssignedAt time.Time `json:"home_assigned_at"` // when home was assigned
+ TotalClients int `json:"total_clients"` // lifetime client count from this studio
+ LastSeen time.Time `json:"last_seen"`
+}
+
+// ConnectRequest is sent when a client connects.
+// Server determines client_ip from X-Forwarded-For — no client_ip field needed.
+type ConnectRequest struct {
+ ServerIP string `json:"server_ip"`
+ NodeID string `json:"node_id"`
+ OS string `json:"os"`
+ Version string `json:"version"`
+}
+
+// DisconnectRequest is sent when a client disconnects.
+type DisconnectRequest struct {
+ ServerIP string `json:"server_ip"`
+ NodeID string `json:"node_id"`
+}
+
+// RecommendationResponse is returned by the recommendation endpoint.
+type RecommendationResponse struct {
+ RecommendedServerIP string `json:"recommended_server_ip"`
+ RecommendedNodeID string `json:"recommended_node_id"`
+ RecommendedTag string `json:"recommended_tag,omitempty"`
+ Reason string `json:"reason"`
+ IsRebalance bool `json:"is_rebalance"` // true if recommending different server than home
+ LoadInfo string `json:"load_info"` // human-readable load summary
+ StudioClients int `json:"studio_clients"` // active clients from same studio
+}
+
+// ServerLoadInfo contains load data for all servers.
+type ServerLoadInfo struct {
+ ServerIP string `json:"server_ip"`
+ ActiveClients int `json:"active_clients"`
+ LoadPercent int `json:"load_percent"` // 0-100
+ MaxCapacity int `json:"max_capacity"`
+}