From d412e64eff705a1daa7a11d89514834b018d7e8d Mon Sep 17 00:00:00 2001 From: Louis Royer Date: Thu, 19 Dec 2024 15:46:59 +0100 Subject: [PATCH] Register in gin.Engine --- internal/app/control.go | 5 +- internal/radio/peer.go | 61 ++++++++++++++ internal/radio/radio.go | 46 +---------- internal/session/establishment-request.go | 55 +++++++++++++ ...session.go => n2-establishment-request.go} | 81 ------------------- internal/session/pdu_sessions.go | 63 +++++++++++++++ 6 files changed, 183 insertions(+), 128 deletions(-) create mode 100644 internal/radio/peer.go create mode 100644 internal/session/establishment-request.go rename internal/session/{pdu_session.go => n2-establishment-request.go} (55%) create mode 100644 internal/session/pdu_sessions.go diff --git a/internal/app/control.go b/internal/app/control.go index 14c7157..1d12ece 100644 --- a/internal/app/control.go +++ b/internal/app/control.go @@ -34,11 +34,10 @@ func NewHttpServerEntity(bindAddr netip.AddrPort, r *radio.Radio, ps *session.Pd h.GET("/status", Status) // Radio - h.POST("/radio/peer", r.Peer) + r.Register(h) // Pdu Sessions - h.POST("/ps/establishment-request", ps.EstablishmentRequest) - h.POST("/ps/n2-establishment-request", ps.N2EstablishmentRequest) + ps.Register(h) logrus.WithFields(logrus.Fields{"http-addr": bindAddr}).Info("HTTP Server created") e := HttpServerEntity{ diff --git a/internal/radio/peer.go b/internal/radio/peer.go new file mode 100644 index 0000000..ea509c9 --- /dev/null +++ b/internal/radio/peer.go @@ -0,0 +1,61 @@ +// Copyright 2024 Louis Royer and the NextMN contributors. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. +// SPDX-License-Identifier: MIT + +package radio + +import ( + "bytes" + "encoding/json" + "net/http" + + "github.com/nextmn/json-api/jsonapi" + "github.com/nextmn/json-api/jsonapi/n1n2" + + "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" +) + +// allow to peer to ue +func (r *Radio) Peer(c *gin.Context) { + var peer n1n2.RadioPeerMsg + if err := c.BindJSON(&peer); err != nil { + logrus.WithError(err).Error("could not deserialize") + c.JSON(http.StatusBadRequest, jsonapi.MessageWithError{Message: "could not deserialize", Error: err}) + return + } + go r.HandlePeer(peer) + c.JSON(http.StatusAccepted, jsonapi.Message{Message: "please refer to logs for more information"}) +} + +func (r *Radio) HandlePeer(peer n1n2.RadioPeerMsg) { + ctx := r.Context() + r.peerMap.Store(peer.Control, peer.Data) + logrus.WithFields(logrus.Fields{ + "peer-control": peer.Control.String(), + "peer-ran": peer.Data, + }).Info("New peer radio link") + msg := n1n2.RadioPeerMsg{ + Control: r.Control, + Data: r.Data, + } + + reqBody, err := json.Marshal(msg) + if err != nil { + logrus.WithError(err).Error("Could not Marshal n1n2.RadioPeerMsg") + return + } + req, err := http.NewRequestWithContext(ctx, http.MethodPost, peer.Control.JoinPath("radio/peer").String(), bytes.NewBuffer(reqBody)) + if err != nil { + logrus.WithError(err).Error("Could not create radio/peer request") + return + } + req.Header.Set("User-Agent", r.UserAgent) + req.Header.Set("Content-Type", "application/json; charset=UTF-8") + if _, err := r.Client.Do(req); err != nil { + logrus.WithError(err).Error("Could not send radio/peer request") + return + } + // TODO: handle ue failure +} diff --git a/internal/radio/radio.go b/internal/radio/radio.go index b3263b2..75909e4 100644 --- a/internal/radio/radio.go +++ b/internal/radio/radio.go @@ -6,16 +6,13 @@ package radio import ( - "bytes" "context" - "encoding/json" "net" "net/http" "net/netip" "sync" "github.com/nextmn/json-api/jsonapi" - "github.com/nextmn/json-api/jsonapi/n1n2" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" @@ -68,45 +65,6 @@ func (r *Radio) Write(pkt []byte, srv *net.UDPConn, ue jsonapi.ControlURI) error return err } -// allow to peer to ue -func (r *Radio) Peer(c *gin.Context) { - var peer n1n2.RadioPeerMsg - if err := c.BindJSON(&peer); err != nil { - logrus.WithError(err).Error("could not deserialize") - c.JSON(http.StatusBadRequest, jsonapi.MessageWithError{Message: "could not deserialize", Error: err}) - return - } - go r.HandlePeer(peer) - c.JSON(http.StatusAccepted, jsonapi.Message{Message: "please refer to logs for more information"}) -} - -func (r *Radio) HandlePeer(peer n1n2.RadioPeerMsg) { - ctx := r.Context() - r.peerMap.Store(peer.Control, peer.Data) - logrus.WithFields(logrus.Fields{ - "peer-control": peer.Control.String(), - "peer-ran": peer.Data, - }).Info("New peer radio link") - msg := n1n2.RadioPeerMsg{ - Control: r.Control, - Data: r.Data, - } - - reqBody, err := json.Marshal(msg) - if err != nil { - logrus.WithError(err).Error("Could not Marshal n1n2.RadioPeerMsg") - return - } - req, err := http.NewRequestWithContext(ctx, http.MethodPost, peer.Control.JoinPath("radio/peer").String(), bytes.NewBuffer(reqBody)) - if err != nil { - logrus.WithError(err).Error("Could not create radio/peer request") - return - } - req.Header.Set("User-Agent", r.UserAgent) - req.Header.Set("Content-Type", "application/json; charset=UTF-8") - if _, err := r.Client.Do(req); err != nil { - logrus.WithError(err).Error("Could not send radio/peer request") - return - } - // TODO: handle ue failure +func (r *Radio) Register(e *gin.Engine) { + e.POST("/radio/peer", r.Peer) } diff --git a/internal/session/establishment-request.go b/internal/session/establishment-request.go new file mode 100644 index 0000000..c668f9d --- /dev/null +++ b/internal/session/establishment-request.go @@ -0,0 +1,55 @@ +// Copyright 2024 Louis Royer and the NextMN contributors. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. +// SPDX-License-Identifier: MIT + +package session + +import ( + "bytes" + "encoding/json" + "net/http" + + "github.com/nextmn/json-api/jsonapi" + "github.com/nextmn/json-api/jsonapi/n1n2" + + "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" +) + +// request from UE +func (p *PduSessions) EstablishmentRequest(c *gin.Context) { + // get PseReq + var ps n1n2.PduSessionEstabReqMsg + if err := c.BindJSON(&ps); err != nil { + logrus.WithError(err).Error("could not deserialize") + c.JSON(http.StatusBadRequest, jsonapi.MessageWithError{Message: "could not deserialize", Error: err}) + return + } + logrus.WithFields(logrus.Fields{ + "ue": ps.Ue.String(), + }).Info("New PDU Session establishment Request") + go p.HandleEstablishmentRequest(ps) + c.JSON(http.StatusAccepted, jsonapi.Message{Message: "please refer to logs for more information"}) +} + +func (p *PduSessions) HandleEstablishmentRequest(ps n1n2.PduSessionEstabReqMsg) { + ctx := p.Context() + // forward to cp + reqBody, err := json.Marshal(ps) + if err != nil { + logrus.WithError(err).Error("Could not marshal n1n2.PduSessionEstabReqMsg") + return + } + req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.Cp.JoinPath("ps/establishment-request").String(), bytes.NewBuffer(reqBody)) + if err != nil { + logrus.WithError(err).Error("Could not create ps/establishment-request") + return + } + req.Header.Set("User-Agent", p.UserAgent) + req.Header.Set("Content-Type", "application/json; charset=UTF-8") + if _, err := p.Client.Do(req); err != nil { + logrus.WithError(err).Error("Could not send ps/establishment-request") + return + } +} diff --git a/internal/session/pdu_session.go b/internal/session/n2-establishment-request.go similarity index 55% rename from internal/session/pdu_session.go rename to internal/session/n2-establishment-request.go index 9c07333..25ea560 100644 --- a/internal/session/pdu_session.go +++ b/internal/session/n2-establishment-request.go @@ -7,11 +7,8 @@ package session import ( "bytes" - "context" "encoding/json" "net/http" - "net/netip" - "sync" "github.com/nextmn/json-api/jsonapi" "github.com/nextmn/json-api/jsonapi/n1n2" @@ -20,84 +17,6 @@ import ( "github.com/sirupsen/logrus" ) -type PduSessions struct { - PduSessionsMap sync.Map // key : UE 5G ip address; value: UE Control URI - UserAgent string - Client http.Client - Control jsonapi.ControlURI - Cp jsonapi.ControlURI - GnbGtp netip.Addr - manager *PduSessionsManager - - // not exported because must not be modified - ctx context.Context -} - -func NewPduSessions(control jsonapi.ControlURI, cp jsonapi.ControlURI, manager *PduSessionsManager, userAgent string, gnbGtp netip.Addr) *PduSessions { - return &PduSessions{ - Client: http.Client{}, - PduSessionsMap: sync.Map{}, - UserAgent: userAgent, - Control: control, - Cp: cp, - GnbGtp: gnbGtp, - manager: manager, - } - -} - -func (p *PduSessions) Init(ctx context.Context) error { - if ctx == nil { - return ErrNilCtx - } - p.ctx = ctx - return nil -} - -func (p *PduSessions) Context() context.Context { - if p.ctx != nil { - return p.ctx - } - return context.Background() -} - -// request from UE -func (p *PduSessions) EstablishmentRequest(c *gin.Context) { - // get PseReq - var ps n1n2.PduSessionEstabReqMsg - if err := c.BindJSON(&ps); err != nil { - logrus.WithError(err).Error("could not deserialize") - c.JSON(http.StatusBadRequest, jsonapi.MessageWithError{Message: "could not deserialize", Error: err}) - return - } - logrus.WithFields(logrus.Fields{ - "ue": ps.Ue.String(), - }).Info("New PDU Session establishment Request") - go p.HandleEstablishmentRequest(ps) - c.JSON(http.StatusAccepted, jsonapi.Message{Message: "please refer to logs for more information"}) -} - -func (p *PduSessions) HandleEstablishmentRequest(ps n1n2.PduSessionEstabReqMsg) { - ctx := p.Context() - // forward to cp - reqBody, err := json.Marshal(ps) - if err != nil { - logrus.WithError(err).Error("Could not marshal n1n2.PduSessionEstabReqMsg") - return - } - req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.Cp.JoinPath("ps/establishment-request").String(), bytes.NewBuffer(reqBody)) - if err != nil { - logrus.WithError(err).Error("Could not create ps/establishment-request") - return - } - req.Header.Set("User-Agent", p.UserAgent) - req.Header.Set("Content-Type", "application/json; charset=UTF-8") - if _, err := p.Client.Do(req); err != nil { - logrus.WithError(err).Error("Could not send ps/establishment-request") - return - } -} - // request from CP func (p *PduSessions) N2EstablishmentRequest(c *gin.Context) { var ps n1n2.N2PduSessionReqMsg diff --git a/internal/session/pdu_sessions.go b/internal/session/pdu_sessions.go new file mode 100644 index 0000000..3ccfc80 --- /dev/null +++ b/internal/session/pdu_sessions.go @@ -0,0 +1,63 @@ +// Copyright 2024 Louis Royer and the NextMN contributors. All rights reserved. +// Use of this source code is governed by a MIT-style license that can be +// found in the LICENSE file. +// SPDX-License-Identifier: MIT + +package session + +import ( + "context" + "net/http" + "net/netip" + "sync" + + "github.com/nextmn/json-api/jsonapi" + + "github.com/gin-gonic/gin" +) + +type PduSessions struct { + PduSessionsMap sync.Map // key : UE 5G ip address; value: UE Control URI + UserAgent string + Client http.Client + Control jsonapi.ControlURI + Cp jsonapi.ControlURI + GnbGtp netip.Addr + manager *PduSessionsManager + + // not exported because must not be modified + ctx context.Context +} + +func NewPduSessions(control jsonapi.ControlURI, cp jsonapi.ControlURI, manager *PduSessionsManager, userAgent string, gnbGtp netip.Addr) *PduSessions { + return &PduSessions{ + Client: http.Client{}, + PduSessionsMap: sync.Map{}, + UserAgent: userAgent, + Control: control, + Cp: cp, + GnbGtp: gnbGtp, + manager: manager, + } + +} + +func (p *PduSessions) Init(ctx context.Context) error { + if ctx == nil { + return ErrNilCtx + } + p.ctx = ctx + return nil +} + +func (p *PduSessions) Context() context.Context { + if p.ctx != nil { + return p.ctx + } + return context.Background() +} + +func (p *PduSessions) Register(e *gin.Engine) { + e.POST("/ps/establishment-request", p.EstablishmentRequest) + e.POST("/ps/n2-establishment-request", p.N2EstablishmentRequest) +}