Skip to content
This repository has been archived by the owner on Oct 20, 2024. It is now read-only.

chore: Adds information element category #12

Merged
merged 3 commits into from
Dec 23, 2023
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (

func main() {
pfcpClient := client.New("1.2.3.4:8805")
recoveryTimeStamp := messages.NewRecoveryTimeStamp(time.Now())
recoveryTimeStamp := ie.NewRecoveryTimeStamp(time.Now())
sequenceNumber := uint32(21)

_, err := pfcpClient.SendHeartbeatRequest(recoveryTimeStamp, sequenceNumber)
Expand Down
19 changes: 10 additions & 9 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package client
import (
"log"

"github.com/dot-5g/pfcp/ie"
"github.com/dot-5g/pfcp/messages"
"github.com/dot-5g/pfcp/network"
)
Expand All @@ -13,17 +14,19 @@ type Pfcp struct {
}

func New(ServerAddress string) *Pfcp {

udpClient, err := network.NewUdp(ServerAddress)
if err != nil {
log.Printf("Failed to initialize UDP client: %v\n", err)
return nil
}

return &Pfcp{ServerAddress: ServerAddress, Udp: udpClient}
}

func (pfcp *Pfcp) sendPfcpMessage(header messages.PFCPHeader, payload []byte, messageType string) error {
func (pfcp *Pfcp) sendPfcpMessage(header messages.PFCPHeader, elements []ie.InformationElement, messageType string) error {
var payload []byte
for _, element := range elements {
payload = append(payload, element.Serialize()...)
}
message := serializeMessage(header, payload)
if err := pfcp.Udp.Send(message); err != nil {
log.Printf("Failed to send PFCP %s: %v\n", messageType, err)
Expand All @@ -39,16 +42,14 @@ func serializeMessage(header messages.PFCPHeader, payload []byte) []byte {
return append(headerBytes, payload...)
}

func (pfcp *Pfcp) SendHeartbeatRequest(recoveryTimeStamp messages.RecoveryTimeStamp, sequenceNumber uint32) (messages.RecoveryTimeStamp, error) {
timeBytes := recoveryTimeStamp.ToBytes()
func (pfcp *Pfcp) SendHeartbeatRequest(recoveryTimeStamp ie.RecoveryTimeStamp, sequenceNumber uint32) (ie.RecoveryTimeStamp, error) {
header := messages.NewPFCPHeader(messages.PFCPHeartbeatRequest, sequenceNumber)
err := pfcp.sendPfcpMessage(header, timeBytes, "Heartbeat Request")
err := pfcp.sendPfcpMessage(header, []ie.InformationElement{recoveryTimeStamp}, "Heartbeat Request")
return recoveryTimeStamp, err
}

func (pfcp *Pfcp) SendHeartbeatResponse(recoveryTimeStamp messages.RecoveryTimeStamp, sequenceNumber uint32) (messages.RecoveryTimeStamp, error) {
timeBytes := recoveryTimeStamp.ToBytes()
func (pfcp *Pfcp) SendHeartbeatResponse(recoveryTimeStamp ie.RecoveryTimeStamp, sequenceNumber uint32) (ie.RecoveryTimeStamp, error) {
header := messages.NewPFCPHeader(messages.PFCPHeartbeatResponse, sequenceNumber)
err := pfcp.sendPfcpMessage(header, timeBytes, "Heartbeat Response")
err := pfcp.sendPfcpMessage(header, []ie.InformationElement{recoveryTimeStamp}, "Heartbeat Response")
return recoveryTimeStamp, err
}
4 changes: 2 additions & 2 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"time"

"github.com/dot-5g/pfcp/client"
"github.com/dot-5g/pfcp/messages"
"github.com/dot-5g/pfcp/ie"
)

type MockUdpSender struct {
Expand All @@ -24,7 +24,7 @@ func TestGivenPfcpWhenSendHeartbeatRequestThenNoError(t *testing.T) {
}
pfcpClient := client.New("127.0.0.1:8805")
pfcpClient.Udp = mockSender
recoveryTimeStamp := messages.NewRecoveryTimeStamp(time.Now())
recoveryTimeStamp := ie.NewRecoveryTimeStamp(time.Now())
sequenceNumber := uint32(21)

_, err := pfcpClient.SendHeartbeatRequest(recoveryTimeStamp, sequenceNumber)
Expand Down
5 changes: 5 additions & 0 deletions ie/ie.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ie

type InformationElement interface {
Serialize() []byte
}
38 changes: 38 additions & 0 deletions ie/recoveryTimeStamp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package ie

import (
"encoding/binary"
"time"
)

const ntpEpochOffset = 2208988800 // Offset between Unix and NTP epoch (seconds)

type RecoveryTimeStamp struct {
Type int
Length int
Value int64 // Seconds since 1900
}

func NewRecoveryTimeStamp(value time.Time) RecoveryTimeStamp {
return RecoveryTimeStamp{
Type: 96,
Length: 8,
Value: value.Unix() + ntpEpochOffset,
}
}

func (rt RecoveryTimeStamp) Serialize() []byte {
bytes := make([]byte, 8)
binary.BigEndian.PutUint16(bytes[0:2], uint16(rt.Type))
binary.BigEndian.PutUint16(bytes[2:4], uint16(rt.Length))
binary.BigEndian.PutUint32(bytes[4:8], uint32(rt.Value))
return bytes
}

func Deserialize(b []byte) RecoveryTimeStamp {
return RecoveryTimeStamp{
Type: int(binary.BigEndian.Uint16(b[0:2])),
Length: int(binary.BigEndian.Uint16(b[2:4])),
Value: int64(binary.BigEndian.Uint32(b[4:8])),
}
}
3 changes: 2 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import (
"time"

"github.com/dot-5g/pfcp/client"
"github.com/dot-5g/pfcp/ie"
"github.com/dot-5g/pfcp/messages"
"github.com/dot-5g/pfcp/server"
)

func main() {
pfcpClient := client.New("1.2.3.4:8805")
recoveryTimeStamp := messages.NewRecoveryTimeStamp(time.Now())
recoveryTimeStamp := ie.NewRecoveryTimeStamp(time.Now())
sequenceNumber := uint32(21)

_, err := pfcpClient.SendHeartbeatRequest(recoveryTimeStamp, sequenceNumber)
Expand Down
9 changes: 5 additions & 4 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@ import (
"time"

"github.com/dot-5g/pfcp/client"
"github.com/dot-5g/pfcp/ie"
"github.com/dot-5g/pfcp/messages"
"github.com/dot-5g/pfcp/server"
)

var (
heartbeatRequestMu sync.Mutex
heartbeatRequesthandlerCalled bool
heartbeatRequestreceivedRecoveryTimestamp messages.RecoveryTimeStamp
heartbeatRequestreceivedRecoveryTimestamp ie.RecoveryTimeStamp
heartbeatRequestReceivedSequenceNumber uint32
)

var (
heartbeatResponseMu sync.Mutex
heartbeatResponsehandlerCalled bool
heartbeatResponsereceivedRecoveryTimestamp messages.RecoveryTimeStamp
heartbeatResponsereceivedRecoveryTimestamp ie.RecoveryTimeStamp
heartbeatResponseReceivedSequenceNumber uint32
)

Expand Down Expand Up @@ -49,7 +50,7 @@ func HeartbeatRequest(t *testing.T) {
pfcpServer := server.New("127.0.0.1:8805")
pfcpServer.HeartbeatRequest(HandleHeartbeatRequest)
sentSequenceNumber := uint32(32)
recoveryTimeStamp := messages.NewRecoveryTimeStamp(time.Now())
recoveryTimeStamp := ie.NewRecoveryTimeStamp(time.Now())

go pfcpServer.Run()

Expand Down Expand Up @@ -81,7 +82,7 @@ func HeartbeatResponse(t *testing.T) {
pfcpServer := server.New("127.0.0.1:8805")
pfcpServer.HeartbeatResponse(HandleHeartbeatResponse)
sentSequenceNumber := uint32(971)
recoveryTimeStamp := messages.NewRecoveryTimeStamp(time.Now())
recoveryTimeStamp := ie.NewRecoveryTimeStamp(time.Now())

go pfcpServer.Run()

Expand Down
39 changes: 3 additions & 36 deletions messages/heartbeat.go
Original file line number Diff line number Diff line change
@@ -1,48 +1,15 @@
package messages

import (
"encoding/binary"
"time"
"github.com/dot-5g/pfcp/ie"
)

type RecoveryTimeStamp struct {
Type int
Length int
Value int64 // Seconds since 1900
}

type HeartbeatRequest struct {
RecoveryTimeStamp RecoveryTimeStamp
RecoveryTimeStamp ie.RecoveryTimeStamp
SequenceNumber uint32
}

type HeartbeatResponse struct {
RecoveryTimeStamp RecoveryTimeStamp
RecoveryTimeStamp ie.RecoveryTimeStamp
SequenceNumber uint32
}

func NewRecoveryTimeStamp(value time.Time) RecoveryTimeStamp {
return RecoveryTimeStamp{
Type: 96,
Length: 8,
Value: value.Unix() + ntpEpochOffset,
}
}

const ntpEpochOffset = 2208988800 // Offset between Unix and NTP epoch (seconds)

func (rt RecoveryTimeStamp) ToBytes() []byte {
bytes := make([]byte, 8)
binary.BigEndian.PutUint16(bytes[0:2], uint16(rt.Type))
binary.BigEndian.PutUint16(bytes[2:4], uint16(rt.Length))
binary.BigEndian.PutUint32(bytes[4:8], uint32(rt.Value))
return bytes
}

func FromBytes(b []byte) RecoveryTimeStamp {
return RecoveryTimeStamp{
Type: int(binary.BigEndian.Uint16(b[0:2])),
Length: int(binary.BigEndian.Uint16(b[2:4])),
Value: int64(binary.BigEndian.Uint32(b[4:8])),
}
}
5 changes: 3 additions & 2 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"log"
"net"

"github.com/dot-5g/pfcp/ie"
"github.com/dot-5g/pfcp/messages"
"github.com/dot-5g/pfcp/network"
)
Expand Down Expand Up @@ -75,7 +76,7 @@ func (server *Server) handleUDPMessage(data []byte, addr net.Addr) {
}

func (server *Server) handleHeartbeatRequest(msg *PfcpMessage, handler HandleHeartbeatRequest) {
recoveryTimeStamp := messages.FromBytes(msg.Message)
recoveryTimeStamp := ie.Deserialize(msg.Message)
heartbeatRequest := messages.HeartbeatRequest{
RecoveryTimeStamp: recoveryTimeStamp,
SequenceNumber: msg.Header.SequenceNumber,
Expand All @@ -84,7 +85,7 @@ func (server *Server) handleHeartbeatRequest(msg *PfcpMessage, handler HandleHea
}

func (server *Server) handleHeartbeatResponse(msg *PfcpMessage, handler HandleHeartbeatResponse) {
recoveryTimeStamp := messages.FromBytes(msg.Message)
recoveryTimeStamp := ie.Deserialize(msg.Message)
heartbeatResponse := messages.HeartbeatResponse{
RecoveryTimeStamp: recoveryTimeStamp,
SequenceNumber: msg.Header.SequenceNumber,
Expand Down
Loading