feat: expose validated assignment endpoints

This commit is contained in:
Josh Creek
2026-09-01 08:17:39 +01:00
parent 0cdb60c0d9
commit 467c25b20c
7 changed files with 51 additions and 8 deletions
+15 -1
View File
@@ -11,6 +11,7 @@ import (
"encoding/json"
"errors"
"io"
"net"
"net/http"
"strconv"
"strings"
@@ -58,6 +59,7 @@ type AssignmentView struct {
ProtocolVersion int `json:"protocol_version"`
Transport string `json:"transport"`
JoinAuthorisation string `json:"join_authorisation"`
Endpoint string `json:"endpoint"`
// Revision is routing metadata for the event stream, not part of the v1
// assignment response. Keeping it alongside the durable view prevents the
// REST recovery boundary from emitting a synthetic revision zero.
@@ -509,7 +511,7 @@ func (s *Service) assignment(w http.ResponseWriter, r *http.Request) {
writeError(w, http.StatusNotFound, "not_found")
return
}
if view.ServerID == "" || view.Slot < 0 || view.Slot > 5 || view.ProtocolVersion < 1 || (view.Transport != "enet" && view.Transport != "steam_sdr") || view.JoinAuthorisation == "" || view.ExpiresAt.IsZero() || !now.Before(view.ExpiresAt) {
if view.ServerID == "" || view.Slot < 0 || view.Slot > 5 || view.ProtocolVersion < 1 || (view.Transport != "enet" && view.Transport != "steam_sdr") || view.JoinAuthorisation == "" || !validAssignmentEndpoint(view.Endpoint) || view.ExpiresAt.IsZero() || !now.Before(view.ExpiresAt) {
writeError(w, http.StatusServiceUnavailable, "assignment_unavailable")
return
}
@@ -517,6 +519,18 @@ func (s *Service) assignment(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusOK, view)
}
func validAssignmentEndpoint(endpoint string) bool {
if endpoint == "" || strings.ContainsAny(endpoint, "/?#") {
return false
}
host, portText, err := net.SplitHostPort(endpoint)
if err != nil || host == "" {
return false
}
port, err := strconv.Atoi(portText)
return err == nil && port >= 1 && port <= 65535
}
func assignmentChangedEvent(view AssignmentView, now time.Time) ControlPlaneEvent {
return ControlPlaneEvent{Event: "assignment_changed", Revision: view.Revision, ResourceID: view.MatchID, OccurredAt: now, MatchID: view.MatchID, ServerID: view.ServerID, PlayerID: view.PlayerID}
}