Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial implementation of Mesh Agent and Multipoint Groups #295

Merged
merged 10 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ dump_*
irdma/

# for gRPC protos
media-proxy/protos/controller.grpc.pb.cc
media-proxy/protos/controller.grpc.pb.h
media-proxy/protos/controller.pb.cc
media-proxy/protos/controller.pb.h
*.pb.cc
*.pb.h
*.pb.go

# for VS Code settings
.vscode/*
Expand Down
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ set(MP_TESTS_DIR ${MP_DIR}/tests)
set(SDK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sdk)
set(SDK_TESTS_DIR ${SDK_DIR}/tests)
set(SDK_INCLUDE_DIR ${SDK_DIR}/include)
set(AGENT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/control-plane-agent)
set(TESTS_VAL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests/validation)

# Setup output folder
Expand All @@ -34,7 +35,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

add_subdirectory(${SDK_DIR})
add_subdirectory(${MP_DIR})

add_subdirectory(${AGENT_DIR})

# Fetch google test dependencies
include(FetchContent)
Expand All @@ -54,4 +55,4 @@ if (BUILD_UNIT_TESTS)
target_link_libraries(media_proxy_lib PUBLIC mcm_dp gtest gmock gtest_main)
else()
target_link_libraries(media_proxy_lib PUBLIC mcm_dp)
endif()
endif()
8 changes: 5 additions & 3 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ as_root ldconfig

# Run unit tests
export LD_LIBRARY_PATH="${PREFIX_DIR}/usr/local/lib:/usr/local/lib64"
ctest --output-on-failure --test-dir "${MCM_BUILD_DIR}" -V

"${MCM_BUILD_DIR}/bin/sdk_unit_tests"
"${MCM_BUILD_DIR}/bin/media_proxy_unit_tests"
tszumski marked this conversation as resolved.
Show resolved Hide resolved
ln -sf "${MCM_BUILD_DIR}" "${SCRIPT_DIR}/build"

log_info "Build Succeeded"
function print_success() { echo -e "\e[48;2;0;255;0;30m $* \e[0m"; }

print_success "Build Succeeded"
Mionsz marked this conversation as resolved.
Show resolved Hide resolved
75 changes: 75 additions & 0 deletions control-plane-agent/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation
#
# SPDX-License-Identifier: BSD-3-Clause

cmake_minimum_required(VERSION 3.10)

# Project name
project(ControlPlaneAgent)

# Set the Go compiler
find_program(GO_EXECUTABLE NAMES go)

if(NOT GO_EXECUTABLE)
message(FATAL_ERROR "Go compiler not found. Please install Go.")
endif()

# Find the protoc compiler
find_program(PROTOC_EXECUTABLE NAMES protoc)

if(NOT PROTOC_EXECUTABLE)
message(FATAL_ERROR "protoc compiler not found. Please install Protocol Buffers.")
endif()

# Define the paths to the protoc-gen-go and protoc-gen-go-grpc plugins
set(PROTOC_GEN_GO_EXECUTABLE "$ENV{HOME}/go/bin/protoc-gen-go")
set(PROTOC_GEN_GO_GRPC_EXECUTABLE "$ENV{HOME}/go/bin/protoc-gen-go-grpc")

if(NOT EXISTS ${PROTOC_GEN_GO_EXECUTABLE})
message(FATAL_ERROR "protoc-gen-go plugin not found. Please install the Go Protocol Buffers plugin.")
endif()

if(NOT EXISTS ${PROTOC_GEN_GO_GRPC_EXECUTABLE})
message(FATAL_ERROR "protoc-gen-go-grpc plugin not found. Please install the Go gRPC plugin.")
endif()

# Define the source directory and the main Go file
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmd/mesh-agent")
set(MAIN_GO_FILE "${SOURCE_DIR}/mesh-agent.go")
set(CMAKE_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/bin)

# Define the proto file and the output directory for generated code
set(PROTO_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../protos/mediaproxy.proto")
set(GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/api/proxy/proto/mediaproxy")

# Define the output directory for the executable
set(OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../_build/mcm/bin")

# Create the output directories if they don't exist
file(MAKE_DIRECTORY ${OUTPUT_DIR})
file(MAKE_DIRECTORY ${GENERATED_DIR})

# Define the output executable name
set(EXECUTABLE_NAME "mesh-agent")

# Add a custom target to generate gRPC code from the proto file
add_custom_target(generate_grpc
COMMAND ${PROTOC_EXECUTABLE}
--proto_path=${CMAKE_CURRENT_SOURCE_DIR}/../protos
--go_out=paths=source_relative:${GENERATED_DIR}
--go-grpc_out=paths=source_relative:${GENERATED_DIR}
--plugin=protoc-gen-go=${PROTOC_GEN_GO_EXECUTABLE}
--plugin=protoc-gen-go-grpc=${PROTOC_GEN_GO_GRPC_EXECUTABLE}
${PROTO_FILE}
COMMENT "Generating gRPC code from proto file..."
)

# Add a custom target to build the Go project
add_custom_target(build ALL
COMMAND ${GO_EXECUTABLE} build -o ${OUTPUT_DIR}/${EXECUTABLE_NAME} ${MAIN_GO_FILE}
WORKING_DIRECTORY ${SOURCE_DIR}
COMMENT "Building Go project..."
DEPENDS generate_grpc
)

install(PROGRAMS ${OUTPUT_DIR}/${EXECUTABLE_NAME} DESTINATION ${CMAKE_INSTALL_PATH})
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