Skip to content

Commit

Permalink
Add MCM Agent
Browse files Browse the repository at this point in the history
* Implement Media Proxy registry.
* Implement Connection registry.
* Implement Bridge registry.
* Implement Multipoint Group registry.
* Implement basic business logic to control the lifecycle of
Multpoint Groups.
* Implement gRPC API server to interface with Media Proxies.
* Implement collection of metrics received from Media Proxies.

Signed-off-by: Konstantin Ilichev <[email protected]>
  • Loading branch information
ko80 committed Dec 9, 2024
1 parent 78bb4a3 commit a667968
Show file tree
Hide file tree
Showing 50 changed files with 6,490 additions and 0 deletions.
4 changes: 4 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,8 @@ export LD_LIBRARY_PATH="${PREFIX_DIR}/usr/local/lib:/usr/local/lib64"
"${MCM_BUILD_DIR}/bin/media_proxy_unit_tests"
ln -sf "${MCM_BUILD_DIR}" "${SCRIPT_DIR}/build"

# Build Control Plane Agent
"${SCRIPT_DIR}/control-plane-agent/scripts/generate-grpc.sh"
"${SCRIPT_DIR}/control-plane-agent/scripts/build.sh"

log_info "Build Succeeded"
97 changes: 97 additions & 0 deletions control-plane-agent/api/control-plane/bridge.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: BSD-3-Clause
*/

package controlplane

import (
"encoding/json"
"errors"
"net/http"

"github.com/gorilla/mux"

"control-plane-agent/internal/model"
"control-plane-agent/internal/registry"
)

func (a *API) ListBridges(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
addStatus := query.Has("status")
addConfig := query.Has("config")

items, err := registry.BridgeRegistry.List(r.Context(), nil, addStatus, addConfig)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

resp := struct {
Bridge []model.Bridge `json:"bridge"`
}{
Bridge: items,
}
applyContentTypeHeaderJSON(w)
json.NewEncoder(w).Encode(resp)
}

func (a *API) GetBridge(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]
addConfig := r.URL.Query().Has("config")

item, err := registry.BridgeRegistry.Get(r.Context(), id, addConfig)
if errors.Is(err, registry.ErrResourceNotFound) {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

item.Id = "" // hide the id in JSON (omitempty)

applyContentTypeHeaderJSON(w)
json.NewEncoder(w).Encode(item)
}

func (a *API) AddBridge(w http.ResponseWriter, r *http.Request) {
// DEBUG
proxyId := r.URL.Query().Get("proxy")
groupId := r.URL.Query().Get("group")
// DEBUG

bridge := model.Bridge{
ProxyId: proxyId,
GroupId: groupId,
Config: &model.BridgeConfig{},
Status: &model.ConnectionStatus{},
}

id, err := registry.BridgeRegistry.Add(r.Context(), bridge)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

bridge = model.Bridge{Id: id}

applyContentTypeHeaderJSON(w)
json.NewEncoder(w).Encode(bridge)
}

func (a *API) DeleteBridge(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

err := registry.BridgeRegistry.Delete(r.Context(), id)
if errors.Is(err, registry.ErrResourceNotFound) {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
}
94 changes: 94 additions & 0 deletions control-plane-agent/api/control-plane/conn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: BSD-3-Clause
*/

package controlplane

import (
"encoding/json"
"errors"
"net/http"

"github.com/gorilla/mux"

"control-plane-agent/internal/model"
"control-plane-agent/internal/registry"
)

func (a *API) ListConnections(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
addStatus := query.Has("status")
addConfig := query.Has("config")

items, err := registry.ConnRegistry.List(r.Context(), nil, addStatus, addConfig)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

resp := struct {
Conn []model.Connection `json:"connection"`
}{
Conn: items,
}
applyContentTypeHeaderJSON(w)
json.NewEncoder(w).Encode(resp)
}

func (a *API) GetConnection(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]
addConfig := r.URL.Query().Has("config")

item, err := registry.ConnRegistry.Get(r.Context(), id, addConfig)
if errors.Is(err, registry.ErrResourceNotFound) {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

item.Id = "" // hide the id in JSON (omitempty)

applyContentTypeHeaderJSON(w)
json.NewEncoder(w).Encode(item)
}

func (a *API) AddConnection(w http.ResponseWriter, r *http.Request) {

conn := model.Connection{
Status: &model.ConnectionStatus{},
Config: &model.ConnectionConfig{
Conn: model.ConnectionST2110{},
// Payload: model.PayloadVideo{},
},
}

id, err := registry.ConnRegistry.Add(r.Context(), conn)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

conn = model.Connection{Id: id}

applyContentTypeHeaderJSON(w)
json.NewEncoder(w).Encode(conn)
}

func (a *API) DeleteConnection(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]

err := registry.ConnRegistry.Delete(r.Context(), id)
if errors.Is(err, registry.ErrResourceNotFound) {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
}
Loading

0 comments on commit a667968

Please sign in to comment.