Add version 0.5.0

Change-Id: Ic052ea806f728c7e437038b1809f84a47af90011
Signed-off-by: Peter Szilagyi <peter.3.szilagyi@nokia.com>
diff --git a/pkg/control/control.go b/pkg/control/control.go
index d213c65..9a5022f 100644
--- a/pkg/control/control.go
+++ b/pkg/control/control.go
@@ -27,69 +27,97 @@
 */
 import "C"
 
-
 import (
-  "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
-  "errors"
-  "strconv"
+	"errors"
+	"gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
+	"github.com/spf13/viper"
+	"math/rand"
+	"strconv"
+	"time"
 )
 
 type Control struct {
-  e2ap *E2ap
-  registry *Registry
+	e2ap     *E2ap
+	registry *Registry
+}
+
+var SEEDSN uint16
+
+func init() {
+	viper.AutomaticEnv()
+	viper.SetEnvPrefix("submgr")
+	viper.AllowEmptyEnv(true)
+	SEEDSN = uint16(viper.GetInt("seed_sn"))
+	if SEEDSN == 0 {
+		rand.Seed(time.Now().UnixNano())
+		SEEDSN = uint16(rand.Intn(65535))
+	}
+	if SEEDSN > 65535 {
+		SEEDSN = 0
+	}
+	xapp.Logger.Info("SUBMGR: Initial Sequence Number: %v", SEEDSN)
 }
 
 func NewControl() Control {
-  return Control{new(E2ap),new(Registry)}
+	registry := new(Registry)
+	registry.Initialize(SEEDSN)
+	return Control{new(E2ap), registry}
 }
 
 func (c *Control) Run() {
-  xapp.Run(c)
+	xapp.Run(c)
 }
 
 func (c *Control) Consume(mtype, sub_id int, len int, payload []byte) (err error) {
-  switch mtype {
-  case C.RIC_SUB_REQ:
-    err = c.handleSubscriptionRequest(&RmrDatagram{mtype, sub_id, payload})
-  case C.RIC_SUB_RESP:
-    err = c.handleSubscriptionResponse(&RmrDatagram{mtype, sub_id, payload})
-  default:
-    err = errors.New("Message Type "+strconv.Itoa(mtype)+" discarded")
-  }
-  return
+	switch mtype {
+	case C.RIC_SUB_REQ:
+		err = c.handleSubscriptionRequest(&RmrDatagram{mtype, uint16(sub_id), payload})
+	case C.RIC_SUB_RESP:
+		err = c.handleSubscriptionResponse(&RmrDatagram{mtype, uint16(sub_id), payload})
+	default:
+		err = errors.New("Message Type " + strconv.Itoa(mtype) + " is discarded")
+	}
+	return
 }
 
 func (c *Control) rmrSend(datagram *RmrDatagram) (err error) {
-  if !xapp.Rmr.Send(datagram.MessageType, datagram.SubscriptionId, len(datagram.Payload), datagram.Payload) {
-    err = errors.New("rmr.Send() failed")
-  }
-  return
+	if !xapp.Rmr.Send(datagram.MessageType, int(datagram.SubscriptionId), len(datagram.Payload), datagram.Payload) {
+		err = errors.New("rmr.Send() failed")
+	}
+	return
 }
 
-func (c *Control) handleSubscriptionRequest(datagram *RmrDatagram) ( err error) {
-  /* TODO: removed to being able to integrate with UEMGR
-  content, err := c.e2ap.GetPayloadContent(datagram.Payload)
-  */
-  xapp.Logger.Info("Subscription Request Message received with ID: %v", datagram.SubscriptionId)
-  new_sub_id := c.registry.GetSubscriptionId()
-  /* TODO: removed to being able to integrate with UEMGR
-  payload, err := c.e2ap.SetSubscriptionSequenceNumber(datagram.Payload, new_sub_id)
-  if err != nil {
-    xapp.Logger.Error("Unable to set Subscription Sequence Number in Payload due to: "+ err.Error())
-    return
-  }
-  */
-  xapp.Logger.Info("New Subscription Registered, forwarding to E2T")
-  c.rmrSend(&RmrDatagram{C.RIC_SUB_REQ , new_sub_id, datagram.Payload})
-  return
+func (c *Control) handleSubscriptionRequest(datagram *RmrDatagram) (err error) {
+	payload_seq_num, err := c.e2ap.GetSubscriptionRequestSequenceNumber(datagram.Payload)
+	if err != nil {
+		err = errors.New("Unable to get Subscription Sequence Number from Payload due to: " + err.Error())
+		return
+	}
+	xapp.Logger.Info("Subscription Request Received. RMR SUBSCRIPTION_ID: %v | PAYLOAD SEQUENCE_NUMBER: %v", datagram.SubscriptionId, payload_seq_num)
+	new_sub_id := c.registry.ReserveSequenceNumber()
+	payload, err := c.e2ap.SetSubscriptionRequestSequenceNumber(datagram.Payload, new_sub_id)
+	if err != nil {
+		err = errors.New("Unable to set Subscription Sequence Number in Payload due to: " + err.Error())
+		return
+	}
+	xapp.Logger.Info("Generated ID: %v. Forwarding to E2 Termination...", int(new_sub_id))
+	c.rmrSend(&RmrDatagram{C.RIC_SUB_REQ, new_sub_id, payload})
+	return
 }
 
-func (c *Control) handleSubscriptionResponse(datagram *RmrDatagram) ( err error) {
-  /* TODO: removed to being able to integrate with UEMGR
-  content, err := c.e2ap.GetPayloadContent(datagram.Payload)
-  */
-  xapp.Logger.Info("Subscription Response Message received with ID: %v", datagram.SubscriptionId)
-  xapp.Logger.Info("Subscription Response Registered, forwarding to Requestor")
-  c.rmrSend(&RmrDatagram{C.RIC_SUB_RESP , datagram.SubscriptionId, datagram.Payload})
-  return
-}
\ No newline at end of file
+func (c *Control) handleSubscriptionResponse(datagram *RmrDatagram) (err error) {
+	payload_seq_num, err := c.e2ap.GetSubscriptionResponseSequenceNumber(datagram.Payload)
+	if err != nil {
+		err = errors.New("Unable to get Subscription Sequence Number from Payload due to: " + err.Error())
+		return
+	}
+	xapp.Logger.Info("Subscription Response Received. RMR SUBSCRIPTION_ID: %v | PAYLOAD SEQUENCE_NUMBER: %v", datagram.SubscriptionId, payload_seq_num)
+	if !c.registry.IsValidSequenceNumber(payload_seq_num) {
+		err = errors.New("Unknown Subscription ID: " + strconv.Itoa(int(payload_seq_num)) + " in Subscritpion Response. Message discarded.")
+		return
+	}
+	c.registry.setSubscriptionToConfirmed(payload_seq_num)
+	xapp.Logger.Info("Subscription Response Registered. Forwarding to Requestor...")
+	c.rmrSend(&RmrDatagram{C.RIC_SUB_RESP, payload_seq_num, datagram.Payload})
+	return
+}
diff --git a/pkg/control/e2ap.go b/pkg/control/e2ap.go
index ff9c778..c6b5e28 100644
--- a/pkg/control/e2ap.go
+++ b/pkg/control/e2ap.go
@@ -19,66 +19,57 @@
 
 package control
 
+/*
+#include <wrapper.h>
+
+#cgo LDFLAGS: -lwrapper
+*/
+import "C"
+
 import (
-  "encoding/gob"
-  "bytes"
-  "errors"
+	"errors"
+	"unsafe"
 )
 
 type E2ap struct {
 }
 
-func (c *E2ap) GetSubscriptionSequenceNumber(payload []byte) (int, error) {
-  asn1 := new(Asn1)
-  message, err := asn1.Decode(payload)
-  if err != nil {
-    return 0, errors.New("Unable to decode payload due to "+ err.Error()) 
-  }
-  return message.SubscriptionId, nil
+func (c *E2ap) GetSubscriptionRequestSequenceNumber(payload []byte) (sub_id uint16, err error) {
+	cptr := unsafe.Pointer(&payload[0])
+	cret := C.e2ap_get_ric_subscription_request_sequence_number(cptr, C.size_t(len(payload)))
+	if cret < 0 {
+		return 0, errors.New("e2ap wrapper is unable to get Subscirption Request Sequence Number due to wrong or invalid payload")
+	}
+	sub_id = uint16(cret)
+	return
 }
 
-func (c *E2ap) SetSubscriptionSequenceNumber(payload []byte, newSubscriptionid int) ([]byte ,error) {
-  asn1 := new(Asn1)
-  message, err := asn1.Decode(payload)
-  if err != nil {
-    return make([]byte,0), errors.New("Unable to decode payload due to "+ err.Error()) 
-  }
-  message.SubscriptionId = newSubscriptionid
-  payload, err = asn1.Encode(message)
-  if err != nil {
-    return make([]byte,0), errors.New("Unable to encode message due to "+ err.Error()) 
-  }
-  return payload, nil
+func (c *E2ap) SetSubscriptionRequestSequenceNumber(payload []byte, newSubscriptionid uint16) (new_payload []byte, err error) {
+	cptr := unsafe.Pointer(&payload[0])
+	size := C.e2ap_set_ric_subscription_request_sequence_number(cptr, C.size_t(len(payload)), C.long(newSubscriptionid))
+	if size < 0 {
+		return make([]byte, 0), errors.New("e2ap wrapper is unable to set Subscirption Request Sequence Number due to wrong or invalid payload")
+	}
+	new_payload = C.GoBytes(cptr, C.int(size))
+	return
 }
 
-
-func (c *E2ap) GetPayloadContent(payload []byte) (content string, err error) {
-  asn1 := new(Asn1)
-  message, err := asn1.Decode(payload)
-  content = message.Content
-  return
-}
-/*
-Serialize and Deserialize message using this until real ASN1 GO wrapper is not in place
-*/
-type Asn1 struct {
+func (c *E2ap) GetSubscriptionResponseSequenceNumber(payload []byte) (sub_id uint16, err error) {
+	cptr := unsafe.Pointer(&payload[0])
+	cret := C.e2ap_get_ric_subscription_response_sequence_number(cptr, C.size_t(len(payload)))
+	if cret < 0 {
+		return 0, errors.New("e2ap wrapper is unable to get Subscirption Response Sequence Number due to wrong or invalid payload")
+	}
+	sub_id = uint16(cret)
+	return
 }
 
-func (a *Asn1) Encode(message RmrPayload) ([]byte, error) {
-	buffer := new(bytes.Buffer)
-	asn1 := gob.NewEncoder(buffer)
-	if err := asn1.Encode(message); err != nil {
-		return nil, err
-  }
-	return buffer.Bytes(), nil
-}
-
-func (a *Asn1) Decode(data []byte) (RmrPayload, error) {
-  message := new(RmrPayload)
-  buffer := bytes.NewBuffer(data)
-	asn1 := gob.NewDecoder(buffer)
-	if err := asn1.Decode(message); err != nil {
-		return RmrPayload{}, err
-  }
-	return *message, nil
+func (c *E2ap) SetSubscriptionResponseSequenceNumber(payload []byte, newSubscriptionid uint16) (new_payload []byte, err error) {
+	cptr := unsafe.Pointer(&payload[0])
+	size := C.e2ap_set_ric_subscription_response_sequence_number(cptr, C.size_t(len(payload)), C.long(newSubscriptionid))
+	if size < 0 {
+		return make([]byte, 0), errors.New("e2ap wrapper is unable to set Subscirption Reponse Sequence Number due to wrong or invalid payload")
+	}
+	new_payload = C.GoBytes(cptr, C.int(size))
+	return
 }
diff --git a/pkg/control/registry.go b/pkg/control/registry.go
index 8f52f97..d182b3e 100644
--- a/pkg/control/registry.go
+++ b/pkg/control/registry.go
@@ -19,15 +19,45 @@
 
 package control
 
+import "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
+
 type Registry struct {
-  counter int
+	register map[uint16]bool
+	counter  uint16
 }
 
-func (r *Registry) GetSubscriptionId() int {
-  return r.generateId()
+// This method should run as a constructor
+func (r *Registry) Initialize(seedsn uint16) {
+	r.register = make(map[uint16]bool)
+	r.counter = seedsn
 }
 
-func (r *Registry) generateId() int {
-  r.counter += 1
-  return r.counter
+// Reserves and returns the next free sequence number
+func (r *Registry) ReserveSequenceNumber() uint16 {
+	sequenceNumber := r.counter
+	r.register[sequenceNumber] = false
+	r.shift()
+	return sequenceNumber
+}
+
+// This function checks the validity of the given subscription id
+func (r *Registry) IsValidSequenceNumber(sn uint16) bool {
+	xapp.Logger.Debug("Registry map: %v", r.register)
+	if _, ok := r.register[sn]; ok {
+		return true
+	}
+	return false
+}
+
+// This function sets the give id as confirmed in the register
+func (r *Registry) setSubscriptionToConfirmed(sn uint16) {
+	r.register[sn] = true
+}
+
+func (r *Registry) shift() {
+	if r.counter == 65535 {
+		r.counter = 0
+	} else {
+		r.counter++
+	}
 }
diff --git a/pkg/control/types.go b/pkg/control/types.go
index 5f46e65..2a4e9d5 100644
--- a/pkg/control/types.go
+++ b/pkg/control/types.go
@@ -19,14 +19,8 @@
 
 package control
 
-type RmrPayload struct {
-	MessageType int
-	SubscriptionId int
-	Content string 
-}
-
 type RmrDatagram struct {
-  MessageType int
-	SubscriptionId int
-	Payload []byte 
+	MessageType    int
+	SubscriptionId uint16
+	Payload        []byte
 }