Skip to content
This repository has been archived by the owner on Aug 21, 2023. It is now read-only.

Commit

Permalink
NLMF support
Browse files Browse the repository at this point in the history
Signed-off-by: Mathis Joffre <[email protected]>
  • Loading branch information
Joffref committed Jan 28, 2023
1 parent af0d29c commit f3f3238
Show file tree
Hide file tree
Showing 13 changed files with 789 additions and 180 deletions.
31 changes: 31 additions & 0 deletions fivegc/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package fivegc

import "net/http"

// ClientConfiguration stores the configuration of the API client
type ClientConfiguration struct {
Host string `json:"host,omitempty"`
Scheme string `json:"scheme,omitempty"`
DefaultHeader map[string]string `json:"defaultHeader,omitempty"`
UserAgent string `json:"userAgent,omitempty"`
Debug bool `json:"debug,omitempty"`
Servers ServerConfigurations
OperationServers map[string]ServerConfigurations
HTTPClient *http.Client
}

type ServerConfigurations []ServerConfiguration

// ServerConfiguration stores the information about a server
type ServerConfiguration struct {
URL string
Description string
Variables map[string]ServerVariable
}

// ServerVariable stores the information about a server variable
type ServerVariable struct {
Description string
DefaultValue string
EnumValues []string
}
111 changes: 111 additions & 0 deletions fivegc/nlmf/broadcast.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package nlmf

import (
"context"
"github.com/5GCoreNet/5GCoreNetSDK/fivegc"
"github.com/5GCoreNet/5GCoreNetSDK/internal/header"
openapinlmfbroadcastclient "github.com/5GCoreNet/client-openapi/Nlmf_Broadcast"
openapinlmfbroadcastserver "github.com/5GCoreNet/server-openapi/Nlmf_Broadcast"
"github.com/gin-gonic/gin"
)

type Broadcast interface {
// Error returns a problem details, it is used to handle errors when unmarshalling the request.
Error(ctx context.Context, err error) openapinlmfbroadcastserver.ProblemDetails
// CipherKeyData returns a cipher response data, a problem details, a redirect response and a status code.
CipherKeyData(context.Context, openapinlmfbroadcastserver.CipherRequestData) (openapinlmfbroadcastserver.CipherResponseData, openapinlmfbroadcastserver.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode)
}

func attachBroadcastHandler(router *gin.RouterGroup, b Broadcast) {
group := router.Group("/nlmf-broadcast/v1")
{
group.POST("/cipher-key-data", func(c *gin.Context) {
var req openapinlmfbroadcastserver.CipherRequestData
if err := c.ShouldBindJSON(&req); err != nil {
problemDetails := b.Error(c, err)
c.JSON(int(problemDetails.Status), problemDetails)
return
}
res, problemDetails, redirectResponse, status := b.CipherKeyData(c, req)
switch status {
case fivegc.StatusOK:
c.JSON(status.ToInt(), res)
case fivegc.StatusTemporaryRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
c.JSON(status.ToInt(), redirectResponse)
case fivegc.StatusPermanentRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
c.JSON(status.ToInt(), redirectResponse)
default:
c.JSON(status.ToInt(), problemDetails)
}
return
})
}
}

// BroadcastClient is a client for the Nlmf_Broadcast service.
type BroadcastClient struct {
client *openapinlmfbroadcastclient.APIClient
}

// NewBroadcastClient creates a new client for the Nlmf_Broadcast service.
func NewBroadcastClient(cfg fivegc.ClientConfiguration) *BroadcastClient {
openapiCfg := &openapinlmfbroadcastclient.Configuration{
Host: cfg.Host,
Scheme: cfg.Scheme,
DefaultHeader: cfg.DefaultHeader,
UserAgent: cfg.UserAgent,
Debug: cfg.Debug,
Servers: []openapinlmfbroadcastclient.ServerConfiguration{},
OperationServers: make(map[string]openapinlmfbroadcastclient.ServerConfigurations),
HTTPClient: cfg.HTTPClient,
}
for _, server := range cfg.Servers {
openapiServer := openapinlmfbroadcastclient.ServerConfiguration{
URL: server.URL,
Description: server.Description,
Variables: make(map[string]openapinlmfbroadcastclient.ServerVariable),
}
for name, variable := range server.Variables {
openapiServer.Variables[name] = openapinlmfbroadcastclient.ServerVariable{
Description: variable.Description,
DefaultValue: variable.DefaultValue,
EnumValues: variable.EnumValues,
}
}
openapiCfg.Servers = append(openapiCfg.Servers, openapiServer)
}
for name, servers := range cfg.OperationServers {
openapiServers := make(openapinlmfbroadcastclient.ServerConfigurations, len(servers))
for i, server := range servers {
openapiServers[i] = openapinlmfbroadcastclient.ServerConfiguration{
URL: server.URL,
Description: server.Description,
Variables: make(map[string]openapinlmfbroadcastclient.ServerVariable),
}
for name, variable := range server.Variables {
openapiServers[i].Variables[name] = openapinlmfbroadcastclient.ServerVariable{
Description: variable.Description,
DefaultValue: variable.DefaultValue,
EnumValues: variable.EnumValues,
}
}
}
openapiCfg.OperationServers[name] = openapiServers
}
return &BroadcastClient{
client: openapinlmfbroadcastclient.NewAPIClient(openapiCfg),
}
}

// CipheringKeyData returns a cipher request.
func (c *BroadcastClient) CipheringKeyData(ctx context.Context) openapinlmfbroadcastclient.ApiCipheringKeyDataRequest {
return c.client.RequestCipheringKeyDataApi.CipheringKeyData(ctx)
}

// CipheringKeyDataExecute executes a cipher request.
func (c *BroadcastClient) CipheringKeyDataExecute(r openapinlmfbroadcastclient.ApiCipheringKeyDataRequest) (*openapinlmfbroadcastclient.CipherResponseData, error) {
resp, _, err := r.Execute()
return resp, err
}
181 changes: 181 additions & 0 deletions fivegc/nlmf/location.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package nlmf

import (
"context"
"github.com/5GCoreNet/5GCoreNetSDK/fivegc"
"github.com/5GCoreNet/5GCoreNetSDK/internal/header"
openapinlmflocationclient "github.com/5GCoreNet/client-openapi/Nlmf_Location"
openapinlmflocationserver "github.com/5GCoreNet/server-openapi/Nlmf_Location"
"github.com/gin-gonic/gin"
"net/http"
)

type Location interface {
// Error returns a problem details, it is used to handle errors when unmarshalling the request.
Error(ctx context.Context, err error) openapinlmflocationserver.ProblemDetails
// CancelLocation cancels a location request.
CancelLocation(context.Context, openapinlmflocationserver.CancelLocData) (openapinlmflocationserver.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode)
// DetermineLocation determines the location of a UE.
DetermineLocation(context.Context, openapinlmflocationserver.InputData) (openapinlmflocationserver.LocationData, openapinlmflocationserver.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode)
// LocationContextTransfer transfers the location context of a UE.
LocationContextTransfer(context.Context, openapinlmflocationserver.LocContextData) (openapinlmflocationserver.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode)
}

func attachLocationHandler(router *gin.RouterGroup, l Location) {
group := router.Group("/nlmf-loc/v1")
{
group.POST("/cancel-location", func(c *gin.Context) {
var req openapinlmflocationserver.CancelLocData
if err := c.ShouldBindJSON(&req); err != nil {
problemDetails := l.Error(c, err)
c.JSON(int(problemDetails.Status), problemDetails)
return
}
problemDetails, redirectResponse, status := l.CancelLocation(c, req)
switch status {
case fivegc.StatusNoContent:
c.JSON(status.ToInt(), nil)
case fivegc.StatusTemporaryRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
c.JSON(status.ToInt(), redirectResponse)
case fivegc.StatusPermanentRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
c.JSON(status.ToInt(), redirectResponse)
default:
c.JSON(status.ToInt(), problemDetails)
}
return
})
group.POST("/determine-location", func(c *gin.Context) {
var req openapinlmflocationserver.InputData
if err := c.ShouldBindJSON(&req); err != nil {
problemDetails := l.Error(c, err)
c.JSON(int(problemDetails.Status), problemDetails)
return
}
res, problemDetails, redirectResponse, status := l.DetermineLocation(c, req)
switch status {
case fivegc.StatusOK:
c.JSON(status.ToInt(), res)
case fivegc.StatusNoContent:
c.JSON(status.ToInt(), nil)
case fivegc.StatusTemporaryRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
c.JSON(status.ToInt(), redirectResponse)
case fivegc.StatusPermanentRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
c.JSON(status.ToInt(), redirectResponse)
default:
c.JSON(status.ToInt(), problemDetails)
}
return
})
group.POST("/location-context-transfer", func(c *gin.Context) {
var req openapinlmflocationserver.LocContextData
if err := c.ShouldBindJSON(&req); err != nil {
problemDetails := l.Error(c, err)
c.JSON(int(problemDetails.Status), problemDetails)
return
}
problemDetails, redirectResponse, status := l.LocationContextTransfer(c, req)
switch status {
case fivegc.StatusNoContent:
c.JSON(status.ToInt(), nil)
case fivegc.StatusTemporaryRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
c.JSON(status.ToInt(), redirectResponse)
case fivegc.StatusPermanentRedirect:
header.BindRedirectHeader(c, redirectResponse.RedirectHeader)
c.JSON(status.ToInt(), redirectResponse)
default:
c.JSON(status.ToInt(), problemDetails)
}
return
})
}
}

// LocationClient is a client for the Nlmf_location service.
type LocationClient struct {
client *openapinlmflocationclient.APIClient
}

// NewLocationClient creates a new client for the Nlmf_location service.
func NewLocationClient(cfg fivegc.ClientConfiguration) *LocationClient {
openapiCfg := &openapinlmflocationclient.Configuration{
Host: cfg.Host,
Scheme: cfg.Scheme,
DefaultHeader: cfg.DefaultHeader,
UserAgent: cfg.UserAgent,
Debug: cfg.Debug,
Servers: []openapinlmflocationclient.ServerConfiguration{},
OperationServers: make(map[string]openapinlmflocationclient.ServerConfigurations),
HTTPClient: cfg.HTTPClient,
}
for _, server := range cfg.Servers {
openapiServer := openapinlmflocationclient.ServerConfiguration{
URL: server.URL,
Description: server.Description,
Variables: make(map[string]openapinlmflocationclient.ServerVariable),
}
for name, variable := range server.Variables {
openapiServer.Variables[name] = openapinlmflocationclient.ServerVariable{
Description: variable.Description,
DefaultValue: variable.DefaultValue,
EnumValues: variable.EnumValues,
}
}
openapiCfg.Servers = append(openapiCfg.Servers, openapiServer)
}
for name, servers := range cfg.OperationServers {
openapiServers := make(openapinlmflocationclient.ServerConfigurations, len(servers))
for i, server := range servers {
openapiServers[i] = openapinlmflocationclient.ServerConfiguration{
URL: server.URL,
Description: server.Description,
Variables: make(map[string]openapinlmflocationclient.ServerVariable),
}
for name, variable := range server.Variables {
openapiServers[i].Variables[name] = openapinlmflocationclient.ServerVariable{
Description: variable.Description,
DefaultValue: variable.DefaultValue,
EnumValues: variable.EnumValues,
}
}
}
openapiCfg.OperationServers[name] = openapiServers
}
return &LocationClient{
client: openapinlmflocationclient.NewAPIClient(openapiCfg),
}
}

// LocationContextTransfer returns location context transfer request
func (l LocationClient) LocationContextTransfer(ctx context.Context) openapinlmflocationclient.ApiLocationContextTransferRequest {
return l.client.LocationContextTransferApi.LocationContextTransfer(ctx)
}

// LocationContextTransferExecute executes the location context transfer request
func (l LocationClient) LocationContextTransferExecute(r openapinlmflocationclient.ApiLocationContextTransferRequest) (*http.Response, error) {
return r.Execute()
}

// DetermineLocation returns determine location request
func (l LocationClient) DetermineLocation(ctx context.Context) openapinlmflocationclient.ApiDetermineLocationRequest {
return l.client.DetermineLocationApi.DetermineLocation(ctx)
}

// DetermineLocationExecute executes the determine location request
func (l LocationClient) DetermineLocationExecute(r openapinlmflocationclient.ApiDetermineLocationRequest) (*openapinlmflocationclient.LocationData, *http.Response, error) {
return r.Execute()
}

// CancelLocation returns cancel location request
func (l LocationClient) CancelLocation(ctx context.Context) openapinlmflocationclient.ApiCancelLocationRequest {
return l.client.CancelLocationApi.CancelLocation(ctx)
}

// CancelLocationExecute executes the cancel location request
func (l LocationClient) CancelLocationExecute(r openapinlmflocationclient.ApiCancelLocationRequest) (*http.Response, error) {
return r.Execute()
}
24 changes: 16 additions & 8 deletions sdk/nlmf/mock/broadcast.go → fivegc/nlmf/mock/broadcast.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,24 @@ package mock

import (
"context"
"github.com/5GCoreNet/5GCoreNetSDK/sdk"
"github.com/5GCoreNet/5GCoreNetSDK/fivegc"
openapinlmfbroadcast "github.com/5GCoreNet/server-openapi/Nlmf_Broadcast"
)

// BroadcastMock is a mock of the Broadcast interface
type BroadcastMock struct {
cipherResponseData openapinlmfbroadcast.CipherResponseData
problemDetails openapinlmfbroadcast.ProblemDetails
redirectResponse sdk.RedirectResponse
statusCode sdk.StatusCode
redirectResponse fivegc.RedirectResponse
statusCode fivegc.StatusCode
}

// NewBroadcastMock creates a new mock of the Broadcast interface
func NewBroadcastMock(
cipherResponseData openapinlmfbroadcast.CipherResponseData,
problemDetails openapinlmfbroadcast.ProblemDetails,
redirectResponse sdk.RedirectResponse,
statusCode sdk.StatusCode,
redirectResponse fivegc.RedirectResponse,
statusCode fivegc.StatusCode,
) *BroadcastMock {
return &BroadcastMock{
cipherResponseData: cipherResponseData,
Expand All @@ -27,26 +29,32 @@ func NewBroadcastMock(
}
}

// ProblemDetails allows to set the problem details of the mock
func (b *BroadcastMock) ProblemDetails(problemDetails openapinlmfbroadcast.ProblemDetails) {
b.problemDetails = problemDetails
}

// CipherResponseData allows to set the cipher response data of the mock
func (b *BroadcastMock) CipherResponseData(cipherResponseData openapinlmfbroadcast.CipherResponseData) {
b.cipherResponseData = cipherResponseData
}

func (b *BroadcastMock) RedirectResponse(redirectResponse sdk.RedirectResponse) {
// RedirectResponse allows to set the redirect response of the mock
func (b *BroadcastMock) RedirectResponse(redirectResponse fivegc.RedirectResponse) {
b.redirectResponse = redirectResponse
}

func (b *BroadcastMock) StatusCode(statusCode sdk.StatusCode) {
// StatusCode allows to set the status code of the mock
func (b *BroadcastMock) StatusCode(statusCode fivegc.StatusCode) {
b.statusCode = statusCode
}

// Error returns the problem details of the mock
func (b *BroadcastMock) Error(ctx context.Context, err error) openapinlmfbroadcast.ProblemDetails {
return b.problemDetails
}

func (b *BroadcastMock) CipherKeyData(ctx context.Context, data openapinlmfbroadcast.CipherRequestData) (openapinlmfbroadcast.CipherResponseData, openapinlmfbroadcast.ProblemDetails, sdk.RedirectResponse, sdk.StatusCode) {
// CipherKeyData returns the cipher response data, the problem details, the redirect response and the status code of the mock
func (b *BroadcastMock) CipherKeyData(ctx context.Context, data openapinlmfbroadcast.CipherRequestData) (openapinlmfbroadcast.CipherResponseData, openapinlmfbroadcast.ProblemDetails, fivegc.RedirectResponse, fivegc.StatusCode) {
return b.cipherResponseData, b.problemDetails, b.redirectResponse, b.statusCode
}
Loading

0 comments on commit f3f3238

Please sign in to comment.