From 1357ea0c8f45f21c01a8630ae8f957683be77c53 Mon Sep 17 00:00:00 2001 From: sechmachine <97589681+sechmachine727@users.noreply.github.com> Date: Wed, 29 Jul 2026 11:34:40 +0700 Subject: [PATCH] feat(gateway): parse Apollo inventory and launch replies --- gateway/apollo_management.go | 42 +++++++++++++++++++++++++++++++ gateway/apollo_management_test.go | 16 ++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 gateway/apollo_management.go create mode 100644 gateway/apollo_management_test.go diff --git a/gateway/apollo_management.go b/gateway/apollo_management.go new file mode 100644 index 0000000..50a1e38 --- /dev/null +++ b/gateway/apollo_management.go @@ -0,0 +1,42 @@ +package gateway + +import ( + "encoding/xml" + "strings" +) + +type apolloLaunchResponse struct { + StatusCode string `xml:"status_code,attr"` + SessionURL string `xml:"sessionUrl0"` +} + +func apolloInventoryContains(data []byte, applicationID string) bool { + if len(data) == 0 || len(data) > 64<<10 || applicationID == "" { + return false + } + var document struct { + Applications []struct { + ID string `xml:"ID"` + } `xml:"App"` + } + if xml.Unmarshal(data, &document) != nil { + return false + } + for _, application := range document.Applications { + if strings.TrimSpace(application.ID) == applicationID { + return true + } + } + return false +} + +func parseApolloLaunchResponse(data []byte) (apolloLaunchResponse, error) { + if len(data) == 0 || len(data) > 64<<10 { + return apolloLaunchResponse{}, ErrProviderMalformed + } + var response apolloLaunchResponse + if xml.Unmarshal(data, &response) != nil || response.StatusCode != "200" || strings.TrimSpace(response.SessionURL) == "" { + return apolloLaunchResponse{}, ErrProviderMalformed + } + return response, nil +} diff --git a/gateway/apollo_management_test.go b/gateway/apollo_management_test.go new file mode 100644 index 0000000..5db51a3 --- /dev/null +++ b/gateway/apollo_management_test.go @@ -0,0 +1,16 @@ +package gateway + +import "testing" + +func TestApolloInventoryAndLaunchResponseRequireExactApplicationAndSuccess(t *testing.T) { + inventory := []byte(`4142`) + if !apolloInventoryContains(inventory, "42") || apolloInventoryContains(inventory, "420") { + t.Fatal("apolloInventoryContains() did not require an exact inventory ID") + } + if _, err := parseApolloLaunchResponse([]byte(`rtspenc://apollo.test:47984`)); err != nil { + t.Fatalf("parseApolloLaunchResponse() error = %v", err) + } + if _, err := parseApolloLaunchResponse([]byte(`rtspenc://apollo.test:47984`)); err == nil { + t.Fatal("parseApolloLaunchResponse() accepted a denied launch") + } +}