+func (c *Control) handleSubscriptionRequestTimer(strId string, nbrId int, tryCount uint64) {
+ xapp.Logger.Info("SubReq timeout: subId: %v, tryCount: %v", nbrId, tryCount)
+
+ subs := c.registry.GetSubscription(uint16(nbrId))
+ if subs == nil {
+ xapp.Logger.Error("SubReq timeout: Unknown payloadSeqNum. Dropping this msg. SubId: %v", nbrId)
+ return
+ }
+
+ trans := subs.GetTransaction()
+ if trans == nil {
+ xapp.Logger.Error("SubReq timeout: Unknown trans. Dropping this msg. SubId: %v", subs.GetSubId())
+ return
+ }
+
+ responseReceived := trans.CheckResponseReceived()
+
+ if responseReceived == true {
+ // Subscription Response or Failure already received
+ return
+ }
+
+ if tryCount < maxSubReqTryCount {
+ xapp.Logger.Info("SubReq timeout: Resending SubReq to E2T: Mtype: %v, SubId: %v, Xid %s, Meid %v", trans.GetMtype(), subs.GetSubId(), trans.GetXid(), trans.GetMeid())
+
+ trans.RetryTransaction()
+
+ c.rmrSend("SubReq(SubReq timer) to E2T", subs, trans, trans.Payload, trans.PayloadLen)
+
+ tryCount++
+ c.timerMap.StartTimer("RIC_SUB_REQ", int(subs.GetSubId()), subReqTime, tryCount, c.handleSubscriptionRequestTimer)
+ return
+ }
+
+ // Delete CREATE transaction
+ trans.Release()
+
+ // Create DELETE transaction (internal and no messages toward xapp)
+ deltrans, err := c.tracker.TrackTransaction(&trans.RmrEndpoint,
+ 12020, // RIC SUBSCRIPTION DELETE
+ trans.GetXid(),
+ trans.GetMeid(),
+ false,
+ false)
+
+ if err != nil {
+ xapp.Logger.Error("SubReq timeout: %s, Dropping this msg.", err.Error())
+ //TODO improve error handling. Important at least in merge
+ c.registry.DelSubscription(subs.GetSubId())
+ return
+ }
+
+ deltrans.SubDelReqMsg = &e2ap.E2APSubscriptionDeleteRequest{}
+ deltrans.SubDelReqMsg.RequestId.Id = trans.SubReqMsg.RequestId.Id
+ deltrans.SubDelReqMsg.RequestId.Seq = uint32(subs.GetSubId())
+ deltrans.SubDelReqMsg.FunctionId = trans.SubReqMsg.FunctionId
+ packedData, err := c.e2ap.PackSubscriptionDeleteRequest(deltrans.SubDelReqMsg)
+ if err != nil {
+ xapp.Logger.Error("SubReq timeout: Packing SubDelReq failed. Err: %v", err)
+ //TODO improve error handling. Important at least in merge
+ deltrans.Release()
+ c.registry.DelSubscription(subs.GetSubId())
+ return
+ }
+ deltrans.PayloadLen = len(packedData.Buf)
+ deltrans.Payload = packedData.Buf
+
+ err = subs.SetTransaction(deltrans)
+ if err != nil {
+ xapp.Logger.Error("SubReq timeout: %s, Dropping this msg.", err.Error())
+ //TODO improve error handling. Important at least in merge
+ deltrans.Release()
+ return
+ }
+
+ c.rmrSend("SubDelReq(SubReq timer) to E2T", subs, deltrans, deltrans.Payload, deltrans.PayloadLen)
+
+ c.timerMap.StartTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()), subDelReqTime, FirstTry, c.handleSubscriptionDeleteRequestTimer)
+ return
+}
+
+func (c *Control) handleSubscriptionDeleteRequest(params *RMRParams) {
+ xapp.Logger.Info("SubDelReq from xapp: %s", params.String())
+
+ //
+ //
+ //
+ trans, err := c.tracker.TrackTransaction(NewRmrEndpoint(params.Src),
+ params.Mtype,
+ params.Xid,
+ params.Meid,
+ false,
+ true)
+
+ if err != nil {
+ xapp.Logger.Error("SubDelReq: %s, Dropping this msg. %s", err.Error(), params.String())
+ return
+ }
+
+ //
+ //
+ //
+ trans.SubDelReqMsg, err = c.e2ap.UnpackSubscriptionDeleteRequest(params.Payload)
+ if err != nil {
+ xapp.Logger.Error("SubDelReq: %s Dropping this msg. %s", err.Error(), trans)
+ trans.Release()
+ return
+ }
+
+ //
+ //
+ //
+ subs := c.registry.GetSubscription(uint16(trans.SubDelReqMsg.RequestId.Seq))
+ if subs == nil && params.SubId > 0 {
+ subs = c.registry.GetSubscription(uint16(params.SubId))
+ }
+
+ if subs == nil {
+ xapp.Logger.Error("SubDelReq: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", trans.SubDelReqMsg.RequestId.Seq, params.SubId, trans)
+ trans.Release()
+ return
+ }
+ xapp.Logger.Info("SubDelReq: subscription found payloadSeqNum: %d, SubId: %d. %s", trans.SubDelReqMsg.RequestId.Seq, params.SubId, trans)
+
+ err = subs.SetTransaction(trans)
+ if err != nil {
+ xapp.Logger.Error("SubDelReq: %s, Dropping this msg. %s", err.Error(), trans)
+ trans.Release()
+ return
+ }
+
+ //
+ // TODO: subscription delete is in fact owned by subscription and not transaction.
+ // Transaction is toward xapp while Subscription is toward ran.
+ // In merge several xapps may wake transactions, while only one subscription
+ // toward ran occurs -> subscription owns subscription creation toward ran
+ //
+ // This is intermediate solution while improving message handling
+ //
+ packedData, err := c.e2ap.PackSubscriptionDeleteRequest(trans.SubDelReqMsg)
+ if err != nil {
+ xapp.Logger.Error("SubDelReq: %s for trans %s", err.Error(), trans)
+ trans.Release()
+ return
+ }
+
+ //Optimize and store packed message to be sent (for retransmission). Again owned by subscription?
+ trans.Payload = packedData.Buf
+ trans.PayloadLen = len(packedData.Buf)
+
+ subs.UnConfirmed()
+
+ c.rmrSend("SubDelReq to E2T", subs, trans, trans.Payload, trans.PayloadLen)
+
+ c.timerMap.StartTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()), subDelReqTime, FirstTry, c.handleSubscriptionDeleteRequestTimer)
+ return
+}
+
+func (c *Control) handleSubscriptionDeleteResponse(params *RMRParams) (err error) {
+ xapp.Logger.Info("SubDelResp from E2T:%s", params.String())
+
+ payloadSeqNum, err := c.e2ap.GetSubscriptionDeleteResponseSequenceNumber(params.Payload)
+ if err != nil {
+ xapp.Logger.Error("SubDelResp: Unable to get Sequence Number from Payload. Dropping this msg. Err: %v, SubId: %v, Xid: %s, Payload %X", err, params.SubId, params.Xid, params.Payload)
+ return
+ }
+ xapp.Logger.Info("SubDelResp: Received payloadSeqNum: %v", payloadSeqNum)
+
+ subs := c.registry.GetSubscription(payloadSeqNum)
+ if subs == nil {
+ xapp.Logger.Error("SubDelResp: Unknown payloadSeqNum. Dropping this msg. PayloadSeqNum: %v, SubId: %v", payloadSeqNum, params.SubId)
+ return
+ }
+
+ trans := subs.GetTransaction()
+ if trans == nil {
+ xapp.Logger.Error("SubDelResp: Unknown trans. Dropping this msg. PayloadSeqNum: %v, SubId: %v", subs.GetSubId(), params.SubId)
+ return
+ }
+
+ c.timerMap.StopTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()))
+
+ responseReceived := trans.CheckResponseReceived()
+ if responseReceived == true {
+ // Subscription Delete timer already received
+ return
+ }
+
+ trans.Release()
+
+ if trans.ForwardRespToXapp == true {
+ c.rmrReplyToSender("SubDelResp to xapp", subs, trans, params.Mtype, params.Payload, params.PayloadLen)
+ time.Sleep(3 * time.Second)
+ }
+
+ xapp.Logger.Info("SubDelResp: Deleting trans record. SubId: %v, Xid: %s", subs.GetSubId(), trans.GetXid())
+ if !c.registry.DelSubscription(subs.GetSubId()) {
+ xapp.Logger.Error("SubDelResp: Failed to release sequency number. SubId: %v, Xid: %s", subs.GetSubId(), trans.GetXid())
+ return
+ }
+ return
+}
+
+func (c *Control) handleSubscriptionDeleteFailure(params *RMRParams) {
+ xapp.Logger.Info("SubDelFail from E2T:%s", params.String())
+
+ payloadSeqNum, err := c.e2ap.GetSubscriptionDeleteFailureSequenceNumber(params.Payload)